10#include <esp_clk_tree.h>
13namespace esp32_rmt_led_strip {
15static const char *
const TAG =
"esp32_rmt_led_strip";
17static const size_t RMT_SYMBOLS_PER_BYTE = 8;
25 esp_clk_tree_src_get_freq_hz((soc_module_clk_t) RMT_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &freq);
29#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
30static size_t IRAM_ATTR HOT encoder_callback(
const void *data,
size_t size,
size_t symbols_written,
size_t symbols_free,
31 rmt_symbol_word_t *symbols,
bool *done,
void *arg) {
32 auto *params =
static_cast<LedParams *
>(arg);
33 const auto *bytes =
static_cast<const uint8_t *
>(data);
34 size_t index = symbols_written / RMT_SYMBOLS_PER_BYTE;
38 if (symbols_free < RMT_SYMBOLS_PER_BYTE) {
41 for (
size_t i = 0; i < RMT_SYMBOLS_PER_BYTE; i++) {
42 if (bytes[index] & (1 << (7 - i))) {
43 symbols[i] = params->bit1;
45 symbols[i] = params->bit0;
48#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1)
49 if ((index + 1) >=
size && params->reset.duration0 == 0 && params->reset.duration1 == 0) {
53 return RMT_SYMBOLS_PER_BYTE;
57 if (symbols_free < 1) {
60 symbols[0] = params->reset;
71 if (this->
buf_ ==
nullptr) {
72 ESP_LOGE(TAG,
"Cannot allocate LED buffer!");
76 memset(this->
buf_, 0, buffer_size);
80 ESP_LOGE(TAG,
"Cannot allocate effect data!");
85#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
95 rmt_tx_channel_config_t channel;
96 memset(&channel, 0,
sizeof(channel));
97 channel.clk_src = RMT_CLK_SRC_DEFAULT;
98 channel.resolution_hz = rmt_resolution_hz();
99 channel.gpio_num = gpio_num_t(this->
pin_);
101 channel.trans_queue_depth = 1;
103 channel.flags.with_dma = this->
use_dma_;
104 channel.intr_priority = 0;
105 if (rmt_new_tx_channel(&channel, &this->
channel_) != ESP_OK) {
106 ESP_LOGE(TAG,
"Channel creation failed");
111#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
112 rmt_simple_encoder_config_t encoder;
113 memset(&encoder, 0,
sizeof(encoder));
114 encoder.callback = encoder_callback;
116 encoder.min_chunk_size = RMT_SYMBOLS_PER_BYTE;
117 if (rmt_new_simple_encoder(&encoder, &this->
encoder_) != ESP_OK) {
118 ESP_LOGE(TAG,
"Encoder creation failed");
123 rmt_copy_encoder_config_t encoder;
124 memset(&encoder, 0,
sizeof(encoder));
125 if (rmt_new_copy_encoder(&encoder, &this->
encoder_) != ESP_OK) {
126 ESP_LOGE(TAG,
"Encoder creation failed");
132 if (rmt_enable(this->
channel_) != ESP_OK) {
133 ESP_LOGE(TAG,
"Enabling channel failed");
141 float ratio = (float) rmt_resolution_hz() / 1e09f;
172 ESP_LOGVV(TAG,
"Writing RGB values to bus");
174 esp_err_t error = rmt_tx_wait_all_done(this->
channel_, 1000);
175 if (error != ESP_OK) {
176 ESP_LOGE(TAG,
"RMT TX timeout");
182#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
189 uint8_t *psrc = this->
buf_;
190 rmt_symbol_word_t *pdest = this->
rmt_buf_;
191 while (size < buffer_size) {
193 for (
int i = 0; i < 8; i++) {
202 if (this->
params_.
reset.duration0 > 0 || this->params_.reset.duration1 > 0) {
209 rmt_transmit_config_t config;
210 memset(&config, 0,
sizeof(config));
211#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
216 if (error != ESP_OK) {
217 ESP_LOGE(TAG,
"RMT TX error");
225 int32_t r = 0, g = 0, b = 0;
259 uint8_t white = this->
is_wrgb_ ? 0 : 3;
261 return {this->
buf_ + (index * multiplier) + r + this->
is_wrgb_,
263 this->
buf_ + (index * multiplier) + b + this->is_wrgb_,
264 this->
is_rgbw_ || this->is_wrgb_ ? this->
buf_ + (index * multiplier) + white :
nullptr,
271 "ESP32 RMT LED Strip:\n"
274 ESP_LOGCONFIG(TAG,
" RMT Symbols: %" PRIu32, this->
rmt_symbols_);
275 const char *rgb_order;
296 rgb_order =
"UNKNOWN";
301 " Max refresh rate: %" PRIu32
"\n"
302 " Number of LEDs: %u",
void mark_failed()
Mark this component as failed.
void status_set_warning()
void status_clear_warning()
An STL allocator that uses SPI or internal RAM.
float get_setup_priority() const override
size_t get_buffer_size_() const
rmt_encoder_handle_t encoder_
void write_state(light::LightState *state) override
light::ESPColorView get_view_internal(int32_t index) const override
int32_t size() const override
rmt_channel_handle_t channel_
void set_led_params(uint32_t bit0_high, uint32_t bit0_low, uint32_t bit1_high, uint32_t bit1_low, uint32_t reset_time_high, uint32_t reset_time_low)
void dump_config() override
optional< uint32_t > max_refresh_rate_
ESPColorCorrection correction_
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
constexpr float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Providing packet encoding functions for exchanging data with a remote host.
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
uint32_t IRAM_ATTR HOT micros()