11#include "SC16IS752Logger.h"
13#define SC16IS752_SERIAL_CONFIG(data_bits, parity_code, stop_bits) \
14 ((((data_bits) - 5) & 0x03) | (((parity_code) & 0x03) << 2) | \
15 ((((stop_bits) - 1) & 0x01) << 4))
18#define SERIAL_5N1 SC16IS752_SERIAL_CONFIG(5, 0, 1)
21#define SERIAL_6N1 SC16IS752_SERIAL_CONFIG(6, 0, 1)
24#define SERIAL_7N1 SC16IS752_SERIAL_CONFIG(7, 0, 1)
27#define SERIAL_8N1 SC16IS752_SERIAL_CONFIG(8, 0, 1)
30#define SERIAL_5N2 SC16IS752_SERIAL_CONFIG(5, 0, 2)
33#define SERIAL_6N2 SC16IS752_SERIAL_CONFIG(6, 0, 2)
36#define SERIAL_7N2 SC16IS752_SERIAL_CONFIG(7, 0, 2)
39#define SERIAL_8N2 SC16IS752_SERIAL_CONFIG(8, 0, 2)
42#define SERIAL_5E1 SC16IS752_SERIAL_CONFIG(5, 2, 1)
45#define SERIAL_6E1 SC16IS752_SERIAL_CONFIG(6, 2, 1)
48#define SERIAL_7E1 SC16IS752_SERIAL_CONFIG(7, 2, 1)
51#define SERIAL_8E1 SC16IS752_SERIAL_CONFIG(8, 2, 1)
54#define SERIAL_5E2 SC16IS752_SERIAL_CONFIG(5, 2, 2)
57#define SERIAL_6E2 SC16IS752_SERIAL_CONFIG(6, 2, 2)
60#define SERIAL_7E2 SC16IS752_SERIAL_CONFIG(7, 2, 2)
63#define SERIAL_8E2 SC16IS752_SERIAL_CONFIG(8, 2, 2)
66#define SERIAL_5O1 SC16IS752_SERIAL_CONFIG(5, 1, 1)
69#define SERIAL_6O1 SC16IS752_SERIAL_CONFIG(6, 1, 1)
72#define SERIAL_7O1 SC16IS752_SERIAL_CONFIG(7, 1, 1)
75#define SERIAL_8O1 SC16IS752_SERIAL_CONFIG(8, 1, 1)
78#define SERIAL_5O2 SC16IS752_SERIAL_CONFIG(5, 1, 2)
81#define SERIAL_6O2 SC16IS752_SERIAL_CONFIG(6, 1, 2)
84#define SERIAL_7O2 SC16IS752_SERIAL_CONFIG(7, 1, 2)
87#define SERIAL_8O2 SC16IS752_SERIAL_CONFIG(8, 1, 2)
90static constexpr uint8_t SC16IS750_I2C_ADDRESS_AA =
92static constexpr uint8_t SC16IS750_I2C_ADDRESS_AB =
94static constexpr uint8_t SC16IS750_I2C_ADDRESS_AC =
96static constexpr uint8_t SC16IS750_I2C_ADDRESS_AD =
98static constexpr uint8_t SC16IS750_I2C_ADDRESS_BA =
100static constexpr uint8_t SC16IS750_I2C_ADDRESS_BB =
102static constexpr uint8_t SC16IS750_I2C_ADDRESS_BC =
104static constexpr uint8_t SC16IS750_I2C_ADDRESS_BD =
106static constexpr uint8_t SC16IS750_I2C_ADDRESS_CA =
108static constexpr uint8_t SC16IS750_I2C_ADDRESS_CB =
110static constexpr uint8_t SC16IS750_I2C_ADDRESS_CC =
112static constexpr uint8_t SC16IS750_I2C_ADDRESS_CD =
114static constexpr uint8_t SC16IS750_I2C_ADDRESS_DA =
116static constexpr uint8_t SC16IS750_I2C_ADDRESS_DB =
118static constexpr uint8_t SC16IS750_I2C_ADDRESS_DC =
120static constexpr uint8_t SC16IS750_I2C_ADDRESS_DD =
128 SC16IS750_RECEIVE_LINE_STATUS_ERROR,
129 SC16IS750_RECEIVE_TIMEOUT_INTERRUPT,
130 SC16IS750_RHR_INTERRUPT,
131 SC16IS750_THR_INTERRUPT,
132 SC16IS750_MODEM_INTERRUPT,
133 SC16IS750_INPUT_PIN_CHANGE_STATE,
134 SC16IS750_RECEIVE_XOFF,
135 SC16IS750_CTS_RTS_CHANGE
138static constexpr uint32_t SC16IS752_DEFAULT_SPEED =
140static constexpr uint32_t SC16IS752_DEFAULT_CONFIG =
142static constexpr uint32_t SC16IS752_DEFAULT_SPI_CLOCK =
197 : parent_(parent), channel_(channel) {}
203 int read()
override {
return parent_.
read(channel_); }
205 int peek()
override {
return parent_.
peek(channel_); }
209 size_t write(uint8_t val)
override {
return parent_.
write(channel_, val); }
242 void begin(uint32_t baudrate = SC16IS752_DEFAULT_SPEED,
243 uint32_t config = SC16IS752_DEFAULT_CONFIG) {
277 SC16IS752(TwoWire& wire, uint8_t addr = SC16IS750_I2C_ADDRESS_AD,
281 device_address_sspin = addr;
284 crystal_freq = crystal_freq_hz;
297 device_address_sspin = ss_pin;
300 crystal_freq = crystal_freq_hz;
336 friend class ChannelStream;
419 bool is_active =
false;
420 uint8_t device_address_sspin;
423 SPISettings spi_settings{SC16IS752_DEFAULT_SPI_CLOCK, MSBFIRST, SPI_MODE0};
426 ChannelStream channel_a_stream;
427 ChannelStream channel_b_stream;
429 uint8_t peek_flag[2];
464 uint32_t config = SC16IS752_DEFAULT_CONFIG) {
487 if (peek_flag[channel] == 0) {
490 peek_flag[channel] = 0;
491 return peek_buf[channel];
540 if (peek_flag[channel] == 0) {
541 peek_buf[channel] =
readByte(channel);
542 if (peek_buf[channel] >= 0) {
543 peek_flag[channel] = 1;
547 return peek_buf[channel];
557 uint32_t start = millis();
561 if ((tmp_lsr & 0x20) != 0) {
564 }
while ((millis() - start) < timeout);
567 logger->
warn(
"flush timeout ch=%d", channel);
587 return SC16IS750_RECEIVE_LINE_STATUS_ERROR;
589 return SC16IS750_RECEIVE_TIMEOUT_INTERRUPT;
591 return SC16IS750_RHR_INTERRUPT;
593 return SC16IS750_THR_INTERRUPT;
595 return SC16IS750_MODEM_INTERRUPT;
597 return SC16IS750_INPUT_PIN_CHANGE_STATE;
599 return SC16IS750_RECEIVE_XOFF;
601 return SC16IS750_CTS_RTS_CHANGE;
633 if (tx_enable == 0) {
646 if (spi_bus !=
nullptr) {
647 pinMode(device_address_sspin, OUTPUT);
668 uint8_t temp_iocontrol;
673 temp_iocontrol |= 0x02;
675 temp_iocontrol &= 0xFD;
685 uint8_t temp_iocontrol;
690 temp_iocontrol &= 0xFE;
692 temp_iocontrol |= 0x01;
706 uint32_t actual_baudrate;
716 divisor = (crystal_freq / prescaler) / (baudrate * 16);
728 actual_baudrate = (crystal_freq / prescaler) / (16 * divisor);
729 error = ((float)actual_baudrate - baudrate) * 1000 / baudrate;
731 logger->
debug(
"Desired baudrate: %d", baudrate);
732 logger->
debug(
"Calculated divisor: %d", divisor);
733 logger->
debug(
"Actual baudrate: %d", actual_baudrate);
734 logger->
debug(
"Baudrate error: %d", (
int)error);
743 if (wire_bus !=
nullptr) {
744 wire_bus->beginTransmission(device_address_sspin);
745 wire_bus->write((reg_addr << 3 | channel << 1));
746 wire_bus->endTransmission(0);
747 wire_bus->requestFrom(device_address_sspin, (uint8_t)1);
748 result = wire_bus->read();
749 }
else if (spi_bus !=
nullptr) {
750 spi_bus->beginTransaction(spi_settings);
752 delayMicroseconds(10);
753 spi_bus->transfer(0x80 | ((reg_addr << 3 | channel << 1)));
754 result = spi_bus->transfer(0xff);
755 delayMicroseconds(10);
757 spi_bus->endTransaction();
762 logger->
debug(
"ReadRegister ch=%X reg=%X res=%X", channel,
763 (reg_addr << 3 | channel << 1), result);
771 logger->
debug(
"WriteRegister ch=%X reg=%X val=%X", channel,
772 (reg_addr << 3 | channel << 1), val);
775 if (wire_bus !=
nullptr) {
776 wire_bus->beginTransmission(device_address_sspin);
777 wire_bus->write((reg_addr << 3 | channel << 1));
778 wire_bus->write(val);
779 wire_bus->endTransmission(1);
781 spi_bus->beginTransaction(spi_settings);
783 delayMicroseconds(10);
784 spi_bus->transfer((reg_addr << 3 | channel << 1));
785 spi_bus->transfer(val);
786 delayMicroseconds(10);
788 spi_bus->endTransaction();
795 uint8_t parity_select, uint8_t stop_length) {
800 logger->
debug(
"LCR Register: %d", temp_lcr);
802 switch (data_length) {
819 if (stop_length == 2) {
824 switch (parity_select) {
847 uint8_t data_length = 8;
848 uint8_t parity_select = 0;
849 uint8_t stop_length = 1;
854 logger->
warn(
"Unsupported serial config %lu, using SERIAL_8N1",
855 (
unsigned long)config);
859 setLine(channel, data_length, parity_select, stop_length);
877 temp_iodir |= (0x01 << pin_number);
879 temp_iodir &= (uint8_t)~(0x01 << pin_number);
888 uint8_t temp_iostate;
891 if (pin_state == 1) {
892 temp_iostate |= (0x01 << pin_number);
894 temp_iostate &= (uint8_t)~(0x01 << pin_number);
903 uint8_t temp_iostate;
906 if ((temp_iostate & (0x01 << pin_number)) == 0) {
941 if (fifo_enable == 0) {
999 logger->
debug(
"Available data: %d", avail);
1015 }
while ((tmp_lsr & 0x20) == 0);
1022 volatile uint8_t val;
1025 logger->
debug(
"No data available");
1030 logger->
debug(
"Data available");
1039 uint8_t* parity_select, uint8_t* stop_length) {
Simple logger for SC16IS752 channels with variadic parameter support and log levels.
Definition SC16IS752Logger.h:13
void warn(const char *format,...)
Log a formatted warning message.
Definition SC16IS752Logger.h:59
void debug(const char *format,...)
Log a formatted debug message.
Definition SC16IS752Logger.h:35
Per-channel Stream adapter for one SC16IS752 UART.
Definition SC16IS752.h:193
int read() override
Reads one byte from this channel.
Definition SC16IS752.h:203
void flush() override
Waits until pending transmission on this channel is complete.
Definition SC16IS752.h:207
uint8_t linestate()
Returns the line status register for this channel.
Definition SC16IS752.h:249
int available() override
Returns the number of bytes available for reading on this channel.
Definition SC16IS752.h:201
void interruptControl(uint8_t int_ena)
Controls interrupt enable bits for this channel.
Definition SC16IS752.h:267
void begin(uint32_t baudrate=SC16IS752_DEFAULT_SPEED, uint32_t config=SC16IS752_DEFAULT_CONFIG)
Initializes this channel with the specified baud rate and serial configuration.
Definition SC16IS752.h:242
void enableRs485(bool invert_rts)
Enables RS485 mode for this channel.
Definition SC16IS752.h:257
uint8_t interruptPendingTest()
Tests whether an interrupt is pending for this channel.
Definition SC16IS752.h:251
ChannelStream(SC16IS752 &parent, SC16IS752_Channel channel)
Creates a stream adapter bound to the selected UART channel.
Definition SC16IS752.h:196
void end()
Gracefully closes this channel.
Definition SC16IS752.h:247
void enableTransmit(uint8_t tx_enable)
Enables or disables transmission for this channel.
Definition SC16IS752.h:262
int peek() override
Peeks one byte from this channel without removing it.
Definition SC16IS752.h:205
size_t write(uint8_t val) override
Writes one byte to this channel.
Definition SC16IS752.h:209
int interruptEventTest()
Returns the decoded interrupt event for this channel.
Definition SC16IS752.h:255
Driver for the NXP SC16IS752 dual UART bridge over I2C or SPI.
Definition SC16IS752.h:170
static constexpr uint8_t SC16IS750_INT_RHR
RX holding register interrupt enable bit.
Definition SC16IS752.h:408
void setTimeout(uint32_t time_out)
Sets read timeout in milliseconds.
Definition SC16IS752.h:325
static constexpr uint8_t SC16IS750_REG_DLL
Divisor Latch LSB.
Definition SC16IS752.h:378
static constexpr uint8_t SC16IS750_REG_EFCR
Extra Features Control Register.
Definition SC16IS752.h:374
void flush(SC16IS752_Channel channel)
Waits for transmission to complete on the channel.
Definition SC16IS752.h:551
void setLogger(SC16IS752Logger *log)
Set logger for debug output.
Definition SC16IS752.h:323
void gpioSetPortState(uint8_t port_state)
Sets output state of all GPIO pins using a bitmask.
Definition SC16IS752.h:919
uint8_t gpioGetPinState(uint8_t pin_number)
Reads one GPIO pin state and returns 0 or 1.
Definition SC16IS752.h:902
static constexpr uint8_t SC16IS750_REG_IOSTATE
GPIO State Register.
Definition SC16IS752.h:368
SC16IS752(TwoWire &wire, uint8_t addr=SC16IS750_I2C_ADDRESS_AD, uint32_t crystal_freq_hz=SC16IS750_CRYSTCAL_FREQ)
Constructs an SC16IS752 instance using I2C transport.
Definition SC16IS752.h:277
uint8_t fifoAvailableSpace(SC16IS752_Channel channel)
Returns free space currently available in TX FIFO.
Definition SC16IS752.h:1005
static constexpr uint8_t SC16IS750_REG_XOFF1
XOFF1 flow-control character.
Definition SC16IS752.h:388
void gpioSetPortMode(uint8_t port_io)
Sets direction of all GPIO pins using a bitmask.
Definition SC16IS752.h:913
uint8_t ping()
Verifies device communication (returns 1 if successful)
Definition SC16IS752.h:511
static constexpr uint8_t SC16IS750_INT_SLEEP
Sleep mode interrupt enable bit.
Definition SC16IS752.h:400
void enableTransmit(SC16IS752_Channel channel, uint8_t tx_enable)
Enables or disables transmission on the specified channel.
Definition SC16IS752.h:630
uint8_t linestate(SC16IS752_Channel channel)
Returns line status register for the channel.
Definition SC16IS752.h:507
static constexpr uint8_t SC16IS750_REG_RXLVL
RX FIFO Level Register.
Definition SC16IS752.h:364
static constexpr uint8_t SC16IS750_REG_IIR
Interrupt Identification Register.
Definition SC16IS752.h:348
void setPinInterrupt(uint8_t io_int_ena)
Configures GPIO pin interrupt settings.
Definition SC16IS752.h:609
int read(SC16IS752_Channel channel)
Reads a byte from the specified channel.
Definition SC16IS752.h:483
uint8_t interruptPendingTest(SC16IS752_Channel channel)
Tests if an interrupt is pending on the channel.
Definition SC16IS752.h:572
static constexpr uint8_t SC16IS750_REG_LSR
Line Status Register.
Definition SC16IS752.h:354
void end()
Gracefully closes both UART channels and resets the device.
Definition SC16IS752.h:328
SC16IS752 & operator=(SC16IS752 &&)=delete
Prevent copying and moving of the driver instance.
bool decodeSerialConfig(uint32_t config, uint8_t *data_length, uint8_t *parity_select, uint8_t *stop_length)
Decodes Arduino SERIAL_* format into data bits, parity, and stop bits.
Definition SC16IS752.h:1038
static constexpr uint8_t SC16IS750_INT_RTS
RTS change interrupt enable bit.
Definition SC16IS752.h:396
static constexpr uint8_t SC16IS750_REG_EFR
Enhanced Features Register.
Definition SC16IS752.h:382
SC16IS752_Channel
UART channel selector used by channel-specific APIs.
Definition SC16IS752.h:176
@ SC16IS752_CHANNEL_A
UART channel A.
Definition SC16IS752.h:177
@ SC16IS752_CHANNEL_BOTH
Broadcast for global/shared registers.
Definition SC16IS752.h:179
@ SC16IS752_CHANNEL_B
UART channel B.
Definition SC16IS752.h:178
int interruptEventTest(SC16IS752_Channel channel)
Returns the type of interrupt event for the channel.
Definition SC16IS752.h:577
SC16IS752 & operator=(const SC16IS752 &)=delete
Prevent copying and moving of the driver instance.
static constexpr uint8_t SC16IS750_INT_THR
TX holding register interrupt enable bit.
Definition SC16IS752.h:406
static constexpr uint8_t SC16IS750_REG_TCR
Transmission Control Register.
Definition SC16IS752.h:358
int16_t setBaudrate(SC16IS752_Channel channel, uint32_t baudrate)
Configures baud rate divisor and returns error in parts-per-thousand.
Definition SC16IS752.h:701
static constexpr uint8_t SC16IS750_REG_TLR
Trigger Level Register.
Definition SC16IS752.h:360
static constexpr uint8_t SC16IS750_REG_IOCONTROL
GPIO/IO Control Register.
Definition SC16IS752.h:372
SC16IS752(SPIClass &spi, uint8_t ss_pin, uint32_t crystal_freq_hz=SC16IS750_CRYSTCAL_FREQ)
Constructs an SC16IS752 instance using SPI transport.
Definition SC16IS752.h:293
static constexpr uint8_t SC16IS750_REG_XON2
XON2 flow-control character.
Definition SC16IS752.h:386
static constexpr uint8_t SC16IS750_REG_IER
Interrupt Enable Register.
Definition SC16IS752.h:344
void gpioSetPinState(uint8_t pin_number, uint8_t pin_state)
Sets one GPIO output pin state (HIGH or LOW).
Definition SC16IS752.h:887
static constexpr uint8_t SC16IS750_REG_MSR
Modem Status Register.
Definition SC16IS752.h:355
static constexpr uint8_t SC16IS750_REG_FCR
FIFO Control Register.
Definition SC16IS752.h:346
static constexpr uint32_t SC16IS750_CRYSTCAL_FREQ
Default crystal frequency (Hz).
Definition SC16IS752.h:414
static constexpr uint8_t SC16IS750_REG_THR
Transmit Holding Register.
Definition SC16IS752.h:342
void fifoSetTriggerLevel(SC16IS752_Channel channel, uint8_t rx_fifo, uint8_t length)
Sets RX or TX FIFO trigger level for interrupt generation.
Definition SC16IS752.h:968
static constexpr uint8_t SC16IS750_INT_XOFF
XOFF interrupt enable bit.
Definition SC16IS752.h:398
void enableRs485(SC16IS752_Channel channel, bool invert_rts)
Definition SC16IS752.h:616
void gpioSetPinMode(uint8_t pin_number, uint8_t i_o)
Sets one GPIO pin direction (OUTPUT or INPUT).
Definition SC16IS752.h:872
ChannelStream & channelA()
Returns channel A stream adapter.
Definition SC16IS752.h:318
SC16IS752(SC16IS752 &&)=delete
Prevent copying and moving of the driver instance.
static constexpr uint8_t SC16IS750_REG_TXLVL
TX FIFO Level Register.
Definition SC16IS752.h:362
static constexpr uint8_t SC16IS750_REG_IODIR
GPIO Direction Register.
Definition SC16IS752.h:366
void writeByte(SC16IS752_Channel channel, uint8_t val)
Writes one byte to TX holding register when transmitter is ready.
Definition SC16IS752.h:1010
void interruptControl(SC16IS752_Channel channel, uint8_t int_ena)
Writes interrupt enable flags for the selected UART channel.
Definition SC16IS752.h:661
static constexpr uint8_t SC16IS750_INT_MODEM
Modem status interrupt enable bit.
Definition SC16IS752.h:402
static constexpr uint8_t SC16IS750_REG_XOFF2
XOFF2 flow-control character.
Definition SC16IS752.h:390
void fifoReset(SC16IS752_Channel channel, uint8_t rx_fifo)
Resets RX or TX FIFO for the selected channel.
Definition SC16IS752.h:952
static constexpr uint8_t SC16IS750_REG_DLH
Divisor Latch MSB.
Definition SC16IS752.h:379
void setLine(SC16IS752_Channel channel, uint32_t config)
Configures data bits, parity, and stop bits from an Arduino SERIAL_* value.
Definition SC16IS752.h:846
static constexpr uint8_t SC16IS750_REG_LCR
Line Control Register.
Definition SC16IS752.h:350
static constexpr uint8_t SC16IS750_REG_XON1
XON1 flow-control character.
Definition SC16IS752.h:384
void modemPin(uint8_t gpio)
Selects whether upper IO pins operate as modem pins or GPIO pins.
Definition SC16IS752.h:666
size_t write(SC16IS752_Channel channel, uint8_t val)
Writes a byte to the specified channel.
Definition SC16IS752.h:496
void fifoEnable(SC16IS752_Channel channel, uint8_t fifo_enable)
Enables or disables FIFO for the selected channel.
Definition SC16IS752.h:936
static constexpr uint8_t SC16IS750_INT_CTS
CTS change interrupt enable bit.
Definition SC16IS752.h:394
uint8_t digitalRead(uint8_t pin)
Reads GPIO pin level (returns 0 or 1)
Definition SC16IS752.h:869
int available(SC16IS752_Channel channel)
Returns number of bytes available to read from the channel.
Definition SC16IS752.h:502
void setLine(SC16IS752_Channel channel, uint8_t data_length, uint8_t parity_select, uint8_t stop_length)
Configures line format by data bits, parity mode, and stop bits.
Definition SC16IS752.h:794
ChannelStream & channelB()
Returns channel B stream adapter.
Definition SC16IS752.h:320
static constexpr uint8_t SC16IS750_REG_MCR
Modem Control Register.
Definition SC16IS752.h:352
void digitalWrite(uint8_t pin, uint8_t value)
Sets GPIO pin output level (HIGH or LOW)
Definition SC16IS752.h:866
void pinMode(uint8_t pin, uint8_t io)
Sets GPIO pin as input or output (OUTPUT or INPUT)
Definition SC16IS752.h:863
SC16IS752(const SC16IS752 &)=delete
Prevent copying and moving of the driver instance.
static constexpr uint8_t SC16IS750_REG_SPR
Scratchpad Register.
Definition SC16IS752.h:357
void endChannel(SC16IS752_Channel channel)
Gracefully closes a specific UART channel.
Definition SC16IS752.h:472
static constexpr uint8_t SC16IS750_REG_RHR
Receive Holding Register.
Definition SC16IS752.h:340
uint8_t gpioGetPortState(void)
Returns the current state of all GPIO pins as a bitmask.
Definition SC16IS752.h:656
static constexpr uint8_t SC16IS750_REG_IOINTENA
GPIO Interrupt Enable Register.
Definition SC16IS752.h:370
uint8_t fifoAvailableData(SC16IS752_Channel channel)
Returns number of bytes currently available in RX FIFO.
Definition SC16IS752.h:996
int readByte(SC16IS752_Channel channel)
Reads one byte from RX holding register, or -1 when no data is available.
Definition SC16IS752.h:1021
void writeRegister(SC16IS752_Channel channel, uint8_t reg_addr, uint8_t val)
Writes one register byte to the selected channel via I2C or SPI.
Definition SC16IS752.h:769
void initializeDevice()
Initializes the SC16IS752 device state on an already configured bus.
Definition SC16IS752.h:644
int peek(SC16IS752_Channel channel)
Reads a byte without removing it from the buffer.
Definition SC16IS752.h:536
void resetDevice()
Issues a software reset to the SC16IS752 device.
Definition SC16IS752.h:925
static constexpr uint8_t SC16IS750_INT_LINE
Line status interrupt enable bit.
Definition SC16IS752.h:404
uint8_t readRegister(SC16IS752_Channel channel, uint8_t reg_addr)
Reads one register byte from the selected channel via I2C or SPI.
Definition SC16IS752.h:741
void gpioLatch(uint8_t latch)
Enables or disables GPIO output latching behavior.
Definition SC16IS752.h:684
void beginChannel(SC16IS752_Channel channel, uint32_t baudrate, uint32_t config=SC16IS752_DEFAULT_CONFIG)
Initializes a specific UART channel with the given baud rate and serial configuration.
Definition SC16IS752.h:463