@@ -37,16 +37,20 @@ extern void serialEvent1(void) __attribute__((weak));
37
37
38
38
// Constructors ////////////////////////////////////////////////////////////////
39
39
40
- CDCSerialClass::CDCSerialClass ( uart_init_info *info, RingBuffer *pRx_buffer,
41
- RingBuffer *pTx_buffer )
40
+ CDCSerialClass::CDCSerialClass (uart_init_info *info)
42
41
{
43
42
this ->info = info;
44
- this ->_rx_buffer = pRx_buffer;
45
- this ->_tx_buffer = pTx_buffer;
46
43
}
47
44
48
45
// Public Methods //////////////////////////////////////////////////////////////
49
46
47
+ void CDCSerialClass::setSharedData (struct cdc_acm_shared_data *cdc_acm_shared_data)
48
+ {
49
+ this ->_shared_data = cdc_acm_shared_data;
50
+ this ->_rx_buffer = cdc_acm_shared_data->rx_buffer ;
51
+ this ->_tx_buffer = cdc_acm_shared_data->tx_buffer ;
52
+ }
53
+
50
54
void CDCSerialClass::begin (const uint32_t dwBaudRate)
51
55
{
52
56
begin (dwBaudRate, (uint8_t )SERIAL_8N1 );
@@ -55,37 +59,43 @@ void CDCSerialClass::begin(const uint32_t dwBaudRate)
55
59
void CDCSerialClass::begin (const uint32_t dwBaudRate, const uint8_t config)
56
60
{
57
61
init (dwBaudRate, config );
58
- opened = true ;
59
62
}
60
63
61
64
62
65
void CDCSerialClass::init (const uint32_t dwBaudRate, const uint8_t modeReg)
63
66
{
67
+ /* Set a per-byte write delay approximately equal to the time it would
68
+ * take to clock out a byte on a standard UART at this baud rate */
69
+ _writeDelayUsec = 8000000 / dwBaudRate;
70
+
64
71
// Make sure both ring buffers are initialized back to empty.
65
- _rx_buffer->_iHead = _rx_buffer->_iTail = 0 ;
66
- _tx_buffer->_iHead = _tx_buffer->_iTail = 0 ;
72
+ _rx_buffer->head = _rx_buffer->tail = 0 ;
73
+ _tx_buffer->head = _tx_buffer->tail = 0 ;
74
+
75
+ _shared_data->device_open = true ;
67
76
}
68
77
69
78
void CDCSerialClass::end ( void )
70
79
{
71
- opened = false ;
72
- _rx_buffer->_iHead = 0 ;
73
- _rx_buffer->_iTail = 0 ;
80
+ _shared_data->device_open = false ;
81
+
82
+ _rx_buffer->head = 0 ;
83
+ _rx_buffer->tail = 0 ;
74
84
}
75
85
76
86
int CDCSerialClass::available ( void )
77
87
{
78
88
#define SBS SERIAL_BUFFER_SIZE
79
- return (int )(SBS + _rx_buffer->_iHead - _rx_buffer->_iTail ) % SBS;
89
+ return (int )(SBS + _rx_buffer->head - _rx_buffer->tail ) % SBS;
80
90
}
81
91
82
92
int CDCSerialClass::availableForWrite (void )
83
93
{
84
- if (!opened )
94
+ if (!_shared_data-> device_open || !_shared_data-> host_open )
85
95
return (0 );
86
96
87
- int head = _tx_buffer->_iHead ;
88
- int tail = _tx_buffer->_iTail ;
97
+ int head = _tx_buffer->head ;
98
+ int tail = _tx_buffer->tail ;
89
99
90
100
if (head >= tail)
91
101
return SERIAL_BUFFER_SIZE - head + tail - 1 ;
@@ -94,37 +104,52 @@ int CDCSerialClass::availableForWrite(void)
94
104
95
105
int CDCSerialClass::peek (void )
96
106
{
97
- if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
107
+ if ( _rx_buffer->head == _rx_buffer->tail )
98
108
return -1 ;
99
109
100
- return _rx_buffer->_aucBuffer [_rx_buffer->_iTail ];
110
+ return _rx_buffer->data [_rx_buffer->tail ];
101
111
}
102
112
103
113
int CDCSerialClass::read ( void )
104
114
{
105
- if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
115
+ if ( _rx_buffer->head == _rx_buffer->tail )
106
116
return -1 ;
107
117
108
- uint8_t uc = _rx_buffer->_aucBuffer [_rx_buffer->_iTail ];
109
- _rx_buffer->_iTail = (_rx_buffer->_iTail + 1 ) % SERIAL_BUFFER_SIZE;
118
+ uint8_t uc = _rx_buffer->data [_rx_buffer->tail ];
119
+ _rx_buffer->tail = (_rx_buffer->tail + 1 ) % SERIAL_BUFFER_SIZE;
110
120
return uc;
111
121
}
112
122
113
123
void CDCSerialClass::flush ( void )
114
124
{
115
- while (_tx_buffer->_iTail != _tx_buffer->_iHead ) {
125
+ while (_tx_buffer->tail != _tx_buffer->head ) {
116
126
delayMicroseconds (1 );
117
127
}
118
128
}
119
129
120
130
size_t CDCSerialClass::write ( const uint8_t uc_data )
121
131
{
122
- if (!opened)
132
+ uint32_t retries = 1 ;
133
+
134
+ if (!_shared_data->device_open || !_shared_data->host_open )
123
135
return (0 );
124
136
125
137
do {
126
- _tx_buffer->store_char (uc_data);
127
- } while (_tx_buffer->_buffer_overflow );
138
+ int i = (uint32_t )(_tx_buffer->head + 1 ) % SERIAL_BUFFER_SIZE;
139
+ // if we should be storing the received character into the location
140
+ // just before the tail (meaning that the head would advance to the
141
+ // current location of the tail), we're about to overflow the buffer
142
+ // and so we don't write the character or advance the head.
143
+ if (i != _tx_buffer->tail ) {
144
+ _tx_buffer->data [_tx_buffer->head ] = uc_data;
145
+ _tx_buffer->head = i;
146
+
147
+ // Mimick the throughput of a typical UART by throttling the data
148
+ // flow according to the configured baud rate
149
+ delayMicroseconds (_writeDelayUsec);
150
+ break ;
151
+ }
152
+ } while (retries--);
128
153
129
154
return 1 ;
130
155
}
0 commit comments