3#include <esp8266_peri.h>
8#ifdef USE_UART_WAKE_LOOP_ON_RX
20static constexpr uint32_t SW_SERIAL_EDGE_MODE_MAX_BAUD = 19200;
23static constexpr uint32_t RX_TICKS_PER_SECOND = 16000000;
25bool ESP8266UartComponent::serial0_in_use =
false;
27bool ESP8266UartComponent::serial0_swapped =
false;
33 config |= UART_PARITY_NONE;
35 config |= UART_PARITY_EVEN;
37 config |= UART_PARITY_ODD;
42 config |= UART_NB_BIT_5;
45 config |= UART_NB_BIT_6;
48 config |= UART_NB_BIT_7;
51 config |= UART_NB_BIT_8;
56 config |= UART_NB_STOP_BIT_1;
58 config |= UART_NB_STOP_BIT_2;
80 setup_pin_if_needed(this->
rx_pin_);
82 setup_pin_if_needed(this->
tx_pin_);
88 SerialConfig config =
static_cast<SerialConfig
>(
get_config());
90#ifdef USE_ESP8266_UART_SERIAL
102 ESP8266UartComponent::serial0_in_use =
true;
103 }
else if (!ESP8266UartComponent::serial0_in_use && (
tx_pin_ ==
nullptr ||
tx_pin_->
get_pin() == 15) &&
115 ESP8266UartComponent::serial0_in_use =
true;
116 ESP8266UartComponent::serial0_swapped =
true;
119#ifdef USE_ESP8266_UART_SERIAL1
134 ESP_LOGCONFIG(TAG,
"Loading UART bus settings");
136 SerialConfig config =
static_cast<SerialConfig
>(
get_config());
139#ifdef USE_ESP8266_UART_SERIAL
141 if (this->
hw_serial_ == &Serial && ESP8266UartComponent::serial0_swapped)
149 ESP_LOGCONFIG(TAG,
"UART bus was reloaded.");
155 ESP_LOGCONFIG(TAG,
"UART Bus:");
156 LOG_PIN(
" TX Pin: ", this->
tx_pin_);
157 LOG_PIN(
" RX Pin: ", this->
rx_pin_);
158 if (this->
rx_pin_ !=
nullptr) {
162 " Baud Rate: %u baud\n"
168 ESP_LOGCONFIG(TAG,
" Using hardware serial interface.");
170 ESP_LOGCONFIG(TAG,
" Using software serial"
171#ifdef USE_UART_WAKE_LOOP_ON_RX
172 "\n Wake on data RX: ENABLED"
175 if (this->
rx_pin_ !=
nullptr) {
176 ESP_LOGCONFIG(TAG,
" RX decoder: %s",
177 this->
baud_rate_ <= SW_SERIAL_EDGE_MODE_MAX_BAUD ? LOG_STR_LITERAL(
"edge")
178 : LOG_STR_LITERAL(
"start bit sampler"));
191 ESP_LOGW(TAG,
" You're using the same serial port for logging and the UART component. Please "
192 "disable logging over the serial port by setting logger->baud_rate to 0.");
201 for (
size_t i = 0; i <
len; i++)
204#ifdef USE_UART_DEBUGGER
205 for (
size_t i = 0; i <
len; i++) {
226 for (
size_t i = 0; i <
len; i++)
229#ifdef USE_UART_DEBUGGER
230 for (
size_t i = 0; i <
len; i++) {
250 ESP_LOGVV(TAG,
" Flushing");
260 size_t rx_buffer_size) {
269 if (tx_pin !=
nullptr) {
276 if (rx_pin !=
nullptr) {
284 buffer =
new uint8_t[rx_buffer_size];
287 stop_bits,
buffer, rx_buffer_size);
289 if (baud_rate <= SW_SERIAL_EDGE_MODE_MAX_BAUD) {
299#if F_CPU != 160000000L
301 return bit_time << (CPU2X & 1);
309 uint32_t wait = bit_time + bit_time / 3 - 500;
314 rec |= arg->
read_bit_(&wait, start, bit_time) << i;
322 arg->
wait_(&wait, start, bit_time);
324 arg->
wait_(&wait, start, bit_time);
329#ifdef USE_UART_WAKE_LOOP_ON_RX
339 [[maybe_unused]]
const bool wake = arg->
rx_.
on_edge(now, level);
340#ifdef USE_UART_WAKE_LOOP_ON_RX
347#ifdef USE_UART_WAKE_LOOP_ON_RX
359 ESP_LOGE(TAG,
"UART doesn't have TX pins set!");
362 bool parity_bit =
false;
363 bool need_parity_bit =
true;
369 need_parity_bit =
false;
379 this->
write_bit_(
false, &wait, start, bit_time);
381 bool bit = data & (1 << i);
382 this->
write_bit_(bit, &wait, start, bit_time);
387 this->
write_bit_(parity_bit, &wait, start, bit_time);
389 this->
write_bit_(
true, &wait, start, bit_time);
391 this->
wait_(&wait, start, bit_time);
400 this->
wait_(wait, start, bit_time);
405 this->
wait_(wait, start, bit_time);
void digital_write(bool value)
Helper class to disable interrupts.
void attach_interrupt(void(*func)(T *), T *arg, gpio::InterruptType type) const
void detach_interrupt() const
ISRInternalGPIOPin to_isr() const
Stream * get_hw_serial() const
UARTSelection get_uart() const
Get the UART used by the logger.
void rx_finalize_pending_()
UARTParityOptions parity_
void write_bit_(bool bit, uint32_t *wait, const uint32_t &start, uint32_t bit_time)
SoftwareSerialRxDecoder rx_
static void gpio_intr_edge(ESP8266SoftwareSerial *arg)
void ESPHOME_ALWAYS_INLINE rx_sync_()
bool read_bit_(uint32_t *wait, const uint32_t &start, uint32_t bit_time)
ISRInternalGPIOPin rx_pin_
void wait_(uint32_t *wait, const uint32_t &start, uint32_t bit_time)
void setup(InternalGPIOPin *tx_pin, InternalGPIOPin *rx_pin, uint32_t baud_rate, uint8_t stop_bits, uint32_t data_bits, UARTParityOptions parity, size_t rx_buffer_size)
InternalGPIOPin * gpio_tx_pin_
InternalGPIOPin * gpio_rx_pin_
static void gpio_intr(ESP8266SoftwareSerial *arg)
Above SW_SERIAL_EDGE_MODE_MAX_BAUD; reads the whole byte in the ISR.
void write_byte(uint8_t data)
ISRInternalGPIOPin tx_pin_
size_t available() override
size_t available_for_write() override
void load_settings()
Load the UART settings.
void check_logger_conflict() override
bool peek_byte(uint8_t *data) override
bool read_array(uint8_t *data, size_t len) override
void dump_config() override
HardwareSerial * hw_serial_
UARTFlushResult flush() override
void write_array(const uint8_t *data, size_t len) override
ESP8266SoftwareSerial * sw_serial_
bool finalize_due(uint32_t now) const
void finalize(uint32_t now)
Call with the ISR masked.
size_t buffer_size() const
void setup(uint32_t bit_ticks, uint8_t data_bits, bool parity, uint8_t stop_bits, uint8_t *buffer, size_t buffer_size)
Configure framing and buffer; drops all state. Follow with reset().
bool ESPHOME_ALWAYS_INLINE on_edge(uint32_t now, bool level)
ISR.
uint8_t peek_byte() const
void reset(uint32_t now, bool level)
Forget any partial frame; level is the current line level.
bool ESPHOME_ALWAYS_INLINE push_byte(uint8_t data)
Drops the byte when full; holds buffer_size - 1 bytes.
UARTParityOptions parity_
bool check_read_timeout_(size_t len=1)
InternalGPIOPin * tx_pin_
uint32_t get_baud_rate() const
CallbackManager< void(UARTDirection, uint8_t)> debug_callback_
InternalGPIOPin * rx_pin_
struct @66::@67 __attribute__
Wake the main loop task from an ISR. ISR-safe.
@ UART_SELECTION_UART0_SWAP
ESPHOME_LOG_TAG(TAG, "uart.binary_sensor")
const LogString * parity_to_str(UARTParityOptions parity)
@ UART_CONFIG_PARITY_EVEN
@ UART_CONFIG_PARITY_NONE
UARTFlushResult
Result of a flush() call.
@ UART_FLUSH_RESULT_ASSUMED_SUCCESS
Platform cannot report result; success is assumed.
uint32_t arch_get_cpu_cycle_count()
void wake_loop_threadsafe()
Non-ISR: always inline.
uint32_t IRAM_ATTR HOT micros()
void ESPHOME_ALWAYS_INLINE wake_loop_isrsafe()
ISR-safe: no task_woken arg because ESP8266 has no FreeRTOS. Caller must be IRAM_ATTR.
Platform-specific main loop wake primitives.