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