From 1ff5cb0596d4a355a96570a296b5c7f58ba7cf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Sun, 12 May 2024 11:12:13 +0200 Subject: [PATCH] Experimental parallel I2S support for ESP32 - increased outputs to 17 - increased max possible color order overrides - use WLED_USE_PARALLEL_I2S during compile WARNING: Do not set up more than 256 LEDs per output when using parallel I2S with NeoPixelBus less than 2.9.0 --- wled00/bus_wrapper.h | 65 +++++++++++++++++++++----- wled00/cfg.cpp | 14 +++--- wled00/const.h | 6 ++- wled00/data/settings_leds.htm | 86 ++++++++++++++++++----------------- wled00/set.cpp | 51 +++++++++++---------- wled00/xml.cpp | 36 ++++++++------- 6 files changed, 156 insertions(+), 102 deletions(-) diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 99ae4c5ef..57e98467e 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -224,8 +224,11 @@ //#define B_32_I0_NEO_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_NEO_3 NeoPixelBusLg -//#define B_32_I1_NEO_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_NEO_3 NeoPixelBusLg // parallel I2S + #endif #endif //RGBW #define B_32_RN_NEO_4 NeoPixelBusLg @@ -234,8 +237,11 @@ //#define B_32_I0_NEO_4 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_NEO_4 NeoPixelBusLg -//#define B_32_I1_NEO_4 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_NEO_4 NeoPixelBusLg // parallel I2S + #endif #endif //400Kbps #define B_32_RN_400_3 NeoPixelBusLg @@ -244,8 +250,11 @@ //#define B_32_I0_400_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_400_3 NeoPixelBusLg -//#define B_32_I1_400_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_400_3 NeoPixelBusLg // parallel I2S + #endif #endif //TM1814 (RGBW) #define B_32_RN_TM1_4 NeoPixelBusLg @@ -254,8 +263,11 @@ //#define B_32_I0_TM1_4 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_TM1_4 NeoPixelBusLg -//#define B_32_I1_TM1_4 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_TM1_4 NeoPixelBusLg // parallel I2S + #endif #endif //TM1829 (RGB) #define B_32_RN_TM2_3 NeoPixelBusLg @@ -264,8 +276,11 @@ //#define B_32_I0_TM2_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_TM2_3 NeoPixelBusLg -//#define B_32_I1_TM2_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_TM2_3 NeoPixelBusLg // parallel I2S + #endif #endif //UCS8903 #define B_32_RN_UCS_3 NeoPixelBusLg @@ -274,8 +289,11 @@ //#define B_32_I0_UCS_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_UCS_3 NeoPixelBusLg -//#define B_32_I1_UCS_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_UCS_3 NeoPixelBusLg // parallel I2S + #endif #endif //UCS8904 #define B_32_RN_UCS_4 NeoPixelBusLg @@ -284,8 +302,11 @@ //#define B_32_I0_UCS_4 NeoPixelBusLg// parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_UCS_4 NeoPixelBusLg -//#define B_32_I1_UCS_4 NeoPixelBusLg// parallel I2S + #else +#define B_32_I1_UCS_4 NeoPixelBusLg// parallel I2S + #endif #endif #define B_32_RN_APA106_3 NeoPixelBusLg #ifndef WLED_NO_I2S0_PIXELBUS @@ -293,8 +314,11 @@ //#define B_32_I0_APA106_3 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_APA106_3 NeoPixelBusLg -//#define B_32_I1_APA106_3 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_APA106_3 NeoPixelBusLg // parallel I2S + #endif #endif //FW1906 GRBCW #define B_32_RN_FW6_5 NeoPixelBusLg @@ -303,8 +327,11 @@ //#define B_32_I0_FW6_5 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_FW6_5 NeoPixelBusLg -//#define B_32_I1_FW6_5 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_FW6_5 NeoPixelBusLg // parallel I2S + #endif #endif //WS2805 RGBWC #define B_32_RN_2805_5 NeoPixelBusLg @@ -313,8 +340,11 @@ //#define B_32_I0_2805_5 NeoPixelBusLg // parallel I2S #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_2805_5 NeoPixelBusLg -//#define B_32_I1_2805_5 NeoPixelBusLg // parallel I2S + #else +#define B_32_I1_2805_5 NeoPixelBusLg // parallel I2S + #endif #endif //TM1914 (RGB) #define B_32_RN_TM1914_3 NeoPixelBusLg @@ -323,8 +353,11 @@ //#define B_32_I0_TM1914_3 NeoPixelBusLg #endif #ifndef WLED_NO_I2S1_PIXELBUS + #ifndef WLED_USE_PARALLEL_I2S #define B_32_I1_TM1914_3 NeoPixelBusLg -//#define B_32_I1_TM1914_3 NeoPixelBusLg + #else +#define B_32_I1_TM1914_3 NeoPixelBusLg + #endif #endif #endif @@ -541,7 +574,11 @@ class PolyBus { #if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3)) // NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation // since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation + #ifdef WLED_USE_PARALLEL_I2S + if (channel > 7) channel -= 8; // accommodate parallel I2S1 which is used 1st on classic ESP32 + #else if (channel > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32 + #endif #endif void* busPtr = nullptr; switch (busType) { @@ -1619,9 +1656,15 @@ class PolyBus { //if (num > 3) offset = num -4; // I2S not supported yet #else // standard ESP32 has 8 RMT and 2 I2S channels + #ifdef WLED_USE_PARALLEL_I2S + if (num > 16) return I_NONE; + if (num < 8) offset = 2; // prefer 8 parallel I2S1 channels + if (num == 16) offset = 1; + #else if (num > 9) return I_NONE; if (num > 8) offset = 1; if (num == 0) offset = 2; // prefer I2S1 for 1st bus (less flickering but more RAM needed) + #endif #endif switch (busType) { case TYPE_WS2812_1CH_X3: diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 22bfe577a..addd3fc5e 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -124,7 +124,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(strip.panels, matrix[F("mpc")]); strip.panel.clear(); JsonArray panels = matrix[F("panels")]; - uint8_t s = 0; + int s = 0; if (!panels.isNull()) { strip.panel.reserve(max(1U,min((size_t)strip.panels,(size_t)WLED_MAX_PANELS))); // pre-allocate memory for panels for (JsonObject pnl : panels) { @@ -156,7 +156,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { JsonArray ins = hw_led["ins"]; if (fromFS || !ins.isNull()) { - uint8_t s = 0; // bus iterator + int s = 0; // bus iterator if (fromFS) BusManager::removeAll(); // can't safely manipulate busses directly in network callback uint32_t mem = 0, globalBufMem = 0; uint16_t maxlen = 0; @@ -790,7 +790,7 @@ void serializeConfig() { JsonObject matrix = hw_led.createNestedObject(F("matrix")); matrix[F("mpc")] = strip.panels; JsonArray panels = matrix.createNestedArray(F("panels")); - for (uint8_t i=0; igetLength()==0) break; JsonObject ins = hw_led_ins.createNestedObject(); @@ -815,7 +815,7 @@ void serializeConfig() { JsonArray ins_pin = ins.createNestedArray("pin"); uint8_t pins[5]; uint8_t nPins = bus->getPins(pins); - for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]); + for (int i = 0; i < nPins; i++) ins_pin.add(pins[i]); ins[F("order")] = bus->getColorOrder(); ins["rev"] = bus->isReversed(); ins[F("skip")] = bus->skippedLeds(); @@ -829,7 +829,7 @@ void serializeConfig() { JsonArray hw_com = hw.createNestedArray(F("com")); const ColorOrderMap& com = BusManager::getColorOrderMap(); - for (uint8_t s = 0; s < com.count(); s++) { + for (int s = 0; s < com.count(); s++) { const ColorOrderMapEntry *entry = com.get(s); if (!entry) break; @@ -846,7 +846,7 @@ void serializeConfig() { JsonArray hw_btn_ins = hw_btn.createNestedArray("ins"); // configuration for all buttons - for (uint8_t i=0; i LED Settings