Fix flip-ee DFU build target accidentally erasing the target FLASH memory space.
[pub/USBasp.git] / Projects / USBtoSerial / USBtoSerial.c
index e775541..fb9ac87 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
+     Copyright (C) Dean Camera, 2012.
 
   dean [at] fourwalledcubicle [dot] 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
   software and its documentation for any purpose is hereby granted
 #include "USBtoSerial.h"
 
 /** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
-RingBuff_t USBtoUSART_Buffer;
+static RingBuffer_t USBtoUSART_Buffer;
 
 /** Underlying data buffer for \ref USBtoUSART_Buffer, where the stored bytes are located. */
-uint8_t    USBtoUSART_Buffer_Data[128];
+static uint8_t      USBtoUSART_Buffer_Data[128];
 
 /** Circular buffer to hold data from the serial port before it is sent to the host. */
-RingBuff_t USARTtoUSB_Buffer;
+static RingBuffer_t USARTtoUSB_Buffer;
 
 /** Underlying data buffer for \ref USARTtoUSB_Buffer, where the stored bytes are located. */
-uint8_t    USARTtoUSB_Buffer_Data[128];
-
+static uint8_t      USARTtoUSB_Buffer_Data[128];
 
 /** 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
@@ -58,21 +57,28 @@ USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
                .Config =
                        {
                                .ControlInterfaceNumber         = 0,
-
-                               .DataINEndpointNumber           = CDC_TX_EPNUM,
-                               .DataINEndpointSize             = CDC_TXRX_EPSIZE,
-                               .DataINEndpointDoubleBank       = false,
-
-                               .DataOUTEndpointNumber          = CDC_RX_EPNUM,
-                               .DataOUTEndpointSize            = CDC_TXRX_EPSIZE,
-                               .DataOUTEndpointDoubleBank      = false,
-
-                               .NotificationEndpointNumber     = CDC_NOTIFICATION_EPNUM,
-                               .NotificationEndpointSize       = CDC_NOTIFICATION_EPSIZE,
-                               .NotificationEndpointDoubleBank = false,
+                               .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,
+                                       },
                        },
        };
 
+
 /** Main program entry point. This routine contains the overall program flow, including initial
  *  setup of all components and the main program loop.
  */
@@ -84,7 +90,7 @@ int main(void)
        RingBuffer_InitBuffer(&USARTtoUSB_Buffer, USARTtoUSB_Buffer_Data, sizeof(USARTtoUSB_Buffer_Data));
 
        LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
-       sei();
+       GlobalInterruptEnable();
 
        for (;;)
        {
@@ -97,32 +103,43 @@ int main(void)
                        if (!(ReceivedByte < 0))
                          RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte);
                }
-               
+
                /* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */
                uint16_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
-               if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
+               if ((TIFR0 & (1 << TOV0)) || (BufferCount > (uint8_t)(sizeof(USARTtoUSB_Buffer_Data) * .75)))
                {
-                       /* Clear flush timer expiry flag */
-                       TIFR0 |= (1 << TOV0);
-
-                       /* Read bytes from the USART receive buffer into the USB IN endpoint */
-                       while (BufferCount--)
+                       Endpoint_SelectEndpoint(VirtualSerial_CDC_Interface.Config.DataINEndpoint.Address);
+                       
+                       /* Check if a packet is already enqueued to the host - if so, we shouldn't try to send more data
+                        * until it completes as there is a chance nothing is listening and a lengthy timeout could occur */
+                       if (Endpoint_IsINReady())
                        {
-                               /* 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(&USARTtoUSB_Buffer)) != ENDPOINT_READYWAIT_NoError)
+                               /* Clear flush timer expiry flag */
+                               TIFR0 |= (1 << TOV0);
+                       
+                               /* Never send more than one bank size less one byte to the host at a time, so that we don't block
+                                * while a Zero Length Packet (ZLP) to terminate the transfer is sent if the host isn't listening */
+                               uint8_t BytesToSend = MIN(BufferCount, (CDC_TXRX_EPSIZE - 1));
+
+                               /* Read bytes from the USART receive buffer into the USB IN endpoint */
+                               while (BytesToSend--)
                                {
-                                       break;
+                                       /* 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(&USARTtoUSB_Buffer)) != ENDPOINT_READYWAIT_NoError)
+                                       {
+                                               break;
+                                       }
+
+                                       /* Dequeue the already sent byte from the buffer now we have confirmed that no transmission error occurred */
+                                       RingBuffer_Remove(&USARTtoUSB_Buffer);
                                }
-
-                               /* Dequeue the already sent byte from the buffer now we have confirmed that no transmission error occurred */
-                               RingBuffer_Remove(&USARTtoUSB_Buffer);
                        }
                }
 
                /* Load the next byte from the USART transmit buffer into the USART */
                if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer)))
-                 Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer));
+                 Serial_SendByte(RingBuffer_Remove(&USBtoUSART_Buffer));
 
                CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
                USB_USBTask();