From adc781f1b9cce0e2278dab4484f7e865db91a7c1 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sun, 19 Jan 2025 22:30:40 -0800 Subject: [PATCH] C6 H2 P4 RMT --- src/internal/XMethods.h | 41 ++- .../ESP/ESP32/Core_2_x/NeoEsp32I2sMethod.h | 2 +- .../ESP/ESP32/Core_2_x/NeoEsp32I2sXMethod.h | 5 +- .../methods/ESP/ESP32/NeoEsp32RmtXMethod.h | 234 +++++++++--------- 4 files changed, 142 insertions(+), 140 deletions(-) diff --git a/src/internal/XMethods.h b/src/internal/XMethods.h index 361a44d..0a45d97 100644 --- a/src/internal/XMethods.h +++ b/src/internal/XMethods.h @@ -27,7 +27,7 @@ License along with NeoPixel. If not, see #pragma once -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) +#if defined(ARDUINO_ARCH_ESP32) //---------------------------------------------------------- #if defined(CONFIG_IDF_TARGET_ESP32S3) @@ -68,26 +68,24 @@ typedef NeoEsp32LcdX16Ws2816Method X16Ws2816Method; typedef NeoEsp32LcdX16Ws2812Method X16Ws2812Method; typedef NeoEsp32LcdX16Lc8812Method X16Lc8812Method; -#elif defined(CONFIG_IDF_TARGET_ESP32C3) + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4) + //---------------------------------------------------------- -/* RMT doesnt have a X method yet -typedef NeoEsp32Rmtx8Ws2812xMethod X8Ws2812xMethod; -typedef NeoEsp32Rmtx8Ws2805Method X8Ws2805Method; -typedef NeoEsp32Rmtx8Sk6812Method X8Sk6812Method; -typedef NeoEsp32Rmtx8Tm1814Method X8Tm1814Method; -typedef NeoEsp32Rmtx8Tm1829Method X8Tm1829Method; -typedef NeoEsp32Rmtx8Tm1914Method X8Tm1914Method; -typedef NeoEsp32Rmtx8800KbpsMethod X8800KbpsMethod; -typedef NeoEsp32Rmtx8400KbpsMethod X8400KbpsMethod; -typedef NeoEsp32Rmtx8Apa106Method X8Apa106Method; -typedef NeoEsp32Rmtx8Ws2814Method X8Ws2814Method; -typedef NeoEsp32Rmtx8Ws2813Method X8Ws2813Method; -typedef NeoEsp32Rmtx8Ws2812dMethod X8Ws2812dMethod; -typedef NeoEsp32Rmtx8Ws2811Method X8Ws2811Method; -typedef NeoEsp32Rmtx8Ws2816Method X8Ws2816Method; -typedef NeoEsp32Rmtx8Ws2812Method X8Ws2812Method; -typedef NeoEsp32Rmtx8Lc8812Method X8Lc8812Method; -*/ +typedef NeoEsp32RmtXWs2812xMethod XWs2812xMethod; +typedef NeoEsp32RmtXWs2805Method XWs2805Method; +typedef NeoEsp32RmtXSk6812Method XSk6812Method; +typedef NeoEsp32RmtXTm1814Method XTm1814Method; +typedef NeoEsp32RmtXTm1829Method XTm1829Method; +typedef NeoEsp32RmtXTm1914Method XTm1914Method; +typedef NeoEsp32RmtX800KbpsMethod X800KbpsMethod; +typedef NeoEsp32RmtX400KbpsMethod X400KbpsMethod; +typedef NeoEsp32RmtXApa106Method XApa106Method; +typedef NeoEsp32RmtXWs2814Method XWs2814Method; +typedef NeoEsp32RmtXWs2813Method XWs2813Method; +typedef NeoEsp32RmtXWs2811Method XWs2811Method; +typedef NeoEsp32RmtXWs2816Method XWs2816Method; +typedef NeoEsp32RmtXLc8812Method XLc8812Method; #elif defined(CONFIG_IDF_TARGET_ESP32S2) //---------------------------------------------------------- @@ -127,6 +125,7 @@ typedef NeoEsp32I2s0X16Ws2816Method X16Ws2816Method; typedef NeoEsp32I2s0X16Ws2812Method X16Ws2812Method; typedef NeoEsp32I2s0X16Lc8812Method X16Lc8812Method; + #else // plain old ESP32 //---------------------------------------------------------- #define NEO_X4_ALIAS @@ -192,7 +191,7 @@ typedef Rp2040x4Pio1Ws2812xMethod X4Ws2812xMethod; typedef Rp2040x4Pio1400KbpsMethod X4400KbpsMethod; #endif -// some plafforms do not have a native x4, so alias it to x8 +// some platforms do not have a native x4, so alias it to x8 // #if defined(NEO_X4_ALIAS) typedef X8Ws2812xMethod X4Ws2813Method; diff --git a/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sMethod.h b/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sMethod.h index 7cf5c20..a3c181f 100644 --- a/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sMethod.h +++ b/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sMethod.h @@ -28,7 +28,7 @@ License along with NeoPixel. If not, see // ESP32 beyond C3 & S3 I2S is not supported yet // due to significant changes to interface -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C63) && !defined(CONFIG_IDF_TARGET_ESP32H6) +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) extern "C" diff --git a/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sXMethod.h b/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sXMethod.h index ecc304a..35934e9 100644 --- a/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sXMethod.h +++ b/src/internal/methods/ESP/ESP32/Core_2_x/NeoEsp32I2sXMethod.h @@ -26,8 +26,9 @@ License along with NeoPixel. If not, see . -------------------------------------------------------------------------*/ -// ESP32C3/S3 I2S is not supported yet due to significant changes to interface -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) +// ESP32 beyond C3 & S3 I2S is not supported yet +// due to significant changes to interface +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4) extern "C" { diff --git a/src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h b/src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h index 5b3e3d0..f7286dc 100644 --- a/src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h +++ b/src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h @@ -55,121 +55,6 @@ struct rmt_led_strip_encoder_t rmt_symbol_word_t reset_code; }; -static size_t rmt_encode_led_strip(rmt_encoder_t* encoder, rmt_channel_handle_t channel, const void* primary_data, size_t data_size, rmt_encode_state_t* ret_state) -{ - rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); - rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder; - rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder; - rmt_encode_state_t session_state = RMT_ENCODING_RESET; - rmt_encode_state_t state = RMT_ENCODING_RESET; - size_t encoded_symbols = 0; - - switch (led_encoder->state) - { - case 0: // send RGB data - encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state); - if (session_state & RMT_ENCODING_COMPLETE) - { - led_encoder->state = 1; // switch to next state when current encoding session finished - } - if (session_state & RMT_ENCODING_MEM_FULL) - { - // static_cast(static_cast(a) | static_cast(b)); - state = static_cast(static_cast(state) | static_cast(RMT_ENCODING_MEM_FULL)); - goto out; // yield if there's no free space for encoding artifacts - } - // fall-through - case 1: // send reset code - encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code, - sizeof(led_encoder->reset_code), &session_state); - if (session_state & RMT_ENCODING_COMPLETE) - { - led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session - state = static_cast(static_cast(state) | static_cast(RMT_ENCODING_COMPLETE)); - } - if (session_state & RMT_ENCODING_MEM_FULL) - { - state = static_cast(static_cast(state) | static_cast(RMT_ENCODING_MEM_FULL)); - goto out; // yield if there's no free space for encoding artifacts - } - } - -out: - *ret_state = state; - return encoded_symbols; -} - -static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t* encoder) -{ - rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); - rmt_del_encoder(led_encoder->bytes_encoder); - rmt_del_encoder(led_encoder->copy_encoder); - delete led_encoder; - return ESP_OK; -} - -static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t* encoder) -{ - rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); - rmt_encoder_reset(led_encoder->bytes_encoder); - rmt_encoder_reset(led_encoder->copy_encoder); - led_encoder->state = RMT_ENCODING_RESET; - return ESP_OK; -} - -static esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t* config, rmt_encoder_handle_t* ret_encoder, uint32_t bit0, uint32_t bit1) -{ - const char* TAG = "TEST_RMT"; //TODO: Remove later - - esp_err_t ret = ESP_OK; - rmt_led_strip_encoder_t* led_encoder = NULL; - uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us - rmt_bytes_encoder_config_t bytes_encoder_config; - rmt_copy_encoder_config_t copy_encoder_config = {}; - rmt_symbol_word_t reset_code_config; - - - ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - led_encoder = new rmt_led_strip_encoder_t(); - ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder"); - led_encoder->base.encode = rmt_encode_led_strip; - led_encoder->base.del = rmt_del_led_strip_encoder; - led_encoder->base.reset = rmt_led_strip_encoder_reset; - - bytes_encoder_config.bit0.val = bit0; - bytes_encoder_config.bit1.val = bit1; - - bytes_encoder_config.flags.msb_first = 1; // WS2812 transfer bit order: G7...G0R7...R0B7...B0 - TODO: more checks - - ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed"); - ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed"); - - reset_code_config.level0 = 0; - reset_code_config.duration0 = reset_ticks; - reset_code_config.level1 = 0; - reset_code_config.duration1 = reset_ticks; - led_encoder->reset_code = reset_code_config; - *ret_encoder = &led_encoder->base; - return ret; - -err: - // AddLog(2,"RMT:could not init led decoder"); - if (led_encoder) - { - if (led_encoder->bytes_encoder) - { - rmt_del_encoder(led_encoder->bytes_encoder); - } - if (led_encoder->copy_encoder) - { - rmt_del_encoder(led_encoder->copy_encoder); - } - delete led_encoder; - } - - return ret; -} - #define NEOPIXELBUS_RMT_INT_FLAGS (ESP_INTR_FLAG_LOWMED) @@ -302,6 +187,121 @@ private: _dataSending = static_cast(malloc(_sizeData)); // no need to initialize it, it gets overwritten on every send } + + + static size_t rmt_encode_led_strip(rmt_encoder_t* encoder, rmt_channel_handle_t channel, const void* primary_data, size_t data_size, rmt_encode_state_t* ret_state) + { + rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); + rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder; + rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder; + rmt_encode_state_t session_state = RMT_ENCODING_RESET; + rmt_encode_state_t state = RMT_ENCODING_RESET; + size_t encoded_symbols = 0; + + switch (led_encoder->state) + { + case 0: // send RGB data + encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state); + if (session_state & RMT_ENCODING_COMPLETE) + { + led_encoder->state = 1; // switch to next state when current encoding session finished + } + if (session_state & RMT_ENCODING_MEM_FULL) + { + // static_cast(static_cast(a) | static_cast(b)); + state = static_cast(static_cast(state) | static_cast(RMT_ENCODING_MEM_FULL)); + goto out; // yield if there's no free space for encoding artifacts + } + // fall-through + case 1: // send reset code + encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code, + sizeof(led_encoder->reset_code), &session_state); + if (session_state & RMT_ENCODING_COMPLETE) + { + led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session + state = static_cast(static_cast(state) | static_cast(RMT_ENCODING_COMPLETE)); + } + if (session_state & RMT_ENCODING_MEM_FULL) + { + state = static_cast(static_cast(state) | static_cast(RMT_ENCODING_MEM_FULL)); + goto out; // yield if there's no free space for encoding artifacts + } + } + + out: + *ret_state = state; + return encoded_symbols; + } + + static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t* encoder) + { + rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); + rmt_del_encoder(led_encoder->bytes_encoder); + rmt_del_encoder(led_encoder->copy_encoder); + delete led_encoder; + return ESP_OK; + } + + static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t* encoder) + { + rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); + rmt_encoder_reset(led_encoder->bytes_encoder); + rmt_encoder_reset(led_encoder->copy_encoder); + led_encoder->state = RMT_ENCODING_RESET; + return ESP_OK; + } + + static esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t* config, rmt_encoder_handle_t* ret_encoder, uint32_t bit0, uint32_t bit1) + { + esp_err_t ret = ESP_OK; + rmt_led_strip_encoder_t* led_encoder = NULL; + uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us + rmt_bytes_encoder_config_t bytes_encoder_config; + rmt_copy_encoder_config_t copy_encoder_config = {}; + rmt_symbol_word_t reset_code_config; + + + ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + led_encoder = new rmt_led_strip_encoder_t(); + ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder"); + led_encoder->base.encode = rmt_encode_led_strip; + led_encoder->base.del = rmt_del_led_strip_encoder; + led_encoder->base.reset = rmt_led_strip_encoder_reset; + + bytes_encoder_config.bit0.val = bit0; + bytes_encoder_config.bit1.val = bit1; + + bytes_encoder_config.flags.msb_first = 1; // WS2812 transfer bit order: G7...G0R7...R0B7...B0 - TODO: more checks + + ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, "TEST_RMT", "create bytes encoder failed"); + ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, "TEST_RMT", "create copy encoder failed"); + + reset_code_config.level0 = 0; + reset_code_config.duration0 = reset_ticks; + reset_code_config.level1 = 0; + reset_code_config.duration1 = reset_ticks; + led_encoder->reset_code = reset_code_config; + *ret_encoder = &led_encoder->base; + return ret; + + err: + // AddLog(2,"RMT:could not init led decoder"); + if (led_encoder) + { + if (led_encoder->bytes_encoder) + { + rmt_del_encoder(led_encoder->bytes_encoder); + } + if (led_encoder->copy_encoder) + { + rmt_del_encoder(led_encoder->copy_encoder); + } + delete led_encoder; + } + + return ret; + } + }; // NOTE: While these are multi-instance auto channel selecting, there are limits @@ -315,6 +315,7 @@ private: typedef NeoEsp32RmtMethodBase NeoEsp32RmtXWs2811Method; typedef NeoEsp32RmtMethodBase NeoEsp32RmtXWs2812xMethod; typedef NeoEsp32RmtXWs2812xMethod NeoEsp32RmtXWs2816Method; +typedef NeoEsp32RmtXWs2812xMethod NeoEsp32RmtXWs2813Method; typedef NeoEsp32RmtMethodBase NeoEsp32RmtXWs2805Method; typedef NeoEsp32RmtXWs2805Method NeoEsp32RmtXWs2814Method; typedef NeoEsp32RmtMethodBase NeoEsp32RmtXSk6812Method; @@ -333,6 +334,7 @@ typedef NeoEsp32RmtMethodBase NeoEsp32RmtX400KbpsMethod typedef NeoEsp32RmtMethodBase NeoEsp32RmtXWs2811InvertedMethod; typedef NeoEsp32RmtMethodBase NeoEsp32RmtXWs2812xInvertedMethod; typedef NeoEsp32RmtXWs2812xInvertedMethod NeoEsp32RmtXWs2816InvertedMethod; +typedef NeoEsp32RmtXWs2812xInvertedMethod NeoEsp32RmtXWs2813InvertedMethod; typedef NeoEsp32RmtMethodBase NeoEsp32RmtXWs2805InvertedMethod; typedef NeoEsp32RmtXWs2805InvertedMethod NeoEsp32RmtXWs2814InvertedMethod; typedef NeoEsp32RmtMethodBase NeoEsp32RmtXSk6812InvertedMethod; @@ -350,7 +352,7 @@ typedef NeoEsp32RmtMethodBase NeoE // Normally I2s method is the default, defining NEOPIXEL_ESP32_RMT_DEFAULT // will switch to use RMT as the default method -// The ESP32S2, ESP32S3, ESP32C3, ESP32C6 will allways default to RMT +// The ESP32S2, ESP32S3, ESP32C3, ESP32C6 will always default to RMT typedef NeoEsp32RmtXWs2805Method NeoWs2805Method; typedef NeoEsp32RmtXWs2811Method NeoWs2811Method;