diff --git a/firmware/main.c b/firmware/main.c index 9eff66d..b4b113b 100755 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,21 +1,13 @@ -/** - * description: Modified LUFA example to get two virtual serial USB devices. - * author: Kai Lauterbach - * date: 08/2016 - * version: v0.1 - * license: GPLv3 - */ - /* LUFA Library - Copyright (C) Dean Camera, 2016. + Copyright (C) Dean Camera, 2015. dean [at] fourwalledcubicle [dot] com www.lufa-lib.org */ /* - Copyright 2016 Dean Camera (dean [at] fourwalledcubicle [dot] com) + Copyright 2015 Dean Camera (dean [at] fourwalledcubicle [dot] com) Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted @@ -38,467 +30,357 @@ /** \file * - * Main source file for the project - based on the Mouse and VirtualSerial lufa demo. - * This file contains the main tasks of the demo and is responsible for the initial - * application hardware configuration. + * Main source file for the iUSB2SerialMux demo. This file contains the main tasks of the demo and + * is responsible for the initial application hardware configuration. */ #include "main.h" -//********************************************************************************// +/**************************************************************************************/ -FIFO_t agent_fifo; -FIFO_t seq_mod_fifo; -FIFO_t seq_val_fifo; +uint32_t EEMEM eep_baudrate; -uint8_t seq_delay = 0; +uint32_t baudrate = 115200; // replacement for the UART_BAUDRATE definition -volatile uint16_t time_measure_cnt = 0; -volatile uint16_t keystroke_delay_time_measure_cnt_old = 0; -volatile uint16_t seq_delay_time_measure_cnt_old = 0; +/**************************************************************************************/ -//********************************************************************************// - -/** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */ -static uint8_t PrevKeyboardHIDReportBuffer[sizeof(USB_KeyboardReport_Data_t)]; - -//********************************************************************************// - -/** LUFA HID Class driver interface configuration and state information. This structure is - * passed to all HID Class driver functions, so that multiple instances of the same class - * within a device can be differentiated from one another. This is for the keyboard HID - * interface within the device. +/** Contains the current baud rate and other settings of the first virtual serial port. While this demo does not use + * the physical USART and thus does not use these settings, they must still be retained and returned to the host + * upon request or the host will assume the device is non-functional. + * + * These values are set by the host via a class-specific request, however they are not required to be used accurately. + * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical + * serial link characteristics and instead sends and receives data in endpoint streams. */ -USB_ClassInfo_HID_Device_t Keyboard_HID_Interface = - { - .Config = - { - .InterfaceNumber = INTERFACE_ID_Keyboard, - .ReportINEndpoint = - { - .Address = KEYBOARD_IN_EPADDR, - .Size = KEYBOARD_EPSIZE, - .Banks = 1, - }, - .PrevReportINBuffer = PrevKeyboardHIDReportBuffer, - .PrevReportINBufferSize = sizeof(PrevKeyboardHIDReportBuffer), - }, - }; +static CDC_LineEncoding_t LineEncoding1 = { .BaudRateBPS = 0, + .CharFormat = CDC_LINEENCODING_OneStopBit, + .ParityType = CDC_PARITY_None, + .DataBits = 8 }; -/** LUFA CDC Class driver interface configuration and state information. This structure is - * passed to all CDC Class driver functions, so that multiple instances of the same class - * within a device can be differentiated from one another. +/** Contains the current baud rate and other settings of the second virtual serial port. While this demo does not use + * the physical USART and thus does not use these settings, they must still be retained and returned to the host + * upon request or the host will assume the device is non-functional. + * + * These values are set by the host via a class-specific request, however they are not required to be used accurately. + * It is possible to completely ignore these value or use other settings as the host is completely unaware of the physical + * serial link characteristics and instead sends and receives data in endpoint streams. */ -USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = - { - .Config = - { - .ControlInterfaceNumber = INTERFACE_ID_CDC_CCI, - .DataINEndpoint = - { - .Address = CDC_TX_EPADDR, - .Size = CDC_TXRX_EPSIZE, - .Banks = 1, - }, - .DataOUTEndpoint = - { - .Address = CDC_RX_EPADDR, - .Size = CDC_TXRX_EPSIZE, - .Banks = 1, - }, - .NotificationEndpoint = - { - .Address = CDC_NOTIFICATION_EPADDR, - .Size = CDC_NOTIFICATION_EPSIZE, - .Banks = 1, - }, - }, - }; +static CDC_LineEncoding_t LineEncoding2 = { .BaudRateBPS = 0, + .CharFormat = CDC_LINEENCODING_OneStopBit, + .ParityType = CDC_PARITY_None, + .DataBits = 8 }; -/** Standard file stream for the CDC interface when set up, so that the virtual - * CDC COM port can be used like any regular character stream in the C APIs. - */ -static FILE USBSerialStream; -//********************************************************************************// - -/** Main program entry point. This routine contains the overall program flow, including initial - * setup of all components and the main program loop. +/** Main program entry point. This routine configures the hardware required by the application, then + * enters a loop to run the application tasks in sequence. */ int main(void) { - // USB/LUFA init SetupHardware(); - // init the timer for time measurements - timer_init(); - - // LED matrix init - lm_init(); - - // KEY matrix init - km_init(); - - // read the key configuration table from EEPROM - ch_readConfig(); - - // init the serial communication command controller + // initialize the command interpreter cc_init(); - FIFO_init( agent_fifo); - FIFO_init(seq_mod_fifo); - FIFO_init(seq_val_fifo); + SET_ERR_MASK(ERRMASK_USB_NOTREADY); - // Create a regular character stream for the interface so that it can be used with the stdio.h functions - CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream); - - SET_GLOB_USB_STATUS(STATUSMASK_USB_NOTREADY); GlobalInterruptEnable(); for (;;) { - SendVirtualSerialData(); - - ProcessVirtualSerialData(); - - CDC_Device_USBTask(&VirtualSerial_CDC_Interface); - - HID_Device_USBTask(&Keyboard_HID_Interface); + CDC1_Task(); + CDC2_Task(); USB_USBTask(); - static uint8_t delay = 0; - if (delay > 50) - { - delay = 0; - lm_show(); - } - delay++; - + //uart_putc('1'); } } -//********************************************************************************// - -void timer_init() -{ - // configure TIMER0 to count using a specified frequency the TCNT0 variable to generate - // a overflow interrupt - TCCR0A = 0x02; // WGM1 = 1; WGM0 = 0 => CTC-mode - TCCR0B = 0x03; // prescaler = 64; WGM2 = 0 => 16MHz * 256 / 64 = ~ 1mz per Overflow Interrupt - TIMSK0 = 0x01; // Overflow Interrupt Enable - - sei(); -} - -ISR(TCC0_OVF_vect) -{ - if (time_measure_cnt >= 65534) - { - // reset all the counter values to prevent unpredictable behaviour - time_measure_cnt = 0; - seq_delay_time_measure_cnt_old = 0; - keystroke_delay_time_measure_cnt_old = 0; - } - time_measure_cnt++; -} - -//********************************************************************************// - -/** Configures the board hardware and chip peripherals for the demo's functionality. - */ -void SetupHardware() +/** Configures the board hardware and chip peripherals for the demo's functionality. */ +void SetupHardware(void) { #if (ARCH == ARCH_AVR8) - // Disable watchdog if enabled by bootloader/fuses + /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable(); - // Disable clock division */ + /* Disable clock division */ clock_prescale_set(clock_div_1); #elif (ARCH == ARCH_XMEGA) - // Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU - // core to run from it + /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */ XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU); XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL); - // Start the 32MHz internal RC oscillator and start the DFLL to increase it to - // 48MHz using the USB SOF as a reference + /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */ XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ); XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB); PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; #endif - // Hardware Initialization */ + // set the three MUX control lines to output + DDRB |= (1 << PIN4) | (1 << PIN5) | (1 << PIN6); + // set every pin to low + EN_MUX_LINE0; + + DDRB |= (1 << PIN0) | (1 << PIN1); + + LED0_OFF; + LED1_OFF; + + /* UART Hardware Initialization */ + eeprom_busy_wait(); + baudrate = eeprom_read_dword(&eep_baudrate); + + if (baudrate == 0xffffffff) + { + eeprom_busy_wait(); + baudrate = 115200; + eeprom_write_dword(&eep_baudrate, baudrate); + } + + uart_init( UART_BAUD_SELECT(baudrate, F_CPU) ); + sei(); + + /* USB Hardware Initialization */ USB_Init(); } -//********************************************************************************// - -void ProcessVirtualSerialData() -{ - - // process the read data from Host here, if there is data to read - int16_t ReceivedBytes = CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface); - if (ReceivedBytes > 0) - { - for (uint16_t i = 0; i < ReceivedBytes; i++) - { - int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); - // call the command controller - command processor - cc_processData((uint8_t)ReceivedByte); - } - } - -} - -//********************************************************************************// - -void SendVirtualSerialData() -{ - char* ReportString = NULL; - - // send the next id from the agent FIFO - if (FIFO_available(agent_fifo)) - { - uint8_t id = FIFO_pop(agent_fifo); - ReportString = " "; - sprintf(ReportString, "%c%c%c%c%c%c", MSG_SOM1, MSG_SOM2, - MSG_TYPE_AGENTID, id, - MSG_EOM1, MSG_EOM2); - } - - if ((ReportString != NULL)) - { - // Write the string to the virtual COM port via the created character stream - USB_serialStreamWriteC(ReportString, 6); - } -} - -//********************************************************************************// - -/** HID class driver callback function for the creation of HID reports to the host. - * - * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced - * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID - * \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature - * \param[out] ReportData Pointer to a buffer where the created report should be stored - * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent) - * - * \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent +/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and + * starts the library USB task to begin the enumeration and USB management process. */ -bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, - uint8_t* const ReportID, - const uint8_t ReportType, - void* ReportData, - uint16_t* const ReportSize) -{ - - // Determine which interface must have its report generated */ - if (HIDInterfaceInfo == &Keyboard_HID_Interface) - { - USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData; - - // update the key matrix values - km_updateKeyStates(); - - // prepare the new sequence related to the pressed key - for (uint8_t k = 0; k < LM_LED_CNT; k++) - { - if (km_getKeyState(k) == KEY_STATE_GO_DOWN) - { - FIFO_push(agent_fifo, k); - - for (uint8_t s = 0; s < EEP_KEY_CNT; s++) - { - // ignore a mod/value combination of 0xff 0xff - // just add the sequence to a "sequence execution FIFO" in case that it - // is not an agent call - // prevent multiple calls - - // TODO manage multikey (simultanous pressed) shortcuts here - - if (key_config[k][s][0] == 0xff && key_config[k][s][1] == 0xff) - { - s = EEP_KEY_CNT; // abort the loop, no more data found - } else { - FIFO_push(seq_mod_fifo, key_config[k][s][0]); - FIFO_push(seq_val_fifo, key_config[k][s][1]); - } - } - } - } - - // TODO maybe we shall do ab bit more precise time measurement - if (seq_delay > 0 && time_measure_cnt > seq_delay_time_measure_cnt_old) - { - seq_delay--; - seq_delay_time_measure_cnt_old = time_measure_cnt; - } - - if (keystroke_delay_cnt > 0 && time_measure_cnt > keystroke_delay_time_measure_cnt_old) - { - // TODO test if NN seconds are gone - keystroke_delay_cnt--; - keystroke_delay_time_measure_cnt_old = time_measure_cnt; - } - - // execute the sequence execution FIFO content - if (FIFO_available(seq_mod_fifo) && FIFO_available(seq_val_fifo) && - seq_delay == 0 && keystroke_delay_cnt == 0) - { - uint8_t mod = FIFO_pop(seq_mod_fifo); - uint8_t val = FIFO_pop(seq_val_fifo); - - // reset the keystroke delay - keystroke_delay_cnt = keystroke_delay; - - // process the data - if ((mod & KEY_MOD_DELAY) != 0) - { - // start the delay - seq_delay = val; - } else { - // TODO be aware of the os_type variable - if ((mod & KEY_MOD_FN) != 0) - KeyboardReport->Modifier += HID_KEYBOARD_MODIFIER_RIGHTSHIFT; // TODO fix the modifier - if ((mod & KEY_MOD_SHIFT) != 0) - KeyboardReport->Modifier += HID_KEYBOARD_MODIFIER_LEFTSHIFT; - if ((mod & KEY_MOD_CTRL) != 0) - KeyboardReport->Modifier += HID_KEYBOARD_MODIFIER_LEFTCTRL; - if ((mod & KEY_MOD_ALT) != 0) - KeyboardReport->Modifier += HID_KEYBOARD_MODIFIER_LEFTALT; - if ((mod & KEY_MOD_ALTGR) != 0) - KeyboardReport->Modifier += HID_KEYBOARD_MODIFIER_RIGHTALT; - if ((mod & KEY_MOD_SUPER) != 0) - KeyboardReport->Modifier += HID_KEYBOARD_MODIFIER_LEFTGUI; - - // possible values: http://www.fourwalledcubicle.com/files/LUFA/Doc/120219/html/group___group___u_s_b_class_h_i_d_common.html - KeyboardReport->KeyCode[0] = val; // TODO one key at a time, up to 6 is supported: http://www.fourwalledcubicle.com/files/LUFA/Doc/120219/html/struct_u_s_b___keyboard_report___data__t.html#a1c24d97011685d58ab05e2f65d7b2c1b - } - } - - // Some debug and test code - for (uint8_t i = 0; i < LM_LED_CNT; i++) - { - if (km_getKeyState(i) == KEY_STATE_GO_DOWN) - lm_ledOn(i); - if (km_getKeyState(i) == KEY_STATE_GO_UP) - lm_ledOff(i); - } - - *ReportSize = sizeof(USB_KeyboardReport_Data_t); - - } - return false; -} - -//********************************************************************************// - -/** HID class driver callback function for the processing of HID reports from the host. - * - * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced - * \param[in] ReportID Report ID of the received report from the host - * \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature - * \param[in] ReportData Pointer to a buffer where the received report has been stored - * \param[in] ReportSize Size in bytes of the received HID report - */ -void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, - const uint8_t ReportID, - const uint8_t ReportType, - const void* ReportData, - const uint16_t ReportSize) -{ - if (HIDInterfaceInfo == &Keyboard_HID_Interface) - { - uint8_t* LEDReport = (uint8_t*)ReportData; - - /* - // TODO process the Keyboard LED status information - if (*LEDReport & HID_KEYBOARD_LED_NUMLOCK) - - if (*LEDReport & HID_KEYBOARD_LED_CAPSLOCK) - - if (*LEDReport & HID_KEYBOARD_LED_SCROLLLOCK) - */ - - } -} - -//********************************************************************************// - -/** CDC class driver callback function the processing of changes to the virtual - * control lines sent from the host.. - * - * \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced - */ -void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo) -{ - // You can get changes to the virtual CDC lines in this callback; a common - // use-case is to use the Data Terminal Ready (DTR) flag to enable and - // disable CDC communications in your application when set to avoid the - // application blocking while waiting for a host to become ready and read - // in the pending data from the USB endpoints. - - bool HostReady = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) != 0; -} - -//********************************************************************************// - -/** Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect(void) { - SET_GLOB_USB_STATUS(STATUSMASK_USB_ENUMERATING); + /* Indicate USB enumerating */ + SET_ERR_MASK(ERRMASK_USB_ENUMERATING); } -/** Event handler for the library USB Disconnection event. */ +/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via + * the status LEDs and stops the USB management and CDC management tasks. + */ void EVENT_USB_Device_Disconnect(void) { - SET_GLOB_USB_STATUS(STATUSMASK_USB_NOTREADY); + /* Indicate USB not ready */ + SET_ERR_MASK(ERRMASK_USB_NOTREADY); } -/** Event handler for the library USB Configuration Changed event. */ +/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration + * of the USB device after enumeration - the device endpoints are configured and the CDC management tasks are started. + */ void EVENT_USB_Device_ConfigurationChanged(void) { bool ConfigSuccess = true; - ConfigSuccess &= HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface); - ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); + /* Setup first CDC Interface's Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC1_TX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1); + ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC1_RX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1); + ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC1_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, 1); - USB_Device_EnableSOFEvents(); + /* Setup second CDC Interface's Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC2_TX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1); + ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC2_RX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1); + ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC2_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, 1); - SET_GLOB_USB_STATUS(ConfigSuccess ? STATUSMASK_USB_READY : STATUSMASK_USB_ERROR); + /* Reset line encoding baud rates so that the host knows to send new values */ + LineEncoding1.BaudRateBPS = 0; + LineEncoding2.BaudRateBPS = 0; + + /* Indicate endpoint configuration success or failure */ + SET_ERR_MASK(ConfigSuccess ? ERRMASK_USB_READY : ERRMASK_USB_ERROR); } -/** Event handler for the library USB Control Request reception event. */ +/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to + * the device from the USB host before passing along unhandled control requests to the library for processing + * internally. + */ void EVENT_USB_Device_ControlRequest(void) { - HID_Device_ProcessControlRequest(&Keyboard_HID_Interface); - CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); -} + /* Determine which interface's Line Coding data is being set from the wIndex parameter */ + void* LineEncodingData = (USB_ControlRequest.wIndex == 0) ? &LineEncoding1 : &LineEncoding2; -/** Event handler for the USB device Start Of Frame event. */ -void EVENT_USB_Device_StartOfFrame(void) -{ - HID_Device_MillisecondElapsed(&Keyboard_HID_Interface); -} - -//********************************************************************************// - -void USB_serialStreamWriteC(char* msg, uint16_t len) -{ - for (uint8_t i = 0; i < len; i++) + /* Process CDC specific control requests */ + switch (USB_ControlRequest.bRequest) { - fputc(msg[i], &USBSerialStream); + case CDC_REQ_GetLineEncoding: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + + /* Write the line coding data to the control endpoint */ + Endpoint_Write_Control_Stream_LE(LineEncodingData, sizeof(CDC_LineEncoding_t)); + Endpoint_ClearOUT(); + } + + break; + case CDC_REQ_SetLineEncoding: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + + /* Read the line coding data in from the host into the global struct */ + Endpoint_Read_Control_Stream_LE(LineEncodingData, sizeof(CDC_LineEncoding_t)); + Endpoint_ClearIN(); + } + + break; + case CDC_REQ_SetControlLineState: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + Endpoint_ClearStatusStage(); + } + + break; } } -void USB_serialStreamWrite(char* msg) +/** Function to manage CDC data transmission and reception to and from the host for the first CDC interface, + * which sends answers or response data to the host. + */ +void CDC1_Task(void) { - fputs(msg, &USBSerialStream); + /* Device must be connected and configured for the task to run */ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + //=========================================================================== + /* Select the Serial Rx Endpoint */ + Endpoint_SelectEndpoint(CDC1_RX_EPADDR); + + if (Endpoint_IsOUTReceived()) + { + /* Create a temp buffer big enough to hold the incoming endpoint packet */ + uint8_t Buffer[Endpoint_BytesInEndpoint()]; + + /* Remember how large the incoming packet is */ + uint16_t DataLength = Endpoint_BytesInEndpoint(); + + /* Read in the incoming packet into the buffer */ + Endpoint_Read_Stream_LE(&Buffer, DataLength, NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearOUT(); + + for (uint16_t i = 0; i < DataLength; i++) + { + // process the received data and descide to do an action + LED0_ON; + cc_processData(Buffer[i]); + LED0_OFF; + } + + } + } -//********************************************************************************// +void USB_serialStreamWriteC(char *data, uint16_t len) +{ + //=========================================================================== + /* Determine if data/answeres should be sent to the host + * the previous RX section should be clarify that behaviour. + */ + + /* Flag management - Only allow one string to be sent per action */ + if (data != NULL && len > 0 && LineEncoding1.BaudRateBPS) + { + + LED1_ON; + + /* Select the Serial Tx Endpoint */ + Endpoint_SelectEndpoint(CDC1_TX_EPADDR); + + /* Write the String to the Endpoint */ + Endpoint_Write_Stream_LE(data, len, NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); + + /* Wait until the endpoint is ready for another packet */ + Endpoint_WaitUntilReady(); + + /* Send an empty packet to ensure that the host does not buffer data sent to it */ + Endpoint_ClearIN(); + + LED1_OFF; + } + +} + +/** Function to manage CDC data transmission and reception to and from the host for the second CDC interface, + * which sends all data received from a node (mux) during USART to the host. + */ +void CDC2_Task(void) +{ + /* Device must be connected and configured for the task to run */ + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + //=========================================================================== + /* Select the Serial Rx Endpoint */ + Endpoint_SelectEndpoint(CDC2_RX_EPADDR); + + /* Check to see if any data has been received */ + if (Endpoint_IsOUTReceived()) + { + /* Create a temp buffer big enough to hold the incoming endpoint packet */ + uint8_t Buffer[Endpoint_BytesInEndpoint()]; + + /* Remember how large the incoming packet is */ + uint16_t DataLength = Endpoint_BytesInEndpoint(); + + /* Read in the incoming packet into the buffer */ + Endpoint_Read_Stream_LE(&Buffer, DataLength, NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearOUT(); + + // TODO at this point send the data to the USART + // Send USART &Buffer + for (uint16_t i = 0; i < DataLength; i++) + { + uart_putc(Buffer[i]); + } + } + + //return; + + //=========================================================================== + uint8_t outBuffer[OUTPUT_BUFFER_SIZE]; + // TODO read the USART data and send them to the host + // Fill &Buffer with USART data or send the USART input buffer direct + uint16_t cnt = 0; + int c = uart_getc(); + while (!(c & UART_NO_DATA) && cnt < OUTPUT_BUFFER_SIZE) + { + //LED0_ON; + outBuffer[cnt] = c; + c = uart_getc(); + cnt++; + } + + /* + cnt = 1; + outBuffer[0] = '2'; + */ + + // send the data which was received from the uart connection + if (cnt > 0) + { + /* Select the Serial Tx Endpoint */ + Endpoint_SelectEndpoint(CDC2_TX_EPADDR); + + /* Write the received data to the endpoint */ + Endpoint_Write_Stream_LE(&outBuffer, cnt, NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); + + /* Wait until the endpoint is ready for the next packet */ + Endpoint_WaitUntilReady(); + + /* Send an empty packet to prevent host buffering */ + Endpoint_ClearIN(); + } +}