/*
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
/** \file
*
* Main source file for the USBtoSerial 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 "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. */
+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. */
+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
*/
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
{
- .Config =
+ .Config =
{
.ControlInterfaceNumber = 0,
},
};
+
/** Main program entry point. This routine contains the overall program flow, including initial
* setup of all components and the main program loop.
*/
int main(void)
{
SetupHardware();
-
- RingBuffer_InitBuffer(&USBtoUSART_Buffer);
- RingBuffer_InitBuffer(&USARTtoUSB_Buffer);
+
+ RingBuffer_InitBuffer(&USBtoUSART_Buffer, USBtoUSART_Buffer_Data, sizeof(USBtoUSART_Buffer_Data));
+ RingBuffer_InitBuffer(&USARTtoUSB_Buffer, USARTtoUSB_Buffer_Data, sizeof(USARTtoUSB_Buffer_Data));
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
sei();
for (;;)
{
- /* Read bytes from the USB OUT endpoint into the USART transmit buffer */
- int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
- if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUSART_Buffer)))
- RingBuffer_AtomicInsert(&USBtoUSART_Buffer, (uint8_t)ReceivedByte);
-
- /* Check if the software USART flush timer has expired */
- if (TIFR0 & (1 << TOV0))
+ /* Only try to read in bytes from the CDC interface if the transmit buffer is not full */
+ if (!(RingBuffer_IsFull(&USBtoUSART_Buffer)))
{
+ int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
+
+ /* Read bytes from the USB OUT endpoint into the USART transmit buffer */
+ 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 > (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 (USARTtoUSB_Buffer.Count)
- CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&USARTtoUSB_Buffer));
+ while (BufferCount--)
+ {
+ /* 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);
+ }
}
-
+
/* Load the next byte from the USART transmit buffer into the USART */
- if (USBtoUSART_Buffer.Count)
- Serial_TxByte(RingBuffer_AtomicRemove(&USBtoUSART_Buffer));
-
+ if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer)))
+ Serial_SendByte(RingBuffer_Remove(&USBtoUSART_Buffer));
+
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
}
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
- LEDs_SetAllLEDs(LEDMASK_USB_READY);
+ bool ConfigSuccess = true;
- if (!(CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface)))
- LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+ ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
+
+ 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)
{
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
}
switch (CDCInterfaceInfo->State.LineEncoding.ParityType)
{
case CDC_PARITY_Odd:
- ConfigMask = ((1 << UPM11) | (1 << UPM10));
+ ConfigMask = ((1 << UPM11) | (1 << UPM10));
break;
case CDC_PARITY_Even:
- ConfigMask = (1 << UPM11);
+ ConfigMask = (1 << UPM11);
break;
}
/* Set the new baud rate before configuring the USART */
UBRR1 = SERIAL_2X_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
-
+
/* Reconfigure the USART in double speed mode for a wider baud rate range at the expense of accuracy */
UCSR1C = ConfigMask;
- UCSR1A = (1 << U2X1);
+ UCSR1A = (1 << U2X1);
UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1));
}
+