diff --git a/esphome/components/esp32_rmt/__init__.py b/esphome/components/esp32_rmt/__init__.py index bda240680b..171c335727 100644 --- a/esphome/components/esp32_rmt/__init__.py +++ b/esphome/components/esp32_rmt/__init__.py @@ -1,7 +1,8 @@ -import esphome.config_validation as cv import esphome.codegen as cg - from esphome.components import esp32 +import esphome.config_validation as cv +from esphome.const import KEY_CORE, KEY_FRAMEWORK_VERSION +from esphome.core import CORE CODEOWNERS = ["@jesserockz"] @@ -36,8 +37,32 @@ RMT_CHANNEL_ENUMS = { } -def validate_rmt_channel(*, tx: bool): +def use_new_rmt_driver(): + framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] + if CORE.using_esp_idf and framework_version >= cv.Version(5, 0, 0): + return True + return False + +def validate_clock_resolution(): + def _validator(value): + cv.only_on_esp32(value) + value = cv.int_(value) + variant = esp32.get_esp32_variant() + if variant == esp32.const.VARIANT_ESP32H2 and value > 32000000: + raise cv.Invalid( + f"ESP32 variant {variant} has a max clock_resolution of 32000000." + ) + if value > 80000000: + raise cv.Invalid( + f"ESP32 variant {variant} has a max clock_resolution of 80000000." + ) + return value + + return _validator + + +def validate_rmt_channel(*, tx: bool): rmt_channels = RMT_TX_CHANNELS if tx else RMT_RX_CHANNELS def _validator(value): diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index c2209f7a6c..8ee890ec10 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -1,5 +1,5 @@ -#include #include "led_strip.h" +#include #ifdef USE_ESP32 @@ -13,9 +13,13 @@ namespace esp32_rmt_led_strip { static const char *const TAG = "esp32_rmt_led_strip"; +#ifdef USE_ESP32_VARIANT_ESP32H2 +static const uint32_t RMT_CLK_FREQ = 32000000; +static const uint8_t RMT_CLK_DIV = 1; +#else static const uint32_t RMT_CLK_FREQ = 80000000; - static const uint8_t RMT_CLK_DIV = 2; +#endif void ESP32RMTLEDStripLightOutput::setup() { ESP_LOGCONFIG(TAG, "Setting up ESP32 LED Strip..."); @@ -37,9 +41,48 @@ void ESP32RMTLEDStripLightOutput::setup() { return; } +#if ESP_IDF_VERSION_MAJOR >= 5 + RAMAllocator rmt_allocator(this->use_psram_ ? 0 : RAMAllocator::ALLOC_INTERNAL); + + // 8 bits per byte, 1 rmt_symbol_word_t per bit + 1 rmt_symbol_word_t for reset + this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 + 1); + + rmt_tx_channel_config_t channel; + memset(&channel, 0, sizeof(channel)); + channel.clk_src = RMT_CLK_SRC_DEFAULT; + channel.resolution_hz = RMT_CLK_FREQ / RMT_CLK_DIV; + channel.gpio_num = gpio_num_t(this->pin_); + channel.mem_block_symbols = this->rmt_symbols_; + channel.trans_queue_depth = 1; + channel.flags.io_loop_back = 0; + channel.flags.io_od_mode = 0; + channel.flags.invert_out = 0; + channel.flags.with_dma = 0; + channel.intr_priority = 0; + if (rmt_new_tx_channel(&channel, &this->channel_) != ESP_OK) { + ESP_LOGE(TAG, "Channel creation failed"); + this->mark_failed(); + return; + } + + rmt_copy_encoder_config_t encoder; + memset(&encoder, 0, sizeof(encoder)); + if (rmt_new_copy_encoder(&encoder, &this->encoder_) != ESP_OK) { + ESP_LOGE(TAG, "Encoder creation failed"); + this->mark_failed(); + return; + } + + if (rmt_enable(this->channel_) != ESP_OK) { + ESP_LOGE(TAG, "Enabling channel failed"); + this->mark_failed(); + return; + } +#else RAMAllocator rmt_allocator(this->use_psram_ ? 0 : RAMAllocator::ALLOC_INTERNAL); - this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 + - 1); // 8 bits per byte, 1 rmt_item32_t per bit + 1 rmt_item32_t for reset + + // 8 bits per byte, 1 rmt_item32_t per bit + 1 rmt_item32_t for reset + this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 + 1); rmt_config_t config; memset(&config, 0, sizeof(config)); @@ -64,6 +107,7 @@ void ESP32RMTLEDStripLightOutput::setup() { this->mark_failed(); return; } +#endif } void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bit0_low, uint32_t bit1_high, @@ -100,7 +144,12 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) { ESP_LOGVV(TAG, "Writing RGB values to bus..."); - if (rmt_wait_tx_done(this->channel_, pdMS_TO_TICKS(1000)) != ESP_OK) { +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_err_t error = rmt_tx_wait_all_done(this->channel_, 1000); +#else + esp_err_t error = rmt_wait_tx_done(this->channel_, pdMS_TO_TICKS(1000)); +#endif + if (error != ESP_OK) { ESP_LOGE(TAG, "RMT TX timeout"); this->status_set_warning(); return; @@ -112,7 +161,11 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) { size_t size = 0; size_t len = 0; uint8_t *psrc = this->buf_; +#if ESP_IDF_VERSION_MAJOR >= 5 + rmt_symbol_word_t *pdest = this->rmt_buf_; +#else rmt_item32_t *pdest = this->rmt_buf_; +#endif while (size < buffer_size) { uint8_t b = *psrc; for (int i = 0; i < 8; i++) { @@ -130,7 +183,16 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) { len++; } - if (rmt_write_items(this->channel_, this->rmt_buf_, len, false) != ESP_OK) { +#if ESP_IDF_VERSION_MAJOR >= 5 + rmt_transmit_config_t config; + memset(&config, 0, sizeof(config)); + config.loop_count = 0; + config.flags.eot_level = 0; + error = rmt_transmit(this->channel_, this->encoder_, this->rmt_buf_, len * sizeof(rmt_symbol_word_t), &config); +#else + error = rmt_write_items(this->channel_, this->rmt_buf_, len, false); +#endif + if (error != ESP_OK) { ESP_LOGE(TAG, "RMT TX error"); this->status_set_warning(); return; @@ -186,7 +248,11 @@ light::ESPColorView ESP32RMTLEDStripLightOutput::get_view_internal(int32_t index void ESP32RMTLEDStripLightOutput::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 RMT LED Strip:"); ESP_LOGCONFIG(TAG, " Pin: %u", this->pin_); +#if ESP_IDF_VERSION_MAJOR >= 5 + ESP_LOGCONFIG(TAG, " RMT Symbols: %" PRIu32, this->rmt_symbols_); +#else ESP_LOGCONFIG(TAG, " Channel: %u", this->channel_); +#endif const char *rgb_order; switch (this->rgb_order_) { case ORDER_RGB: diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.h b/esphome/components/esp32_rmt_led_strip/led_strip.h index d21bd86e75..fe49b9a2f3 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.h +++ b/esphome/components/esp32_rmt_led_strip/led_strip.h @@ -9,8 +9,14 @@ #include "esphome/core/helpers.h" #include -#include #include +#include + +#if ESP_IDF_VERSION_MAJOR >= 5 +#include +#else +#include +#endif namespace esphome { namespace esp32_rmt_led_strip { @@ -54,7 +60,11 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { uint32_t reset_time_high, uint32_t reset_time_low); void set_rgb_order(RGBOrder rgb_order) { this->rgb_order_ = rgb_order; } +#if ESP_IDF_VERSION_MAJOR >= 5 + void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; } +#else void set_rmt_channel(rmt_channel_t channel) { this->channel_ = channel; } +#endif void clear_effect_data() override { for (int i = 0; i < this->size(); i++) @@ -70,7 +80,17 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { uint8_t *buf_{nullptr}; uint8_t *effect_data_{nullptr}; +#if ESP_IDF_VERSION_MAJOR >= 5 + rmt_channel_handle_t channel_{nullptr}; + rmt_encoder_handle_t encoder_{nullptr}; + rmt_symbol_word_t *rmt_buf_{nullptr}; + rmt_symbol_word_t bit0_, bit1_, reset_; + uint32_t rmt_symbols_; +#else rmt_item32_t *rmt_buf_{nullptr}; + rmt_item32_t bit0_, bit1_, reset_; + rmt_channel_t channel_{RMT_CHANNEL_0}; +#endif uint8_t pin_; uint16_t num_leds_; @@ -78,9 +98,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight { bool is_wrgb_; bool use_psram_; - rmt_item32_t bit0_, bit1_, reset_; RGBOrder rgb_order_; - rmt_channel_t channel_; uint32_t last_refresh_{0}; optional max_refresh_rate_{}; diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 976f70e858..67a0e31461 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -13,6 +13,7 @@ from esphome.const import ( CONF_PIN, CONF_RGB_ORDER, CONF_RMT_CHANNEL, + CONF_RMT_SYMBOLS, ) CODEOWNERS = ["@jesserockz"] @@ -23,8 +24,6 @@ ESP32RMTLEDStripLightOutput = esp32_rmt_led_strip_ns.class_( "ESP32RMTLEDStripLightOutput", light.AddressableLight ) -rmt_channel_t = cg.global_ns.enum("rmt_channel_t") - RGBOrder = esp32_rmt_led_strip_ns.enum("RGBOrder") RGB_ORDERS = { @@ -65,6 +64,13 @@ CONF_RESET_HIGH = "reset_high" CONF_RESET_LOW = "reset_low" +def final_validation(config): + if not esp32_rmt.use_new_rmt_driver() and CONF_RMT_CHANNEL not in config: + raise cv.Invalid("rmt_channel is a required option.") + + +FINAL_VALIDATE_SCHEMA = final_validation + CONFIG_SCHEMA = cv.All( light.ADDRESSABLE_LIGHT_SCHEMA.extend( { @@ -72,7 +78,18 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_PIN): pins.internal_gpio_output_pin_number, cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, cv.Required(CONF_RGB_ORDER): cv.enum(RGB_ORDERS, upper=True), - cv.Required(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True), + cv.Optional(CONF_RMT_CHANNEL): cv.All( + cv.only_with_arduino, esp32_rmt.validate_rmt_channel(tx=True) + ), + cv.SplitDefault( + CONF_RMT_SYMBOLS, + esp32_idf=64, + esp32_s2_idf=64, + esp32_s3_idf=48, + esp32_c3_idf=48, + esp32_c6_idf=48, + esp32_h2_idf=48, + ): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)), cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds, cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), cv.Optional(CONF_IS_RGBW, default=False): cv.boolean, @@ -148,8 +165,12 @@ async def to_code(config): cg.add(var.set_is_wrgb(config[CONF_IS_WRGB])) cg.add(var.set_use_psram(config[CONF_USE_PSRAM])) - cg.add( - var.set_rmt_channel( - getattr(rmt_channel_t, f"RMT_CHANNEL_{config[CONF_RMT_CHANNEL]}") + if esp32_rmt.use_new_rmt_driver(): + cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS])) + else: + rmt_channel_t = cg.global_ns.enum("rmt_channel_t") + cg.add( + var.set_rmt_channel( + getattr(rmt_channel_t, f"RMT_CHANNEL_{config[CONF_RMT_CHANNEL]}") + ) ) - ) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index fdfd0b43cc..5dff2c6a38 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -8,7 +8,7 @@ namespace remote_base { static const char *const TAG = "remote_base"; -#ifdef USE_ESP32 +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5 RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_block_num) { static rmt_channel_t next_rmt_channel = RMT_CHANNEL_0; this->channel_ = next_rmt_channel; diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index c31127735a..70691177ef 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -8,7 +8,7 @@ #include "esphome/core/component.h" #include "esphome/core/hal.h" -#ifdef USE_ESP32 +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5 #include #endif @@ -112,25 +112,43 @@ class RemoteComponentBase { #ifdef USE_ESP32 class RemoteRMTChannel { public: +#if ESP_IDF_VERSION_MAJOR >= 5 + void set_clock_resolution(uint32_t clock_resolution) { this->clock_resolution_ = clock_resolution; } + void set_rmt_symbols(uint32_t rmt_symbols) { this->rmt_symbols_ = rmt_symbols; } +#else explicit RemoteRMTChannel(uint8_t mem_block_num = 1); explicit RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num = 1); void config_rmt(rmt_config_t &rmt); void set_clock_divider(uint8_t clock_divider) { this->clock_divider_ = clock_divider; } +#endif protected: uint32_t from_microseconds_(uint32_t us) { +#if ESP_IDF_VERSION_MAJOR >= 5 + const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u; +#else const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u; +#endif return us * ticks_per_ten_us / 10; } uint32_t to_microseconds_(uint32_t ticks) { +#if ESP_IDF_VERSION_MAJOR >= 5 + const uint32_t ticks_per_ten_us = this->clock_resolution_ / 100000u; +#else const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u; +#endif return (ticks * 10) / ticks_per_ten_us; } RemoteComponentBase *remote_base_; +#if ESP_IDF_VERSION_MAJOR >= 5 + uint32_t clock_resolution_{1000000}; + uint32_t rmt_symbols_; +#else rmt_channel_t channel_{RMT_CHANNEL_0}; uint8_t mem_block_num_; uint8_t clock_divider_{80}; +#endif }; #endif diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index d3f61977c6..b01443a974 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -1,10 +1,11 @@ from esphome import pins import esphome.codegen as cg -from esphome.components import esp32_rmt, remote_base +from esphome.components import esp32, esp32_rmt, remote_base import esphome.config_validation as cv from esphome.const import ( CONF_BUFFER_SIZE, CONF_CLOCK_DIVIDER, + CONF_CLOCK_RESOLUTION, CONF_DUMP, CONF_FILTER, CONF_ID, @@ -12,12 +13,17 @@ from esphome.const import ( CONF_MEMORY_BLOCKS, CONF_PIN, CONF_RMT_CHANNEL, + CONF_RMT_SYMBOLS, CONF_TOLERANCE, CONF_TYPE, + CONF_USE_DMA, CONF_VALUE, ) from esphome.core import CORE, TimePeriod +CONF_FILTER_SYMBOLS = "filter_symbols" +CONF_RECEIVE_SYMBOLS = "receive_symbols" + AUTO_LOAD = ["remote_base"] remote_receiver_ns = cg.esphome_ns.namespace("remote_receiver") remote_base_ns = cg.esphome_ns.namespace("remote_base") @@ -97,15 +103,43 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.positive_time_period_microseconds, cv.Range(max=TimePeriod(microseconds=4294967295)), ), - cv.SplitDefault(CONF_CLOCK_DIVIDER, esp32=80): cv.All( - cv.only_on_esp32, cv.Range(min=1, max=255) + cv.SplitDefault(CONF_CLOCK_DIVIDER, esp32_arduino=80): cv.All( + cv.only_on_esp32, + cv.only_with_arduino, + cv.int_range(min=1, max=255), + ), + cv.Optional(CONF_CLOCK_RESOLUTION): cv.All( + cv.only_on_esp32, + cv.only_with_esp_idf, + esp32_rmt.validate_clock_resolution(), ), cv.Optional(CONF_IDLE, default="10ms"): cv.All( cv.positive_time_period_microseconds, cv.Range(max=TimePeriod(microseconds=4294967295)), ), - cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), - cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=False), + cv.SplitDefault(CONF_MEMORY_BLOCKS, esp32_arduino=3): cv.All( + cv.only_with_arduino, cv.int_range(min=1, max=8) + ), + cv.Optional(CONF_RMT_CHANNEL): cv.All( + cv.only_with_arduino, esp32_rmt.validate_rmt_channel(tx=False) + ), + cv.SplitDefault( + CONF_RMT_SYMBOLS, + esp32_idf=192, + esp32_s2_idf=192, + esp32_s3_idf=192, + esp32_c3_idf=96, + esp32_c6_idf=96, + esp32_h2_idf=96, + ): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)), + cv.Optional(CONF_FILTER_SYMBOLS): cv.All( + cv.only_with_esp_idf, cv.int_range(min=0) + ), + cv.SplitDefault( + CONF_RECEIVE_SYMBOLS, + esp32_idf=192, + ): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)), + cv.Optional(CONF_USE_DMA): cv.All(cv.only_with_esp_idf, cv.boolean), } ).extend(cv.COMPONENT_SCHEMA) ) @@ -114,13 +148,27 @@ CONFIG_SCHEMA = remote_base.validate_triggers( async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) if CORE.is_esp32: - if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None: - var = cg.new_Pvariable( - config[CONF_ID], pin, rmt_channel, config[CONF_MEMORY_BLOCKS] - ) + if esp32_rmt.use_new_rmt_driver(): + var = cg.new_Pvariable(config[CONF_ID], pin) + cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS])) + cg.add(var.set_receive_symbols(config[CONF_RECEIVE_SYMBOLS])) + if CONF_USE_DMA in config: + cg.add(var.set_with_dma(config[CONF_USE_DMA])) + if CONF_CLOCK_RESOLUTION in config: + cg.add(var.set_clock_resolution(config[CONF_CLOCK_RESOLUTION])) + if CONF_FILTER_SYMBOLS in config: + cg.add(var.set_filter_symbols(config[CONF_FILTER_SYMBOLS])) + if CORE.using_esp_idf: + esp32.add_idf_sdkconfig_option("CONFIG_RMT_RECV_FUNC_IN_IRAM", True) + esp32.add_idf_sdkconfig_option("CONFIG_RMT_ISR_IRAM_SAFE", True) else: - var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) - cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER])) + if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None: + var = cg.new_Pvariable( + config[CONF_ID], pin, rmt_channel, config[CONF_MEMORY_BLOCKS] + ) + else: + var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) + cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER])) else: var = cg.new_Pvariable(config[CONF_ID], pin) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index 773f8cf636..8d19d5490f 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -5,6 +5,10 @@ #include +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5 +#include +#endif + namespace esphome { namespace remote_receiver { @@ -25,6 +29,21 @@ struct RemoteReceiverComponentStore { uint32_t filter_us{10}; ISRInternalGPIOPin pin; }; +#elif defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5 +struct RemoteReceiverComponentStore { + /// Stores RMT symbols and rx done event data + volatile uint8_t *buffer{nullptr}; + /// The position last written to + volatile uint32_t buffer_write{0}; + /// The position last read from + volatile uint32_t buffer_read{0}; + bool overflow{false}; + uint32_t buffer_size{1000}; + uint32_t receive_size{0}; + uint32_t filter_symbols{0}; + esp_err_t error{ESP_OK}; + rmt_receive_config_t config; +}; #endif class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, @@ -33,9 +52,10 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, , public remote_base::RemoteRMTChannel #endif + { public: -#ifdef USE_ESP32 +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5 RemoteReceiverComponent(InternalGPIOPin *pin, uint8_t mem_block_num = 1) : RemoteReceiverBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {} @@ -49,19 +69,32 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void loop() override; float get_setup_priority() const override { return setup_priority::DATA; } +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5 + void set_filter_symbols(uint32_t filter_symbols) { this->filter_symbols_ = filter_symbols; } + void set_receive_symbols(uint32_t receive_symbols) { this->receive_symbols_ = receive_symbols; } + void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; } +#endif void set_buffer_size(uint32_t buffer_size) { this->buffer_size_ = buffer_size; } void set_filter_us(uint32_t filter_us) { this->filter_us_ = filter_us; } void set_idle_us(uint32_t idle_us) { this->idle_us_ = idle_us; } protected: #ifdef USE_ESP32 - void decode_rmt_(rmt_item32_t *item, size_t len); +#if ESP_IDF_VERSION_MAJOR >= 5 + void decode_rmt_(rmt_symbol_word_t *item, size_t item_count); + rmt_channel_handle_t channel_{NULL}; + uint32_t filter_symbols_{0}; + uint32_t receive_symbols_{0}; + bool with_dma_{false}; +#else + void decode_rmt_(rmt_item32_t *item, size_t item_count); RingbufHandle_t ringbuf_; +#endif esp_err_t error_code_{ESP_OK}; std::string error_string_{""}; #endif -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || (defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5) RemoteReceiverComponentStore store_; HighFrequencyLoopRequester high_freq_; #endif diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index 91295871e2..48b84d61d4 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -2,15 +2,104 @@ #include "esphome/core/log.h" #ifdef USE_ESP32 -#include namespace esphome { namespace remote_receiver { static const char *const TAG = "remote_receiver.esp32"; +#ifdef USE_ESP32_VARIANT_ESP32H2 +static const uint32_t RMT_CLK_FREQ = 32000000; +#else +static const uint32_t RMT_CLK_FREQ = 80000000; +#endif + +#if ESP_IDF_VERSION_MAJOR >= 5 +static bool IRAM_ATTR HOT rmt_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *event, void *arg) { + RemoteReceiverComponentStore *store = (RemoteReceiverComponentStore *) arg; + rmt_rx_done_event_data_t *event_buffer = (rmt_rx_done_event_data_t *) (store->buffer + store->buffer_write); + uint32_t event_size = sizeof(rmt_rx_done_event_data_t); + uint32_t next_write = store->buffer_write + event_size + event->num_symbols * sizeof(rmt_symbol_word_t); + if (next_write + event_size + store->receive_size > store->buffer_size) { + next_write = 0; + } + if (store->buffer_read - next_write < event_size + store->receive_size) { + next_write = store->buffer_write; + store->overflow = true; + } + if (event->num_symbols <= store->filter_symbols) { + next_write = store->buffer_write; + } + store->error = + rmt_receive(channel, (uint8_t *) store->buffer + next_write + event_size, store->receive_size, &store->config); + event_buffer->num_symbols = event->num_symbols; + event_buffer->received_symbols = event->received_symbols; + store->buffer_write = next_write; + return false; +} +#endif void RemoteReceiverComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up Remote Receiver..."); +#if ESP_IDF_VERSION_MAJOR >= 5 + rmt_rx_channel_config_t channel; + memset(&channel, 0, sizeof(channel)); + channel.clk_src = RMT_CLK_SRC_DEFAULT; + channel.resolution_hz = this->clock_resolution_; + channel.mem_block_symbols = rmt_symbols_; + channel.gpio_num = gpio_num_t(this->pin_->get_pin()); + channel.intr_priority = 0; + channel.flags.invert_in = 0; + channel.flags.with_dma = this->with_dma_; + channel.flags.io_loop_back = 0; + esp_err_t error = rmt_new_rx_channel(&channel, &this->channel_); + if (error != ESP_OK) { + this->error_code_ = error; + if (error == ESP_ERR_NOT_FOUND) { + this->error_string_ = "out of RMT symbol memory"; + } else { + this->error_string_ = "in rmt_new_rx_channel"; + } + this->mark_failed(); + return; + } + error = rmt_enable(this->channel_); + if (error != ESP_OK) { + this->error_code_ = error; + this->error_string_ = "in rmt_enable"; + this->mark_failed(); + return; + } + + rmt_rx_event_callbacks_t callbacks; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.on_recv_done = rmt_callback; + error = rmt_rx_register_event_callbacks(this->channel_, &callbacks, &this->store_); + if (error != ESP_OK) { + this->error_code_ = error; + this->error_string_ = "in rmt_rx_register_event_callbacks"; + this->mark_failed(); + return; + } + + uint32_t event_size = sizeof(rmt_rx_done_event_data_t); + uint32_t max_filter_ns = 255u * 1000 / (RMT_CLK_FREQ / 1000000); + uint32_t max_idle_ns = 65535u * 1000; + memset(&this->store_.config, 0, sizeof(this->store_.config)); + this->store_.config.signal_range_min_ns = std::min(this->filter_us_ * 1000, max_filter_ns); + this->store_.config.signal_range_max_ns = std::min(this->idle_us_ * 1000, max_idle_ns); + this->store_.filter_symbols = this->filter_symbols_; + this->store_.receive_size = this->receive_symbols_ * sizeof(rmt_symbol_word_t); + this->store_.buffer_size = std::max((event_size + this->store_.receive_size) * 2, this->buffer_size_); + this->store_.buffer = new uint8_t[this->buffer_size_]; + error = rmt_receive(this->channel_, (uint8_t *) this->store_.buffer + event_size, this->store_.receive_size, + &this->store_.config); + if (error != ESP_OK) { + this->error_code_ = error; + this->error_string_ = "in rmt_receive"; + this->mark_failed(); + return; + } +#else this->pin_->setup(); rmt_config_t rmt{}; this->config_rmt(rmt); @@ -59,7 +148,9 @@ void RemoteReceiverComponent::setup() { this->mark_failed(); return; } +#endif } + void RemoteReceiverComponent::dump_config() { ESP_LOGCONFIG(TAG, "Remote Receiver:"); LOG_PIN(" Pin: ", this->pin_); @@ -67,9 +158,16 @@ void RemoteReceiverComponent::dump_config() { ESP_LOGW(TAG, "Remote Receiver Signal starts with a HIGH value. Usually this means you have to " "invert the signal using 'inverted: True' in the pin schema!"); } +#if ESP_IDF_VERSION_MAJOR >= 5 + ESP_LOGCONFIG(TAG, " Clock resolution: %" PRIu32 " hz", this->clock_resolution_); + ESP_LOGCONFIG(TAG, " RMT symbols: %" PRIu32, this->rmt_symbols_); + ESP_LOGCONFIG(TAG, " Filter symbols: %" PRIu32, this->filter_symbols_); + ESP_LOGCONFIG(TAG, " Receive symbols: %" PRIu32, this->receive_symbols_); +#else ESP_LOGCONFIG(TAG, " Channel: %d", this->channel_); ESP_LOGCONFIG(TAG, " RMT memory blocks: %d", this->mem_block_num_); ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_); +#endif ESP_LOGCONFIG(TAG, " Tolerance: %" PRIu32 "%s", this->tolerance_, (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %" PRIu32 " us", this->filter_us_); @@ -81,10 +179,38 @@ void RemoteReceiverComponent::dump_config() { } void RemoteReceiverComponent::loop() { +#if ESP_IDF_VERSION_MAJOR >= 5 + if (this->store_.error != ESP_OK) { + ESP_LOGE(TAG, "Receive error"); + this->error_code_ = this->store_.error; + this->error_string_ = "in rmt_callback"; + this->mark_failed(); + } + if (this->store_.overflow) { + ESP_LOGW(TAG, "Buffer overflow"); + this->store_.overflow = false; + } + uint32_t buffer_write = this->store_.buffer_write; + while (this->store_.buffer_read != buffer_write) { + rmt_rx_done_event_data_t *event = (rmt_rx_done_event_data_t *) (this->store_.buffer + this->store_.buffer_read); + uint32_t event_size = sizeof(rmt_rx_done_event_data_t); + uint32_t next_read = this->store_.buffer_read + event_size + event->num_symbols * sizeof(rmt_symbol_word_t); + if (next_read + event_size + this->store_.receive_size > this->store_.buffer_size) { + next_read = 0; + } + this->decode_rmt_(event->received_symbols, event->num_symbols); + this->store_.buffer_read = next_read; + + if (!this->temp_.empty()) { + this->temp_.push_back(-this->idle_us_); + this->call_listeners_dumpers_(); + } + } +#else size_t len = 0; auto *item = (rmt_item32_t *) xRingbufferReceive(this->ringbuf_, &len, 0); if (item != nullptr) { - this->decode_rmt_(item, len); + this->decode_rmt_(item, len / sizeof(rmt_item32_t)); vRingbufferReturnItem(this->ringbuf_, item); if (this->temp_.empty()) @@ -93,13 +219,18 @@ void RemoteReceiverComponent::loop() { this->temp_.push_back(-this->idle_us_); this->call_listeners_dumpers_(); } +#endif } -void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { + +#if ESP_IDF_VERSION_MAJOR >= 5 +void RemoteReceiverComponent::decode_rmt_(rmt_symbol_word_t *item, size_t item_count) { +#else +void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t item_count) { +#endif bool prev_level = false; uint32_t prev_length = 0; this->temp_.clear(); int32_t multiplier = this->pin_->is_inverted() ? -1 : 1; - size_t item_count = len / sizeof(rmt_item32_t); uint32_t filter_ticks = this->from_microseconds_(this->filter_us_); ESP_LOGVV(TAG, "START:"); @@ -124,7 +255,8 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { this->temp_.reserve(item_count * 2); // each RMT item has 2 pulses for (size_t i = 0; i < item_count; i++) { if (item[i].duration0 == 0u) { - // Do nothing + // EOF, sometimes garbage follows, break early + break; } else if ((bool(item[i].level0) == prev_level) || (item[i].duration0 < filter_ticks)) { prev_length += item[i].duration0; } else { @@ -140,7 +272,8 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { } if (item[i].duration1 == 0u) { - // Do nothing + // EOF, sometimes garbage follows, break early + break; } else if ((bool(item[i].level1) == prev_level) || (item[i].duration1 < filter_ticks)) { prev_length += item[i].duration1; } else { diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index f979939739..ea29751671 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -2,12 +2,23 @@ from esphome import automation, pins import esphome.codegen as cg from esphome.components import esp32_rmt, remote_base import esphome.config_validation as cv -from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN, CONF_RMT_CHANNEL +from esphome.const import ( + CONF_CARRIER_DUTY_PERCENT, + CONF_CLOCK_DIVIDER, + CONF_CLOCK_RESOLUTION, + CONF_ID, + CONF_PIN, + CONF_RMT_CHANNEL, + CONF_RMT_SYMBOLS, + CONF_USE_DMA, +) +from esphome.core import CORE AUTO_LOAD = ["remote_base"] CONF_ON_TRANSMIT = "on_transmit" CONF_ON_COMPLETE = "on_complete" +CONF_ONE_WIRE = "one_wire" remote_transmitter_ns = cg.esphome_ns.namespace("remote_transmitter") RemoteTransmitterComponent = remote_transmitter_ns.class_( @@ -22,7 +33,28 @@ CONFIG_SCHEMA = cv.Schema( cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( cv.percentage_int, cv.Range(min=1, max=100) ), - cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True), + cv.Optional(CONF_CLOCK_RESOLUTION): cv.All( + cv.only_on_esp32, + cv.only_with_esp_idf, + esp32_rmt.validate_clock_resolution(), + ), + cv.Optional(CONF_CLOCK_DIVIDER): cv.All( + cv.only_on_esp32, cv.only_with_arduino, cv.int_range(min=1, max=255) + ), + cv.Optional(CONF_ONE_WIRE): cv.All(cv.only_with_esp_idf, cv.boolean), + cv.Optional(CONF_USE_DMA): cv.All(cv.only_with_esp_idf, cv.boolean), + cv.SplitDefault( + CONF_RMT_SYMBOLS, + esp32_idf=64, + esp32_s2_idf=64, + esp32_s3_idf=48, + esp32_c3_idf=48, + esp32_c6_idf=48, + esp32_h2_idf=48, + ): cv.All(cv.only_with_esp_idf, cv.int_range(min=2)), + cv.Optional(CONF_RMT_CHANNEL): cv.All( + cv.only_with_arduino, esp32_rmt.validate_rmt_channel(tx=True) + ), cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), } @@ -31,8 +63,24 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) - if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None: - var = cg.new_Pvariable(config[CONF_ID], pin, rmt_channel) + if CORE.is_esp32: + if esp32_rmt.use_new_rmt_driver(): + var = cg.new_Pvariable(config[CONF_ID], pin) + cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS])) + if CONF_CLOCK_RESOLUTION in config: + cg.add(var.set_clock_resolution(config[CONF_CLOCK_RESOLUTION])) + if CONF_USE_DMA in config: + cg.add(var.set_with_dma(config[CONF_USE_DMA])) + if CONF_ONE_WIRE in config: + cg.add(var.set_one_wire(config[CONF_ONE_WIRE])) + else: + if (rmt_channel := config.get(CONF_RMT_CHANNEL, None)) is not None: + var = cg.new_Pvariable(config[CONF_ID], pin, rmt_channel) + else: + var = cg.new_Pvariable(config[CONF_ID], pin) + if CONF_CLOCK_DIVIDER in config: + cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER])) + else: var = cg.new_Pvariable(config[CONF_ID], pin) await cg.register_component(var, config) diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index 4abe687d23..20b98d5488 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -5,6 +5,10 @@ #include +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5 +#include +#endif + namespace esphome { namespace remote_transmitter { @@ -16,7 +20,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, #endif { public: -#ifdef USE_ESP32 +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 5 RemoteTransmitterComponent(InternalGPIOPin *pin, uint8_t mem_block_num = 1) : remote_base::RemoteTransmitterBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {} @@ -29,10 +33,16 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } + // transmitter setup must run after receiver setup to allow the same GPIO to be used by both + float get_setup_priority() const override { return setup_priority::DATA - 1; } void set_carrier_duty_percent(uint8_t carrier_duty_percent) { this->carrier_duty_percent_ = carrier_duty_percent; } +#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR >= 5 + void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; } + void set_one_wire(bool one_wire) { this->one_wire_ = one_wire; } +#endif + Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; }; Trigger<> *get_complete_trigger() const { return this->complete_trigger_; }; @@ -54,7 +64,15 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, uint32_t current_carrier_frequency_{38000}; bool initialized_{false}; +#if ESP_IDF_VERSION_MAJOR >= 5 + std::vector rmt_temp_; + bool with_dma_{false}; + bool one_wire_{false}; + rmt_channel_handle_t channel_{NULL}; + rmt_encoder_handle_t encoder_{NULL}; +#else std::vector rmt_temp_; +#endif esp_err_t error_code_{ESP_OK}; std::string error_string_{""}; bool inverted_{false}; diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index bce2408723..efb1735bfd 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -9,13 +9,22 @@ namespace remote_transmitter { static const char *const TAG = "remote_transmitter"; -void RemoteTransmitterComponent::setup() { this->configure_rmt_(); } +void RemoteTransmitterComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up Remote Transmitter..."); + this->configure_rmt_(); +} void RemoteTransmitterComponent::dump_config() { - ESP_LOGCONFIG(TAG, "Remote Transmitter..."); + ESP_LOGCONFIG(TAG, "Remote Transmitter:"); +#if ESP_IDF_VERSION_MAJOR >= 5 + ESP_LOGCONFIG(TAG, " One wire: %s", this->one_wire_ ? "true" : "false"); + ESP_LOGCONFIG(TAG, " Clock resolution: %" PRIu32 " hz", this->clock_resolution_); + ESP_LOGCONFIG(TAG, " RMT symbols: %" PRIu32, this->rmt_symbols_); +#else ESP_LOGCONFIG(TAG, " Channel: %d", this->channel_); ESP_LOGCONFIG(TAG, " RMT memory blocks: %d", this->mem_block_num_); ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_); +#endif LOG_PIN(" Pin: ", this->pin_); if (this->current_carrier_frequency_ != 0 && this->carrier_duty_percent_ != 100) { @@ -29,6 +38,72 @@ void RemoteTransmitterComponent::dump_config() { } void RemoteTransmitterComponent::configure_rmt_() { +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_err_t error; + + if (!this->initialized_) { + rmt_tx_channel_config_t channel; + memset(&channel, 0, sizeof(channel)); + channel.clk_src = RMT_CLK_SRC_DEFAULT; + channel.resolution_hz = this->clock_resolution_; + channel.gpio_num = gpio_num_t(this->pin_->get_pin()); + channel.mem_block_symbols = this->rmt_symbols_; + channel.trans_queue_depth = 1; + channel.flags.io_loop_back = this->one_wire_; + channel.flags.io_od_mode = this->one_wire_; + channel.flags.invert_out = 0; + channel.flags.with_dma = this->with_dma_; + channel.intr_priority = 0; + error = rmt_new_tx_channel(&channel, &this->channel_); + if (error != ESP_OK) { + this->error_code_ = error; + if (error == ESP_ERR_NOT_FOUND) { + this->error_string_ = "out of RMT symbol memory"; + } else { + this->error_string_ = "in rmt_new_tx_channel"; + } + this->mark_failed(); + return; + } + + rmt_copy_encoder_config_t encoder; + memset(&encoder, 0, sizeof(encoder)); + error = rmt_new_copy_encoder(&encoder, &this->encoder_); + if (error != ESP_OK) { + this->error_code_ = error; + this->error_string_ = "in rmt_new_copy_encoder"; + this->mark_failed(); + return; + } + + error = rmt_enable(this->channel_); + if (error != ESP_OK) { + this->error_code_ = error; + this->error_string_ = "in rmt_enable"; + this->mark_failed(); + return; + } + this->initialized_ = true; + } + + if (this->current_carrier_frequency_ == 0 || this->carrier_duty_percent_ == 100) { + error = rmt_apply_carrier(this->channel_, nullptr); + } else { + rmt_carrier_config_t carrier; + memset(&carrier, 0, sizeof(carrier)); + carrier.frequency_hz = this->current_carrier_frequency_; + carrier.duty_cycle = (float) this->carrier_duty_percent_ / 100.0f; + carrier.flags.polarity_active_low = this->inverted_; + carrier.flags.always_on = 1; + error = rmt_apply_carrier(this->channel_, &carrier); + } + if (error != ESP_OK) { + this->error_code_ = error; + this->error_string_ = "in rmt_apply_carrier"; + this->mark_failed(); + return; + } +#else rmt_config_t c{}; this->config_rmt(c); @@ -76,6 +151,7 @@ void RemoteTransmitterComponent::configure_rmt_() { } this->initialized_ = true; } +#endif } void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t send_wait) { @@ -90,7 +166,11 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen this->rmt_temp_.clear(); this->rmt_temp_.reserve((this->temp_.get_data().size() + 1) / 2); uint32_t rmt_i = 0; +#if ESP_IDF_VERSION_MAJOR >= 5 + rmt_symbol_word_t rmt_item; +#else rmt_item32_t rmt_item; +#endif for (int32_t val : this->temp_.get_data()) { bool level = val >= 0; @@ -125,6 +205,31 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen return; } this->transmit_trigger_->trigger(); +#if ESP_IDF_VERSION_MAJOR >= 5 + for (uint32_t i = 0; i < send_times; i++) { + rmt_transmit_config_t config; + memset(&config, 0, sizeof(config)); + config.loop_count = 0; + config.flags.eot_level = this->inverted_; + esp_err_t error = rmt_transmit(this->channel_, this->encoder_, this->rmt_temp_.data(), + this->rmt_temp_.size() * sizeof(rmt_symbol_word_t), &config); + if (error != ESP_OK) { + ESP_LOGW(TAG, "rmt_transmit failed: %s", esp_err_to_name(error)); + this->status_set_warning(); + } else { + this->status_clear_warning(); + } + error = rmt_tx_wait_all_done(this->channel_, -1); + if (error != ESP_OK) { + ESP_LOGW(TAG, "rmt_tx_wait_all_done failed: %s", esp_err_to_name(error)); + this->status_set_warning(); + } else { + this->status_clear_warning(); + } + if (i + 1 < send_times) + delayMicroseconds(send_wait); + } +#else for (uint32_t i = 0; i < send_times; i++) { esp_err_t error = rmt_write_items(this->channel_, this->rmt_temp_.data(), this->rmt_temp_.size(), true); if (error != ESP_OK) { @@ -136,6 +241,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) delayMicroseconds(send_wait); } +#endif this->complete_trigger_->trigger(); } diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml index 8d04d3370b..93318d0581 100644 --- a/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_rmt_led_strip/test.esp32-c3-idf.yaml @@ -3,14 +3,12 @@ light: id: led_strip pin: 4 num_leds: 60 - rmt_channel: 0 rgb_order: GRB chipset: ws2812 - platform: esp32_rmt_led_strip id: led_strip2 pin: 5 num_leds: 60 - rmt_channel: 1 rgb_order: RGB bit0_high: 100µs bit0_low: 100µs diff --git a/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml b/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml index 6e1763b339..228af17189 100644 --- a/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml +++ b/tests/components/esp32_rmt_led_strip/test.esp32-idf.yaml @@ -3,14 +3,12 @@ light: id: led_strip pin: 13 num_leds: 60 - rmt_channel: 6 rgb_order: GRB chipset: ws2812 - platform: esp32_rmt_led_strip id: led_strip2 pin: 14 num_leds: 60 - rmt_channel: 2 rgb_order: RGB bit0_high: 100µs bit0_low: 100µs diff --git a/tests/components/remote_receiver/common-actions.yaml b/tests/components/remote_receiver/common-actions.yaml new file mode 100644 index 0000000000..23589aed22 --- /dev/null +++ b/tests/components/remote_receiver/common-actions.yaml @@ -0,0 +1,144 @@ +on_abbwelcome: + then: + - logger.log: + format: "on_abbwelcome: %u" + args: ["x.data()[0]"] +on_aeha: + then: + - logger.log: + format: "on_aeha: %u %u" + args: ["x.address", "x.data.front()"] +on_byronsx: + then: + - logger.log: + format: "on_byronsx: %u %u" + args: ["x.address", "x.command"] +on_canalsat: + then: + - logger.log: + format: "on_canalsat: %u %u" + args: ["x.address", "x.command"] +# on_canalsatld: +# then: +# - logger.log: +# format: "on_canalsatld: %u %u" +# args: ["x.address", "x.command"] +on_coolix: + then: + - logger.log: + format: "on_coolix: %lu %lu" + args: ["long(x.first)", "long(x.second)"] +on_dish: + then: + - logger.log: + format: "on_dish: %u %u" + args: ["x.address", "x.command"] +on_dooya: + then: + - logger.log: + format: "on_dooya: %u %u %u" + args: ["x.channel", "x.button", "x.check"] +on_drayton: + then: + - logger.log: + format: "on_drayton: %u %u %u" + args: ["x.address", "x.channel", "x.command"] +on_jvc: + then: + - logger.log: + format: "on_jvc: %lu" + args: ["long(x.data)"] +on_keeloq: + then: + - logger.log: + format: "on_keeloq: %lu %lu %u" + args: ["long(x.encrypted)", "long(x.address)", "x.command"] +on_haier: + then: + - logger.log: + format: "on_haier: %u" + args: ["x.data.front()"] +on_lg: + then: + - logger.log: + format: "on_lg: %lu %u" + args: ["long(x.data)", "x.nbits"] +on_magiquest: + then: + - logger.log: + format: "on_magiquest: %u %lu" + args: ["x.magnitude", "long(x.wand_id)"] +on_midea: + then: + - logger.log: + format: "on_midea: %u %u" + args: ["x.size()", "x.data()[0]"] +on_nec: + then: + - logger.log: + format: "on_nec: %u %u" + args: ["x.address", "x.command"] +on_nexa: + then: + - logger.log: + format: "on_nexa: %lu %u %u %u %u" + args: ["long(x.device)", "x.group", "x.state", "x.channel", "x.level"] +on_panasonic: + then: + - logger.log: + format: "on_panasonic: %u %lu" + args: ["x.address", "long(x.command)"] +on_pioneer: + then: + - logger.log: + format: "on_pioneer: %u %u" + args: ["x.rc_code_1", "x.rc_code_2"] +on_pronto: + then: + - logger.log: + format: "on_pronto: %s" + args: ["x.data.c_str()"] +on_raw: + then: + - logger.log: + format: "on_raw: %lu" + args: ["long(x.front())"] +on_rc5: + then: + - logger.log: + format: "on_rc5: %u %u" + args: ["x.address", "x.command"] +on_rc6: + then: + - logger.log: + format: "on_rc6: %u %u" + args: ["x.address", "x.command"] +on_rc_switch: + then: + - logger.log: + format: "on_rc_switch: %llu %u" + args: ["x.code", "x.protocol"] +on_samsung: + then: + - logger.log: + format: "on_samsung: %llu %u" + args: ["x.data", "x.nbits"] +on_samsung36: + then: + - logger.log: + format: "on_samsung36: %u %lu" + args: ["x.address", "long(x.command)"] +on_sony: + then: + - logger.log: + format: "on_sony: %lu %u" + args: ["long(x.data)", "x.nbits"] +on_toshiba_ac: + then: + - logger.log: + format: "on_toshiba_ac: %llu %llu" + args: ["x.rc_code_1", "x.rc_code_2"] +on_mirage: + then: + - lambda: |- + ESP_LOGD("mirage", "Mirage data: %s", format_hex(x.data).c_str()); diff --git a/tests/components/remote_receiver/esp32-common-ard.yaml b/tests/components/remote_receiver/esp32-common-ard.yaml new file mode 100644 index 0000000000..e331a35307 --- /dev/null +++ b/tests/components/remote_receiver/esp32-common-ard.yaml @@ -0,0 +1,14 @@ +remote_receiver: + - id: rcvr + pin: ${pin} + rmt_channel: ${rmt_channel} + dump: all + tolerance: 25% + <<: !include common-actions.yaml + +binary_sensor: + - platform: remote_receiver + name: Panasonic Remote Input + panasonic: + address: 0x4004 + command: 0x100BCBD diff --git a/tests/components/remote_receiver/esp32-common-idf.yaml b/tests/components/remote_receiver/esp32-common-idf.yaml new file mode 100644 index 0000000000..b314880f8a --- /dev/null +++ b/tests/components/remote_receiver/esp32-common-idf.yaml @@ -0,0 +1,18 @@ +remote_receiver: + - id: rcvr + pin: ${pin} + dump: all + tolerance: 25% + clock_resolution: ${clock_resolution} + filter_symbols: ${filter_symbols} + receive_symbols: ${receive_symbols} + rmt_symbols: ${rmt_symbols} + use_dma: ${use_dma} + <<: !include common-actions.yaml + +binary_sensor: + - platform: remote_receiver + name: Panasonic Remote Input + panasonic: + address: 0x4004 + command: 0x100BCBD diff --git a/tests/components/remote_receiver/esp32-common.yaml b/tests/components/remote_receiver/esp32-common.yaml deleted file mode 100644 index 7e5d2cce32..0000000000 --- a/tests/components/remote_receiver/esp32-common.yaml +++ /dev/null @@ -1,157 +0,0 @@ -remote_receiver: - id: rcvr - pin: ${pin} - rmt_channel: ${rmt_channel} - dump: all - tolerance: 25% - on_abbwelcome: - then: - - logger.log: - format: "on_abbwelcome: %u" - args: ["x.data()[0]"] - on_aeha: - then: - - logger.log: - format: "on_aeha: %u %u" - args: ["x.address", "x.data.front()"] - on_byronsx: - then: - - logger.log: - format: "on_byronsx: %u %u" - args: ["x.address", "x.command"] - on_canalsat: - then: - - logger.log: - format: "on_canalsat: %u %u" - args: ["x.address", "x.command"] - # on_canalsatld: - # then: - # - logger.log: - # format: "on_canalsatld: %u %u" - # args: ["x.address", "x.command"] - on_coolix: - then: - - logger.log: - format: "on_coolix: %lu %lu" - args: ["long(x.first)", "long(x.second)"] - on_dish: - then: - - logger.log: - format: "on_dish: %u %u" - args: ["x.address", "x.command"] - on_dooya: - then: - - logger.log: - format: "on_dooya: %u %u %u" - args: ["x.channel", "x.button", "x.check"] - on_drayton: - then: - - logger.log: - format: "on_drayton: %u %u %u" - args: ["x.address", "x.channel", "x.command"] - on_jvc: - then: - - logger.log: - format: "on_jvc: %lu" - args: ["long(x.data)"] - on_keeloq: - then: - - logger.log: - format: "on_keeloq: %lu %lu %u" - args: ["long(x.encrypted)", "long(x.address)", "x.command"] - on_haier: - then: - - logger.log: - format: "on_haier: %u" - args: ["x.data.front()"] - on_lg: - then: - - logger.log: - format: "on_lg: %lu %u" - args: ["long(x.data)", "x.nbits"] - on_magiquest: - then: - - logger.log: - format: "on_magiquest: %u %lu" - args: ["x.magnitude", "long(x.wand_id)"] - on_midea: - then: - - logger.log: - format: "on_midea: %u %u" - args: ["x.size()", "x.data()[0]"] - on_nec: - then: - - logger.log: - format: "on_nec: %u %u" - args: ["x.address", "x.command"] - on_nexa: - then: - - logger.log: - format: "on_nexa: %lu %u %u %u %u" - args: ["long(x.device)", "x.group", "x.state", "x.channel", "x.level"] - on_panasonic: - then: - - logger.log: - format: "on_panasonic: %u %lu" - args: ["x.address", "long(x.command)"] - on_pioneer: - then: - - logger.log: - format: "on_pioneer: %u %u" - args: ["x.rc_code_1", "x.rc_code_2"] - on_pronto: - then: - - logger.log: - format: "on_pronto: %s" - args: ["x.data.c_str()"] - on_raw: - then: - - logger.log: - format: "on_raw: %lu" - args: ["long(x.front())"] - on_rc5: - then: - - logger.log: - format: "on_rc5: %u %u" - args: ["x.address", "x.command"] - on_rc6: - then: - - logger.log: - format: "on_rc6: %u %u" - args: ["x.address", "x.command"] - on_rc_switch: - then: - - logger.log: - format: "on_rc_switch: %llu %u" - args: ["x.code", "x.protocol"] - on_samsung: - then: - - logger.log: - format: "on_samsung: %llu %u" - args: ["x.data", "x.nbits"] - on_samsung36: - then: - - logger.log: - format: "on_samsung36: %u %lu" - args: ["x.address", "long(x.command)"] - on_sony: - then: - - logger.log: - format: "on_sony: %lu %u" - args: ["long(x.data)", "x.nbits"] - on_toshiba_ac: - then: - - logger.log: - format: "on_toshiba_ac: %llu %llu" - args: ["x.rc_code_1", "x.rc_code_2"] - on_mirage: - then: - - lambda: |- - ESP_LOGD("mirage", "Mirage data: %s", format_hex(x.data).c_str()); - -binary_sensor: - - platform: remote_receiver - name: Panasonic Remote Input - panasonic: - address: 0x4004 - command: 0x100BCBD diff --git a/tests/components/remote_receiver/test.esp32-ard.yaml b/tests/components/remote_receiver/test.esp32-ard.yaml index 16d276958a..5d29187206 100644 --- a/tests/components/remote_receiver/test.esp32-ard.yaml +++ b/tests/components/remote_receiver/test.esp32-ard.yaml @@ -3,4 +3,4 @@ substitutions: rmt_channel: "2" packages: - common: !include esp32-common.yaml + common: !include esp32-common-ard.yaml diff --git a/tests/components/remote_receiver/test.esp32-c3-ard.yaml b/tests/components/remote_receiver/test.esp32-c3-ard.yaml index 16d276958a..5d29187206 100644 --- a/tests/components/remote_receiver/test.esp32-c3-ard.yaml +++ b/tests/components/remote_receiver/test.esp32-c3-ard.yaml @@ -3,4 +3,4 @@ substitutions: rmt_channel: "2" packages: - common: !include esp32-common.yaml + common: !include esp32-common-ard.yaml diff --git a/tests/components/remote_receiver/test.esp32-c3-idf.yaml b/tests/components/remote_receiver/test.esp32-c3-idf.yaml index 16d276958a..495bb293c3 100644 --- a/tests/components/remote_receiver/test.esp32-c3-idf.yaml +++ b/tests/components/remote_receiver/test.esp32-c3-idf.yaml @@ -1,6 +1,10 @@ substitutions: pin: GPIO2 - rmt_channel: "2" + clock_resolution: "2000000" + filter_symbols: "2" + receive_symbols: "4" + rmt_symbols: "64" + use_dma: "true" packages: - common: !include esp32-common.yaml + common: !include esp32-common-idf.yaml diff --git a/tests/components/remote_receiver/test.esp32-idf.yaml b/tests/components/remote_receiver/test.esp32-idf.yaml index 16d276958a..495bb293c3 100644 --- a/tests/components/remote_receiver/test.esp32-idf.yaml +++ b/tests/components/remote_receiver/test.esp32-idf.yaml @@ -1,6 +1,10 @@ substitutions: pin: GPIO2 - rmt_channel: "2" + clock_resolution: "2000000" + filter_symbols: "2" + receive_symbols: "4" + rmt_symbols: "64" + use_dma: "true" packages: - common: !include esp32-common.yaml + common: !include esp32-common-idf.yaml diff --git a/tests/components/remote_receiver/test.esp32-s3-idf.yaml b/tests/components/remote_receiver/test.esp32-s3-idf.yaml index 265ecda771..e678ba456d 100644 --- a/tests/components/remote_receiver/test.esp32-s3-idf.yaml +++ b/tests/components/remote_receiver/test.esp32-s3-idf.yaml @@ -1,6 +1,10 @@ substitutions: pin: GPIO38 - rmt_channel: "5" + clock_resolution: "2000000" + filter_symbols: "2" + receive_symbols: "4" + rmt_symbols: "64" + use_dma: "true" packages: - common: !include esp32-common.yaml + common: !include esp32-common-idf.yaml diff --git a/tests/components/remote_receiver/test.esp8266-ard.yaml b/tests/components/remote_receiver/test.esp8266-ard.yaml index 27d36d4a16..c9784ae003 100644 --- a/tests/components/remote_receiver/test.esp8266-ard.yaml +++ b/tests/components/remote_receiver/test.esp8266-ard.yaml @@ -2,150 +2,7 @@ remote_receiver: id: rcvr pin: GPIO5 dump: all - on_abbwelcome: - then: - - logger.log: - format: "on_abbwelcome: %u" - args: ["x.data()[0]"] - on_aeha: - then: - - logger.log: - format: "on_aeha: %u %u" - args: ["x.address", "x.data.front()"] - on_byronsx: - then: - - logger.log: - format: "on_byronsx: %u %u" - args: ["x.address", "x.command"] - on_canalsat: - then: - - logger.log: - format: "on_canalsat: %u %u" - args: ["x.address", "x.command"] - # on_canalsatld: - # then: - # - logger.log: - # format: "on_canalsatld: %u %u" - # args: ["x.address", "x.command"] - on_coolix: - then: - - logger.log: - format: "on_coolix: %u %u" - args: ["x.first", "x.second"] - on_dish: - then: - - logger.log: - format: "on_dish: %u %u" - args: ["x.address", "x.command"] - on_dooya: - then: - - logger.log: - format: "on_dooya: %u %u %u" - args: ["x.channel", "x.button", "x.check"] - on_drayton: - then: - - logger.log: - format: "on_drayton: %u %u %u" - args: ["x.address", "x.channel", "x.command"] - on_jvc: - then: - - logger.log: - format: "on_jvc: %u" - args: ["x.data"] - on_keeloq: - then: - - logger.log: - format: "on_keeloq: %u %u %u" - args: ["x.encrypted", "x.address", "x.command"] - on_haier: - then: - - logger.log: - format: "on_haier: %u" - args: ["x.data.front()"] - on_lg: - then: - - logger.log: - format: "on_lg: %u %u" - args: ["x.data", "x.nbits"] - on_magiquest: - then: - - logger.log: - format: "on_magiquest: %u %u" - args: ["x.magnitude", "x.wand_id"] - on_midea: - then: - - logger.log: - format: "on_midea: %u %u" - args: ["x.size()", "x.data()[0]"] - on_nec: - then: - - logger.log: - format: "on_nec: %u %u" - args: ["x.address", "x.command"] - on_nexa: - then: - - logger.log: - format: "on_nexa: %u %u %u %u %u" - args: ["x.device", "x.group", "x.state", "x.channel", "x.level"] - on_panasonic: - then: - - logger.log: - format: "on_panasonic: %u %u" - args: ["x.address", "x.command"] - on_pioneer: - then: - - logger.log: - format: "on_pioneer: %u %u" - args: ["x.rc_code_1", "x.rc_code_2"] - on_pronto: - then: - - logger.log: - format: "on_pronto: %s" - args: ["x.data.c_str()"] - on_raw: - then: - - logger.log: - format: "on_raw: %u" - args: ["x.front()"] - on_rc5: - then: - - logger.log: - format: "on_rc5: %u %u" - args: ["x.address", "x.command"] - on_rc6: - then: - - logger.log: - format: "on_rc6: %u %u" - args: ["x.address", "x.command"] - on_rc_switch: - then: - - logger.log: - format: "on_rc_switch: %llu %u" - args: ["x.code", "x.protocol"] - on_samsung: - then: - - logger.log: - format: "on_samsung: %llu %u" - args: ["x.data", "x.nbits"] - on_samsung36: - then: - - logger.log: - format: "on_samsung36: %u %u" - args: ["x.address", "x.command"] - on_sony: - then: - - logger.log: - format: "on_sony: %u %u" - args: ["x.data", "x.nbits"] - on_toshiba_ac: - then: - - logger.log: - format: "on_toshiba_ac: %llu %llu" - args: ["x.rc_code_1", "x.rc_code_2"] - on_mirage: - then: - - lambda: |- - ESP_LOGD("mirage", "Mirage data: %s", format_hex(x.data).c_str()); + <<: !include common-actions.yaml binary_sensor: - platform: remote_receiver diff --git a/tests/components/remote_transmitter/esp32-common-ard.yaml b/tests/components/remote_transmitter/esp32-common-ard.yaml new file mode 100644 index 0000000000..420cea326d --- /dev/null +++ b/tests/components/remote_transmitter/esp32-common-ard.yaml @@ -0,0 +1,8 @@ +remote_transmitter: + - id: xmitr + pin: ${pin} + rmt_channel: ${rmt_channel} + carrier_duty_percent: 50% + +packages: + buttons: !include common-buttons.yaml diff --git a/tests/components/remote_transmitter/esp32-common-idf.yaml b/tests/components/remote_transmitter/esp32-common-idf.yaml new file mode 100644 index 0000000000..3b8b5e2aef --- /dev/null +++ b/tests/components/remote_transmitter/esp32-common-idf.yaml @@ -0,0 +1,11 @@ +remote_transmitter: + - id: xmitr + pin: ${pin} + carrier_duty_percent: 50% + clock_resolution: ${clock_resolution} + one_wire: ${one_wire} + rmt_symbols: ${rmt_symbols} + use_dma: ${use_dma} + +packages: + buttons: !include common-buttons.yaml diff --git a/tests/components/remote_transmitter/esp32-common.yaml b/tests/components/remote_transmitter/esp32-common.yaml deleted file mode 100644 index 3f3cd3f8c7..0000000000 --- a/tests/components/remote_transmitter/esp32-common.yaml +++ /dev/null @@ -1,8 +0,0 @@ -remote_transmitter: - id: rcvr - pin: ${pin} - rmt_channel: ${rmt_channel} - carrier_duty_percent: 50% - -packages: - buttons: !include common-buttons.yaml diff --git a/tests/components/remote_transmitter/test.esp32-ard.yaml b/tests/components/remote_transmitter/test.esp32-ard.yaml index 16d276958a..5d29187206 100644 --- a/tests/components/remote_transmitter/test.esp32-ard.yaml +++ b/tests/components/remote_transmitter/test.esp32-ard.yaml @@ -3,4 +3,4 @@ substitutions: rmt_channel: "2" packages: - common: !include esp32-common.yaml + common: !include esp32-common-ard.yaml diff --git a/tests/components/remote_transmitter/test.esp32-c3-ard.yaml b/tests/components/remote_transmitter/test.esp32-c3-ard.yaml index 3e2dc88e5a..c755b11563 100644 --- a/tests/components/remote_transmitter/test.esp32-c3-ard.yaml +++ b/tests/components/remote_transmitter/test.esp32-c3-ard.yaml @@ -3,4 +3,4 @@ substitutions: rmt_channel: "1" packages: - common: !include esp32-common.yaml + common: !include esp32-common-ard.yaml diff --git a/tests/components/remote_transmitter/test.esp32-c3-idf.yaml b/tests/components/remote_transmitter/test.esp32-c3-idf.yaml index 3e2dc88e5a..1a27f29dac 100644 --- a/tests/components/remote_transmitter/test.esp32-c3-idf.yaml +++ b/tests/components/remote_transmitter/test.esp32-c3-idf.yaml @@ -1,6 +1,9 @@ substitutions: pin: GPIO2 - rmt_channel: "1" + clock_resolution: "2000000" + one_wire: "true" + rmt_symbols: "64" + use_dma: "true" packages: - common: !include esp32-common.yaml + common: !include esp32-common-idf.yaml diff --git a/tests/components/remote_transmitter/test.esp32-idf.yaml b/tests/components/remote_transmitter/test.esp32-idf.yaml index 16d276958a..1a27f29dac 100644 --- a/tests/components/remote_transmitter/test.esp32-idf.yaml +++ b/tests/components/remote_transmitter/test.esp32-idf.yaml @@ -1,6 +1,9 @@ substitutions: pin: GPIO2 - rmt_channel: "2" + clock_resolution: "2000000" + one_wire: "true" + rmt_symbols: "64" + use_dma: "true" packages: - common: !include esp32-common.yaml + common: !include esp32-common-idf.yaml diff --git a/tests/components/remote_transmitter/test.esp32-s3-idf.yaml b/tests/components/remote_transmitter/test.esp32-s3-idf.yaml index 31851dc54c..25bdbd4772 100644 --- a/tests/components/remote_transmitter/test.esp32-s3-idf.yaml +++ b/tests/components/remote_transmitter/test.esp32-s3-idf.yaml @@ -1,6 +1,9 @@ substitutions: pin: GPIO38 - rmt_channel: "3" + clock_resolution: "2000000" + one_wire: "true" + rmt_symbols: "64" + use_dma: "true" packages: - common: !include esp32-common.yaml + common: !include esp32-common-idf.yaml diff --git a/tests/components/remote_transmitter/test.esp8266-ard.yaml b/tests/components/remote_transmitter/test.esp8266-ard.yaml index de494485f4..19759360f4 100644 --- a/tests/components/remote_transmitter/test.esp8266-ard.yaml +++ b/tests/components/remote_transmitter/test.esp8266-ard.yaml @@ -1,5 +1,5 @@ remote_transmitter: - id: trns + id: xmitr pin: GPIO5 carrier_duty_percent: 50%