Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions cores/arduino/Uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,24 @@
#include "Arduino.h"
#include "wiring_private.h"

Uart::Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX)
#define NO_RTS_PIN 255
#define NO_CTS_PIN 255
#define RTS_RX_THRESHOLD 10

Uart::Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX) :
Uart(_s, _pinRX, _pinTX, _padRX, _padTX, NO_RTS_PIN, NO_CTS_PIN)
{
}

Uart::Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX, uint8_t _pinRTS, uint8_t _pinCTS)
{
sercom = _s;
uc_pinRX = _pinRX;
uc_pinTX = _pinTX;
uc_padRX=_padRX ;
uc_padTX=_padTX;
uc_padRX = _padRX ;
uc_padTX = _padTX;
uc_pinRTS = _pinRTS;
uc_pinCTS = _pinCTS;
}

void Uart::begin(unsigned long baudrate)
Expand All @@ -39,6 +50,23 @@ void Uart::begin(unsigned long baudrate, uint16_t config)
pinPeripheral(uc_pinRX, g_APinDescription[uc_pinRX].ulPinType);
pinPeripheral(uc_pinTX, g_APinDescription[uc_pinTX].ulPinType);

if (uc_padTX == UART_TX_RTS_CTS_PAD_0_2_3) {
if (uc_pinCTS != NO_CTS_PIN) {
pinPeripheral(uc_pinCTS, g_APinDescription[uc_pinCTS].ulPinType);
}
}

if (uc_pinRTS != NO_RTS_PIN) {
pinMode(uc_pinRTS, OUTPUT);

EPortType rtsPort = g_APinDescription[uc_pinRTS].ulPort;
pul_outsetRTS = &PORT->Group[rtsPort].OUTSET.reg;
pul_outclrRTS = &PORT->Group[rtsPort].OUTCLR.reg;
ul_pinMaskRTS = (1ul << g_APinDescription[uc_pinRTS].ulPin);

*pul_outclrRTS = ul_pinMaskRTS;
}

sercom->initUART(UART_INT_CLOCK, SAMPLE_RATE_x16, baudrate);
sercom->initFrame(extractCharSize(config), LSB_FIRST, extractParity(config), extractNbStopBit(config));
sercom->initPads(uc_padTX, uc_padRX);
Expand All @@ -64,6 +92,13 @@ void Uart::IrqHandler()
{
if (sercom->availableDataUART()) {
rxBuffer.store_char(sercom->readDataUART());

if (uc_pinRTS != NO_RTS_PIN) {
// RX buffer space is below the threshold, de-assert RTS
if (rxBuffer.availableForStore() < RTS_RX_THRESHOLD) {
*pul_outsetRTS = ul_pinMaskRTS;
}
}
}

if (sercom->isDataRegisterEmptyUART()) {
Expand Down Expand Up @@ -102,7 +137,16 @@ int Uart::peek()

int Uart::read()
{
return rxBuffer.read_char();
int c = rxBuffer.read_char();

if (uc_pinRTS != NO_RTS_PIN) {
// if there is enough space in the RX buffer, assert RTS
if (rxBuffer.availableForStore() > RTS_RX_THRESHOLD) {
*pul_outclrRTS = ul_pinMaskRTS;
}
}

return c;
}

size_t Uart::write(const uint8_t data)
Expand Down
6 changes: 6 additions & 0 deletions cores/arduino/Uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Uart : public HardwareSerial
{
public:
Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX);
Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX, uint8_t _pinRTS, uint8_t _pinCTS);
void begin(unsigned long baudRate);
void begin(unsigned long baudrate, uint16_t config);
void end();
Expand All @@ -52,6 +53,11 @@ class Uart : public HardwareSerial
uint8_t uc_pinTX;
SercomRXPad uc_padRX;
SercomUartTXPad uc_padTX;
uint8_t uc_pinRTS;
volatile uint32_t* pul_outsetRTS;
volatile uint32_t* pul_outclrRTS;
uint32_t ul_pinMaskRTS;
uint8_t uc_pinCTS;

SercomNumberStopBit extractNbStopBit(uint16_t config);
SercomUartCharSize extractCharSize(uint16_t config);
Expand Down