From d49ee470188939f2d197b950419f081f17d9c6fa Mon Sep 17 00:00:00 2001 From: puuu Date: Fri, 1 May 2020 10:59:51 +0900 Subject: [PATCH] esp32 remote: make RMT memory blocks configureable (#1002) --- .../components/remote_base/remote_base.cpp | 16 ++++++++--- esphome/components/remote_base/remote_base.h | 27 ++++++++++--------- .../components/remote_receiver/__init__.py | 9 +++++-- .../remote_receiver/remote_receiver.h | 18 ++++++++++--- .../remote_receiver/remote_receiver_esp32.cpp | 6 ++--- .../remote_transmitter/remote_transmitter.h | 9 ++++++- .../remote_transmitter_esp32.cpp | 5 ++-- esphome/const.py | 1 + 8 files changed, 63 insertions(+), 28 deletions(-) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 3da1daff63..04407ad3b1 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -6,14 +6,24 @@ namespace remote_base { static const char *TAG = "remote_base"; -RemoteComponentBase::RemoteComponentBase(GPIOPin *pin) : pin_(pin) { #ifdef ARDUINO_ARCH_ESP32 +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; - next_rmt_channel = rmt_channel_t(int(next_rmt_channel) + 1); -#endif + next_rmt_channel = rmt_channel_t(int(next_rmt_channel) + mem_block_num); } +void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) { + if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_7) { + this->mem_block_num_ = int(RMT_CHANNEL_7) - int(this->channel_) + 1; + ESP_LOGW(TAG, "Not enough RMT memory blocks avaiable, reduced to %i blocks.", this->mem_block_num_); + } + rmt.channel = this->channel_; + rmt.clk_div = this->clock_divider_; + rmt.mem_block_num = this->mem_block_num_; +} +#endif + void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); } void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) { diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 36be25add7..250b59e55e 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -146,15 +146,21 @@ template class RemoteProtocol { class RemoteComponentBase { public: - explicit RemoteComponentBase(GPIOPin *pin); - -#ifdef ARDUINO_ARCH_ESP32 - void set_channel(rmt_channel_t channel) { this->channel_ = channel; } - void set_clock_divider(uint8_t clock_divider) { this->clock_divider_ = clock_divider; } -#endif + explicit RemoteComponentBase(GPIOPin *pin) : pin_(pin){}; protected: + GPIOPin *pin_; +}; + #ifdef ARDUINO_ARCH_ESP32 +class RemoteRMTChannel { + public: + explicit RemoteRMTChannel(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; } + + protected: uint32_t from_microseconds(uint32_t us) { const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u; return us * ticks_per_ten_us / 10; @@ -163,15 +169,12 @@ class RemoteComponentBase { const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u; return (ticks * 10) / ticks_per_ten_us; } -#endif - - GPIOPin *pin_; -#ifdef ARDUINO_ARCH_ESP32 + RemoteComponentBase *remote_base_; rmt_channel_t channel_{RMT_CHANNEL_0}; + uint8_t mem_block_num_; uint8_t clock_divider_{80}; - esp_err_t error_code_{ESP_OK}; -#endif }; +#endif class RemoteTransmitterBase : public RemoteComponentBase { public: diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 5742876e36..28570a7c62 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -3,7 +3,8 @@ import esphome.config_validation as cv from esphome import pins from esphome.components import remote_base from esphome.const import CONF_BUFFER_SIZE, CONF_DUMP, CONF_FILTER, CONF_ID, CONF_IDLE, \ - CONF_PIN, CONF_TOLERANCE + CONF_PIN, CONF_TOLERANCE, CONF_MEMORY_BLOCKS +from esphome.core import CORE AUTO_LOAD = ['remote_base'] remote_receiver_ns = cg.esphome_ns.namespace('remote_receiver') @@ -21,12 +22,16 @@ CONFIG_SCHEMA = remote_base.validate_triggers(cv.Schema({ cv.SplitDefault(CONF_BUFFER_SIZE, esp32='10000b', esp8266='1000b'): cv.validate_bytes, cv.Optional(CONF_FILTER, default='50us'): cv.positive_time_period_microseconds, cv.Optional(CONF_IDLE, default='10ms'): cv.positive_time_period_microseconds, + cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), }).extend(cv.COMPONENT_SCHEMA)) def to_code(config): pin = yield cg.gpio_pin_expression(config[CONF_PIN]) - var = cg.new_Pvariable(config[CONF_ID], pin) + if CORE.is_esp32: + var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) + else: + var = cg.new_Pvariable(config[CONF_ID], pin) yield remote_base.build_dumpers(config[CONF_DUMP]) yield remote_base.build_triggers(config) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index 7a0accf65c..25262e3366 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -25,9 +25,20 @@ struct RemoteReceiverComponentStore { }; #endif -class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, public Component { +class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, + public Component +#ifdef ARDUINO_ARCH_ESP32 + , + public remote_base::RemoteRMTChannel +#endif +{ public: +#ifdef ARDUINO_ARCH_ESP32 + RemoteReceiverComponent(GPIOPin *pin, uint8_t mem_block_num = 1) + : RemoteReceiverBase(pin), remote_base::RemoteRMTChannel(mem_block_num) {} +#else RemoteReceiverComponent(GPIOPin *pin) : RemoteReceiverBase(pin) {} +#endif void setup() override; void dump_config() override; void loop() override; @@ -40,11 +51,10 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, public C protected: #ifdef ARDUINO_ARCH_ESP32 void decode_rmt_(rmt_item32_t *item, size_t len); + RingbufHandle_t ringbuf_; + esp_err_t error_code_{ESP_OK}; #endif -#ifdef ARDUINO_ARCH_ESP32 - RingbufHandle_t ringbuf_; -#endif #ifdef ARDUINO_ARCH_ESP8266 RemoteReceiverComponentStore store_; HighFrequencyLoopRequester high_freq_; diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index 3d2e6e4b9a..89de4da92a 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -2,6 +2,7 @@ #include "esphome/core/log.h" #ifdef ARDUINO_ARCH_ESP32 +#include namespace esphome { namespace remote_receiver { @@ -11,10 +12,8 @@ static const char *TAG = "remote_receiver.esp32"; void RemoteReceiverComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up Remote Receiver..."); rmt_config_t rmt{}; - rmt.channel = this->channel_; + this->config_rmt(rmt); rmt.gpio_num = gpio_num_t(this->pin_->get_pin()); - rmt.clk_div = this->clock_divider_; - rmt.mem_block_num = 1; rmt.rmt_mode = RMT_MODE_RX; if (this->filter_us_ == 0) { rmt.rx_config.filter_en = false; @@ -58,6 +57,7 @@ void RemoteReceiverComponent::dump_config() { "invert the signal using 'inverted: True' in the pin schema!"); } 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_); ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index a746d43926..000fbabfee 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -6,7 +6,13 @@ namespace esphome { namespace remote_transmitter { -class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, public Component { +class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, + public Component +#ifdef ARDUINO_ARCH_ESP32 + , + public remote_base::RemoteRMTChannel +#endif +{ public: explicit RemoteTransmitterComponent(GPIOPin *pin) : remote_base::RemoteTransmitterBase(pin) {} @@ -34,6 +40,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, pu uint32_t current_carrier_frequency_{UINT32_MAX}; bool initialized_{false}; std::vector rmt_temp_; + esp_err_t error_code_{ESP_OK}; #endif uint8_t carrier_duty_percent_{50}; }; diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index 0930d1cb18..d5e4a7b1b8 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -14,6 +14,7 @@ void RemoteTransmitterComponent::setup() {} void RemoteTransmitterComponent::dump_config() { ESP_LOGCONFIG(TAG, "Remote Transmitter..."); 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_); LOG_PIN(" Pin: ", this->pin_); @@ -29,11 +30,9 @@ void RemoteTransmitterComponent::dump_config() { void RemoteTransmitterComponent::configure_rmt() { rmt_config_t c{}; + this->config_rmt(c); c.rmt_mode = RMT_MODE_TX; - c.channel = this->channel_; - c.clk_div = this->clock_divider_; c.gpio_num = gpio_num_t(this->pin_->get_pin()); - c.mem_block_num = 1; c.tx_config.loop_en = false; if (this->current_carrier_frequency_ == 0 || this->carrier_duty_percent_ == 100) { diff --git a/esphome/const.py b/esphome/const.py index 8974009d30..31359e610d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -250,6 +250,7 @@ CONF_MAX_VOLTAGE = 'max_voltage' CONF_MEASUREMENT_DURATION = 'measurement_duration' CONF_MEASUREMENT_SEQUENCE_NUMBER = 'measurement_sequence_number' CONF_MEDIUM = 'medium' +CONF_MEMORY_BLOCKS = 'memory_blocks' CONF_METHOD = 'method' CONF_MIN_LENGTH = 'min_length' CONF_MIN_LEVEL = 'min_level'