Add extra LUFA TAR archive export exclusions.
[pub/USBasp.git] / Projects / XPLAINBridge / XPLAINBridge.c
index 0764bb9..bee770a 100644 (file)
@@ -1,21 +1,21 @@
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
-              
+     Copyright (C) Dean Camera, 2012.
+
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
-  Permission to use, copy, modify, distribute, and sell this 
+  Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
-  without fee, provided that the above copyright notice appear in 
+  without fee, provided that the above copyright notice appear in
   all copies and that both that the copyright notice and this
-  permission notice and warranty disclaimer appear in supporting 
-  documentation, and that the name of the author not be used in 
-  advertising or publicity pertaining to distribution of the 
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
   software without specific, written prior permission.
 
   The author disclaim all warranties with regard to this
@@ -31,7 +31,7 @@
 /** \file
  *
  *  Main source file for the XPLAINBridge project. This file contains the main tasks of
- *  the demo and is responsible for the initial application hardware configuration.
+ *  the project and is responsible for the initial application hardware configuration.
  */
 
 #include "XPLAINBridge.h"
@@ -45,7 +45,7 @@ bool CurrentFirmwareMode = MODE_USART_BRIDGE;
  */
 USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
        {
-               .Config = 
+               .Config =
                        {
                                .ControlInterfaceNumber         = 0,
 
@@ -64,10 +64,16 @@ USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
        };
 
 /** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
-RingBuff_t USBtoUART_Buffer;
+RingBuffer_t   USBtoUART_Buffer;
+
+/** Underlying data buffer for \ref USBtoUART_Buffer, where the stored bytes are located. */
+static uint8_t USBtoUART_Buffer_Data[128];
 
 /** Circular buffer to hold data from the serial port before it is sent to the host. */
-RingBuff_t UARTtoUSB_Buffer;
+RingBuffer_t   UARTtoUSB_Buffer;
+
+/** Underlying data buffer for \ref UARTtoUSB_Buffer, where the stored bytes are located. */
+static uint8_t UARTtoUSB_Buffer_Data[128];
 
 
 /** Main program entry point. This routine contains the overall program flow, including initial
@@ -100,7 +106,7 @@ void AVRISP_Task(void)
        V2Params_UpdateParamValues();
 
        Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM);
-       
+
        /* Check to see if a V2 Protocol command has been received */
        if (Endpoint_IsOUTReceived())
        {
@@ -119,20 +125,36 @@ void UARTBridge_Task(void)
        if (USB_DeviceState != DEVICE_STATE_Configured)
          return;
 
-       /* Read bytes from the USB OUT endpoint into the UART transmit buffer */
-       int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
-       if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUART_Buffer)))
-         RingBuffer_Insert(&USBtoUART_Buffer, ReceivedByte);
-       
+       /* Only try to read in bytes from the CDC interface if the transmit buffer is not full */
+       if (!(RingBuffer_IsFull(&USBtoUART_Buffer)))
+       {
+               int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
+
+               /* Read bytes from the USB OUT endpoint into the UART transmit buffer */
+               if (!(ReceivedByte < 0))
+                 RingBuffer_Insert(&USBtoUART_Buffer, ReceivedByte);
+       }
+
        /* Check if the UART receive buffer flush timer has expired or buffer is nearly full */
-       RingBuff_Count_t BufferCount = RingBuffer_GetCount(&UARTtoUSB_Buffer);
+       uint16_t BufferCount = RingBuffer_GetCount(&UARTtoUSB_Buffer);
        if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
        {
+               /* Clear flush timer expiry flag */
                TIFR0 |= (1 << TOV0);
 
-               /* Read bytes from the UART receive buffer into the USB IN endpoint */
+               /* Read bytes from the USART receive buffer into the USB IN endpoint */
                while (BufferCount--)
-                 CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&UARTtoUSB_Buffer));
+               {
+                       /* Try to send the next byte of data to the host, abort if there is an error without dequeuing */
+                       if (CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
+                                                                       RingBuffer_Peek(&UARTtoUSB_Buffer)) != ENDPOINT_READYWAIT_NoError)
+                       {
+                               break;
+                       }
+
+                       /* Dequeue the already sent byte from the buffer now we have confirmed that no transmission error occurred */
+                       RingBuffer_Remove(&UARTtoUSB_Buffer);
+               }
        }
 
        CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
@@ -159,7 +181,7 @@ void SetupHardware(void)
 
        /* Enable pull-up on the JTAG TDI pin so we can use it to select the mode */
        PORTF |= (1 << 7);
-       _delay_ms(10);
+       Delay_MS(10);
 
        /* Select the firmware mode based on the JTD pin's value */
        CurrentFirmwareMode = (PINF & (1 << 7)) ? MODE_USART_BRIDGE : MODE_PDI_PROGRAMMER;
@@ -183,9 +205,9 @@ void EVENT_USB_Device_ConfigurationChanged(void)
                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);
-               
+               RingBuffer_InitBuffer(&USBtoUART_Buffer, USBtoUART_Buffer_Data, sizeof(USBtoUART_Buffer_Data));
+               RingBuffer_InitBuffer(&UARTtoUSB_Buffer, UARTtoUSB_Buffer_Data, sizeof(UARTtoUSB_Buffer_Data));
+
                /* Start the software USART */
                SoftUART_Init();
        }
@@ -198,7 +220,7 @@ void EVENT_USB_Device_ConfigurationChanged(void)
                ConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_IN_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_IN,
                                                            AVRISP_DATA_EPSIZE, ENDPOINT_BANK_SINGLE);
                #endif
-       
+
                /* Configure the V2 protocol packet handler */
                V2Protocol_Init();
        }
@@ -206,8 +228,8 @@ void EVENT_USB_Device_ConfigurationChanged(void)
        LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
 }
 
-/** Event handler for the library USB Unhandled Control Request event. */
-void EVENT_USB_Device_UnhandledControlRequest(void)
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
 {
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
          CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
@@ -257,3 +279,4 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
        else
          return AVRISP_GetDescriptor(wValue, wIndex, DescriptorAddress);
 }
+