33
33
34
34
#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
35
35
36
- struct ring_buffer {
37
- uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
38
- volatile uint32_t head;
39
- volatile uint32_t tail;
40
- volatile bool full;
41
- };
42
- ring_buffer cdc_rx_buffer = {{0 }, 0 , 0 , false };
43
-
44
36
typedef struct {
45
37
uint32_t dwDTERate;
46
38
uint8_t bCharFormat;
@@ -146,7 +138,6 @@ bool CDC_Setup(USBSetup& setup)
146
138
return false ;
147
139
}
148
140
149
- uint32_t _serialPeek = -1 ;
150
141
void Serial_::begin (uint32_t /* baud_count */ )
151
142
{
152
143
// uart config is ignored in USB-CDC
@@ -161,85 +152,50 @@ void Serial_::end(void)
161
152
{
162
153
}
163
154
164
- void Serial_::accept (void )
155
+ int Serial_::available (void )
165
156
{
166
- uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
167
- uint32_t len = usb.recv (CDC_ENDPOINT_OUT, &buffer, CDC_SERIAL_BUFFER_SIZE);
168
-
169
- uint8_t enableInterrupts = ((__get_PRIMASK () & 0x1 ) == 0 );
170
- __disable_irq ();
171
-
172
- ring_buffer *ringBuffer = &cdc_rx_buffer;
173
- uint32_t i = ringBuffer->head ;
174
-
175
- // if we should be storing the received character into the location
176
- // just before the tail (meaning that the head would advance to the
177
- // current location of the tail), we're about to overflow the buffer
178
- // and so we don't write the character or advance the head.
179
- uint32_t k = 0 ;
180
- while (len > 0 && !ringBuffer->full ) {
181
- len--;
182
- ringBuffer->buffer [i++] = buffer[k++];
183
- i %= CDC_SERIAL_BUFFER_SIZE;
184
- if (i == ringBuffer->tail )
185
- ringBuffer->full = true ;
186
- }
187
- ringBuffer->head = i;
188
- if (enableInterrupts) {
189
- __enable_irq ();
190
- }
157
+ return usb.available (CDC_ENDPOINT_OUT);
191
158
}
192
159
193
- int Serial_::available (void )
160
+ int Serial_::availableForWrite (void )
194
161
{
195
- ring_buffer *buffer = &cdc_rx_buffer;
196
- if (buffer->full ) {
197
- return CDC_SERIAL_BUFFER_SIZE;
198
- }
199
- if (buffer->head == buffer->tail ) {
200
- USB->DEVICE .DeviceEndpoint [CDC_ENDPOINT_OUT].EPINTENSET .reg = USB_DEVICE_EPINTENCLR_TRCPT (1 );
201
- }
202
- return (uint32_t )(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail ) % CDC_SERIAL_BUFFER_SIZE;
162
+ // return the number of bytes left in the current bank,
163
+ // always EP size - 1, because bank is flushed on every write
164
+ return (EPX_SIZE - 1 );
203
165
}
204
166
167
+ int _serialPeek = -1 ;
168
+
205
169
int Serial_::peek (void )
206
170
{
207
- ring_buffer *buffer = &cdc_rx_buffer;
208
- if (buffer->head == buffer->tail && !buffer->full ) {
209
- return -1 ;
210
- } else {
211
- return buffer->buffer [buffer->tail ];
212
- }
171
+ if (_serialPeek != -1 )
172
+ return _serialPeek;
173
+ _serialPeek = read ();
174
+ return _serialPeek;
213
175
}
214
176
215
-
216
- // if the ringBuffer is empty: try to fill it
217
- // if it's still empty: return -1
218
- // else return the last char
219
- // so the buffer is filled only when needed
220
177
int Serial_::read (void )
221
178
{
222
- ring_buffer *buffer = &cdc_rx_buffer;
223
-
224
- // if the head isn't ahead of the tail, we don't have any characters
225
- if (buffer->head == buffer->tail && !buffer->full )
226
- {
227
- if (usb.available (CDC_ENDPOINT_OUT))
228
- accept ();
229
- }
230
- if (buffer->head == buffer->tail && !buffer->full )
231
- {
232
- return -1 ;
179
+ if (_serialPeek != -1 ) {
180
+ int res = _serialPeek;
181
+ _serialPeek = -1 ;
182
+ return res;
233
183
}
234
- else
184
+ return usb.recv (CDC_ENDPOINT_OUT);
185
+ }
186
+
187
+ size_t Serial_::readBytes (char *buffer, size_t length)
188
+ {
189
+ size_t count = 0 ;
190
+ _startMillis = millis ();
191
+ while (count < length)
235
192
{
236
- unsigned char c = buffer->buffer [buffer->tail ];
237
- buffer->tail = (uint32_t )(buffer->tail + 1 ) % CDC_SERIAL_BUFFER_SIZE;
238
- buffer->full = false ;
239
- // if (usb.available(CDC_ENDPOINT_OUT))
240
- // accept();
241
- return c;
193
+ uint32_t n = usb.recv (CDC_ENDPOINT_OUT, buffer+count, length-count);
194
+ if (n == 0 && (millis () - _startMillis) >= _timeout)
195
+ break ;
196
+ count += n;
242
197
}
198
+ return count;
243
199
}
244
200
245
201
void Serial_::flush (void )
@@ -249,28 +205,14 @@ void Serial_::flush(void)
249
205
250
206
size_t Serial_::write (const uint8_t *buffer, size_t size)
251
207
{
252
- /* only try to send bytes if the high-level CDC connection itself
253
- is open (not just the pipe) - the OS should set lineState when the port
254
- is opened and clear lineState when the port is closed.
255
- bytes sent before the user opens the connection or after
256
- the connection is closed are lost - just like with a UART. */
257
-
258
- // TODO - ZE - check behavior on different OSes and test what happens if an
259
- // open connection isn't broken cleanly (cable is yanked out, host dies
260
- // or locks up, or host virtual serial port hangs)
261
- if (_usbLineInfo.lineState > 0 ) // Problem with Windows(R)
262
- {
263
- uint32_t r = usb.send (CDC_ENDPOINT_IN, buffer, size);
208
+ uint32_t r = usb.send (CDC_ENDPOINT_IN, buffer, size);
264
209
265
- if (r == 0 ) {
266
- return r;
267
- } else {
268
- setWriteError ();
269
- return 0 ;
270
- }
210
+ if (r > 0 ) {
211
+ return r;
212
+ } else {
213
+ setWriteError ();
214
+ return 0 ;
271
215
}
272
- setWriteError ();
273
- return 0 ;
274
216
}
275
217
276
218
size_t Serial_::write (uint8_t c) {
0 commit comments