From 52b688416aeeaefe8b5faa4712307ea5f147339c Mon Sep 17 00:00:00 2001 From: Pavlo Dudnytskyi Date: Thu, 11 Jul 2024 18:04:22 +0200 Subject: [PATCH] Removed accidently added uart --- components/uart/__init__.py | 440 ------------------ components/uart/automation.h | 38 -- components/uart/button/__init__.py | 35 -- components/uart/button/uart_button.cpp | 17 - components/uart/button/uart_button.h | 24 - components/uart/switch/__init__.py | 58 --- components/uart/switch/uart_switch.cpp | 61 --- components/uart/switch/uart_switch.h | 35 -- components/uart/uart.cpp | 47 -- components/uart/uart.h | 72 --- components/uart/uart_component.cpp | 24 - components/uart/uart_component.h | 175 ------- .../uart/uart_component_esp32_arduino.cpp | 213 --------- .../uart/uart_component_esp32_arduino.h | 60 --- components/uart/uart_component_esp8266.cpp | 320 ------------- components/uart/uart_component_esp8266.h | 94 ---- components/uart/uart_component_esp_idf.cpp | 248 ---------- components/uart/uart_component_esp_idf.h | 58 --- components/uart/uart_component_host.cpp | 295 ------------ components/uart/uart_component_host.h | 38 -- components/uart/uart_component_libretiny.cpp | 168 ------- components/uart/uart_component_libretiny.h | 43 -- components/uart/uart_component_rp2040.cpp | 184 -------- components/uart/uart_component_rp2040.h | 46 -- components/uart/uart_debugger.cpp | 202 -------- components/uart/uart_debugger.h | 101 ---- 26 files changed, 3096 deletions(-) delete mode 100644 components/uart/__init__.py delete mode 100644 components/uart/automation.h delete mode 100644 components/uart/button/__init__.py delete mode 100644 components/uart/button/uart_button.cpp delete mode 100644 components/uart/button/uart_button.h delete mode 100644 components/uart/switch/__init__.py delete mode 100644 components/uart/switch/uart_switch.cpp delete mode 100644 components/uart/switch/uart_switch.h delete mode 100644 components/uart/uart.cpp delete mode 100644 components/uart/uart.h delete mode 100644 components/uart/uart_component.cpp delete mode 100644 components/uart/uart_component.h delete mode 100644 components/uart/uart_component_esp32_arduino.cpp delete mode 100644 components/uart/uart_component_esp32_arduino.h delete mode 100644 components/uart/uart_component_esp8266.cpp delete mode 100644 components/uart/uart_component_esp8266.h delete mode 100644 components/uart/uart_component_esp_idf.cpp delete mode 100644 components/uart/uart_component_esp_idf.h delete mode 100644 components/uart/uart_component_host.cpp delete mode 100644 components/uart/uart_component_host.h delete mode 100644 components/uart/uart_component_libretiny.cpp delete mode 100644 components/uart/uart_component_libretiny.h delete mode 100644 components/uart/uart_component_rp2040.cpp delete mode 100644 components/uart/uart_component_rp2040.h delete mode 100644 components/uart/uart_debugger.cpp delete mode 100644 components/uart/uart_debugger.h diff --git a/components/uart/__init__.py b/components/uart/__init__.py deleted file mode 100644 index 2e6fa7e..0000000 --- a/components/uart/__init__.py +++ /dev/null @@ -1,440 +0,0 @@ -from typing import Optional -import re -import esphome.codegen as cg -import esphome.config_validation as cv -import esphome.final_validate as fv -from esphome.yaml_util import make_data_base -from esphome import pins, automation -from esphome.const import ( - CONF_BAUD_RATE, - CONF_ID, - CONF_NUMBER, - CONF_RX_PIN, - CONF_TX_PIN, - CONF_PORT, - CONF_UART_ID, - CONF_DATA, - CONF_RX_BUFFER_SIZE, - CONF_INVERTED, - CONF_INVERT, - CONF_TRIGGER_ID, - CONF_SEQUENCE, - CONF_TIMEOUT, - CONF_DEBUG, - CONF_DIRECTION, - CONF_AFTER, - CONF_BYTES, - CONF_DELIMITER, - CONF_DUMMY_RECEIVER, - CONF_DUMMY_RECEIVER_ID, - CONF_LAMBDA, - PLATFORM_HOST, -) -from esphome.core import CORE - -CODEOWNERS = ["@esphome/core"] -uart_ns = cg.esphome_ns.namespace("uart") -UARTComponent = uart_ns.class_("UARTComponent") - -IDFUARTComponent = uart_ns.class_("IDFUARTComponent", UARTComponent, cg.Component) -ESP32ArduinoUARTComponent = uart_ns.class_( - "ESP32ArduinoUARTComponent", UARTComponent, cg.Component -) -ESP8266UartComponent = uart_ns.class_( - "ESP8266UartComponent", UARTComponent, cg.Component -) -RP2040UartComponent = uart_ns.class_("RP2040UartComponent", UARTComponent, cg.Component) -LibreTinyUARTComponent = uart_ns.class_( - "LibreTinyUARTComponent", UARTComponent, cg.Component -) -HostUartComponent = uart_ns.class_("HostUartComponent", UARTComponent, cg.Component) - -NATIVE_UART_CLASSES = ( - str(IDFUARTComponent), - str(ESP32ArduinoUARTComponent), - str(ESP8266UartComponent), - str(RP2040UartComponent), - str(LibreTinyUARTComponent), -) - -HOST_BAUD_RATES = [ - 50, - 75, - 110, - 134, - 150, - 200, - 300, - 600, - 1200, - 1800, - 2400, - 4800, - 9600, - 19200, - 38400, - 57600, - 115200, - 230400, - 460800, - 500000, - 576000, - 921600, - 1000000, - 1152000, - 1500000, - 2000000, - 2500000, - 3000000, - 3500000, - 4000000, -] - -UARTDevice = uart_ns.class_("UARTDevice") -UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action) -UARTDebugger = uart_ns.class_("UARTDebugger", cg.Component, automation.Action) -UARTDummyReceiver = uart_ns.class_("UARTDummyReceiver", cg.Component) -MULTI_CONF = True -MULTI_CONF_NO_DEFAULT = True - - -def validate_raw_data(value): - if isinstance(value, str): - return value.encode("utf-8") - if isinstance(value, str): - return value - if isinstance(value, list): - return cv.Schema([cv.hex_uint8_t])(value) - raise cv.Invalid( - "data must either be a string wrapped in quotes or a list of bytes" - ) - - -def validate_rx_pin(value): - value = pins.internal_gpio_input_pin_schema(value) - if CORE.is_esp8266 and value[CONF_NUMBER] >= 16: - raise cv.Invalid("Pins GPIO16 and GPIO17 cannot be used as RX pins on ESP8266.") - return value - - -def validate_invert_esp32(config): - if ( - CORE.is_esp32 - and CORE.using_arduino - and CONF_TX_PIN in config - and CONF_RX_PIN in config - and config[CONF_TX_PIN][CONF_INVERTED] != config[CONF_RX_PIN][CONF_INVERTED] - ): - raise cv.Invalid( - "Different invert values for TX and RX pin are not supported for ESP32 when using Arduino." - ) - return config - - -def validate_host_config(config): - if CORE.is_host: - if CONF_TX_PIN in config or CONF_RX_PIN in config: - raise cv.Invalid( - "TX and RX pins are not supported for UART on host platform." - ) - if config[CONF_BAUD_RATE] not in HOST_BAUD_RATES: - raise cv.Invalid( - f"Host platform doesn't support baud rate {config[CONF_BAUD_RATE]}", - path=[CONF_BAUD_RATE], - ) - return config - - -def _uart_declare_type(value): - if CORE.is_esp8266: - return cv.declare_id(ESP8266UartComponent)(value) - if CORE.is_esp32: - if CORE.using_arduino: - return cv.declare_id(ESP32ArduinoUARTComponent)(value) - if CORE.using_esp_idf: - return cv.declare_id(IDFUARTComponent)(value) - if CORE.is_rp2040: - return cv.declare_id(RP2040UartComponent)(value) - if CORE.is_libretiny: - return cv.declare_id(LibreTinyUARTComponent)(value) - if CORE.is_host: - return cv.declare_id(HostUartComponent)(value) - raise NotImplementedError - - -UARTParityOptions = uart_ns.enum("UARTParityOptions") -UART_PARITY_OPTIONS = { - "NONE": UARTParityOptions.UART_CONFIG_PARITY_NONE, - "EVEN": UARTParityOptions.UART_CONFIG_PARITY_EVEN, - "ODD": UARTParityOptions.UART_CONFIG_PARITY_ODD, -} - -CONF_STOP_BITS = "stop_bits" -CONF_DATA_BITS = "data_bits" -CONF_PARITY = "parity" - -UARTDirection = uart_ns.enum("UARTDirection") -UART_DIRECTIONS = { - "RX": UARTDirection.UART_DIRECTION_RX, - "TX": UARTDirection.UART_DIRECTION_TX, - "BOTH": UARTDirection.UART_DIRECTION_BOTH, -} - -# The reason for having CONF_BYTES at 150 by default: -# -# The log message buffer size is 512 bytes by default. About 35 bytes are -# used for the log prefix. That leaves us with 477 bytes for logging data. -# The default log output is hex, which uses 3 characters per represented -# byte (2 hex chars + 1 separator). That means that 477 / 3 = 159 bytes -# can be represented in a single log line. Using 150, because people love -# round numbers. -AFTER_DEFAULTS = {CONF_BYTES: 150, CONF_TIMEOUT: "100ms"} - -# By default, log in hex format when no specific sequence is provided. -DEFAULT_DEBUG_OUTPUT = "UARTDebug::log_hex(direction, bytes, ':');" -DEFAULT_SEQUENCE = [{CONF_LAMBDA: make_data_base(DEFAULT_DEBUG_OUTPUT)}] - - -def maybe_empty_debug(value): - if value is None: - value = {} - return DEBUG_SCHEMA(value) - - -def validate_port(value): - if not re.match(r"^\/dev\/(?:tty|cu|(?:pts\/)).+$", value): - raise cv.Invalid("Port must be a valid Linux device path") - return value - - -DEBUG_SCHEMA = cv.Schema( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UARTDebugger), - cv.Optional(CONF_DIRECTION, default="BOTH"): cv.enum( - UART_DIRECTIONS, upper=True - ), - cv.Optional(CONF_AFTER, default=AFTER_DEFAULTS): cv.Schema( - { - cv.Optional( - CONF_BYTES, default=AFTER_DEFAULTS[CONF_BYTES] - ): cv.validate_bytes, - cv.Optional( - CONF_TIMEOUT, default=AFTER_DEFAULTS[CONF_TIMEOUT] - ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_DELIMITER): cv.templatable(validate_raw_data), - } - ), - cv.Optional( - CONF_SEQUENCE, default=DEFAULT_SEQUENCE - ): automation.validate_automation(), - cv.Optional(CONF_DUMMY_RECEIVER, default=False): cv.boolean, - cv.GenerateID(CONF_DUMMY_RECEIVER_ID): cv.declare_id(UARTDummyReceiver), - } -) - -CONFIG_SCHEMA = cv.All( - cv.Schema( - { - cv.GenerateID(): _uart_declare_type, - cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), - cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_RX_PIN): validate_rx_pin, - cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)), - cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, - cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), - cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), - cv.Optional(CONF_PARITY, default="NONE"): cv.enum( - UART_PARITY_OPTIONS, upper=True - ), - cv.Optional(CONF_INVERT): cv.invalid( - "This option has been removed. Please instead use invert in the tx/rx pin schemas." - ), - cv.Optional(CONF_DEBUG): maybe_empty_debug, - } - ).extend(cv.COMPONENT_SCHEMA), - cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT), - validate_invert_esp32, - validate_host_config, -) - - -async def debug_to_code(config, parent): - trigger = cg.new_Pvariable(config[CONF_TRIGGER_ID], parent) - await cg.register_component(trigger, config) - for action in config[CONF_SEQUENCE]: - await automation.build_automation( - trigger, - [(UARTDirection, "direction"), (cg.std_vector.template(cg.uint8), "bytes")], - action, - ) - cg.add(trigger.set_direction(config[CONF_DIRECTION])) - after = config[CONF_AFTER] - cg.add(trigger.set_after_bytes(after[CONF_BYTES])) - cg.add(trigger.set_after_timeout(after[CONF_TIMEOUT])) - if CONF_DELIMITER in after: - data = after[CONF_DELIMITER] - if isinstance(data, bytes): - data = list(data) - for byte in after[CONF_DELIMITER]: - cg.add(trigger.add_delimiter_byte(byte)) - if config[CONF_DUMMY_RECEIVER]: - dummy = cg.new_Pvariable(config[CONF_DUMMY_RECEIVER_ID], parent) - await cg.register_component(dummy, {}) - cg.add_define("USE_UART_DEBUGGER") - - -async def to_code(config): - cg.add_global(uart_ns.using) - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - - cg.add(var.set_baud_rate(config[CONF_BAUD_RATE])) - - if CONF_TX_PIN in config: - tx_pin = await cg.gpio_pin_expression(config[CONF_TX_PIN]) - cg.add(var.set_tx_pin(tx_pin)) - if CONF_RX_PIN in config: - rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN]) - cg.add(var.set_rx_pin(rx_pin)) - if CONF_PORT in config: - cg.add(var.set_name(config[CONF_PORT])) - cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE])) - cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) - cg.add(var.set_data_bits(config[CONF_DATA_BITS])) - cg.add(var.set_parity(config[CONF_PARITY])) - - if CONF_DEBUG in config: - await debug_to_code(config[CONF_DEBUG], var) - - -# A schema to use for all UART devices, all UART integrations must extend this! -UART_DEVICE_SCHEMA = cv.Schema( - { - cv.GenerateID(CONF_UART_ID): cv.use_id(UARTComponent), - } -) - -KEY_UART_DEVICES = "uart_devices" - - -def final_validate_device_schema( - name: str, - *, - uart_bus: str = CONF_UART_ID, - baud_rate: Optional[int] = None, - require_tx: bool = False, - require_rx: bool = False, - data_bits: Optional[int] = None, - parity: Optional[str] = None, - stop_bits: Optional[int] = None, -): - def validate_baud_rate(value): - if value != baud_rate: - raise cv.Invalid( - f"Component {name} requires baud rate {baud_rate} for the uart referenced by {uart_bus}" - ) - return value - - def validate_pin(opt, device): - def validator(value): - if opt in device: - raise cv.Invalid( - f"The uart {opt} is used both by {name} and {device[opt]}, " - f"but can only be used by one. Please create a new uart bus for {name}." - ) - device[opt] = name - return value - - return validator - - def validate_data_bits(value): - if value != data_bits: - raise cv.Invalid( - f"Component {name} requires {data_bits} data bits for the uart referenced by {uart_bus}" - ) - return value - - def validate_parity(value): - if value != parity: - raise cv.Invalid( - f"Component {name} requires parity {parity} for the uart referenced by {uart_bus}" - ) - return value - - def validate_stop_bits(value): - if value != stop_bits: - raise cv.Invalid( - f"Component {name} requires {stop_bits} stop bits for the uart referenced by {uart_bus}" - ) - return value - - def validate_hub(hub_config): - hub_schema = {} - uart_id = hub_config[CONF_ID] - uart_id_type_str = str(uart_id.type) - devices = fv.full_config.get().data.setdefault(KEY_UART_DEVICES, {}) - device = devices.setdefault(uart_id, {}) - - if require_tx and uart_id_type_str in NATIVE_UART_CLASSES: - hub_schema[ - cv.Required( - CONF_TX_PIN, - msg=f"Component {name} requires uart referenced by {uart_bus} to declare a tx_pin", - ) - ] = validate_pin(CONF_TX_PIN, device) - if require_rx and uart_id_type_str in NATIVE_UART_CLASSES: - hub_schema[ - cv.Required( - CONF_RX_PIN, - msg=f"Component {name} requires uart referenced by {uart_bus} to declare a rx_pin", - ) - ] = validate_pin(CONF_RX_PIN, device) - if baud_rate is not None: - hub_schema[cv.Required(CONF_BAUD_RATE)] = validate_baud_rate - if data_bits is not None: - hub_schema[cv.Required(CONF_DATA_BITS)] = validate_data_bits - if parity is not None: - hub_schema[cv.Required(CONF_PARITY)] = validate_parity - if stop_bits is not None: - hub_schema[cv.Required(CONF_STOP_BITS)] = validate_stop_bits - return cv.Schema(hub_schema, extra=cv.ALLOW_EXTRA)(hub_config) - - return cv.Schema( - {cv.Required(uart_bus): fv.id_declaration_match_schema(validate_hub)}, - extra=cv.ALLOW_EXTRA, - ) - - -async def register_uart_device(var, config): - """Register a UART device, setting up all the internal values. - - This is a coroutine, you need to await it with a 'yield' expression! - """ - parent = await cg.get_variable(config[CONF_UART_ID]) - cg.add(var.set_uart_parent(parent)) - - -@automation.register_action( - "uart.write", - UARTWriteAction, - cv.maybe_simple_value( - { - cv.GenerateID(): cv.use_id(UARTComponent), - cv.Required(CONF_DATA): cv.templatable(validate_raw_data), - }, - key=CONF_DATA, - ), -) -async def uart_write_to_code(config, action_id, template_arg, args): - var = cg.new_Pvariable(action_id, template_arg) - await cg.register_parented(var, config[CONF_ID]) - data = config[CONF_DATA] - if isinstance(data, bytes): - data = list(data) - - if cg.is_template(data): - templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) - cg.add(var.set_data_template(templ)) - else: - cg.add(var.set_data_static(data)) - return var diff --git a/components/uart/automation.h b/components/uart/automation.h deleted file mode 100644 index b6a50ea..0000000 --- a/components/uart/automation.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "uart.h" -#include "esphome/core/automation.h" - -#include - -namespace esphome { -namespace uart { - -template class UARTWriteAction : public Action, public Parented { - public: - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; - this->static_ = false; - } - void set_data_static(const std::vector &data) { - this->data_static_ = data; - this->static_ = true; - } - - void play(Ts... x) override { - if (this->static_) { - this->parent_->write_array(this->data_static_); - } else { - auto val = this->data_func_(x...); - this->parent_->write_array(val); - } - } - - protected: - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; -}; - -} // namespace uart -} // namespace esphome diff --git a/components/uart/button/__init__.py b/components/uart/button/__init__.py deleted file mode 100644 index 0590951..0000000 --- a/components/uart/button/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import button, uart -from esphome.const import CONF_DATA -from esphome.core import HexInt -from .. import uart_ns, validate_raw_data - -CODEOWNERS = ["@ssieb"] - -DEPENDENCIES = ["uart"] - -UARTButton = uart_ns.class_("UARTButton", button.Button, uart.UARTDevice, cg.Component) - - -CONFIG_SCHEMA = ( - button.button_schema(UARTButton) - .extend( - { - cv.Required(CONF_DATA): validate_raw_data, - } - ) - .extend(uart.UART_DEVICE_SCHEMA) - .extend(cv.COMPONENT_SCHEMA) -) - - -async def to_code(config): - var = await button.new_button(config) - await cg.register_component(var, config) - await uart.register_uart_device(var, config) - - data = config[CONF_DATA] - if isinstance(data, bytes): - data = [HexInt(x) for x in data] - cg.add(var.set_data(data)) diff --git a/components/uart/button/uart_button.cpp b/components/uart/button/uart_button.cpp deleted file mode 100644 index 4db164c..0000000 --- a/components/uart/button/uart_button.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "uart_button.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart.button"; - -void UARTButton::press_action() { - ESP_LOGD(TAG, "'%s': Sending data...", this->get_name().c_str()); - this->write_array(this->data_.data(), this->data_.size()); -} - -void UARTButton::dump_config() { LOG_BUTTON("", "UART Button", this); } - -} // namespace uart -} // namespace esphome diff --git a/components/uart/button/uart_button.h b/components/uart/button/uart_button.h deleted file mode 100644 index 2d600b1..0000000 --- a/components/uart/button/uart_button.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/uart/uart.h" -#include "esphome/components/button/button.h" - -#include - -namespace esphome { -namespace uart { - -class UARTButton : public button::Button, public UARTDevice, public Component { - public: - void set_data(const std::vector &data) { this->data_ = data; } - - void dump_config() override; - - protected: - void press_action() override; - std::vector data_; -}; - -} // namespace uart -} // namespace esphome diff --git a/components/uart/switch/__init__.py b/components/uart/switch/__init__.py deleted file mode 100644 index 8853a61..0000000 --- a/components/uart/switch/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import switch, uart -from esphome.const import CONF_DATA, CONF_SEND_EVERY -from esphome.core import HexInt -from .. import uart_ns, validate_raw_data - -DEPENDENCIES = ["uart"] - -UARTSwitch = uart_ns.class_("UARTSwitch", switch.Switch, uart.UARTDevice, cg.Component) - -CONF_TURN_OFF = "turn_off" -CONF_TURN_ON = "turn_on" - -CONFIG_SCHEMA = ( - switch.switch_schema(UARTSwitch, block_inverted=True) - .extend( - { - cv.Required(CONF_DATA): cv.Any( - validate_raw_data, - cv.Schema( - { - cv.Optional(CONF_TURN_OFF): validate_raw_data, - cv.Optional(CONF_TURN_ON): validate_raw_data, - } - ), - ), - cv.Optional(CONF_SEND_EVERY): cv.positive_time_period_milliseconds, - }, - ) - .extend(uart.UART_DEVICE_SCHEMA) - .extend(cv.COMPONENT_SCHEMA) -) - - -async def to_code(config): - var = await switch.new_switch(config) - await cg.register_component(var, config) - await uart.register_uart_device(var, config) - - data = config[CONF_DATA] - if isinstance(data, dict): - if data_on := data.get(CONF_TURN_ON): - if isinstance(data_on, bytes): - data_on = [HexInt(x) for x in data_on] - cg.add(var.set_data_on(data_on)) - if data_off := data.get(CONF_TURN_OFF): - if isinstance(data_off, bytes): - data_off = [HexInt(x) for x in data_off] - cg.add(var.set_data_off(data_off)) - else: - data = config[CONF_DATA] - if isinstance(data, bytes): - data = [HexInt(x) for x in data] - cg.add(var.set_data_on(data)) - cg.add(var.set_single_state(True)) - if CONF_SEND_EVERY in config: - cg.add(var.set_send_every(config[CONF_SEND_EVERY])) diff --git a/components/uart/switch/uart_switch.cpp b/components/uart/switch/uart_switch.cpp deleted file mode 100644 index 1edb546..0000000 --- a/components/uart/switch/uart_switch.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "uart_switch.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart.switch"; - -void UARTSwitch::loop() { - if (this->send_every_) { - const uint32_t now = millis(); - if (now - this->last_transmission_ > this->send_every_) { - this->write_command_(this->state); - this->last_transmission_ = now; - } - } -} - -void UARTSwitch::write_command_(bool state) { - if (state && !this->data_on_.empty()) { - ESP_LOGD(TAG, "'%s': Sending on data...", this->get_name().c_str()); - this->write_array(this->data_on_.data(), this->data_on_.size()); - } - if (!state && !this->data_off_.empty()) { - ESP_LOGD(TAG, "'%s': Sending off data...", this->get_name().c_str()); - this->write_array(this->data_off_.data(), this->data_off_.size()); - } -} - -void UARTSwitch::write_state(bool state) { - if (!this->single_state_) { - this->publish_state(state); - this->write_command_(state); - this->last_transmission_ = millis(); - return; - } - - if (!state) { - this->publish_state(false); - return; - } - - this->publish_state(true); - this->write_command_(true); - - if (this->send_every_ == 0) { - this->publish_state(false); - } else { - this->last_transmission_ = millis(); - } -} - -void UARTSwitch::dump_config() { - LOG_SWITCH("", "UART Switch", this); - if (this->send_every_) { - ESP_LOGCONFIG(TAG, " Send Every: %" PRIu32, this->send_every_); - } -} - -} // namespace uart -} // namespace esphome diff --git a/components/uart/switch/uart_switch.h b/components/uart/switch/uart_switch.h deleted file mode 100644 index 4ef5b6d..0000000 --- a/components/uart/switch/uart_switch.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/uart/uart.h" -#include "esphome/components/switch/switch.h" - -#include -#include - -namespace esphome { -namespace uart { - -class UARTSwitch : public switch_::Switch, public UARTDevice, public Component { - public: - void loop() override; - - void set_data_on(const std::vector &data) { this->data_on_ = data; } - void set_data_off(const std::vector &data) { this->data_off_ = data; } - void set_send_every(uint32_t send_every) { this->send_every_ = send_every; } - void set_single_state(bool single) { this->single_state_ = single; } - - void dump_config() override; - - protected: - void write_command_(bool state); - void write_state(bool state) override; - std::vector data_on_; - std::vector data_off_; - bool single_state_{false}; - uint32_t send_every_; - uint32_t last_transmission_; -}; - -} // namespace uart -} // namespace esphome diff --git a/components/uart/uart.cpp b/components/uart/uart.cpp deleted file mode 100644 index 9834462..0000000 --- a/components/uart/uart.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "uart.h" -#include "esphome/core/log.h" -#include "esphome/core/helpers.h" -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart"; - -void UARTDevice::check_uart_settings(uint32_t baud_rate, uint8_t stop_bits, UARTParityOptions parity, - uint8_t data_bits) { - if (this->parent_->get_baud_rate() != baud_rate) { - ESP_LOGE(TAG, " Invalid baud_rate: Integration requested baud_rate %" PRIu32 " but you have %" PRIu32 "!", - baud_rate, this->parent_->get_baud_rate()); - } - if (this->parent_->get_stop_bits() != stop_bits) { - ESP_LOGE(TAG, " Invalid stop bits: Integration requested stop_bits %u but you have %u!", stop_bits, - this->parent_->get_stop_bits()); - } - if (this->parent_->get_data_bits() != data_bits) { - ESP_LOGE(TAG, " Invalid number of data bits: Integration requested %u data bits but you have %u!", data_bits, - this->parent_->get_data_bits()); - } - if (this->parent_->get_parity() != parity) { - ESP_LOGE(TAG, " Invalid parity: Integration requested parity %s but you have %s!", - LOG_STR_ARG(parity_to_str(parity)), LOG_STR_ARG(parity_to_str(this->parent_->get_parity()))); - } -} - -const LogString *parity_to_str(UARTParityOptions parity) { - switch (parity) { - case UART_CONFIG_PARITY_NONE: - return LOG_STR("NONE"); - case UART_CONFIG_PARITY_EVEN: - return LOG_STR("EVEN"); - case UART_CONFIG_PARITY_ODD: - return LOG_STR("ODD"); - default: - return LOG_STR("UNKNOWN"); - } -} - -} // namespace uart -} // namespace esphome diff --git a/components/uart/uart.h b/components/uart/uart.h deleted file mode 100644 index d41dbe2..0000000 --- a/components/uart/uart.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class UARTDevice { - public: - UARTDevice() = default; - UARTDevice(UARTComponent *parent) : parent_(parent) {} - - void set_uart_parent(UARTComponent *parent) { this->parent_ = parent; } - - void write_byte(uint8_t data) { this->parent_->write_byte(data); } - - void write_array(const uint8_t *data, size_t len) { this->parent_->write_array(data, len); } - void write_array(const std::vector &data) { this->parent_->write_array(data); } - template void write_array(const std::array &data) { - this->parent_->write_array(data.data(), data.size()); - } - - void write_str(const char *str) { this->parent_->write_str(str); } - - bool read_byte(uint8_t *data) { return this->parent_->read_byte(data); } - bool peek_byte(uint8_t *data) { return this->parent_->peek_byte(data); } - - bool read_array(uint8_t *data, size_t len) { return this->parent_->read_array(data, len); } - template optional> read_array() { // NOLINT - std::array res; - if (!this->read_array(res.data(), N)) { - return {}; - } - return res; - } - - int available() { return this->parent_->available(); } - - void flush() { return this->parent_->flush(); } - - // Compat APIs - int read() { - uint8_t data; - if (!this->read_byte(&data)) - return -1; - return data; - } - size_t write(uint8_t data) { - this->write_byte(data); - return 1; - } - int peek() { - uint8_t data; - if (!this->peek_byte(&data)) - return -1; - return data; - } - - /// Check that the configuration of the UART bus matches the provided values and otherwise print a warning - void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits = 1, - UARTParityOptions parity = UART_CONFIG_PARITY_NONE, uint8_t data_bits = 8); - - protected: - UARTComponent *parent_{nullptr}; -}; - -} // namespace uart -} // namespace esphome diff --git a/components/uart/uart_component.cpp b/components/uart/uart_component.cpp deleted file mode 100644 index 09b8c97..0000000 --- a/components/uart/uart_component.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "uart_component.h" - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart"; - -bool UARTComponent::check_read_timeout_(size_t len) { - if (this->available() >= int(len)) - return true; - - uint32_t start_time = millis(); - while (this->available() < int(len)) { - if (millis() - start_time > 100) { - ESP_LOGE(TAG, "Reading from UART timed out at byte %u!", this->available()); - return false; - } - yield(); - } - return true; -} - -} // namespace uart -} // namespace esphome diff --git a/components/uart/uart_component.h b/components/uart/uart_component.h deleted file mode 100644 index a57910c..0000000 --- a/components/uart/uart_component.h +++ /dev/null @@ -1,175 +0,0 @@ -#pragma once - -#include -#include -#include "esphome/core/defines.h" -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#ifdef USE_UART_DEBUGGER -#include "esphome/core/automation.h" -#endif - -namespace esphome { -namespace uart { - -enum UARTParityOptions { - UART_CONFIG_PARITY_NONE, - UART_CONFIG_PARITY_EVEN, - UART_CONFIG_PARITY_ODD, -}; - -#ifdef USE_UART_DEBUGGER -enum UARTDirection { - UART_DIRECTION_RX, - UART_DIRECTION_TX, - UART_DIRECTION_BOTH, -}; -#endif - -const LogString *parity_to_str(UARTParityOptions parity); - -class UARTComponent { - public: - // Writes an array of bytes to the UART bus. - // @param data A vector of bytes to be written. - void write_array(const std::vector &data) { this->write_array(&data[0], data.size()); } - - // Writes a single byte to the UART bus. - // @param data The byte to be written. - void write_byte(uint8_t data) { this->write_array(&data, 1); }; - - // Writes a null-terminated string to the UART bus. - // @param str Pointer to the null-terminated string. - void write_str(const char *str) { - const auto *data = reinterpret_cast(str); - this->write_array(data, strlen(str)); - }; - - // Pure virtual method to write an array of bytes to the UART bus. - // @param data Pointer to the array of bytes. - // @param len Length of the array. - virtual void write_array(const uint8_t *data, size_t len) = 0; - - // Reads a single byte from the UART bus. - // @param data Pointer to the byte where the read data will be stored. - // @return True if a byte was successfully read, false otherwise. - bool read_byte(uint8_t *data) { return this->read_array(data, 1); }; - - // Pure virtual method to peek the next byte in the UART buffer without removing it. - // @param data Pointer to the byte where the peeked data will be stored. - // @return True if a byte is available to peek, false otherwise. - virtual bool peek_byte(uint8_t *data) = 0; - - // Pure virtual method to read an array of bytes from the UART bus. - // @param data Pointer to the array where the read data will be stored. - // @param len Number of bytes to read. - // @return True if the specified number of bytes were successfully read, false otherwise. - virtual bool read_array(uint8_t *data, size_t len) = 0; - - // Pure virtual method to return the number of bytes available for reading. - // @return Number of available bytes. - virtual int available() = 0; - - // Pure virtual method to block until all bytes have been written to the UART bus. - virtual void flush() = 0; - - // Sets the TX (transmit) pin for the UART bus. - // @param tx_pin Pointer to the internal GPIO pin used for transmission. - void set_tx_pin(InternalGPIOPin *tx_pin) { this->tx_pin_ = tx_pin; } - - // Sets the RX (receive) pin for the UART bus. - // @param rx_pin Pointer to the internal GPIO pin used for reception. - void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; } - - // Sets the size of the RX buffer. - // @param rx_buffer_size Size of the RX buffer in bytes. - void set_rx_buffer_size(size_t rx_buffer_size) { this->rx_buffer_size_ = rx_buffer_size; } - - // Gets the size of the RX buffer. - // @return Size of the RX buffer in bytes. - size_t get_rx_buffer_size() { return this->rx_buffer_size_; } - - // Sets the number of stop bits used in UART communication. - // @param stop_bits Number of stop bits. - void set_stop_bits(uint8_t stop_bits) { this->stop_bits_ = stop_bits; } - - // Gets the number of stop bits used in UART communication. - // @return Number of stop bits. - uint8_t get_stop_bits() const { return this->stop_bits_; } - - // Set the number of data bits used in UART communication. - // @param data_bits Number of data bits. - void set_data_bits(uint8_t data_bits) { this->data_bits_ = data_bits; } - - // Get the number of data bits used in UART communication. - // @return Number of data bits. - uint8_t get_data_bits() const { return this->data_bits_; } - - // Set the parity used in UART communication. - // @param parity Parity option. - void set_parity(UARTParityOptions parity) { this->parity_ = parity; } - - // Get the parity used in UART communication. - // @return Parity option. - UARTParityOptions get_parity() const { return this->parity_; } - - // Set the baud rate for UART communication. - // @param baud_rate Baud rate in bits per second. - void set_baud_rate(uint32_t baud_rate) { baud_rate_ = baud_rate; } - - // Get the baud rate for UART communication. - // @return Baud rate in bits per second. - uint32_t get_baud_rate() const { return baud_rate_; } - -#if defined(USE_ESP8266) || defined(USE_ESP32) - /** - * Load the UART settings. - * @param dump_config If true (default), output the new settings to logs; otherwise, change settings quietly. - * - * Example: - * ```cpp - * id(uart1).load_settings(false); - * ``` - * - * This will load the current UART interface with the latest settings (baud_rate, parity, etc). - */ - virtual void load_settings(bool dump_config){}; - - /** - * Load the UART settings. - * - * Example: - * ```cpp - * id(uart1).load_settings(); - * ``` - * - * This will load the current UART interface with the latest settings (baud_rate, parity, etc). - */ - virtual void load_settings(){}; -#endif // USE_ESP8266 || USE_ESP32 - -#ifdef USE_UART_DEBUGGER - void add_debug_callback(std::function &&callback) { - this->debug_callback_.add(std::move(callback)); - } -#endif - - protected: - virtual void check_logger_conflict() = 0; - bool check_read_timeout_(size_t len = 1); - - InternalGPIOPin *tx_pin_; - InternalGPIOPin *rx_pin_; - size_t rx_buffer_size_; - uint32_t baud_rate_; - uint8_t stop_bits_; - uint8_t data_bits_; - UARTParityOptions parity_; -#ifdef USE_UART_DEBUGGER - CallbackManager debug_callback_{}; -#endif -}; - -} // namespace uart -} // namespace esphome diff --git a/components/uart/uart_component_esp32_arduino.cpp b/components/uart/uart_component_esp32_arduino.cpp deleted file mode 100644 index 793c1d5..0000000 --- a/components/uart/uart_component_esp32_arduino.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#ifdef USE_ESP32_FRAMEWORK_ARDUINO -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" -#include "uart_component_esp32_arduino.h" - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -namespace esphome { -namespace uart { -static const char *const TAG = "uart.arduino_esp32"; - -static const uint32_t UART_PARITY_EVEN = 0 << 0; -static const uint32_t UART_PARITY_ODD = 1 << 0; -static const uint32_t UART_PARITY_ENABLE = 1 << 1; -static const uint32_t UART_NB_BIT_5 = 0 << 2; -static const uint32_t UART_NB_BIT_6 = 1 << 2; -static const uint32_t UART_NB_BIT_7 = 2 << 2; -static const uint32_t UART_NB_BIT_8 = 3 << 2; -static const uint32_t UART_NB_STOP_BIT_1 = 1 << 4; -static const uint32_t UART_NB_STOP_BIT_2 = 3 << 4; -static const uint32_t UART_TICK_APB_CLOCK = 1 << 27; - -uint32_t ESP32ArduinoUARTComponent::get_config() { - uint32_t config = 0; - - /* - * All bits numbers below come from - * framework-arduinoespressif32/cores/esp32/esp32-hal-uart.h - * And more specifically conf0 union in uart_dev_t. - * - * Below is bit used from conf0 union. - * : - * parity:0 0:even 1:odd - * parity_en:1 Set this bit to enable uart parity check. - * bit_num:2-4 0:5bits 1:6bits 2:7bits 3:8bits - * stop_bit_num:4-6 stop bit. 1:1bit 2:1.5bits 3:2bits - * tick_ref_always_on:27 select the clock.1:apb clock:ref_tick - */ - - if (this->parity_ == UART_CONFIG_PARITY_EVEN) { - config |= UART_PARITY_EVEN | UART_PARITY_ENABLE; - } else if (this->parity_ == UART_CONFIG_PARITY_ODD) { - config |= UART_PARITY_ODD | UART_PARITY_ENABLE; - } - - switch (this->data_bits_) { - case 5: - config |= UART_NB_BIT_5; - break; - case 6: - config |= UART_NB_BIT_6; - break; - case 7: - config |= UART_NB_BIT_7; - break; - case 8: - config |= UART_NB_BIT_8; - break; - } - - if (this->stop_bits_ == 1) { - config |= UART_NB_STOP_BIT_1; - } else { - config |= UART_NB_STOP_BIT_2; - } - - config |= UART_TICK_APB_CLOCK; - - return config; -} - -void ESP32ArduinoUARTComponent::setup() { - ESP_LOGCONFIG(TAG, "Setting up UART..."); - // Use Arduino HardwareSerial UARTs if all used pins match the ones - // preconfigured by the platform. For example if RX disabled but TX pin - // is 1 we still want to use Serial. - bool is_default_tx, is_default_rx; -#ifdef CONFIG_IDF_TARGET_ESP32C3 - is_default_tx = tx_pin_ == nullptr || tx_pin_->get_pin() == 21; - is_default_rx = rx_pin_ == nullptr || rx_pin_->get_pin() == 20; -#else - is_default_tx = tx_pin_ == nullptr || tx_pin_->get_pin() == 1; - is_default_rx = rx_pin_ == nullptr || rx_pin_->get_pin() == 3; -#endif - static uint8_t next_uart_num = 0; - if (is_default_tx && is_default_rx && next_uart_num == 0) { -#if ARDUINO_USB_CDC_ON_BOOT - this->hw_serial_ = &Serial0; -#else - this->hw_serial_ = &Serial; -#endif - next_uart_num++; - } else { -#ifdef USE_LOGGER - bool logger_uses_hardware_uart = true; - -#ifdef USE_LOGGER_USB_CDC - if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_CDC) { - // this is not a hardware UART, ignore it - logger_uses_hardware_uart = false; - } -#endif // USE_LOGGER_USB_CDC - -#ifdef USE_LOGGER_USB_SERIAL_JTAG - if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_SERIAL_JTAG) { - // this is not a hardware UART, ignore it - logger_uses_hardware_uart = false; - } -#endif // USE_LOGGER_USB_SERIAL_JTAG - - if (logger_uses_hardware_uart && logger::global_logger->get_baud_rate() > 0 && - logger::global_logger->get_uart() == next_uart_num) { - next_uart_num++; - } -#endif // USE_LOGGER - - if (next_uart_num >= UART_NUM_MAX) { - ESP_LOGW(TAG, "Maximum number of UART components created already."); - this->mark_failed(); - return; - } - - this->number_ = next_uart_num; - this->hw_serial_ = new HardwareSerial(next_uart_num++); // NOLINT(cppcoreguidelines-owning-memory) - } - - this->load_settings(false); -} - -void ESP32ArduinoUARTComponent::load_settings(bool dump_config) { - int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; - int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; - bool invert = false; - if (tx_pin_ != nullptr && tx_pin_->is_inverted()) - invert = true; - if (rx_pin_ != nullptr && rx_pin_->is_inverted()) - invert = true; - this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); - this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert); - if (dump_config) { - ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->number_); - this->dump_config(); - } -} - -void ESP32ArduinoUARTComponent::dump_config() { - ESP_LOGCONFIG(TAG, "UART Bus %d:", this->number_); - LOG_PIN(" TX Pin: ", tx_pin_); - LOG_PIN(" RX Pin: ", rx_pin_); - if (this->rx_pin_ != nullptr) { - ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); - } - ESP_LOGCONFIG(TAG, " Baud Rate: %u baud", this->baud_rate_); - ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_); - ESP_LOGCONFIG(TAG, " Parity: %s", LOG_STR_ARG(parity_to_str(this->parity_))); - ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); - this->check_logger_conflict(); -} - -void ESP32ArduinoUARTComponent::write_array(const uint8_t *data, size_t len) { - this->hw_serial_->write(data, len); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_TX, data[i]); - } -#endif -} - -bool ESP32ArduinoUARTComponent::peek_byte(uint8_t *data) { - if (!this->check_read_timeout_()) - return false; - *data = this->hw_serial_->peek(); - return true; -} - -bool ESP32ArduinoUARTComponent::read_array(uint8_t *data, size_t len) { - if (!this->check_read_timeout_(len)) - return false; - this->hw_serial_->readBytes(data, len); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_RX, data[i]); - } -#endif - return true; -} - -int ESP32ArduinoUARTComponent::available() { return this->hw_serial_->available(); } -void ESP32ArduinoUARTComponent::flush() { - ESP_LOGVV(TAG, " Flushing..."); - this->hw_serial_->flush(); -} - -void ESP32ArduinoUARTComponent::check_logger_conflict() { -#ifdef USE_LOGGER - if (this->hw_serial_ == nullptr || logger::global_logger->get_baud_rate() == 0) { - return; - } - - if (this->hw_serial_ == logger::global_logger->get_hw_serial()) { - ESP_LOGW(TAG, " You're using the same serial port for logging and the UART component. Please " - "disable logging over the serial port by setting logger->baud_rate to 0."); - } -#endif -} - -} // namespace uart -} // namespace esphome -#endif // USE_ESP32_FRAMEWORK_ARDUINO diff --git a/components/uart/uart_component_esp32_arduino.h b/components/uart/uart_component_esp32_arduino.h deleted file mode 100644 index de17d97..0000000 --- a/components/uart/uart_component_esp32_arduino.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#ifdef USE_ESP32_FRAMEWORK_ARDUINO - -#include -#include -#include -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class ESP32ArduinoUARTComponent : public UARTComponent, public Component { - public: - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::BUS; } - - void write_array(const uint8_t *data, size_t len) override; - - bool peek_byte(uint8_t *data) override; - bool read_array(uint8_t *data, size_t len) override; - - int available() override; - void flush() override; - - uint32_t get_config(); - - HardwareSerial *get_hw_serial() { return this->hw_serial_; } - uint8_t get_hw_serial_number() { return this->number_; } - - /** - * Load the UART with the current settings. - * @param dump_config (Optional, default `true`): True for displaying new settings or - * false to change it quitely - * - * Example: - * ```cpp - * id(uart1).load_settings(); - * ``` - * - * This will load the current UART interface with the latest settings (baud_rate, parity, etc). - */ - void load_settings(bool dump_config) override; - void load_settings() override { this->load_settings(true); } - - protected: - void check_logger_conflict() override; - - HardwareSerial *hw_serial_{nullptr}; - uint8_t number_{0}; -}; - -} // namespace uart -} // namespace esphome - -#endif // USE_ESP32_FRAMEWORK_ARDUINO diff --git a/components/uart/uart_component_esp8266.cpp b/components/uart/uart_component_esp8266.cpp deleted file mode 100644 index fa8dc3f..0000000 --- a/components/uart/uart_component_esp8266.cpp +++ /dev/null @@ -1,320 +0,0 @@ -#ifdef USE_ESP8266 -#include "uart_component_esp8266.h" -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart.arduino_esp8266"; -bool ESP8266UartComponent::serial0_in_use = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - -uint32_t ESP8266UartComponent::get_config() { - uint32_t config = 0; - - if (this->parity_ == UART_CONFIG_PARITY_NONE) { - config |= UART_PARITY_NONE; - } else if (this->parity_ == UART_CONFIG_PARITY_EVEN) { - config |= UART_PARITY_EVEN; - } else if (this->parity_ == UART_CONFIG_PARITY_ODD) { - config |= UART_PARITY_ODD; - } - - switch (this->data_bits_) { - case 5: - config |= UART_NB_BIT_5; - break; - case 6: - config |= UART_NB_BIT_6; - break; - case 7: - config |= UART_NB_BIT_7; - break; - case 8: - config |= UART_NB_BIT_8; - break; - } - - if (this->stop_bits_ == 1) { - config |= UART_NB_STOP_BIT_1; - } else { - config |= UART_NB_STOP_BIT_2; - } - - if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) - config |= BIT(22); - if (this->rx_pin_ != nullptr && this->rx_pin_->is_inverted()) - config |= BIT(19); - - return config; -} - -void ESP8266UartComponent::setup() { - ESP_LOGCONFIG(TAG, "Setting up UART bus..."); - // Use Arduino HardwareSerial UARTs if all used pins match the ones - // preconfigured by the platform. For example if RX disabled but TX pin - // is 1 we still want to use Serial. - SerialConfig config = static_cast(get_config()); - - if (!ESP8266UartComponent::serial0_in_use && (tx_pin_ == nullptr || tx_pin_->get_pin() == 1) && - (rx_pin_ == nullptr || rx_pin_->get_pin() == 3) -#ifdef USE_LOGGER - // we will use UART0 if logger isn't using it in swapped mode - && (logger::global_logger->get_hw_serial() == nullptr || - logger::global_logger->get_uart() != logger::UART_SELECTION_UART0_SWAP) -#endif - ) { - this->hw_serial_ = &Serial; - this->hw_serial_->begin(this->baud_rate_, config); - this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); - ESP8266UartComponent::serial0_in_use = true; - } else if (!ESP8266UartComponent::serial0_in_use && (tx_pin_ == nullptr || tx_pin_->get_pin() == 15) && - (rx_pin_ == nullptr || rx_pin_->get_pin() == 13) -#ifdef USE_LOGGER - // we will use UART0 swapped if logger isn't using it in regular mode - && (logger::global_logger->get_hw_serial() == nullptr || - logger::global_logger->get_uart() != logger::UART_SELECTION_UART0) -#endif - ) { - this->hw_serial_ = &Serial; - this->hw_serial_->begin(this->baud_rate_, config); - this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); - this->hw_serial_->swap(); - ESP8266UartComponent::serial0_in_use = true; - } else if ((tx_pin_ == nullptr || tx_pin_->get_pin() == 2) && (rx_pin_ == nullptr || rx_pin_->get_pin() == 8)) { - this->hw_serial_ = &Serial1; - this->hw_serial_->begin(this->baud_rate_, config); - this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); - } else { - this->sw_serial_ = new ESP8266SoftwareSerial(); // NOLINT - this->sw_serial_->setup(tx_pin_, rx_pin_, this->baud_rate_, this->stop_bits_, this->data_bits_, this->parity_, - this->rx_buffer_size_); - } -} - -void ESP8266UartComponent::load_settings(bool dump_config) { - ESP_LOGCONFIG(TAG, "Loading UART bus settings..."); - if (this->hw_serial_ != nullptr) { - SerialConfig config = static_cast(get_config()); - this->hw_serial_->begin(this->baud_rate_, config); - this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); - } else { - this->sw_serial_->setup(this->tx_pin_, this->rx_pin_, this->baud_rate_, this->stop_bits_, this->data_bits_, - this->parity_, this->rx_buffer_size_); - } - if (dump_config) { - ESP_LOGCONFIG(TAG, "UART bus was reloaded."); - this->dump_config(); - } -} - -void ESP8266UartComponent::dump_config() { - ESP_LOGCONFIG(TAG, "UART Bus:"); - LOG_PIN(" TX Pin: ", this->tx_pin_); - LOG_PIN(" RX Pin: ", this->rx_pin_); - if (this->rx_pin_ != nullptr) { - ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); // NOLINT - } - ESP_LOGCONFIG(TAG, " Baud Rate: %u baud", this->baud_rate_); - ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_); - ESP_LOGCONFIG(TAG, " Parity: %s", LOG_STR_ARG(parity_to_str(this->parity_))); - ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); - if (this->hw_serial_ != nullptr) { - ESP_LOGCONFIG(TAG, " Using hardware serial interface."); - } else { - ESP_LOGCONFIG(TAG, " Using software serial"); - } - this->check_logger_conflict(); -} - -void ESP8266UartComponent::check_logger_conflict() { -#ifdef USE_LOGGER - if (this->hw_serial_ == nullptr || logger::global_logger->get_baud_rate() == 0) { - return; - } - - if (this->hw_serial_ == logger::global_logger->get_hw_serial()) { - ESP_LOGW(TAG, " You're using the same serial port for logging and the UART component. Please " - "disable logging over the serial port by setting logger->baud_rate to 0."); - } -#endif -} - -void ESP8266UartComponent::write_array(const uint8_t *data, size_t len) { - if (this->hw_serial_ != nullptr) { - this->hw_serial_->write(data, len); - } else { - for (size_t i = 0; i < len; i++) - this->sw_serial_->write_byte(data[i]); - } -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_TX, data[i]); - } -#endif -} -bool ESP8266UartComponent::peek_byte(uint8_t *data) { - if (!this->check_read_timeout_()) - return false; - if (this->hw_serial_ != nullptr) { - *data = this->hw_serial_->peek(); - } else { - *data = this->sw_serial_->peek_byte(); - } - return true; -} -bool ESP8266UartComponent::read_array(uint8_t *data, size_t len) { - if (!this->check_read_timeout_(len)) - return false; - if (this->hw_serial_ != nullptr) { - this->hw_serial_->readBytes(data, len); - } else { - for (size_t i = 0; i < len; i++) - data[i] = this->sw_serial_->read_byte(); - } -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_RX, data[i]); - } -#endif - return true; -} -int ESP8266UartComponent::available() { - if (this->hw_serial_ != nullptr) { - return this->hw_serial_->available(); - } else { - return this->sw_serial_->available(); - } -} -void ESP8266UartComponent::flush() { - ESP_LOGVV(TAG, " Flushing..."); - if (this->hw_serial_ != nullptr) { - this->hw_serial_->flush(); - } else { - this->sw_serial_->flush(); - } -} -void ESP8266SoftwareSerial::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) { - this->bit_time_ = F_CPU / baud_rate; - this->rx_buffer_size_ = rx_buffer_size; - this->stop_bits_ = stop_bits; - this->data_bits_ = data_bits; - this->parity_ = parity; - if (tx_pin != nullptr) { - gpio_tx_pin_ = tx_pin; - gpio_tx_pin_->setup(); - tx_pin_ = gpio_tx_pin_->to_isr(); - tx_pin_.digital_write(true); - } - if (rx_pin != nullptr) { - gpio_rx_pin_ = rx_pin; - gpio_rx_pin_->setup(); - rx_pin_ = gpio_rx_pin_->to_isr(); - rx_buffer_ = new uint8_t[this->rx_buffer_size_]; // NOLINT - gpio_rx_pin_->attach_interrupt(ESP8266SoftwareSerial::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); - } -} -void IRAM_ATTR ESP8266SoftwareSerial::gpio_intr(ESP8266SoftwareSerial *arg) { - uint32_t wait = arg->bit_time_ + arg->bit_time_ / 3 - 500; - const uint32_t start = arch_get_cpu_cycle_count(); - uint8_t rec = 0; - // Manually unroll the loop - for (int i = 0; i < arg->data_bits_; i++) - rec |= arg->read_bit_(&wait, start) << i; - - /* If parity is enabled, just read it and ignore it. */ - /* TODO: Should we check parity? Or is it too slow for nothing added..*/ - if (arg->parity_ == UART_CONFIG_PARITY_EVEN || arg->parity_ == UART_CONFIG_PARITY_ODD) - arg->read_bit_(&wait, start); - - // Stop bit - arg->wait_(&wait, start); - if (arg->stop_bits_ == 2) - arg->wait_(&wait, start); - - arg->rx_buffer_[arg->rx_in_pos_] = rec; - arg->rx_in_pos_ = (arg->rx_in_pos_ + 1) % arg->rx_buffer_size_; - // Clear RX pin so that the interrupt doesn't re-trigger right away again. - arg->rx_pin_.clear_interrupt(); -} -void IRAM_ATTR HOT ESP8266SoftwareSerial::write_byte(uint8_t data) { - if (this->gpio_tx_pin_ == nullptr) { - ESP_LOGE(TAG, "UART doesn't have TX pins set!"); - return; - } - bool parity_bit = false; - bool need_parity_bit = true; - if (this->parity_ == UART_CONFIG_PARITY_EVEN) { - parity_bit = false; - } else if (this->parity_ == UART_CONFIG_PARITY_ODD) { - parity_bit = true; - } else { - need_parity_bit = false; - } - - { - InterruptLock lock; - uint32_t wait = this->bit_time_; - const uint32_t start = arch_get_cpu_cycle_count(); - // Start bit - this->write_bit_(false, &wait, start); - for (int i = 0; i < this->data_bits_; i++) { - bool bit = data & (1 << i); - this->write_bit_(bit, &wait, start); - if (need_parity_bit) - parity_bit ^= bit; - } - if (need_parity_bit) - this->write_bit_(parity_bit, &wait, start); - // Stop bit - this->write_bit_(true, &wait, start); - if (this->stop_bits_ == 2) - this->wait_(&wait, start); - } -} -void IRAM_ATTR ESP8266SoftwareSerial::wait_(uint32_t *wait, const uint32_t &start) { - while (arch_get_cpu_cycle_count() - start < *wait) - ; - *wait += this->bit_time_; -} -bool IRAM_ATTR ESP8266SoftwareSerial::read_bit_(uint32_t *wait, const uint32_t &start) { - this->wait_(wait, start); - return this->rx_pin_.digital_read(); -} -void IRAM_ATTR ESP8266SoftwareSerial::write_bit_(bool bit, uint32_t *wait, const uint32_t &start) { - this->tx_pin_.digital_write(bit); - this->wait_(wait, start); -} -uint8_t ESP8266SoftwareSerial::read_byte() { - if (this->rx_in_pos_ == this->rx_out_pos_) - return 0; - uint8_t data = this->rx_buffer_[this->rx_out_pos_]; - this->rx_out_pos_ = (this->rx_out_pos_ + 1) % this->rx_buffer_size_; - return data; -} -uint8_t ESP8266SoftwareSerial::peek_byte() { - if (this->rx_in_pos_ == this->rx_out_pos_) - return 0; - return this->rx_buffer_[this->rx_out_pos_]; -} -void ESP8266SoftwareSerial::flush() { - // Flush is a NO-OP with software serial, all bytes are written immediately. -} -int ESP8266SoftwareSerial::available() { - int avail = int(this->rx_in_pos_) - int(this->rx_out_pos_); - if (avail < 0) - return avail + this->rx_buffer_size_; - return avail; -} - -} // namespace uart -} // namespace esphome -#endif // USE_ESP8266 diff --git a/components/uart/uart_component_esp8266.h b/components/uart/uart_component_esp8266.h deleted file mode 100644 index 749dd4c..0000000 --- a/components/uart/uart_component_esp8266.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#ifdef USE_ESP8266 - -#include -#include -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class ESP8266SoftwareSerial { - public: - 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); - - uint8_t read_byte(); - uint8_t peek_byte(); - - void flush(); - - void write_byte(uint8_t data); - - int available(); - - protected: - static void gpio_intr(ESP8266SoftwareSerial *arg); - - void wait_(uint32_t *wait, const uint32_t &start); - bool read_bit_(uint32_t *wait, const uint32_t &start); - void write_bit_(bool bit, uint32_t *wait, const uint32_t &start); - - uint32_t bit_time_{0}; - uint8_t *rx_buffer_{nullptr}; - size_t rx_buffer_size_; - volatile size_t rx_in_pos_{0}; - size_t rx_out_pos_{0}; - uint8_t stop_bits_; - uint8_t data_bits_; - UARTParityOptions parity_; - InternalGPIOPin *gpio_tx_pin_{nullptr}; - ISRInternalGPIOPin tx_pin_; - InternalGPIOPin *gpio_rx_pin_{nullptr}; - ISRInternalGPIOPin rx_pin_; -}; - -class ESP8266UartComponent : public UARTComponent, public Component { - public: - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::BUS; } - - void write_array(const uint8_t *data, size_t len) override; - - bool peek_byte(uint8_t *data) override; - bool read_array(uint8_t *data, size_t len) override; - - int available() override; - void flush() override; - - uint32_t get_config(); - - /** - * Load the UART with the current settings. - * @param dump_config (Optional, default `true`): True for displaying new settings or - * false to change it quitely - * - * Example: - * ```cpp - * id(uart1).load_settings(); - * ``` - * - * This will load the current UART interface with the latest settings (baud_rate, parity, etc). - */ - void load_settings(bool dump_config) override; - void load_settings() override { this->load_settings(true); } - - protected: - void check_logger_conflict() override; - - HardwareSerial *hw_serial_{nullptr}; - ESP8266SoftwareSerial *sw_serial_{nullptr}; - - private: - static bool serial0_in_use; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -}; - -} // namespace uart -} // namespace esphome - -#endif // USE_ESP8266 diff --git a/components/uart/uart_component_esp_idf.cpp b/components/uart/uart_component_esp_idf.cpp deleted file mode 100644 index 6999dfb..0000000 --- a/components/uart/uart_component_esp_idf.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#ifdef USE_ESP_IDF - -#include "uart_component_esp_idf.h" -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" -#include - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -namespace esphome { -namespace uart { -static const char *const TAG = "uart.idf"; - -uart_config_t IDFUARTComponent::get_config_() { - uart_parity_t parity = UART_PARITY_DISABLE; - if (this->parity_ == UART_CONFIG_PARITY_EVEN) { - parity = UART_PARITY_EVEN; - } else if (this->parity_ == UART_CONFIG_PARITY_ODD) { - parity = UART_PARITY_ODD; - } - - uart_word_length_t data_bits; - switch (this->data_bits_) { - case 5: - data_bits = UART_DATA_5_BITS; - break; - case 6: - data_bits = UART_DATA_6_BITS; - break; - case 7: - data_bits = UART_DATA_7_BITS; - break; - case 8: - data_bits = UART_DATA_8_BITS; - break; - default: - data_bits = UART_DATA_BITS_MAX; - break; - } - - uart_config_t uart_config; - uart_config.baud_rate = this->baud_rate_; - uart_config.data_bits = data_bits; - uart_config.parity = parity; - uart_config.stop_bits = this->stop_bits_ == 1 ? UART_STOP_BITS_1 : UART_STOP_BITS_2; - uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - uart_config.source_clk = UART_SCLK_DEFAULT; -#else - uart_config.source_clk = UART_SCLK_APB; -#endif - uart_config.rx_flow_ctrl_thresh = 122; - - return uart_config; -} - -void IDFUARTComponent::setup() { - static uint8_t next_uart_num = 0; - -#ifdef USE_LOGGER - bool logger_uses_hardware_uart = true; - -#ifdef USE_LOGGER_USB_CDC - if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_CDC) { - // this is not a hardware UART, ignore it - logger_uses_hardware_uart = false; - } -#endif // USE_LOGGER_USB_CDC - -#ifdef USE_LOGGER_USB_SERIAL_JTAG - if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_SERIAL_JTAG) { - // this is not a hardware UART, ignore it - logger_uses_hardware_uart = false; - } -#endif // USE_LOGGER_USB_SERIAL_JTAG - - if (logger_uses_hardware_uart && logger::global_logger->get_baud_rate() > 0 && - logger::global_logger->get_uart_num() == next_uart_num) { - next_uart_num++; - } -#endif // USE_LOGGER - - if (next_uart_num >= UART_NUM_MAX) { - ESP_LOGW(TAG, "Maximum number of UART components created already."); - this->mark_failed(); - return; - } - this->uart_num_ = static_cast(next_uart_num++); - ESP_LOGCONFIG(TAG, "Setting up UART %u...", this->uart_num_); - - this->lock_ = xSemaphoreCreateMutex(); - - xSemaphoreTake(this->lock_, portMAX_DELAY); - - uart_config_t uart_config = this->get_config_(); - esp_err_t err = uart_param_config(this->uart_num_, &uart_config); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } - - int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; - int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; - - uint32_t invert = 0; - if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) - invert |= UART_SIGNAL_TXD_INV; - if (this->rx_pin_ != nullptr && this->rx_pin_->is_inverted()) - invert |= UART_SIGNAL_RXD_INV; - - err = uart_set_line_inverse(this->uart_num_, invert); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_set_line_inverse failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } - - err = uart_set_pin(this->uart_num_, tx, rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } - - err = uart_driver_install(this->uart_num_, /* UART RX ring buffer size. */ this->rx_buffer_size_, - /* UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will - block task until all data have been sent out.*/ - 0, - /* UART event queue size/depth. */ 20, &(this->uart_event_queue_), - /* Flags used to allocate the interrupt. */ 0); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_driver_install failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } - - xSemaphoreGive(this->lock_); -} - -void IDFUARTComponent::load_settings(bool dump_config) { - uart_config_t uart_config = this->get_config_(); - esp_err_t err = uart_param_config(this->uart_num_, &uart_config); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } else if (dump_config) { - ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->uart_num_); - this->dump_config(); - } -} - -void IDFUARTComponent::dump_config() { - ESP_LOGCONFIG(TAG, "UART Bus %u:", this->uart_num_); - LOG_PIN(" TX Pin: ", tx_pin_); - LOG_PIN(" RX Pin: ", rx_pin_); - if (this->rx_pin_ != nullptr) { - ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); - } - ESP_LOGCONFIG(TAG, " Baud Rate: %" PRIu32 " baud", this->baud_rate_); - ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_); - ESP_LOGCONFIG(TAG, " Parity: %s", LOG_STR_ARG(parity_to_str(this->parity_))); - ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); - this->check_logger_conflict(); -} - -void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { - xSemaphoreTake(this->lock_, portMAX_DELAY); - uart_write_bytes(this->uart_num_, data, len); - xSemaphoreGive(this->lock_); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_TX, data[i]); - } -#endif -} - -bool IDFUARTComponent::peek_byte(uint8_t *data) { - if (!this->check_read_timeout_()) - return false; - xSemaphoreTake(this->lock_, portMAX_DELAY); - if (this->has_peek_) { - *data = this->peek_byte_; - } else { - int len = uart_read_bytes(this->uart_num_, data, 1, 20 / portTICK_PERIOD_MS); - if (len == 0) { - *data = 0; - } else { - this->has_peek_ = true; - this->peek_byte_ = *data; - } - } - xSemaphoreGive(this->lock_); - return true; -} - -bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { - size_t length_to_read = len; - if (!this->check_read_timeout_(len)) - return false; - xSemaphoreTake(this->lock_, portMAX_DELAY); - if (this->has_peek_) { - length_to_read--; - *data = this->peek_byte_; - data++; - this->has_peek_ = false; - } - if (length_to_read > 0) - uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS); - xSemaphoreGive(this->lock_); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_RX, data[i]); - } -#endif - return true; -} - -int IDFUARTComponent::available() { - size_t available; - - xSemaphoreTake(this->lock_, portMAX_DELAY); - uart_get_buffered_data_len(this->uart_num_, &available); - if (this->has_peek_) - available++; - xSemaphoreGive(this->lock_); - - return available; -} - -void IDFUARTComponent::flush() { - ESP_LOGVV(TAG, " Flushing..."); - xSemaphoreTake(this->lock_, portMAX_DELAY); - uart_wait_tx_done(this->uart_num_, portMAX_DELAY); - xSemaphoreGive(this->lock_); -} - -void IDFUARTComponent::check_logger_conflict() {} - -} // namespace uart -} // namespace esphome - -#endif // USE_ESP32 diff --git a/components/uart/uart_component_esp_idf.h b/components/uart/uart_component_esp_idf.h deleted file mode 100644 index 215641e..0000000 --- a/components/uart/uart_component_esp_idf.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#ifdef USE_ESP_IDF - -#include -#include "esphome/core/component.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class IDFUARTComponent : public UARTComponent, public Component { - public: - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::BUS; } - - void write_array(const uint8_t *data, size_t len) override; - - bool peek_byte(uint8_t *data) override; - bool read_array(uint8_t *data, size_t len) override; - - int available() override; - void flush() override; - - uint8_t get_hw_serial_number() { return this->uart_num_; } - QueueHandle_t *get_uart_event_queue() { return &this->uart_event_queue_; } - - /** - * Load the UART with the current settings. - * @param dump_config (Optional, default `true`): True for displaying new settings or - * false to change it quitely - * - * Example: - * ```cpp - * id(uart1).load_settings(); - * ``` - * - * This will load the current UART interface with the latest settings (baud_rate, parity, etc). - */ - void load_settings(bool dump_config) override; - void load_settings() override { this->load_settings(true); } - - protected: - void check_logger_conflict() override; - uart_port_t uart_num_; - QueueHandle_t uart_event_queue_; - uart_config_t get_config_(); - SemaphoreHandle_t lock_; - - bool has_peek_{false}; - uint8_t peek_byte_; -}; - -} // namespace uart -} // namespace esphome - -#endif // USE_ESP_IDF diff --git a/components/uart/uart_component_host.cpp b/components/uart/uart_component_host.cpp deleted file mode 100644 index d8d2fd7..0000000 --- a/components/uart/uart_component_host.cpp +++ /dev/null @@ -1,295 +0,0 @@ -#ifdef USE_HOST -#include "uart_component_host.h" -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" - -#ifndef __linux__ -#error This HostUartComponent implementation is only for Linux -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -namespace { - -speed_t get_baud(int baud) { - switch (baud) { - case 50: - return B50; - case 75: - return B75; - case 110: - return B110; - case 134: - return B134; - case 150: - return B150; - case 200: - return B200; - case 300: - return B300; - case 600: - return B600; - case 1200: - return B1200; - case 1800: - return B1800; - case 2400: - return B2400; - case 4800: - return B4800; - case 9600: - return B9600; - case 19200: - return B19200; - case 38400: - return B38400; - case 57600: - return B57600; - case 115200: - return B115200; - case 230400: - return B230400; - case 460800: - return B460800; - case 500000: - return B500000; - case 576000: - return B576000; - case 921600: - return B921600; - case 1000000: - return B1000000; - case 1152000: - return B1152000; - case 1500000: - return B1500000; - case 2000000: - return B2000000; - case 2500000: - return B2500000; - case 3000000: - return B3000000; - case 3500000: - return B3500000; - case 4000000: - return B4000000; - default: - return B0; - } -} - -} // namespace - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart.host"; - -HostUartComponent::~HostUartComponent() { - if (this->file_descriptor_ != -1) { - close(this->file_descriptor_); - this->file_descriptor_ = -1; - } -} - -void HostUartComponent::setup() { - ESP_LOGCONFIG(TAG, "Opening UART port..."); - speed_t baud = get_baud(this->baud_rate_); - if (baud == B0) { - ESP_LOGE(TAG, "Unsupported baud rate: %d", this->baud_rate_); - this->mark_failed(); - return; - } - this->file_descriptor_ = ::open(this->port_name_.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); - if (this->file_descriptor_ == -1) { - this->update_error_(strerror(errno)); - this->mark_failed(); - return; - } - fcntl(this->file_descriptor_, F_SETFL, 0); - struct termios options; - tcgetattr(this->file_descriptor_, &options); - options.c_cflag &= ~CRTSCTS; - options.c_cflag |= CREAD | CLOCAL; - options.c_lflag &= ~ICANON; - options.c_lflag &= ~ECHO; - options.c_lflag &= ~ECHOE; - options.c_lflag &= ~ECHONL; - options.c_lflag &= ~ISIG; - options.c_iflag &= ~(IXON | IXOFF | IXANY); - options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); - options.c_oflag &= ~OPOST; - options.c_oflag &= ~ONLCR; - // Set data bits - options.c_cflag &= ~CSIZE; // Mask the character size bits - switch (this->data_bits_) { - case 5: - options.c_cflag |= CS5; - break; - case 6: - options.c_cflag |= CS6; - break; - case 7: - options.c_cflag |= CS7; - break; - case 8: - default: - options.c_cflag |= CS8; - break; - } - // Set parity - switch (this->parity_) { - case UART_CONFIG_PARITY_NONE: - options.c_cflag &= ~PARENB; - break; - case UART_CONFIG_PARITY_EVEN: - options.c_cflag |= PARENB; - options.c_cflag &= ~PARODD; - break; - case UART_CONFIG_PARITY_ODD: - options.c_cflag |= PARENB; - options.c_cflag |= PARODD; - break; - }; - // Set stop bits - if (this->stop_bits_ == 2) { - options.c_cflag |= CSTOPB; - } else { - options.c_cflag &= ~CSTOPB; - } - cfsetispeed(&options, baud); - cfsetospeed(&options, baud); - tcsetattr(this->file_descriptor_, TCSANOW, &options); -} - -void HostUartComponent::dump_config() { - ESP_LOGCONFIG(TAG, "UART:"); - ESP_LOGCONFIG(TAG, " Port: %s", this->port_name_.c_str()); - if (this->file_descriptor_ == -1) { - ESP_LOGCONFIG(TAG, " Port status: Not opened"); - if (!this->first_error_.empty()) { - ESP_LOGCONFIG(TAG, " Error: %s", this->first_error_.c_str()); - } - return; - } - ESP_LOGCONFIG(TAG, " Port status: opened"); - ESP_LOGCONFIG(TAG, " Baud Rate: %d", this->baud_rate_); - ESP_LOGCONFIG(TAG, " Data Bits: %d", this->data_bits_); - ESP_LOGCONFIG(TAG, " Parity: %s", - this->parity_ == UART_CONFIG_PARITY_NONE ? "None" - : this->parity_ == UART_CONFIG_PARITY_EVEN ? "Even" - : "Odd"); - ESP_LOGCONFIG(TAG, " Stop Bits: %d", this->stop_bits_); - this->check_logger_conflict(); -} - -void HostUartComponent::write_array(const uint8_t *data, size_t len) { - if (this->file_descriptor_ == -1) { - return; - } - size_t written = ::write(this->file_descriptor_, data, len); - if (written != len) { - this->update_error_(strerror(errno)); - return; - } -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_TX, data[i]); - } -#endif - return; -} - -bool HostUartComponent::peek_byte(uint8_t *data) { - if (this->file_descriptor_ == -1) { - return false; - } - if (!this->has_peek_) { - if (!this->check_read_timeout_()) { - return false; - } - if (::read(this->file_descriptor_, &this->peek_byte_, 1) != 1) { - this->update_error_(strerror(errno)); - return false; - } - this->has_peek_ = true; - } - *data = this->peek_byte_; - return true; -} - -bool HostUartComponent::read_array(uint8_t *data, size_t len) { - if ((this->file_descriptor_ == -1) || (len == 0)) { - return false; - } - if (!this->check_read_timeout_(len)) - return false; - uint8_t *data_ptr = data; - size_t length_to_read = len; - if (this->has_peek_) { - length_to_read--; - *data_ptr = this->peek_byte_; - data_ptr++; - this->has_peek_ = false; - } - if (length_to_read > 0) { - int sz = ::read(this->file_descriptor_, data_ptr, length_to_read); - if (sz == -1) { - this->update_error_(strerror(errno)); - return false; - } - } -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_RX, data[i]); - } -#endif - return true; -} - -int HostUartComponent::available() { - if (this->file_descriptor_ == -1) { - return 0; - } - int available; - int res = ioctl(this->file_descriptor_, FIONREAD, &available); - if (res == -1) { - this->update_error_(strerror(errno)); - return 0; - } - if (this->has_peek_) - available++; - return available; -}; - -void HostUartComponent::flush() { - if (this->file_descriptor_ == -1) { - return; - } - tcflush(this->file_descriptor_, TCIOFLUSH); - ESP_LOGV(TAG, " Flushing..."); -} - -void HostUartComponent::update_error_(const std::string &error) { - if (this->first_error_.empty()) { - this->first_error_ = error; - } - ESP_LOGE(TAG, "Port error: %s", error.c_str()); -} - -} // namespace uart -} // namespace esphome - -#endif // USE_HOST diff --git a/components/uart/uart_component_host.h b/components/uart/uart_component_host.h deleted file mode 100644 index c1f1dd0..0000000 --- a/components/uart/uart_component_host.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#ifdef USE_HOST - -#include "esphome/core/component.h" -#include "esphome/core/log.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class HostUartComponent : public UARTComponent, public Component { - public: - virtual ~HostUartComponent(); - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::BUS; } - void write_array(const uint8_t *data, size_t len) override; - bool peek_byte(uint8_t *data) override; - bool read_array(uint8_t *data, size_t len) override; - int available() override; - void flush() override; - void set_name(std::string port_name) { port_name_ = port_name; }; - - protected: - void update_error_(const std::string &error); - void check_logger_conflict() override {} - std::string port_name_; - std::string first_error_{""}; - int file_descriptor_ = -1; - bool has_peek_{false}; - uint8_t peek_byte_; -}; - -} // namespace uart -} // namespace esphome - -#endif // USE_HOST diff --git a/components/uart/uart_component_libretiny.cpp b/components/uart/uart_component_libretiny.cpp deleted file mode 100644 index c5e299e..0000000 --- a/components/uart/uart_component_libretiny.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifdef USE_LIBRETINY - -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" -#include "uart_component_libretiny.h" - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -#if LT_ARD_HAS_SOFTSERIAL -#include -#endif - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart.lt"; - -static const char *UART_TYPE[] = { - "hardware", - "software", -}; - -uint16_t LibreTinyUARTComponent::get_config() { - uint16_t config = 0; - - switch (this->parity_) { - case UART_CONFIG_PARITY_NONE: - config |= SERIAL_PARITY_NONE; - break; - case UART_CONFIG_PARITY_EVEN: - config |= SERIAL_PARITY_EVEN; - break; - case UART_CONFIG_PARITY_ODD: - config |= SERIAL_PARITY_ODD; - break; - } - - config |= (this->data_bits_ - 4) << 8; - config |= 0x10 + (this->stop_bits_ - 1) * 0x20; - - return config; -} - -void LibreTinyUARTComponent::setup() { - ESP_LOGCONFIG(TAG, "Setting up UART..."); - - int8_t tx_pin = tx_pin_ == nullptr ? -1 : tx_pin_->get_pin(); - int8_t rx_pin = rx_pin_ == nullptr ? -1 : rx_pin_->get_pin(); - bool tx_inverted = tx_pin_ != nullptr && tx_pin_->is_inverted(); - bool rx_inverted = rx_pin_ != nullptr && rx_pin_->is_inverted(); - - if (false) - return; -#if LT_HW_UART0 - else if ((tx_pin == -1 || tx_pin == PIN_SERIAL0_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL0_RX)) { - this->serial_ = &Serial0; - this->hardware_idx_ = 0; - } -#endif -#if LT_HW_UART1 - else if ((tx_pin == -1 || tx_pin == PIN_SERIAL1_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL1_RX)) { - this->serial_ = &Serial1; - this->hardware_idx_ = 1; - } -#endif -#if LT_HW_UART2 - else if ((tx_pin == -1 || tx_pin == PIN_SERIAL2_TX) && (rx_pin == -1 || rx_pin == PIN_SERIAL2_RX)) { - this->serial_ = &Serial2; - this->hardware_idx_ = 2; - } -#endif - else { -#if LT_ARD_HAS_SOFTSERIAL - this->serial_ = new SoftwareSerial(rx_pin, tx_pin, rx_inverted || tx_inverted); -#else - this->serial_ = &Serial; - ESP_LOGE(TAG, " SoftwareSerial is not implemented for this chip. Only hardware pins are supported:"); -#if LT_HW_UART0 - ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL0_TX, PIN_SERIAL0_RX); -#endif -#if LT_HW_UART1 - ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL1_TX, PIN_SERIAL1_RX); -#endif -#if LT_HW_UART2 - ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL2_TX, PIN_SERIAL2_RX); -#endif - this->mark_failed(); - return; -#endif - } - - this->serial_->begin(this->baud_rate_, get_config()); -} - -void LibreTinyUARTComponent::dump_config() { - bool is_software = this->hardware_idx_ == -1; - ESP_LOGCONFIG(TAG, "UART Bus:"); - ESP_LOGCONFIG(TAG, " Type: %s", UART_TYPE[is_software]); - if (!is_software) { - ESP_LOGCONFIG(TAG, " Port number: %d", this->hardware_idx_); - } - LOG_PIN(" TX Pin: ", tx_pin_); - LOG_PIN(" RX Pin: ", rx_pin_); - if (this->rx_pin_ != nullptr) { - ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); - } - ESP_LOGCONFIG(TAG, " Baud Rate: %u baud", this->baud_rate_); - ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_); - ESP_LOGCONFIG(TAG, " Parity: %s", LOG_STR_ARG(parity_to_str(this->parity_))); - ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); - this->check_logger_conflict(); -} - -void LibreTinyUARTComponent::write_array(const uint8_t *data, size_t len) { - this->serial_->write(data, len); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_TX, data[i]); - } -#endif -} - -bool LibreTinyUARTComponent::peek_byte(uint8_t *data) { - if (!this->check_read_timeout_()) - return false; - *data = this->serial_->peek(); - return true; -} - -bool LibreTinyUARTComponent::read_array(uint8_t *data, size_t len) { - if (!this->check_read_timeout_(len)) - return false; - this->serial_->readBytes(data, len); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_RX, data[i]); - } -#endif - return true; -} - -int LibreTinyUARTComponent::available() { return this->serial_->available(); } -void LibreTinyUARTComponent::flush() { - ESP_LOGVV(TAG, " Flushing..."); - this->serial_->flush(); -} - -void LibreTinyUARTComponent::check_logger_conflict() { -#ifdef USE_LOGGER - if (this->hardware_idx_ == -1 || logger::global_logger->get_baud_rate() == 0) { - return; - } - - if (this->serial_ == logger::global_logger->get_hw_serial()) { - ESP_LOGW(TAG, " You're using the same serial port for logging and the UART component. Please " - "disable logging over the serial port by setting logger->baud_rate to 0."); - } -#endif -} - -} // namespace uart -} // namespace esphome - -#endif // USE_LIBRETINY diff --git a/components/uart/uart_component_libretiny.h b/components/uart/uart_component_libretiny.h deleted file mode 100644 index 00982fd..0000000 --- a/components/uart/uart_component_libretiny.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#ifdef USE_LIBRETINY - -#include -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class LibreTinyUARTComponent : public UARTComponent, public Component { - public: - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::BUS; } - - void write_array(const uint8_t *data, size_t len) override; - - bool peek_byte(uint8_t *data) override; - bool read_array(uint8_t *data, size_t len) override; - - int available() override; - void flush() override; - - uint16_t get_config(); - - HardwareSerial *get_hw_serial() { return this->serial_; } - int8_t get_hw_serial_number() { return this->hardware_idx_; } - - protected: - void check_logger_conflict() override; - - HardwareSerial *serial_{nullptr}; - int8_t hardware_idx_{-1}; -}; - -} // namespace uart -} // namespace esphome - -#endif // USE_LIBRETINY diff --git a/components/uart/uart_component_rp2040.cpp b/components/uart/uart_component_rp2040.cpp deleted file mode 100644 index e2c4708..0000000 --- a/components/uart/uart_component_rp2040.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#ifdef USE_RP2040 -#include "uart_component_rp2040.h" -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" - -#include - -#ifdef USE_LOGGER -#include "esphome/components/logger/logger.h" -#endif - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart.arduino_rp2040"; - -uint16_t RP2040UartComponent::get_config() { - uint16_t config = 0; - - if (this->parity_ == UART_CONFIG_PARITY_NONE) { - config |= UART_PARITY_NONE; - } else if (this->parity_ == UART_CONFIG_PARITY_EVEN) { - config |= UART_PARITY_EVEN; - } else if (this->parity_ == UART_CONFIG_PARITY_ODD) { - config |= UART_PARITY_ODD; - } - - switch (this->data_bits_) { - case 5: - config |= SERIAL_DATA_5; - break; - case 6: - config |= SERIAL_DATA_6; - break; - case 7: - config |= SERIAL_DATA_7; - break; - case 8: - config |= SERIAL_DATA_8; - break; - } - - if (this->stop_bits_ == 1) { - config |= SERIAL_STOP_BIT_1; - } else { - config |= SERIAL_STOP_BIT_2; - } - - return config; -} - -void RP2040UartComponent::setup() { - ESP_LOGCONFIG(TAG, "Setting up UART bus..."); - - uint16_t config = get_config(); - - constexpr uint32_t valid_tx_uart_0 = __bitset({0, 12, 16, 28}); - constexpr uint32_t valid_tx_uart_1 = __bitset({4, 8, 20, 24}); - - constexpr uint32_t valid_rx_uart_0 = __bitset({1, 13, 17, 29}); - constexpr uint32_t valid_rx_uart_1 = __bitset({5, 9, 21, 25}); - - int8_t tx_hw = -1; - int8_t rx_hw = -1; - - if (this->tx_pin_ != nullptr) { - if (this->tx_pin_->is_inverted()) { - ESP_LOGD(TAG, "An inverted TX pin %u can only be used with SerialPIO", this->tx_pin_->get_pin()); - } else { - if (((1 << this->tx_pin_->get_pin()) & valid_tx_uart_0) != 0) { - tx_hw = 0; - } else if (((1 << this->tx_pin_->get_pin()) & valid_tx_uart_1) != 0) { - tx_hw = 1; - } else { - ESP_LOGD(TAG, "TX pin %u can only be used with SerialPIO", this->tx_pin_->get_pin()); - } - } - } - - if (this->rx_pin_ != nullptr) { - if (this->rx_pin_->is_inverted()) { - ESP_LOGD(TAG, "An inverted RX pin %u can only be used with SerialPIO", this->rx_pin_->get_pin()); - } else { - if (((1 << this->rx_pin_->get_pin()) & valid_rx_uart_0) != 0) { - rx_hw = 0; - } else if (((1 << this->rx_pin_->get_pin()) & valid_rx_uart_1) != 0) { - rx_hw = 1; - } else { - ESP_LOGD(TAG, "RX pin %u can only be used with SerialPIO", this->rx_pin_->get_pin()); - } - } - } - -#ifdef USE_LOGGER - if (tx_hw == rx_hw && logger::global_logger->get_uart() == tx_hw) { - ESP_LOGD(TAG, "Using SerialPIO as UART%d is taken by the logger", tx_hw); - tx_hw = -1; - rx_hw = -1; - } -#endif - - if (tx_hw == -1 || rx_hw == -1 || tx_hw != rx_hw) { - ESP_LOGV(TAG, "Using SerialPIO"); - pin_size_t tx = this->tx_pin_ == nullptr ? SerialPIO::NOPIN : this->tx_pin_->get_pin(); - pin_size_t rx = this->rx_pin_ == nullptr ? SerialPIO::NOPIN : this->rx_pin_->get_pin(); - auto *serial = new SerialPIO(tx, rx, this->rx_buffer_size_); // NOLINT(cppcoreguidelines-owning-memory) - serial->begin(this->baud_rate_, config); - if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) - gpio_set_outover(tx, GPIO_OVERRIDE_INVERT); - if (this->rx_pin_ != nullptr && this->rx_pin_->is_inverted()) - gpio_set_inover(rx, GPIO_OVERRIDE_INVERT); - this->serial_ = serial; - } else { - ESP_LOGV(TAG, "Using Hardware Serial"); - SerialUART *serial; - if (tx_hw == 0) { - serial = &Serial1; - } else { - serial = &Serial2; - } - serial->setTX(this->tx_pin_->get_pin()); - serial->setRX(this->rx_pin_->get_pin()); - serial->setFIFOSize(this->rx_buffer_size_); - serial->begin(this->baud_rate_, config); - this->serial_ = serial; - this->hw_serial_ = true; - } -} - -void RP2040UartComponent::dump_config() { - ESP_LOGCONFIG(TAG, "UART Bus:"); - LOG_PIN(" TX Pin: ", tx_pin_); - LOG_PIN(" RX Pin: ", rx_pin_); - if (this->rx_pin_ != nullptr) { - ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); - } - ESP_LOGCONFIG(TAG, " Baud Rate: %u baud", this->baud_rate_); - ESP_LOGCONFIG(TAG, " Data Bits: %u", this->data_bits_); - ESP_LOGCONFIG(TAG, " Parity: %s", LOG_STR_ARG(parity_to_str(this->parity_))); - ESP_LOGCONFIG(TAG, " Stop bits: %u", this->stop_bits_); - if (this->hw_serial_) { - ESP_LOGCONFIG(TAG, " Using hardware serial"); - } else { - ESP_LOGCONFIG(TAG, " Using SerialPIO"); - } -} - -void RP2040UartComponent::write_array(const uint8_t *data, size_t len) { - this->serial_->write(data, len); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_TX, data[i]); - } -#endif -} -bool RP2040UartComponent::peek_byte(uint8_t *data) { - if (!this->check_read_timeout_()) - return false; - *data = this->serial_->peek(); - return true; -} -bool RP2040UartComponent::read_array(uint8_t *data, size_t len) { - if (!this->check_read_timeout_(len)) - return false; - this->serial_->readBytes(data, len); -#ifdef USE_UART_DEBUGGER - for (size_t i = 0; i < len; i++) { - this->debug_callback_.call(UART_DIRECTION_RX, data[i]); - } -#endif - return true; -} -int RP2040UartComponent::available() { return this->serial_->available(); } -void RP2040UartComponent::flush() { - ESP_LOGVV(TAG, " Flushing..."); - this->serial_->flush(); -} - -} // namespace uart -} // namespace esphome - -#endif // USE_RP2040 diff --git a/components/uart/uart_component_rp2040.h b/components/uart/uart_component_rp2040.h deleted file mode 100644 index f26c913..0000000 --- a/components/uart/uart_component_rp2040.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#ifdef USE_RP2040 - -#include -#include - -#include -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/log.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -class RP2040UartComponent : public UARTComponent, public Component { - public: - void setup() override; - void dump_config() override; - float get_setup_priority() const override { return setup_priority::BUS; } - - void write_array(const uint8_t *data, size_t len) override; - - bool peek_byte(uint8_t *data) override; - bool read_array(uint8_t *data, size_t len) override; - - int available() override; - void flush() override; - - uint16_t get_config(); - - bool is_hw_serial() { return this->hw_serial_; } - HardwareSerial *get_hw_serial() { return this->serial_; } - - protected: - void check_logger_conflict() override {} - bool hw_serial_{false}; - - HardwareSerial *serial_{nullptr}; -}; - -} // namespace uart -} // namespace esphome - -#endif // USE_RP2040 diff --git a/components/uart/uart_debugger.cpp b/components/uart/uart_debugger.cpp deleted file mode 100644 index e2d92ea..0000000 --- a/components/uart/uart_debugger.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "esphome/core/defines.h" -#ifdef USE_UART_DEBUGGER - -#include -#include "uart_debugger.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace uart { - -static const char *const TAG = "uart_debug"; - -UARTDebugger::UARTDebugger(UARTComponent *parent) { - parent->add_debug_callback([this](UARTDirection direction, uint8_t byte) { - if (!this->is_my_direction_(direction) || this->is_recursive_()) { - return; - } - this->trigger_after_direction_change_(direction); - this->store_byte_(direction, byte); - this->trigger_after_delimiter_(byte); - this->trigger_after_bytes_(); - }); -} - -void UARTDebugger::loop() { this->trigger_after_timeout_(); } - -bool UARTDebugger::is_my_direction_(UARTDirection direction) { - return this->for_direction_ == UART_DIRECTION_BOTH || this->for_direction_ == direction; -} - -bool UARTDebugger::is_recursive_() { return this->is_triggering_; } - -void UARTDebugger::trigger_after_direction_change_(UARTDirection direction) { - if (this->has_buffered_bytes_() && this->for_direction_ == UART_DIRECTION_BOTH && - this->last_direction_ != direction) { - this->fire_trigger_(); - } -} - -void UARTDebugger::store_byte_(UARTDirection direction, uint8_t byte) { - this->bytes_.push_back(byte); - this->last_direction_ = direction; - this->last_time_ = millis(); -} - -void UARTDebugger::trigger_after_delimiter_(uint8_t byte) { - if (this->after_delimiter_.empty() || !this->has_buffered_bytes_()) { - return; - } - if (this->after_delimiter_[this->after_delimiter_pos_] != byte) { - this->after_delimiter_pos_ = 0; - return; - } - this->after_delimiter_pos_++; - if (this->after_delimiter_pos_ == this->after_delimiter_.size()) { - this->fire_trigger_(); - this->after_delimiter_pos_ = 0; - } -} - -void UARTDebugger::trigger_after_bytes_() { - if (this->has_buffered_bytes_() && this->after_bytes_ > 0 && this->bytes_.size() >= this->after_bytes_) { - this->fire_trigger_(); - } -} - -void UARTDebugger::trigger_after_timeout_() { - if (this->has_buffered_bytes_() && this->after_timeout_ > 0 && millis() - this->last_time_ >= this->after_timeout_) { - this->fire_trigger_(); - } -} - -bool UARTDebugger::has_buffered_bytes_() { return !this->bytes_.empty(); } - -void UARTDebugger::fire_trigger_() { - this->is_triggering_ = true; - trigger(this->last_direction_, this->bytes_); - this->bytes_.clear(); - this->is_triggering_ = false; -} - -void UARTDummyReceiver::loop() { - // Reading up to a limited number of bytes, to make sure that this loop() - // won't lock up the system on a continuous incoming stream of bytes. - uint8_t data; - int count = 50; - while (this->available() && count--) { - this->read_byte(&data); - } -} - -// In the upcoming log functions, a delay was added after all log calls. -// This is done to allow the system to ship the log lines via the API -// TCP connection(s). Without these delays, debug log lines could go -// missing when UART devices block the main loop for too long. - -void UARTDebug::log_hex(UARTDirection direction, std::vector bytes, uint8_t separator) { - std::string res; - if (direction == UART_DIRECTION_RX) { - res += "<<< "; - } else { - res += ">>> "; - } - size_t len = bytes.size(); - char buf[5]; - for (size_t i = 0; i < len; i++) { - if (i > 0) { - res += separator; - } - sprintf(buf, "%02X", bytes[i]); - res += buf; - } - ESP_LOGD(TAG, "%s", res.c_str()); - delay(10); -} - -void UARTDebug::log_string(UARTDirection direction, std::vector bytes) { - std::string res; - if (direction == UART_DIRECTION_RX) { - res += "<<< \""; - } else { - res += ">>> \""; - } - size_t len = bytes.size(); - char buf[5]; - for (size_t i = 0; i < len; i++) { - if (bytes[i] == 7) { - res += "\\a"; - } else if (bytes[i] == 8) { - res += "\\b"; - } else if (bytes[i] == 9) { - res += "\\t"; - } else if (bytes[i] == 10) { - res += "\\n"; - } else if (bytes[i] == 11) { - res += "\\v"; - } else if (bytes[i] == 12) { - res += "\\f"; - } else if (bytes[i] == 13) { - res += "\\r"; - } else if (bytes[i] == 27) { - res += "\\e"; - } else if (bytes[i] == 34) { - res += "\\\""; - } else if (bytes[i] == 39) { - res += "\\'"; - } else if (bytes[i] == 92) { - res += "\\\\"; - } else if (bytes[i] < 32 || bytes[i] > 127) { - sprintf(buf, "\\x%02X", bytes[i]); - res += buf; - } else { - res += bytes[i]; - } - } - res += '"'; - ESP_LOGD(TAG, "%s", res.c_str()); - delay(10); -} - -void UARTDebug::log_int(UARTDirection direction, std::vector bytes, uint8_t separator) { - std::string res; - size_t len = bytes.size(); - if (direction == UART_DIRECTION_RX) { - res += "<<< "; - } else { - res += ">>> "; - } - for (size_t i = 0; i < len; i++) { - if (i > 0) { - res += separator; - } - res += to_string(bytes[i]); - } - ESP_LOGD(TAG, "%s", res.c_str()); - delay(10); -} - -void UARTDebug::log_binary(UARTDirection direction, std::vector bytes, uint8_t separator) { - std::string res; - size_t len = bytes.size(); - if (direction == UART_DIRECTION_RX) { - res += "<<< "; - } else { - res += ">>> "; - } - char buf[20]; - for (size_t i = 0; i < len; i++) { - if (i > 0) { - res += separator; - } - sprintf(buf, "0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(bytes[i]), bytes[i]); - res += buf; - } - ESP_LOGD(TAG, "%s", res.c_str()); - delay(10); -} - -} // namespace uart -} // namespace esphome -#endif diff --git a/components/uart/uart_debugger.h b/components/uart/uart_debugger.h deleted file mode 100644 index 4f9b6d0..0000000 --- a/components/uart/uart_debugger.h +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once -#include "esphome/core/defines.h" -#ifdef USE_UART_DEBUGGER - -#include -#include "esphome/core/component.h" -#include "esphome/core/automation.h" -#include "uart.h" -#include "uart_component.h" - -namespace esphome { -namespace uart { - -/// The UARTDebugger class adds debugging support to a UART bus. -/// -/// It accumulates bytes that travel over the UART bus and triggers one or -/// more actions that can log the data at an appropriate time. What -/// 'appropriate time' means exactly, is determined by a number of -/// configurable constraints. E.g. when a given number of bytes is gathered -/// and/or when no more data has been seen for a given time interval. -class UARTDebugger : public Component, public Trigger> { - public: - explicit UARTDebugger(UARTComponent *parent); - void loop() override; - - /// Set the direction in which to inspect the bytes: incoming, outgoing - /// or both. When debugging in both directions, logging will be triggered - /// when the direction of the data stream changes. - void set_direction(UARTDirection direction) { this->for_direction_ = direction; } - - /// Set the maximum number of bytes to accumulate. When the number of bytes - /// is reached, logging will be triggered. - void set_after_bytes(size_t size) { this->after_bytes_ = size; } - - /// Set a timeout for the data stream. When no new bytes are seen during - /// this timeout, logging will be triggered. - void set_after_timeout(uint32_t timeout) { this->after_timeout_ = timeout; } - - /// Add a delimiter byte. This can be called multiple times to setup a - /// multi-byte delimiter (a typical example would be '\r\n'). - /// When the constructed byte sequence is found in the data stream, - /// logging will be triggered. - void add_delimiter_byte(uint8_t byte) { this->after_delimiter_.push_back(byte); } - - protected: - UARTDirection for_direction_; - UARTDirection last_direction_{}; - std::vector bytes_{}; - size_t after_bytes_; - uint32_t after_timeout_; - uint32_t last_time_{}; - std::vector after_delimiter_{}; - size_t after_delimiter_pos_{}; - bool is_triggering_{false}; - - bool is_my_direction_(UARTDirection direction); - bool is_recursive_(); - void store_byte_(UARTDirection direction, uint8_t byte); - void trigger_after_direction_change_(UARTDirection direction); - void trigger_after_delimiter_(uint8_t byte); - void trigger_after_bytes_(); - void trigger_after_timeout_(); - bool has_buffered_bytes_(); - void fire_trigger_(); -}; - -/// This UARTDevice is used by the serial debugger to read data from a -/// serial interface when the 'dummy_receiver' option is enabled. -/// The data are not stored, nor processed. This is most useful when the -/// debugger is used to reverse engineer a serial protocol, for which no -/// specific UARTDevice implementation exists (yet), but for which the -/// incoming bytes must be read to drive the debugger. -class UARTDummyReceiver : public Component, public UARTDevice { - public: - UARTDummyReceiver(UARTComponent *parent) : UARTDevice(parent) {} - void loop() override; -}; - -/// This class contains some static methods, that can be used to easily -/// create a logging action for the debugger. -class UARTDebug { - public: - /// Log the bytes as hex values, separated by the provided separator - /// character. - static void log_hex(UARTDirection direction, std::vector bytes, uint8_t separator); - - /// Log the bytes as string values, escaping unprintable characters. - static void log_string(UARTDirection direction, std::vector bytes); - - /// Log the bytes as integer values, separated by the provided separator - /// character. - static void log_int(UARTDirection direction, std::vector bytes, uint8_t separator); - - /// Log the bytes as ' ()' values, separated by the provided - /// separator. - static void log_binary(UARTDirection direction, std::vector bytes, uint8_t separator); -}; - -} // namespace uart -} // namespace esphome -#endif