Skip to content

Commit 7db47ca

Browse files
committed
feat(uart): Add function to invert hardware UART Tx line
Simply clone existing Rx functionality for Tx. Allow granular control over both lines. Avoid overloading HardwareSerial::begin() to change the bool invert parameter to a bitmask type. Add an untested implementation for ESP32C6, ESP32H2, ESP32P4 that references the different register naming on those chips.
1 parent f3ae2a6 commit 7db47ca

File tree

5 files changed

+52
-4
lines changed

5 files changed

+52
-4
lines changed

cores/esp32/HardwareSerial.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,10 @@ void HardwareSerial::setRxInvert(bool invert) {
578578
uartSetRxInvert(_uart, invert);
579579
}
580580

581+
void HardwareSerial::setTxInvert(bool invert) {
582+
uartSetTxInvert(_uart, invert);
583+
}
584+
581585
// negative Pin value will keep it unmodified
582586
// can be called after or before begin()
583587
bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) {

cores/esp32/HardwareSerial.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ class HardwareSerial : public Stream {
349349
void setDebugOutput(bool);
350350

351351
void setRxInvert(bool);
352+
void setTxInvert(bool);
352353

353354
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
354355
// setPins() can be called after or before begin()

cores/esp32/esp32-hal-uart.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -827,18 +827,23 @@ void uartSetRxInvert(uart_t *uart, bool invert) {
827827
if (uart == NULL) {
828828
return;
829829
}
830-
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
831830
// POTENTIAL ISSUE :: original code only set/reset rxd_inv bit
832831
// IDF or LL set/reset the whole inv_mask!
833832
// if (invert)
834833
// ESP_ERROR_CHECK(uart_set_line_inverse(uart->num, UART_SIGNAL_RXD_INV));
835834
// else
836835
// ESP_ERROR_CHECK(uart_set_line_inverse(uart->num, UART_SIGNAL_INV_DISABLE));
837-
log_e("uartSetRxInvert is not supported in ESP32C6, ESP32H2 and ESP32P4");
838-
#else
839836
// this implementation is better over IDF API because it only affects RXD
840-
// this is supported in ESP32, ESP32-S2 and ESP32-C3
841837
uart_dev_t *hw = UART_LL_GET_HW(uart->num);
838+
839+
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
840+
if (invert) {
841+
hw->conf0_sync.rxd_inv = 1;
842+
} else {
843+
hw->conf0_sync.rxd_inv = 0;
844+
}
845+
#else
846+
// this is supported in ESP32, ESP32-S2 and ESP32-C3
842847
if (invert) {
843848
hw->conf0.rxd_inv = 1;
844849
} else {
@@ -847,6 +852,35 @@ void uartSetRxInvert(uart_t *uart, bool invert) {
847852
#endif
848853
}
849854

855+
void uartSetTxInvert(uart_t *uart, bool invert) {
856+
if (uart == NULL) {
857+
return;
858+
}
859+
// POTENTIAL ISSUE :: original code only set/reset txd_inv bit
860+
// IDF or LL set/reset the whole inv_mask!
861+
// if (invert)
862+
// ESP_ERROR_CHECK(uart_set_line_inverse(uart->num, UART_SIGNAL_TXD_INV));
863+
// else
864+
// ESP_ERROR_CHECK(uart_set_line_inverse(uart->num, UART_SIGNAL_INV_DISABLE));
865+
// this implementation is better over IDF API because it only affects TXD
866+
uart_dev_t *hw = UART_LL_GET_HW(uart->num);
867+
868+
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
869+
if (invert) {
870+
hw->conf0_sync.txd_inv = 1;
871+
} else {
872+
hw->conf0_sync.txd_inv = 0;
873+
}
874+
#else
875+
// this is supported in ESP32, ESP32-S2 and ESP32-C3
876+
if (invert) {
877+
hw->conf0.txd_inv = 1;
878+
} else {
879+
hw->conf0.txd_inv = 0;
880+
}
881+
#endif
882+
}
883+
850884
uint32_t uartAvailable(uart_t *uart) {
851885

852886
if (uart == NULL) {

cores/esp32/esp32-hal-uart.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ bool uartSetBaudRate(uart_t *uart, uint32_t baud_rate);
6262
uint32_t uartGetBaudRate(uart_t *uart);
6363

6464
void uartSetRxInvert(uart_t *uart, bool invert);
65+
void uartSetTxInvert(uart_t *uart, bool invert);
6566
bool uartSetRxTimeout(uart_t *uart, uint8_t numSymbTimeout);
6667
bool uartSetRxFIFOFull(uart_t *uart, uint8_t numBytesFIFOFull);
6768
void uartSetFastReading(uart_t *uart);

tests/validation/uart/uart.ino

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ void enabled_uart_calls_test(void) {
276276
Serial1.setRxInvert(true);
277277
Serial1.setRxInvert(false);
278278

279+
log_d("Checking if Serial 1 TX can be inverted while running");
280+
Serial1.setTxInvert(true);
281+
Serial1.setTxInvert(false);
282+
279283
Serial.println("Enabled UART calls test successful");
280284
}
281285

@@ -351,6 +355,10 @@ void disabled_uart_calls_test(void) {
351355
Serial1.setRxInvert(true);
352356
Serial1.setRxInvert(false);
353357

358+
log_d("Checking if Serial 1 TX can be inverted when stopped");
359+
Serial1.setTxInvert(true);
360+
Serial1.setTxInvert(false);
361+
354362
Serial.println("Disabled UART calls test successful");
355363
}
356364

0 commit comments

Comments
 (0)