@@ -32,7 +32,7 @@ HardwareSerial::HardwareSerial(XMC_UART_t *xmc_uart_config,
32
32
RingBuffer *tx_buffer) {
33
33
_XMC_UART_config = xmc_uart_config;
34
34
_rx_buffer = rx_buffer;
35
- _tx_buffer = tx_buffer; // TODO: replaced by TBUF (hardware register), can be actually removed
35
+ _tx_buffer = tx_buffer;
36
36
}
37
37
38
38
// Public Methods //////////////////////////////////////////////////////////////
@@ -119,12 +119,10 @@ int HardwareSerial::available(void) {
119
119
}
120
120
121
121
int HardwareSerial::availableForWrite (void ) {
122
- int available = XMC_USIC_CH_GetTransmitBufferStatus (_XMC_UART_config->channel );
123
- if (available == XMC_USIC_CH_TBUF_STATUS_IDLE) {
124
- return 0 ;
125
- } else {
126
- return 1 ;
127
- } // TODO: should return bytes avaliable to write! need to enable txFIFO in the future
122
+ int tail = _tx_buffer->_iTail ; // Snapshot index affected by irq
123
+ if (_tx_buffer->_iHead >= tail)
124
+ return SERIAL_BUFFER_SIZE - 1 - _tx_buffer->_iHead + tail;
125
+ return tail - _tx_buffer->_iHead - 1 ;
128
126
}
129
127
130
128
int HardwareSerial::peek (void ) {
@@ -146,19 +144,59 @@ int HardwareSerial::read(void) {
146
144
}
147
145
148
146
void HardwareSerial::flush (void ) {
147
+ while (_tx_buffer->_iHead != _tx_buffer->_iTail )
148
+ ; // wait for transmit data to be sent
149
+
149
150
while (XMC_USIC_CH_GetTransmitBufferStatus (_XMC_UART_config->channel ) ==
150
151
XMC_USIC_CH_TBUF_STATUS_BUSY)
151
152
;
152
153
}
153
154
154
155
size_t HardwareSerial::write (const uint8_t uc_data) {
155
- // Is the hardware currently busy?
156
-
157
- // Make sure TX interrupt is enabled
158
- XMC_UART_CH_EnableEvent (_XMC_UART_config->channel , XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
159
- // Bypass buffering and send character directly
160
- XMC_UART_CH_Transmit (_XMC_UART_config->channel , uc_data);
161
-
156
+ // Is the hardware currently busy?
157
+ #if defined(SERIAL_USE_U1C1)
158
+ if (_tx_buffer->_iTail != _tx_buffer->_iHead )
159
+ #else
160
+ if ((XMC_USIC_CH_GetTransmitBufferStatus (_XMC_UART_config->channel ) ==
161
+ XMC_USIC_CH_TBUF_STATUS_BUSY) ||
162
+ (_tx_buffer->_iTail != _tx_buffer->_iHead ))
163
+ #endif
164
+ {
165
+ // If busy we buffer
166
+ int nextWrite = _tx_buffer->_iHead + 1 ;
167
+ if (nextWrite >= SERIAL_BUFFER_SIZE)
168
+ nextWrite = 0 ;
169
+
170
+ // This should always be false but in case transmission is completed before buffer, we need
171
+ // to reenable IRQ
172
+ if (XMC_USIC_CH_GetTransmitBufferStatus (_XMC_UART_config->channel ) !=
173
+ XMC_USIC_CH_TBUF_STATUS_BUSY) {
174
+ XMC_UART_CH_EnableEvent (_XMC_UART_config->channel , XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
175
+ XMC_UART_CH_Transmit (_XMC_UART_config->channel ,
176
+ _tx_buffer->_aucBuffer [_tx_buffer->_iTail ]);
177
+ _tx_buffer->_iTail ++;
178
+ if (_tx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
179
+ _tx_buffer->_iTail %= SERIAL_BUFFER_SIZE; // If iTail is larger than Serial Buffer
180
+ // Size calculate the correct index value
181
+ }
182
+
183
+ unsigned long startTime = millis ();
184
+ while (_tx_buffer->_iTail == nextWrite) {
185
+ if (millis () - startTime > 1000 ) {
186
+ return 0 ; // Spin locks if we're about to overwrite the buffer. This continues once
187
+ // the data is
188
+ // sent
189
+ }
190
+ }
191
+
192
+ _tx_buffer->_aucBuffer [_tx_buffer->_iHead ] = uc_data;
193
+ _tx_buffer->_iHead = nextWrite;
194
+ } else {
195
+ // Make sure TX interrupt is enabled
196
+ XMC_UART_CH_EnableEvent (_XMC_UART_config->channel , XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
197
+ // Bypass buffering and send character directly
198
+ XMC_UART_CH_Transmit (_XMC_UART_config->channel , uc_data);
199
+ }
162
200
return 1 ;
163
201
}
164
202
@@ -182,11 +220,20 @@ void HardwareSerial::IrqHandler(void) {
182
220
XMC_UART_CH_ClearStatusFlag (_XMC_UART_config->channel ,
183
221
XMC_UART_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION);
184
222
185
- // Mask off transmit interrupt so we don't get it any more
186
- XMC_UART_CH_DisableEvent (_XMC_UART_config->channel , XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
223
+ if (_tx_buffer->_iTail != _tx_buffer->_iHead ) {
224
+ XMC_UART_CH_Transmit (_XMC_UART_config->channel ,
225
+ _tx_buffer->_aucBuffer [_tx_buffer->_iTail ]);
226
+ _tx_buffer->_iTail ++;
227
+ if (_tx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
228
+ _tx_buffer->_iTail %= SERIAL_BUFFER_SIZE; // If iTail is larger than Serial Buffer
229
+ // Size calculate the correct index value
230
+ } else {
231
+ // Mask off transmit interrupt so we don't get it any more
232
+ XMC_UART_CH_DisableEvent (_XMC_UART_config->channel , XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
233
+ }
187
234
}
188
235
}
189
236
190
237
// ****************************************************************************
191
238
// END OF FILE
192
- // ****************************************************************************
239
+ // ****************************************************************************
0 commit comments