root / arduino-1.0 / hardware / arduino / firmwares / arduino-usbserial / Arduino-usbserial.c @ 58d82c77
History | View | Annotate | Download (8.25 KB)
1 | 58d82c77 | Tom Mullins | /*
|
---|---|---|---|
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 | } |