2017-04-09 21:55:07 -07:00
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* USBSerial core library for Arduino STM32 + HAL + CubeMX (HALMX).
|
|
|
|
*
|
|
|
|
* Copyright (c) 2016 by Vassilis Serasidis <info@serasidis.gr>
|
|
|
|
* Home: http://www.serasidis.gr
|
|
|
|
* email: avrsite@yahoo.gr
|
|
|
|
*
|
|
|
|
* Arduino_STM32 forum: http://www.stm32duino.com
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for
|
|
|
|
* any purpose with or without fee is hereby granted, provided that the
|
|
|
|
* above copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* Some functions follow the sam and samd arduino core libray files.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
|
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
|
|
|
* BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
|
|
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
|
|
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2017-04-18 09:54:02 -07:00
|
|
|
#ifdef MENU_USB_SERIAL
|
2017-04-09 21:55:07 -07:00
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
#include <SerialUSB.h>
|
2017-04-09 21:55:07 -07:00
|
|
|
#include "variant.h"
|
|
|
|
|
|
|
|
// Constructors ////////////////////////////////////////////////////////////////
|
2017-04-17 11:45:47 -07:00
|
|
|
SerialUSBClass::SerialUSBClass(){
|
2017-04-09 21:55:07 -07:00
|
|
|
// Make sure Rx ring buffer is initialized back to empty.
|
|
|
|
rx_buffer.iHead = rx_buffer.iTail = 0;
|
|
|
|
//tx_buffer.iHead = tx_buffer.iTail = 0;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
void SerialUSBClass::init(void){
|
2017-04-09 21:55:07 -07:00
|
|
|
/* Re-enumerate the USB */
|
|
|
|
volatile unsigned int i;
|
|
|
|
|
|
|
|
#ifdef USB_DISC_PIN
|
|
|
|
pinMode(USB_DISC_PIN, OUTPUT);
|
|
|
|
digitalWrite(USB_DISC_PIN, HIGH);
|
|
|
|
for(i=0;i<512;i++);
|
|
|
|
digitalWrite(USB_DISC_PIN, LOW);
|
|
|
|
#else
|
|
|
|
//pinMode(USBDP_PIN, OUTPUT);
|
|
|
|
//digitalWrite(USBDP_PIN, LOW);
|
|
|
|
//for(i=0;i<512;i++);
|
|
|
|
//digitalWrite(USBDP_PIN, HIGH);
|
|
|
|
|
|
|
|
|
|
|
|
pinMode(PA12, OUTPUT);
|
|
|
|
digitalWrite(PA12, LOW);
|
|
|
|
//HAL_Delay(1000);
|
|
|
|
for(i=0;i<512;i++){};
|
|
|
|
digitalWrite(PA12, HIGH);
|
|
|
|
//HAL_Delay(1000);
|
|
|
|
for(i=0;i<512;i++){};
|
|
|
|
#endif
|
|
|
|
MX_USB_DEVICE_Init();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
void SerialUSBClass::begin(uint32_t baud_count){
|
2017-04-09 21:55:07 -07:00
|
|
|
init();
|
|
|
|
// suppress "unused parameter" warning
|
|
|
|
(void)baud_count;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
void SerialUSBClass::begin(uint32_t baud_count, uint8_t config){
|
2017-04-09 21:55:07 -07:00
|
|
|
init();
|
|
|
|
//suppress "unused parameter" warning
|
|
|
|
(void)baud_count;
|
|
|
|
(void)config;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
void SerialUSBClass::end(void){
|
2017-04-09 21:55:07 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
int SerialUSBClass::availableForWrite(void){
|
2017-04-09 21:55:07 -07:00
|
|
|
//return (CDC_SERIAL_BUFFER_SIZE - available());
|
|
|
|
//return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + tx_buffer.iHead - tx_buffer.iTail) % CDC_SERIAL_BUFFER_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
int SerialUSBClass::available(void){
|
2017-04-09 21:55:07 -07:00
|
|
|
return (uint32_t)(CDC_SERIAL_BUFFER_SIZE + rx_buffer.iHead - rx_buffer.iTail) % CDC_SERIAL_BUFFER_SIZE;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
int SerialUSBClass::peek(void)
|
2017-04-09 21:55:07 -07:00
|
|
|
{
|
|
|
|
if ( rx_buffer.iHead == rx_buffer.iTail )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return rx_buffer.buffer[rx_buffer.iTail];
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
int SerialUSBClass::read(void)
|
2017-04-09 21:55:07 -07:00
|
|
|
{
|
|
|
|
// if the head isn't ahead of the tail, we don't have any characters
|
|
|
|
if ( rx_buffer.iHead == rx_buffer.iTail )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
uint8_t uc = rx_buffer.buffer[rx_buffer.iTail];
|
|
|
|
rx_buffer.iTail = (unsigned int)(rx_buffer.iTail + 1) % CDC_SERIAL_BUFFER_SIZE;
|
|
|
|
|
|
|
|
return uc;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
void SerialUSBClass::flush(void){
|
2017-04-09 21:55:07 -07:00
|
|
|
//It's not implemented yet.
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
size_t SerialUSBClass::write(const uint8_t *buffer, size_t size){
|
2017-04-09 21:55:07 -07:00
|
|
|
unsigned long timeout=millis()+5;
|
|
|
|
if(hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED)
|
|
|
|
{
|
|
|
|
while(millis()<timeout)
|
|
|
|
{
|
|
|
|
if(CDC_Transmit_FS((uint8_t*)buffer, size) == USBD_OK)
|
|
|
|
{
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
/* uint8_t i;
|
|
|
|
|
|
|
|
if(hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED){
|
|
|
|
|
|
|
|
//HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
|
|
|
|
for(i=0;i<200;i++)
|
|
|
|
if(CDC_Transmit_FS((uint8_t*)buffer, size) == USBD_OK){
|
|
|
|
return size;
|
|
|
|
//break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
|
|
|
|
}
|
|
|
|
return 0; */
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
size_t SerialUSBClass::write(uint8_t c) {
|
2017-04-09 21:55:07 -07:00
|
|
|
return write(&c, 1);
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
void SerialUSBClass::CDC_RxHandler (uint8_t* Buf, uint16_t Len){
|
2017-04-09 21:55:07 -07:00
|
|
|
|
|
|
|
for(uint16_t i=0;i<Len;i++){
|
|
|
|
if(available() < (CDC_SERIAL_BUFFER_SIZE - 1)){
|
|
|
|
rx_buffer.buffer[rx_buffer.iHead] = *Buf++;
|
|
|
|
rx_buffer.iHead = (uint16_t)(rx_buffer.iHead + 1) % CDC_SERIAL_BUFFER_SIZE;
|
|
|
|
}else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This operator is a convenient way for a sketch to check whether the
|
|
|
|
// port has actually been configured and opened by the host (as opposed
|
|
|
|
// to just being connected to the host). It can be used, for example, in
|
|
|
|
// setup() before printing to ensure that an application on the host is
|
|
|
|
// actually ready to receive and display the data.
|
|
|
|
// We add a short delay before returning to fix a bug observed by Federico
|
|
|
|
// where the port is configured (lineState != 0) but not quite opened.
|
2017-04-17 11:45:47 -07:00
|
|
|
SerialUSBClass::operator bool()
|
2017-04-09 21:55:07 -07:00
|
|
|
{
|
|
|
|
// this is here to avoid spurious opening after upload
|
|
|
|
if (millis() < 500)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
/* if (_usbLineInfo.lineState > 0)
|
|
|
|
{
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
delay(10); */
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
uint32_t SerialUSBClass::baud() {
|
2017-04-09 21:55:07 -07:00
|
|
|
//return _usbLineInfo.dwDTERate;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
uint8_t SerialUSBClass::stopbits() {
|
2017-04-09 21:55:07 -07:00
|
|
|
//return _usbLineInfo.bCharFormat;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
uint8_t SerialUSBClass::paritytype() {
|
2017-04-09 21:55:07 -07:00
|
|
|
//return _usbLineInfo.bParityType;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
uint8_t SerialUSBClass::numbits() {
|
2017-04-09 21:55:07 -07:00
|
|
|
//return _usbLineInfo.bDataBits;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
bool SerialUSBClass::dtr() {
|
2017-04-09 21:55:07 -07:00
|
|
|
//return _usbLineInfo.lineState & 0x1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
bool SerialUSBClass::rts() {
|
2017-04-09 21:55:07 -07:00
|
|
|
//return _usbLineInfo.lineState & 0x2;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern PCD_HandleTypeDef hpcd_USB_FS;
|
|
|
|
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
|
|
|
|
|
|
|
//F1
|
|
|
|
extern "C" void USB_LP_CAN1_RX0_IRQHandler(void) {
|
|
|
|
HAL_PCD_IRQHandler(&hpcd_USB_FS);
|
|
|
|
}
|
2017-05-04 08:51:01 -07:00
|
|
|
//F4 F7
|
2017-04-09 21:55:07 -07:00
|
|
|
extern "C" void OTG_FS_IRQHandler(void) {
|
|
|
|
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
|
|
|
|
}
|
|
|
|
//L0
|
|
|
|
extern "C" void USB_IRQHandler(void) {
|
|
|
|
HAL_PCD_IRQHandler(&hpcd_USB_FS);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void USBSerial_Rx_Handler(uint8_t *data, uint16_t len){
|
|
|
|
SerialUSB.CDC_RxHandler(data, len);
|
|
|
|
}
|
|
|
|
|
2017-04-17 11:45:47 -07:00
|
|
|
SerialUSBClass SerialUSB;
|
2017-04-09 21:55:07 -07:00
|
|
|
|
|
|
|
#endif
|