@@ -32,7 +32,7 @@ HardwareSerial::HardwareSerial(XMC_UART_t *xmc_uart_config,
3232 RingBuffer *tx_buffer) {
3333 _XMC_UART_config = xmc_uart_config;
3434 _rx_buffer = rx_buffer;
35- _tx_buffer = tx_buffer; // TODO: replaced by TBUF (hardware register), can be actually removed
35+ _tx_buffer = tx_buffer;
3636}
3737
3838// Public Methods //////////////////////////////////////////////////////////////
@@ -119,12 +119,10 @@ int HardwareSerial::available(void) {
119119}
120120
121121int 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 ;
128126}
129127
130128int HardwareSerial::peek (void ) {
@@ -146,19 +144,59 @@ int HardwareSerial::read(void) {
146144}
147145
148146void HardwareSerial::flush (void ) {
147+ while (_tx_buffer->_iHead != _tx_buffer->_iTail )
148+ ; // wait for transmit data to be sent
149+
149150 while (XMC_USIC_CH_GetTransmitBufferStatus (_XMC_UART_config->channel ) ==
150151 XMC_USIC_CH_TBUF_STATUS_BUSY)
151152 ;
152153}
153154
154155size_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+ }
162200 return 1 ;
163201}
164202
@@ -182,11 +220,20 @@ void HardwareSerial::IrqHandler(void) {
182220 XMC_UART_CH_ClearStatusFlag (_XMC_UART_config->channel ,
183221 XMC_UART_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION);
184222
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+ }
187234 }
188235}
189236
190237// ****************************************************************************
191238// END OF FILE
192- // ****************************************************************************
239+ // ****************************************************************************
0 commit comments