root / arduino-1.0 / hardware / arduino / firmwares / arduino-usbserial / Arduino-usbserial.c @ 58d82c77
History | View | Annotate | Download (8.25 KB)
1 |
/*
|
---|---|
2 |
LUFA Library
|
3 |
Copyright (C) Dean Camera, 2010.
|
4 |
|
5 |
dean [at] fourwalledcubicle [dot] com
|
6 |
www.fourwalledcubicle.com
|
7 |
*/
|
8 |
|
9 |
/*
|
10 |
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
11 |
|
12 |
Permission to use, copy, modify, distribute, and sell this
|
13 |
software and its documentation for any purpose is hereby granted
|
14 |
without fee, provided that the above copyright notice appear in
|
15 |
all copies and that both that the copyright notice and this
|
16 |
permission notice and warranty disclaimer appear in supporting
|
17 |
documentation, and that the name of the author not be used in
|
18 |
advertising or publicity pertaining to distribution of the
|
19 |
software without specific, written prior permission.
|
20 |
|
21 |
The author disclaim all warranties with regard to this
|
22 |
software, including all implied warranties of merchantability
|
23 |
and fitness. In no event shall the author be liable for any
|
24 |
special, indirect or consequential damages or any damages
|
25 |
whatsoever resulting from loss of use, data or profits, whether
|
26 |
in an action of contract, negligence or other tortious action,
|
27 |
arising out of or in connection with the use or performance of
|
28 |
this software.
|
29 |
*/
|
30 |
|
31 |
/** \file
|
32 |
*
|
33 |
* Main source file for the Arduino-usbserial project. This file contains the main tasks of
|
34 |
* the project and is responsible for the initial application hardware configuration.
|
35 |
*/
|
36 |
|
37 |
#include "Arduino-usbserial.h" |
38 |
|
39 |
/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */
|
40 |
RingBuff_t USBtoUSART_Buffer; |
41 |
|
42 |
/** Circular buffer to hold data from the serial port before it is sent to the host. */
|
43 |
RingBuff_t USARTtoUSB_Buffer; |
44 |
|
45 |
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
|
46 |
volatile struct |
47 |
{ |
48 |
uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
|
49 |
uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
|
50 |
uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */
|
51 |
} PulseMSRemaining; |
52 |
|
53 |
/** LUFA CDC Class driver interface configuration and state information. This structure is
|
54 |
* passed to all CDC Class driver functions, so that multiple instances of the same class
|
55 |
* within a device can be differentiated from one another.
|
56 |
*/
|
57 |
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = |
58 |
{ |
59 |
.Config = |
60 |
{ |
61 |
.ControlInterfaceNumber = 0,
|
62 |
|
63 |
.DataINEndpointNumber = CDC_TX_EPNUM, |
64 |
.DataINEndpointSize = CDC_TXRX_EPSIZE, |
65 |
.DataINEndpointDoubleBank = false,
|
66 |
|
67 |
.DataOUTEndpointNumber = CDC_RX_EPNUM, |
68 |
.DataOUTEndpointSize = CDC_TXRX_EPSIZE, |
69 |
.DataOUTEndpointDoubleBank = false,
|
70 |
|
71 |
.NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM, |
72 |
.NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE, |
73 |
.NotificationEndpointDoubleBank = false,
|
74 |
}, |
75 |
}; |
76 |
|
77 |
/** Main program entry point. This routine contains the overall program flow, including initial
|
78 |
* setup of all components and the main program loop.
|
79 |
*/
|
80 |
int main(void) |
81 |
{ |
82 |
SetupHardware(); |
83 |
|
84 |
RingBuffer_InitBuffer(&USBtoUSART_Buffer); |
85 |
RingBuffer_InitBuffer(&USARTtoUSB_Buffer); |
86 |
|
87 |
sei(); |
88 |
|
89 |
for (;;)
|
90 |
{ |
91 |
/* Only try to read in bytes from the CDC interface if the transmit buffer is not full */
|
92 |
if (!(RingBuffer_IsFull(&USBtoUSART_Buffer)))
|
93 |
{ |
94 |
int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); |
95 |
|
96 |
/* Read bytes from the USB OUT endpoint into the USART transmit buffer */
|
97 |
if (!(ReceivedByte < 0)) |
98 |
RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte); |
99 |
} |
100 |
|
101 |
/* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */
|
102 |
RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer); |
103 |
if ((TIFR0 & (1 << TOV0)) || (BufferCount > BUFFER_NEARLY_FULL)) |
104 |
{ |
105 |
TIFR0 |= (1 << TOV0);
|
106 |
|
107 |
if (USARTtoUSB_Buffer.Count) {
|
108 |
LEDs_TurnOnLEDs(LEDMASK_TX); |
109 |
PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS; |
110 |
} |
111 |
|
112 |
/* Read bytes from the USART receive buffer into the USB IN endpoint */
|
113 |
while (BufferCount--)
|
114 |
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&USARTtoUSB_Buffer)); |
115 |
|
116 |
/* Turn off TX LED(s) once the TX pulse period has elapsed */
|
117 |
if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse))
|
118 |
LEDs_TurnOffLEDs(LEDMASK_TX); |
119 |
|
120 |
/* Turn off RX LED(s) once the RX pulse period has elapsed */
|
121 |
if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse))
|
122 |
LEDs_TurnOffLEDs(LEDMASK_RX); |
123 |
} |
124 |
|
125 |
/* Load the next byte from the USART transmit buffer into the USART */
|
126 |
if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) {
|
127 |
Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer)); |
128 |
|
129 |
LEDs_TurnOnLEDs(LEDMASK_RX); |
130 |
PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS; |
131 |
} |
132 |
|
133 |
CDC_Device_USBTask(&VirtualSerial_CDC_Interface); |
134 |
USB_USBTask(); |
135 |
} |
136 |
} |
137 |
|
138 |
/** Configures the board hardware and chip peripherals for the demo's functionality. */
|
139 |
void SetupHardware(void) |
140 |
{ |
141 |
/* Disable watchdog if enabled by bootloader/fuses */
|
142 |
MCUSR &= ~(1 << WDRF);
|
143 |
wdt_disable(); |
144 |
|
145 |
/* Hardware Initialization */
|
146 |
Serial_Init(9600, false); |
147 |
LEDs_Init(); |
148 |
USB_Init(); |
149 |
|
150 |
/* Start the flush timer so that overflows occur rapidly to push received bytes to the USB interface */
|
151 |
TCCR0B = (1 << CS02);
|
152 |
|
153 |
/* Pull target /RESET line high */
|
154 |
AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; |
155 |
AVR_RESET_LINE_DDR |= AVR_RESET_LINE_MASK; |
156 |
} |
157 |
|
158 |
/** Event handler for the library USB Configuration Changed event. */
|
159 |
void EVENT_USB_Device_ConfigurationChanged(void) |
160 |
{ |
161 |
CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); |
162 |
} |
163 |
|
164 |
/** Event handler for the library USB Unhandled Control Request event. */
|
165 |
void EVENT_USB_Device_UnhandledControlRequest(void) |
166 |
{ |
167 |
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); |
168 |
} |
169 |
|
170 |
/** Event handler for the CDC Class driver Line Encoding Changed event.
|
171 |
*
|
172 |
* \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced
|
173 |
*/
|
174 |
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) |
175 |
{ |
176 |
uint8_t ConfigMask = 0;
|
177 |
|
178 |
switch (CDCInterfaceInfo->State.LineEncoding.ParityType)
|
179 |
{ |
180 |
case CDC_PARITY_Odd:
|
181 |
ConfigMask = ((1 << UPM11) | (1 << UPM10)); |
182 |
break;
|
183 |
case CDC_PARITY_Even:
|
184 |
ConfigMask = (1 << UPM11);
|
185 |
break;
|
186 |
} |
187 |
|
188 |
if (CDCInterfaceInfo->State.LineEncoding.CharFormat == CDC_LINEENCODING_TwoStopBits)
|
189 |
ConfigMask |= (1 << USBS1);
|
190 |
|
191 |
switch (CDCInterfaceInfo->State.LineEncoding.DataBits)
|
192 |
{ |
193 |
case 6: |
194 |
ConfigMask |= (1 << UCSZ10);
|
195 |
break;
|
196 |
case 7: |
197 |
ConfigMask |= (1 << UCSZ11);
|
198 |
break;
|
199 |
case 8: |
200 |
ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10)); |
201 |
break;
|
202 |
} |
203 |
|
204 |
/* Must turn off USART before reconfiguring it, otherwise incorrect operation may occur */
|
205 |
UCSR1B = 0;
|
206 |
UCSR1A = 0;
|
207 |
UCSR1C = 0;
|
208 |
|
209 |
/* Special case 57600 baud for compatibility with the ATmega328 bootloader. */
|
210 |
UBRR1 = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600)
|
211 |
? SERIAL_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS) |
212 |
: SERIAL_2X_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS); |
213 |
|
214 |
UCSR1C = ConfigMask; |
215 |
UCSR1A = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) ? 0 : (1 << U2X1); |
216 |
UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1)); |
217 |
} |
218 |
|
219 |
/** ISR to manage the reception of data from the serial port, placing received bytes into a circular buffer
|
220 |
* for later transmission to the host.
|
221 |
*/
|
222 |
ISR(USART1_RX_vect, ISR_BLOCK) |
223 |
{ |
224 |
uint8_t ReceivedByte = UDR1; |
225 |
|
226 |
if (USB_DeviceState == DEVICE_STATE_Configured)
|
227 |
RingBuffer_Insert(&USARTtoUSB_Buffer, ReceivedByte); |
228 |
} |
229 |
|
230 |
/** Event handler for the CDC Class driver Host-to-Device Line Encoding Changed event.
|
231 |
*
|
232 |
* \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced
|
233 |
*/
|
234 |
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) |
235 |
{ |
236 |
bool CurrentDTRState = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR);
|
237 |
|
238 |
if (CurrentDTRState)
|
239 |
AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK; |
240 |
else
|
241 |
AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; |
242 |
} |