11/*
2- Copyright (c) 2014 Arduino. All right reserved.
2+ Copyright (c) 2015 Arduino LLC . All right reserved.
33
44 This library is free software; you can redistribute it and/or
55 modify it under the terms of the GNU Lesser General Public
1616 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1717*/
1818
19+ #include < Arduino.h>
20+ #include < Reset.h> // Needed for auto-reset with 1200bps port touch
21+
1922#include < stdlib.h>
2023#include < stdio.h>
2124#include < stdint.h>
2225
23- // Include Atmel headers
24- #include " Arduino.h"
25- #include " sam.h"
26- #include " wiring_constants.h"
27- #include " USBCore.h"
28- #include " USB/USB_device.h"
29- #include " USBDesc.h"
30- #include " USBAPI.h"
31-
32- #include " Reset.h"
33-
34-
3526#ifdef CDC_ENABLED
3627
37- #define CDC_SERIAL_BUFFER_SIZE 64
28+ #define CDC_SERIAL_BUFFER_SIZE 256
3829
3930/* For information purpose only since RTS is not always handled by the terminal application */
4031#define CDC_LINESTATE_DTR 0x01 // Data Terminal Ready
4132#define CDC_LINESTATE_RTS 0x02 // Ready to Send
4233
4334#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
4435
45- struct ring_buffer
46- {
36+ struct ring_buffer {
4737 uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
4838 volatile uint32_t head;
4939 volatile uint32_t tail;
40+ volatile bool full;
5041};
51-
52- ring_buffer cdc_rx_buffer = { { 0 }, 0 , 0 };
53-
54- typedef struct
55- {
56- uint32_t dwDTERate;
57- uint8_t bCharFormat;
58- uint8_t bParityType;
59- uint8_t bDataBits;
60- uint8_t lineState;
42+ ring_buffer cdc_rx_buffer = {{0 }, 0 , 0 , false };
43+
44+ typedef struct {
45+ uint32_t dwDTERate;
46+ uint8_t bCharFormat;
47+ uint8_t bParityType;
48+ uint8_t bDataBits;
49+ uint8_t lineState;
6150} LineInfo;
6251
6352_Pragma (" pack(1)" )
6453static volatile LineInfo _usbLineInfo = {
65- 115200 , // dWDTERate
66- 0x00 , // bCharFormat
67- 0x00 , // bParityType
68- 0x08 , // bDataBits
69- 0x00 // lineState
54+ 115200 , // dWDTERate
55+ 0x00 , // bCharFormat
56+ 0x00 , // bParityType
57+ 0x08 , // bDataBits
58+ 0x00 // lineState
7059};
7160
72- static const CDCDescriptor _cdcInterface =
73- {
74- #if (defined CDC_ENABLED) && defined(HID_ENABLED)
61+ static CDCDescriptor _cdcInterface = {
7562 D_IAD (0 , 2 , CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0 ),
76- # endif
77- // CDC communication interface
78- D_INTERFACE (CDC_ACM_INTERFACE,1 , CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0 ),
79- D_CDCCS ( CDC_HEADER, CDC_V1_10 & 0xFF , (CDC_V1_10>>8 ) & 0x0FF ), // Header (1.10 bcd)
80-
81- D_CDCCS4 (CDC_ABSTRACT_CONTROL_MANAGEMENT,6 ), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
82- D_CDCCS (CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
83- D_CDCCS (CDC_CALL_MANAGEMENT,1 , 1 ), // Device handles call management (not)
84- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10 , 0x10 ),
85-
86- // CDC data interface
87- D_INTERFACE (CDC_DATA_INTERFACE,2 , CDC_DATA_INTERFACE_CLASS,0 , 0 ),
88- D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,EPX_SIZE,0 ),
89- D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,EPX_SIZE,0 )
63+
64+ // CDC communication interface
65+ D_INTERFACE (CDC_ACM_INTERFACE, 1 , CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0 ),
66+ D_CDCCS (CDC_HEADER, CDC_V1_10 & 0xFF , (CDC_V1_10>>8 ) & 0x0FF ), // Header (1.10 bcd)
67+
68+ D_CDCCS4 (CDC_ABSTRACT_CONTROL_MANAGEMENT, 6 ), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
69+ D_CDCCS (CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
70+ D_CDCCS (CDC_CALL_MANAGEMENT, 1 , 1 ), // Device handles call management (not)
71+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10 , 0x10 ),
72+
73+ // CDC data interface
74+ D_INTERFACE (CDC_DATA_INTERFACE, 2 , CDC_DATA_INTERFACE_CLASS, 0 , 0 ),
75+ D_ENDPOINT (USB_ENDPOINT_OUT (CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0 ),
76+ D_ENDPOINT (USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0 )
9077};
9178_Pragma (" pack()" )
9279
93- const void * WEAK CDC_GetInterface (void )
80+ const void * _CDC_GetInterface (void )
9481{
95- return &_cdcInterface;
82+ return &_cdcInterface;
9683}
9784
98- uint32_t WEAK CDC_GetInterfaceLength (void )
85+ uint32_t _CDC_GetInterfaceLength (void )
9986{
100- return sizeof ( _cdcInterface );
87+ return sizeof (_cdcInterface);
10188}
10289
103- bool WEAK CDC_Setup (Setup& setup)
90+ int CDC_GetInterface (uint8_t * interfaceNum)
91+ {
92+ interfaceNum[0 ] += 2 ; // uses 2
93+ return USBDevice.sendControl (&_cdcInterface,sizeof (_cdcInterface));
94+ }
95+
96+ bool CDC_Setup (USBSetup& setup)
10497{
105- uint8_t r = setup.bRequest ;
10698 uint8_t requestType = setup.bmRequestType ;
99+ uint8_t r = setup.bRequest ;
107100
108- if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType )
101+ if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE )
109102 {
110- if (CDC_GET_LINE_CODING == r )
103+ if (r == CDC_GET_LINE_CODING )
111104 {
112- USBD_SendControl ( 0 , (void *)&_usbLineInfo,7 );
105+ USBDevice. sendControl ( (void *)&_usbLineInfo, 7 );
113106 return true ;
114107 }
115108 }
116109
117- if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType )
110+ if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE )
118111 {
119- if (CDC_SET_LINE_CODING == r )
112+ if (r == CDC_SET_LINE_CODING )
120113 {
121- USBD_RecvControl ((void *)&_usbLineInfo,7 );
114+ USBDevice. recvControl ((void *)&_usbLineInfo, 7 );
122115 }
123116
124- if (CDC_SET_CONTROL_LINE_STATE == r )
117+ if (r == CDC_SET_CONTROL_LINE_STATE )
125118 {
126119 _usbLineInfo.lineState = setup.wValueL ;
127120 }
128121
129- if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r )
122+ if (r == CDC_SET_LINE_CODING || r == CDC_SET_CONTROL_LINE_STATE )
130123 {
131124 // auto-reset into the bootloader is triggered when the port, already
132125 // open at 1200 bps, is closed. We check DTR state to determine if host
133126 // port is open (bit 0 of lineState).
134- if (1200 == _usbLineInfo. dwDTERate && (_usbLineInfo.lineState & 0x01 ) == 0 )
127+ if (_usbLineInfo. dwDTERate == 1200 && (_usbLineInfo.lineState & 0x01 ) == 0 )
135128 {
136129 initiateReset (250 );
137130 }
@@ -146,12 +139,14 @@ bool WEAK CDC_Setup(Setup& setup)
146139}
147140
148141uint32_t _serialPeek = -1 ;
149- void Serial_::begin (uint32_t baud_count)
142+ void Serial_::begin (uint32_t /* baud_count */ )
150143{
144+ // uart config is ignored in USB-CDC
151145}
152146
153- void Serial_::begin (uint32_t baud_count, uint8_t config)
147+ void Serial_::begin (uint32_t /* baud_count */ , uint8_t /* config */ )
154148{
149+ // uart config is ignored in USB-CDC
155150}
156151
157152void Serial_::end (void )
@@ -161,7 +156,7 @@ void Serial_::end(void)
161156void Serial_::accept (void )
162157{
163158 uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
164- uint32_t len = USBD_Recv (CDC_ENDPOINT_OUT, ( void *) &buffer, CDC_SERIAL_BUFFER_SIZE);
159+ uint32_t len = usb. recv (CDC_ENDPOINT_OUT, &buffer, CDC_SERIAL_BUFFER_SIZE);
165160
166161 noInterrupts ();
167162 ring_buffer *ringBuffer = &cdc_rx_buffer;
@@ -172,58 +167,72 @@ void Serial_::accept(void)
172167 // current location of the tail), we're about to overflow the buffer
173168 // and so we don't write the character or advance the head.
174169 uint32_t k = 0 ;
175- i = (i + 1 ) % CDC_SERIAL_BUFFER_SIZE;
176- while (i != ringBuffer->tail && len>0 ) {
170+ while (len > 0 && !ringBuffer->full ) {
177171 len--;
178- ringBuffer->buffer [ringBuffer->head ] = buffer[k++];
179- ringBuffer->head = i;
180- i = (i + 1 ) % CDC_SERIAL_BUFFER_SIZE;
172+ ringBuffer->buffer [i++] = buffer[k++];
173+ i %= CDC_SERIAL_BUFFER_SIZE;
174+ if (i == ringBuffer->tail )
175+ ringBuffer->full = true ;
181176 }
177+ ringBuffer->head = i;
182178 interrupts ();
183179}
184180
185181int Serial_::available (void )
186182{
187183 ring_buffer *buffer = &cdc_rx_buffer;
184+ if (buffer->full ) {
185+ return CDC_SERIAL_BUFFER_SIZE;
186+ }
187+ if (buffer->head == buffer->tail ) {
188+ USB->DEVICE .DeviceEndpoint [CDC_ENDPOINT_OUT].EPINTENSET .reg = USB_DEVICE_EPINTENCLR_TRCPT (1 );
189+ }
188190 return (uint32_t )(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail ) % CDC_SERIAL_BUFFER_SIZE;
189191}
190192
191193int Serial_::peek (void )
192194{
193195 ring_buffer *buffer = &cdc_rx_buffer;
194-
195- if (buffer->head == buffer->tail )
196- {
196+ if (buffer->head == buffer->tail && !buffer->full ) {
197197 return -1 ;
198- }
199- else
200- {
198+ } else {
201199 return buffer->buffer [buffer->tail ];
202200 }
203201}
204202
203+
204+ // if the ringBuffer is empty: try to fill it
205+ // if it's still empty: return -1
206+ // else return the last char
207+ // so the buffer is filled only when needed
205208int Serial_::read (void )
206209{
207210 ring_buffer *buffer = &cdc_rx_buffer;
208211
209212 // if the head isn't ahead of the tail, we don't have any characters
210- if (buffer->head == buffer->tail )
213+ if (buffer->head == buffer->tail && !buffer->full )
214+ {
215+ if (usb.available (CDC_ENDPOINT_OUT))
216+ accept ();
217+ }
218+ if (buffer->head == buffer->tail && !buffer->full )
211219 {
212220 return -1 ;
213221 }
214222 else
215223 {
216224 unsigned char c = buffer->buffer [buffer->tail ];
217225 buffer->tail = (uint32_t )(buffer->tail + 1 ) % CDC_SERIAL_BUFFER_SIZE;
218- if (USBD_Available (CDC_ENDPOINT_OUT))
219- accept ();
226+ buffer->full = false ;
227+ // if (usb.available(CDC_ENDPOINT_OUT))
228+ // accept();
220229 return c;
221230 }
222231}
223232
224233void Serial_::flush (void )
225234{
226- USBD_Flush (CDC_ENDPOINT_IN);
235+ usb. flush (CDC_ENDPOINT_IN);
227236}
228237
229238size_t Serial_::write (const uint8_t *buffer, size_t size)
@@ -237,15 +246,13 @@ size_t Serial_::write(const uint8_t *buffer, size_t size)
237246 // TODO - ZE - check behavior on different OSes and test what happens if an
238247 // open connection isn't broken cleanly (cable is yanked out, host dies
239248 // or locks up, or host virtual serial port hangs)
240- // if (_usbLineInfo.lineState > 0) // Problem with Windows(R)
249+ if (_usbLineInfo.lineState > 0 ) // Problem with Windows(R)
241250 {
242- uint32_t r = USBD_Send (CDC_ENDPOINT_IN, buffer, size);
251+ uint32_t r = usb. send (CDC_ENDPOINT_IN, buffer, size);
243252
244- if (r > 0 )
245- {
253+ if (r == 0 ) {
246254 return r;
247- } else
248- {
255+ } else {
249256 setWriteError ();
250257 return 0 ;
251258 }
@@ -282,6 +289,6 @@ Serial_::operator bool()
282289 return result;
283290}
284291
285- Serial_ SerialUSB;
292+ Serial_ SerialUSB (USBDevice) ;
286293
287294#endif
0 commit comments