mirror of
https://github.com/esphome/esphome.git
synced 2025-10-26 20:53:50 +00:00
[esp32_rmt] Updates for IDF 5+ (#7770)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#include <cinttypes>
|
||||
#include "led_strip.h"
|
||||
#include <cinttypes>
|
||||
|
||||
#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_symbol_word_t> rmt_allocator(this->use_psram_ ? 0 : RAMAllocator<rmt_symbol_word_t>::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_item32_t> rmt_allocator(this->use_psram_ ? 0 : RAMAllocator<rmt_item32_t>::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:
|
||||
|
||||
@@ -9,8 +9,14 @@
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/rmt.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_idf_version.h>
|
||||
|
||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||
#include <driver/rmt_tx.h>
|
||||
#else
|
||||
#include <driver/rmt.h>
|
||||
#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<uint32_t> max_refresh_rate_{};
|
||||
|
||||
@@ -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]}")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user