Skip to content
8 changes: 8 additions & 0 deletions cores/arduino/RingBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ int RingBuffer::available()
return delta;
}

int RingBuffer::availableForStore()
{
if (_iHead >= _iTail)
return SERIAL_BUFFER_SIZE - 1 - _iHead + _iTail;
else
return _iTail - _iHead - 1;
}

int RingBuffer::peek()
{
if(_iTail == _iHead)
Expand Down
1 change: 1 addition & 0 deletions cores/arduino/RingBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class RingBuffer
void clear();
int read_char();
int available();
int availableForStore();
int peek();
bool isFull();

Expand Down
10 changes: 10 additions & 0 deletions cores/arduino/SERCOM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ int SERCOM::writeDataUART(uint8_t data)
return 1;
}

void SERCOM::enableDataRegisterEmptyInterruptUART()
{
sercom->USART.INTENSET.reg |= SERCOM_USART_INTENSET_DRE;
}

void SERCOM::disableDataRegisterEmptyInterruptUART()
{
sercom->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE;
}

/* =========================
* ===== Sercom SPI
* =========================
Expand Down
2 changes: 2 additions & 0 deletions cores/arduino/SERCOM.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class SERCOM
int writeDataUART(uint8_t data) ;
bool isUARTError() ;
void acknowledgeUARTError() ;
void enableDataRegisterEmptyInterruptUART();
void disableDataRegisterEmptyInterruptUART();

/* ========== SPI ========== */
void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder) ;
Expand Down
26 changes: 24 additions & 2 deletions cores/arduino/Uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ void Uart::end()
{
sercom->resetUART();
rxBuffer.clear();
txBuffer.clear();
}

void Uart::flush()
{
while(txBuffer.available()); // wait until TX buffer is empty

sercom->flushUART();
}

Expand All @@ -63,6 +66,16 @@ void Uart::IrqHandler()
rxBuffer.store_char(sercom->readDataUART());
}

if (sercom->isDataRegisterEmptyUART()) {
if (txBuffer.available()) {
uint8_t data = txBuffer.read_char();

sercom->writeDataUART(data);
} else {
sercom->disableDataRegisterEmptyInterruptUART();
}
}

if (sercom->isUARTError()) {
sercom->acknowledgeUARTError();
// TODO: if (sercom->isBufferOverflowErrorUART()) ....
Expand All @@ -79,7 +92,7 @@ int Uart::available()

int Uart::availableForWrite()
{
return (sercom->isDataRegisterEmptyUART() ? 1 : 0);
return txBuffer.availableForStore();
}

int Uart::peek()
Expand All @@ -94,7 +107,16 @@ int Uart::read()

size_t Uart::write(const uint8_t data)
{
sercom->writeDataUART(data);
if (sercom->isDataRegisterEmptyUART() && txBuffer.available() == 0) {
sercom->writeDataUART(data);
} else {
while(txBuffer.isFull()); // spin lock until a spot opens up in the buffer

txBuffer.store_char(data);

sercom->enableDataRegisterEmptyInterruptUART();
}

return 1;
}

Expand Down
1 change: 1 addition & 0 deletions cores/arduino/Uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Uart : public HardwareSerial
private:
SERCOM *sercom;
RingBuffer rxBuffer;
RingBuffer txBuffer;

uint8_t uc_pinRX;
uint8_t uc_pinTX;
Expand Down