Fixed Benito and USBtoSerial projects not turning off the USART before reconfiguring...
[pub/USBasp.git] / Projects / XPLAINBridge / XPLAINBridge.c
index 35a3951..2835481 100644 (file)
@@ -76,24 +76,16 @@ RingBuff_t UARTtoUSB_Buffer;
 int main(void)
 {
        SetupHardware();
-       
-       RingBuffer_InitBuffer(&USBtoUART_Buffer);
-       RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
-       
+
        LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
        sei();
 
        for (;;)
        {
                if (CurrentFirmwareMode == MODE_USART_BRIDGE)
-               {
-                       USARTBridge_Task();
-               }
+                 UARTBridge_Task();
                else
-               {
-                       AVRISP_Task();
-                       V2Params_UpdateParamValues();
-               }
+                 AVRISP_Task();
 
                USB_USBTask();
        }
@@ -105,6 +97,8 @@ void AVRISP_Task(void)
        if (USB_DeviceState != DEVICE_STATE_Configured)
          return;
 
+       V2Params_UpdateParamValues();
+
        Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM);
        
        /* Check to see if a V2 Protocol command has been received */
@@ -119,19 +113,25 @@ void AVRISP_Task(void)
        }
 }
 
-void USARTBridge_Task(void)
+void UARTBridge_Task(void)
 {
        /* Must be in the configured state for the USART Bridge code to process data */
        if (USB_DeviceState != DEVICE_STATE_Configured)
          return;
 
        /* Read bytes from the USB OUT endpoint into the UART transmit buffer */
-       if (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))
-         RingBuffer_Insert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
+       if (CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface) && !(RingBuffer_IsFull(&USBtoUART_Buffer)))
+         RingBuffer_AtomicInsert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
        
-       /* Read bytes from the UART receive buffer into the USB IN endpoint */
-       if (UARTtoUSB_Buffer.Count)
-         CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&UARTtoUSB_Buffer));
+       /* Check if the software UART flush timer has expired */
+       if (TIFR0 & (1 << TOV0))
+       {
+               TIFR0 |= (1 << TOV0);
+
+               /* Read bytes from the UART receive buffer into the USB IN endpoint */
+               while (UARTtoUSB_Buffer.Count)
+                 CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&UARTtoUSB_Buffer));
+       }
 
        CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
 }
@@ -150,13 +150,12 @@ void SetupHardware(void)
        SoftUART_Init();
        LEDs_Init();
        USB_Init();
-       V2Protocol_Init();
 
        /* Disable JTAG debugging */
        MCUCR |= (1 << JTD);
        MCUCR |= (1 << JTD);
 
-       /* Enable pullup on the JTAG TDI pin so we can use it to select the mode */
+       /* Enable pull-up on the JTAG TDI pin so we can use it to select the mode */
        PORTF |= (1 << 7);
        _delay_ms(10);
 
@@ -177,6 +176,13 @@ void EVENT_USB_Device_ConfigurationChanged(void)
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
        {
                EndpointConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
+
+               /* Configure the UART flush timer - run at Fcpu/1024 for maximum interval before overflow */
+               TCCR0B = ((1 << CS02) | (1 << CS00));
+
+               /* Initialize ring buffers used to hold serial data between USB and software UART interfaces */
+               RingBuffer_InitBuffer(&USBtoUART_Buffer);
+               RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
        }
        else
        {
@@ -189,6 +195,9 @@ void EVENT_USB_Device_ConfigurationChanged(void)
                                                                    ENDPOINT_DIR_IN, AVRISP_DATA_EPSIZE,
                                                                    ENDPOINT_BANK_SINGLE);
                #endif
+       
+               /* Configure the V2 protocol packet handler */
+               V2Protocol_Init();
        }
 
        if (EndpointConfigSuccess)
@@ -216,13 +225,31 @@ void EVENT_USB_Device_Disconnect(void)
        LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
 }
 
+/** Event handler for the CDC Class driver Line Encoding Changed event.
+ *
+ *  \param[in] CDCInterfaceInfo  Pointer to the CDC class interface configuration structure being referenced
+ */
+void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+       /* Change the software UART's baud rate to match the new baud rate */
+       SoftUART_SetBaud(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
+}
+
 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
  *  documentation) by the application code so that the address and size of a requested descriptor can be given
  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
  *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
  *  USB host.
+ *
+ *  \param[in]  wValue  Descriptor type and index to retrieve
+ *  \param[in]  wIndex  Sub-index to retrieve (such as a localized string language)
+ *  \param[out] DescriptorAddress  Address of the retrieved descriptor
+ *
+ *  \return Length of the retrieved descriptor in bytes, or NO_DESCRIPTOR if the descriptor was not found
  */
-uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+                                    const uint8_t wIndex,
+                                    void** const DescriptorAddress)
 {
        /* Return the correct descriptors based on the selected mode */
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)