ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
uart_component_libretiny.cpp
Go to the documentation of this file.
1#ifdef USE_LIBRETINY
2
6#include "esphome/core/log.h"
8
9#ifdef USE_LOGGER
11#endif
12
13#if LT_ARD_HAS_SOFTSERIAL
14#include <SoftwareSerial.h>
15#endif
16
17namespace esphome::uart {
18
19static const char *const TAG = "uart.lt";
20
21static const char *const UART_TYPE[] = {
22 "hardware",
23 "software",
24};
25
27 uint16_t config = 0;
28
29 switch (this->parity_) {
31 config |= SERIAL_PARITY_NONE;
32 break;
34 config |= SERIAL_PARITY_EVEN;
35 break;
37 config |= SERIAL_PARITY_ODD;
38 break;
39 }
40
41 config |= (this->data_bits_ - 4) << 8;
42 config |= 0x10 + (this->stop_bits_ - 1) * 0x20;
43
44 return config;
45}
46
48 int16_t tx_pin = tx_pin_ == nullptr ? -1 : tx_pin_->get_pin();
49 int16_t rx_pin = rx_pin_ == nullptr ? -1 : rx_pin_->get_pin();
50
51 auto should_fallback_to_software_serial = [&]() -> bool {
52 auto has_flags = [](InternalGPIOPin *pin, const gpio::Flags mask) -> bool {
53 return pin && (pin->get_flags() & mask) != gpio::Flags::FLAG_NONE;
54 };
55 if (has_flags(this->tx_pin_,
57 has_flags(this->rx_pin_,
59#if LT_ARD_HAS_SOFTSERIAL
60 ESP_LOGI(TAG, "Pins have flags set. Using Software Serial");
61 return true;
62#else
63 ESP_LOGW(TAG, "Pin flags are set but not supported for hardware serial. Ignoring");
64#endif
65 }
66 return false;
67 };
68
69 if (false) { // NOLINT(readability-simplify-boolean-expr)
70 return;
71 }
72#if LT_HW_UART0
73 else if ((tx_pin == -1 || tx_pin == PIN_SERIAL0_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL0_RX) &&
74 !should_fallback_to_software_serial()) {
75 this->serial_ = &Serial0;
76 this->hardware_idx_ = 0;
77 }
78#endif
79#if LT_HW_UART1
80 else if ((tx_pin == -1 || tx_pin == PIN_SERIAL1_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL1_RX) &&
81 !should_fallback_to_software_serial()) {
82 this->serial_ = &Serial1;
83 this->hardware_idx_ = 1;
84 }
85#endif
86#if LT_HW_UART2
87 else if ((tx_pin == -1 || tx_pin == PIN_SERIAL2_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL2_RX) &&
88 !should_fallback_to_software_serial()) {
89 this->serial_ = &Serial2;
90 this->hardware_idx_ = 2;
91 }
92#endif
93 else {
94#if LT_ARD_HAS_SOFTSERIAL
95 if (this->rx_pin_) {
96 this->rx_pin_->setup();
97 }
98 if (this->tx_pin_ && this->rx_pin_ != this->tx_pin_) {
99 this->tx_pin_->setup();
100 }
101 bool tx_inverted = tx_pin_ != nullptr && tx_pin_->is_inverted();
102 bool rx_inverted = rx_pin_ != nullptr && rx_pin_->is_inverted();
103 this->serial_ = new SoftwareSerial(rx_pin, tx_pin, rx_inverted || tx_inverted);
104#else
105 this->serial_ = &Serial;
106 ESP_LOGE(TAG, " SoftwareSerial is not implemented for this chip. Only hardware pins are supported:");
107#if LT_HW_UART0
108 ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL0_TX, PIN_SERIAL0_RX);
109#endif
110#if LT_HW_UART1
111 ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL1_TX, PIN_SERIAL1_RX);
112#endif
113#if LT_HW_UART2
114 ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL2_TX, PIN_SERIAL2_RX);
115#endif
116 this->mark_failed(LOG_STR("SoftwareSerial is not implemented for this chip."));
117 return;
118#endif
119 }
120
121 this->serial_->begin(this->baud_rate_, get_config());
122}
123
125 bool is_software = this->hardware_idx_ == -1;
126 ESP_LOGCONFIG(TAG,
127 "UART Bus:\n"
128 " Type: %s",
129 UART_TYPE[is_software]);
130 if (!is_software) {
131 ESP_LOGCONFIG(TAG, " Port number: %d", this->hardware_idx_);
132 }
133 LOG_PIN(" TX Pin: ", tx_pin_);
134 LOG_PIN(" RX Pin: ", rx_pin_);
135 if (this->rx_pin_ != nullptr) {
136 ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
137 }
138 ESP_LOGCONFIG(TAG,
139 " Baud Rate: %" PRIu32 " baud\n"
140 " Data Bits: %u\n"
141 " Parity: %s\n"
142 " Stop bits: %u",
143 this->baud_rate_, this->data_bits_, LOG_STR_ARG(parity_to_str(this->parity_)), this->stop_bits_);
144 this->check_logger_conflict();
145}
146
147void LibreTinyUARTComponent::write_array(const uint8_t *data, size_t len) {
148 this->serial_->write(data, len);
149#ifdef USE_UART_DEBUGGER
150 for (size_t i = 0; i < len; i++) {
151 this->debug_callback_.call(UART_DIRECTION_TX, data[i]);
152 }
153#endif
154}
155
157 if (!this->check_read_timeout_())
158 return false;
159 *data = this->serial_->peek();
160 return true;
161}
162
163bool LibreTinyUARTComponent::read_array(uint8_t *data, size_t len) {
164 if (!this->check_read_timeout_(len))
165 return false;
166 this->serial_->readBytes(data, len);
167#ifdef USE_UART_DEBUGGER
168 for (size_t i = 0; i < len; i++) {
169 this->debug_callback_.call(UART_DIRECTION_RX, data[i]);
170 }
171#endif
172 return true;
173}
174
175size_t LibreTinyUARTComponent::available() { return this->serial_->available(); }
177 ESP_LOGVV(TAG, " Flushing");
178 this->serial_->flush();
180}
181
183#ifdef USE_LOGGER
184 if (this->hardware_idx_ == -1 || logger::global_logger->get_baud_rate() == 0) {
185 return;
186 }
187
189 ESP_LOGW(TAG, " You're using the same serial port for logging and the UART component. Please "
190 "disable logging over the serial port by setting logger->baud_rate to 0.");
191 }
192#endif
193}
194
195} // namespace esphome::uart
196#endif // USE_LIBRETINY
void mark_failed()
Mark this component as failed.
virtual void setup()=0
virtual gpio::Flags get_flags() const =0
Retrieve GPIO pin flags.
virtual uint8_t get_pin() const =0
virtual bool is_inverted() const =0
bool read_array(uint8_t *data, size_t len) override
void write_array(const uint8_t *data, size_t len) override
bool check_read_timeout_(size_t len=1)
CallbackManager< void(UARTDirection, uint8_t)> debug_callback_
@ FLAG_OPEN_DRAIN
Definition gpio.h:27
@ FLAG_NONE
Definition gpio.h:24
@ FLAG_PULLUP
Definition gpio.h:28
@ FLAG_PULLDOWN
Definition gpio.h:29
Logger * global_logger
Definition logger.cpp:279
const char *const TAG
Definition spi.cpp:7
const LogString * parity_to_str(UARTParityOptions parity)
Definition uart.cpp:36
UARTFlushResult
Result of a flush() call.
@ UART_FLUSH_RESULT_ASSUMED_SUCCESS
Platform cannot report result; success is assumed.
const void size_t len
Definition hal.h:64