From 79402208eebe49977354701433bee80727f5e14b Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:18:57 -0400 Subject: [PATCH 001/123] Allow E131_MAX_UNIVERSE_COUNT override --- wled00/const.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/wled00/const.h b/wled00/const.h index d4ec0442..5203d774 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -425,13 +425,15 @@ #endif #endif -#ifdef WLED_USE_ETHERNET - #define E131_MAX_UNIVERSE_COUNT 20 -#else - #ifdef ESP8266 - #define E131_MAX_UNIVERSE_COUNT 9 +#ifndef E131_MAX_UNIVERSE_COUNT + #ifdef WLED_USE_ETHERNET + #define E131_MAX_UNIVERSE_COUNT 20 #else - #define E131_MAX_UNIVERSE_COUNT 12 + #ifdef ESP8266 + #define E131_MAX_UNIVERSE_COUNT 9 + #else + #define E131_MAX_UNIVERSE_COUNT 12 + #endif #endif #endif From a84ac5b1eeae1a0e9322205c4c80cffaeedf07ad Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:25:00 +0200 Subject: [PATCH 002/123] Merge pull request #4060 from DedeHai/0_15_bootdelay boot-up delay to fix wifi not starting in some setups use `-D WLED_BOOTUPDELAY=500` (or some other delay you want, in milliseconds) in platformio env definition to add 500ms of delay before hardware init. --- wled00/wled.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 71050d99..171be5c7 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -448,6 +448,9 @@ void WLED::setup() #ifdef ARDUINO_ARCH_ESP32 pinMode(hardwareRX, INPUT_PULLDOWN); delay(1); // suppress noise in case RX pin is floating (at low noise energy) - see issue #3128 #endif + #ifdef WLED_BOOTUPDELAY + delay(WLED_BOOTUPDELAY); // delay to let voltage stabilize, helps with boot issues on some setups + #endif Serial.begin(115200); if (!Serial) delay(1000); // WLEDMM make sure that Serial has initalized From 0562debbe1670fc72971d95da296cc9fb53f5f9a Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 28 Jul 2024 10:38:39 +0100 Subject: [PATCH 003/123] hub75 - slow updates to reduce wifi performance issues --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4af34b86..5f53cd1d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1035,8 +1035,9 @@ HUB75_build_flags = -D NO_GFX ;; Disable the use of Adafruit_GFX by the HUB75 driver -D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size -D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already + -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips ;; HUB75_lib_deps = https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.10 ;; does not work any more -HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; something strange is going on here ... +HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) NetDebug_build_flags = From ecb8817c907caf2dafd36352850d0d6c9eb4e550 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:03:19 +0200 Subject: [PATCH 004/123] Update audio_source.h - swapped channel bug still exists in 2.0.17 Actually we could even check for " < 5.0.0 " - arduino 2.0.x is in maintenance mode now, and I see little chance that a fix will appear before 3.0.0. --- usermods/audioreactive/audio_source.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index d7c0478c..77111446 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -93,7 +93,7 @@ * if you want to receive two channels, one is the actual data from microphone and another channel is suppose to receive 0, it's different data in two channels, you need to choose I2S_CHANNEL_FMT_RIGHT_LEFT in this case. */ -#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)) && (ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 6)) // fixed in IDF 4.4.5, however arduino-esp32 2.0.14 did an "I2S rollback" to 4.4.4 +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)) && (ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 8)) // should be fixed in IDF 4.4.5, however arduino-esp32 2.0.14 - 2.0.17 did an "I2S rollback" to 4.4.4 // espressif bug: only_left has no sound, left and right are swapped // https://github.com/espressif/esp-idf/issues/9635 I2S mic not working since 4.4 (IDFGH-8138) // https://github.com/espressif/esp-idf/issues/8538 I2S channel selection issue? (IDFGH-6918) From 114cdfefd842cb9f570dafff18bd4ca5bd1b7a73 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:16:44 +0200 Subject: [PATCH 005/123] Hub75 lib versions rollback 3.0.11 breaks the gh build. --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 5f53cd1d..59b43b1f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1037,7 +1037,8 @@ HUB75_build_flags = -D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips ;; HUB75_lib_deps = https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.10 ;; does not work any more -HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 +;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30) +HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; something strange is going on here ... HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) NetDebug_build_flags = From 18f9d64e24fe31921d4c8f0cfc88a8830898e7dc Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 3 Aug 2024 23:49:13 +0200 Subject: [PATCH 006/123] HUB75 lib version 3.0.11 using the git hash of version 3.0.11 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 59b43b1f..ec1a387d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1036,9 +1036,9 @@ HUB75_build_flags = -D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size -D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips -;; HUB75_lib_deps = https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.10 ;; does not work any more ;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30) -HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; something strange is going on here ... +;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... +HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11 HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) NetDebug_build_flags = From 5f4834dec4acb4cfe3613a1145cc06697c5582ed Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:06:38 +0200 Subject: [PATCH 007/123] small improvements * optimized fadeToBlackBy() - don't repaint unchanged pixels * made MIN_HEAP_SIZE configurable by build_flags * specific error message when not enough memory for LEDs buffer --- wled00/FX_fcn.cpp | 8 +++++--- wled00/const.h | 3 +++ wled00/data/index.js | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 65849ff1..4c43218a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -132,7 +132,7 @@ void Segment::allocLeds() { ledsrgbSize = ledsrgb?size:0; if (ledsrgb == nullptr) { USER_PRINTLN("allocLeds failed!!"); - errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag + errorFlag = ERR_LOW_BUF; // WLEDMM raise errorflag } } else { @@ -1442,8 +1442,10 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) { // WLEDMM minor optimization if(is2D()) { - for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) { - setPixelColorXY((uint16_t)x, (uint16_t)y, CRGB(getPixelColorXY(x,y)).nscale8(scaledown)); + for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { + uint32_t cc = getPixelColorXY(x,y); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion + uint32_t cc2 = color_fade(cc, scaledown); // fade + if (cc2 != cc) setPixelColorXY((uint16_t)x, (uint16_t)y, cc2); // WLEDMM only re-paint if faded color is different } } else { for (uint_fast16_t x = 0; x < cols; x++) { diff --git a/wled00/const.h b/wled00/const.h index 5203d774..ff8b0371 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -352,6 +352,7 @@ #define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM) #define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws) #define ERR_LOW_AJAX_MEM 36 // WLEDMM: low memory (oappend) +#define ERR_LOW_BUF 37 // WLEDMM: low memory (LED buffer from allocLEDs) // Timer mode types #define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness @@ -480,7 +481,9 @@ #endif //#define MIN_HEAP_SIZE (8k for AsyncWebServer) +#if !defined(MIN_HEAP_SIZE) #define MIN_HEAP_SIZE 8192 +#endif // Maximum size of node map (list of other WLED instances) #ifdef ESP8266 diff --git a/wled00/data/index.js b/wled00/data/index.js index e89ad78e..61480d5e 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2008,6 +2008,9 @@ function readState(s,command=false) case 36: errstr = "Low Memory (oappend buffer)."; break; + case 37: + errstr = "no memory for LEDs buffer."; + break; } showToast('Error ' + s.error + ": " + errstr, true); } From 6505e04cbf9b978068feed57588c41a49a2fc61b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:09:50 +0200 Subject: [PATCH 008/123] minor effect improvements * 2DBlackHole: improved accuracy * 2Dfloatingblobs: draw anti-aliased blobs when "blur" slider = 1 * FX framework: un-clutter and optimize "XY()" --- wled00/FX.cpp | 16 +++++++++------- wled00/FX.h | 6 ++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 4f89af77..4cce3230 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4922,17 +4922,18 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma } SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails - unsigned long t = strip.now/128; // timebase + const unsigned long ratio = 128; // rotation speed + unsigned long t = strip.now; // timebase // outer stars - for (size_t i = 0; i < 8; i++) { - x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i); + for (unsigned i = 0; i < 8; i++) { + x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio); + y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio); SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255)); } // inner stars for (size_t i = 0; i < 4; i++) { - x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i); + x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio); + y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio); SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255)); } // central white dot @@ -6270,6 +6271,7 @@ uint16_t mode_2Dfloatingblobs(void) { } SEGMENT.fadeToBlackBy(20); + bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 5); //WLEDMM // Bounce balls around for (size_t i = 0; i < Amount; i++) { @@ -6289,7 +6291,7 @@ uint16_t mode_2Dfloatingblobs(void) { } } uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0); - if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c); + if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c, drawAA); else SEGMENT.setPixelColorXY((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c); // move x if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f)); diff --git a/wled00/FX.h b/wled00/FX.h index af707b41..00ae3183 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -661,10 +661,8 @@ typedef struct Segment { #ifndef WLED_DISABLE_2D inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed - uint_fast16_t width = virtualWidth(); // segment width in logical pixels - uint_fast16_t height = virtualHeight(); // segment height in logical pixels - if (width == 0) return 0; // softhack007 avoid div/0 - if (height == 0) return (x%width); // softhack007 avoid div/0 + uint_fast16_t width = max(uint16_t(1), virtualWidth()); // segment width in logical pixels -- softhack007 avoid div/0 + uint_fast16_t height = max(uint16_t(1), virtualHeight()); // segment height in logical pixels -- softhack007 avoid div/0 return (x%width) + (y%height) * width; } From 078bd7077504f8fca97dfb5c1cac5613a50f6fa0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:28:03 +0200 Subject: [PATCH 009/123] HUB75 speedups and minor improvements * HUB75: allow to use native driver gamma correction - requires to undo WLED gamma * added unGamma24() function * HUB75: optimized setPixelColor() * some experimental HUB75 stuff --- wled00/bus_manager.cpp | 33 ++++++++++++++++++++++++--------- wled00/bus_manager.h | 3 ++- wled00/colors.cpp | 6 ++++++ wled00/fcn_declare.h | 1 + wled00/wled.h | 2 +- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a24fdf28..604a92c5 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -501,6 +501,7 @@ void BusNetwork::cleanup() { BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { + _valid = false; mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory @@ -594,6 +595,13 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.d = 21; mxconfig.gpio.e = 12; + // mxconfig.double_buff = true; // <------------- Turn on double buffer + // mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver + //mxconfig.latch_blanking = 3; + // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz + //mxconfig.min_refresh_rate = 90; + //mxconfig.min_refresh_rate = 120; + #else USER_PRINTLN("MatrixPanel_I2S_DMA - Default pins"); /* @@ -691,18 +699,25 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh } void BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { - r = R(c); - g = G(c); - b = B(c); + if (!_valid || pix >= _len) return; +#ifndef NO_CIE1931 + c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction +#endif + uint8_t r = R(c); + uint8_t g = G(c); + uint8_t b = B(c); + if(fourScanPanel != nullptr) { - x = pix % fourScanPanel->width(); - y = floor(pix / fourScanPanel->width()); - fourScanPanel->drawPixelRGB888(x, y, r, g, b); + int pxwidth = fourScanPanel->width(); + int x = pix % pxwidth; + int y = pix / pxwidth; + fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } else { - x = pix % display->width(); - y = floor(pix / display->width()); - display->drawPixelRGB888(x, y, r, g, b); + int pxwidth = display->width(); + int x = pix % pxwidth; + int y = pix / pxwidth; + display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 0bfd3e04..40fc0061 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -4,6 +4,7 @@ #ifdef WLED_ENABLE_HUB75MATRIX #include #include +//extern volatile bool previousBufferFree; // experimental #endif /* * Class for addressing various light types @@ -348,6 +349,7 @@ class BusHub75Matrix : public Bus { void show() { if(mxconfig.double_buff) { display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels) + // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. display->clearScreen(); // Now clear the back-buffer } } @@ -377,7 +379,6 @@ class BusHub75Matrix : public Bus { MatrixPanel_I2S_DMA *display = nullptr; VirtualMatrixPanel *fourScanPanel = nullptr; HUB75_I2S_CFG mxconfig; - uint8_t r, g, b, x, y; }; #endif diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 465fefbb..f7751861 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -413,6 +413,12 @@ uint8_t unGamma8(uint8_t value) { if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal); return gammaTinv[value]; } + +uint32_t unGamma24(uint32_t c) { + if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return c; + if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal); + return RGBW32(gammaTinv[R(c)], gammaTinv[G(c)], gammaTinv[B(c)], W(c)); +} // wleDMM end uint8_t gamma8_cal(uint8_t b, float gamma) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index aa0645d0..a0713d0f 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -69,6 +69,7 @@ void calcGammaTable(float gamma); uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure uint32_t __attribute__((pure)) gamma32(uint32_t); // WLEDMM: added attribute pure uint8_t unGamma8(uint8_t value); // WLEDMM revert gamma correction +uint32_t unGamma24(uint32_t c); // WLEDMM for 24bit color (white left as-is) //dmx_output.cpp void initDMXOutput(); diff --git a/wled00/wled.h b/wled00/wled.h index 5d881cf0..be21de04 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2407171 +#define VERSION 2408050 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 5240c3450b116dc1df935926487c1549e525b304 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:30:25 +0200 Subject: [PATCH 010/123] Segment drawing optimizations (FASTPATH only) * cache width, height, and a few more values that are normally re-calculated for each pixel * make normal sPC a bit faster * Segment::fade_out() optimization --> only active in FASTPATH mode, to preserve flash on small devices (8266) --> code still needs some polishing --> up to 20% speedup with some 2D effects (esp32, flash qio 80Mhz, -O2) --- wled00/FX.h | 50 ++++++++++++++++++++++++++++++++++++++++++++- wled00/FX_2Dfcn.cpp | 23 ++++++++++++++++++--- wled00/FX_fcn.cpp | 24 ++++++++++++++++------ wled00/wled.h | 2 +- 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 00ae3183..aa5014e2 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -434,6 +434,19 @@ typedef struct Segment { static size_t _usedSegmentData; // WLEDMM uint16_t is too small void setPixelColorXY_fast(int x, int y,uint32_t c, uint32_t scaled_col, int cols, int rows); // set relative pixel within segment with color - faster, but no error checking!!! +#ifdef WLEDMM_FASTPATH + // WLEDMM cache some values that won't change while drawing a frame + bool _isSimpleSegment = false; + bool _isValid2D = false; + uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity + uint16_t _2dWidth = 0; // virtualWidth + uint16_t _2dHeight = 0; // virtualHeight + + void setPixelColorXY_slow(int x, int y, uint32_t c); // set relative pixel within segment with color - full slow version +#else + void setPixelColorXY_slow(int x, int y, uint32_t c) { setPixelColorXY(x,y,c); } // not FASTPATH - slow is the normal +#endif + // perhaps this should be per segment, not static static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette()) @@ -587,6 +600,7 @@ typedef struct Segment { bool allocateData(size_t len); void deallocateData(void); void resetIfRequired(void); + void startFrame(void); // cache a few values that don't change while an effect is drawing /** * Flags that before the next effect is calculated, * the internal segment state should be reset. @@ -642,6 +656,7 @@ typedef struct Segment { uint32_t __attribute__((pure)) color_wheel(uint8_t pos); // 2D matrix +#ifndef WLEDMM_FASTPATH inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline uint_fast16_t groupLen = groupLength(); uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen; @@ -654,6 +669,23 @@ typedef struct Segment { if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED return vHeight; } +#else + inline uint16_t virtualWidth() const { return(_2dWidth);} // WLEDMM get pre-calculated virtualWidth + inline uint16_t virtualHeight() const { return(_2dHeight);} // WLEDMM get pre-calculated virtualHeight + + uint16_t calc_virtualWidth() const { + uint_fast16_t groupLen = groupLength(); + uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen; + if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED + return vWidth; + } + uint16_t calc_virtualHeight() const { + uint_fast16_t groupLen = groupLength(); + uint_fast16_t vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen; + if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED + return vHeight; + } +#endif uint16_t nrOfVStrips(void) const; void createjMap(); //WLEDMM jMap @@ -666,8 +698,24 @@ typedef struct Segment { return (x%width) + (y%height) * width; } - //void setPixelColorXY_fast(int x, int y,uint32_t c); // set relative pixel within segment with color - wrapper for _fast +#ifdef WLEDMM_FASTPATH + // WLEDMM this is a "gateway" function - we either call _fast or fall back to "slow" + inline void setPixelColorXY(int x, int y, uint32_t col) { + if (!_isSimpleSegment) { // slow path + setPixelColorXY_slow(x, y, col); + } else { // fast path + // some sanity checks + if (!_isValid2D) return; // not active + if ((unsigned(x) >= _2dWidth) || (unsigned(y) >= _2dHeight)) return; // check if (x,y) are out-of-range - due to 2's complement, this also catches negative values + if (!_brightness && !transitional) return; // black-out + + uint32_t scaled_col = (_brightness == 255) ? col : color_fade(col, _brightness); // calculate final color + setPixelColorXY_fast(x, y, col, scaled_col, int(_2dWidth), int(_2dHeight)); // call "fast" function + } +} +#else void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color +#endif inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); } inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 83ec0f54..df4387db 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -217,6 +217,19 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) { #ifndef WLED_DISABLE_2D +// WLEDMM cache some values so we don't need to re-calc then for each pixel +void Segment::startFrame(void) { +#ifdef WLEDMM_FASTPATH + _isValid2D = isActive() && is2D(); + _brightness = currentBri(on ? opacity : 0); + _isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved + // if (reverse_y) _isSimpleSegment = false; // for A/B testing + _2dWidth = is2D() ? calc_virtualWidth() : virtualLength(); + _2dHeight = calc_virtualHeight(); +#endif +} +// WLEDMM end + // XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element) // WLEDMM Segment::XY()is declared inline, see FX.h @@ -266,7 +279,11 @@ void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_ // normal Segment::setPixelColorXY with error checking, and support for grouping / spacing +#ifdef WLEDMM_FASTPATH +void IRAM_ATTR_YN Segment::setPixelColorXY_slow(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally, renamed to "_slow" +#else void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +#endif { if (Segment::maxHeight==1) return; // not a matrix set-up const int_fast16_t cols = virtualWidth(); // WLEDMM optimization @@ -520,7 +537,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) { for (int j = 0; j < dim1; j++) { int x = vertical ? i : j; int y = vertical ? j : i; - setPixelColorXY(x, y, out[j]); + if (in[j] != out[j]) setPixelColorXY(x, y, out[j]); } } @@ -698,7 +715,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 // single pixel (line length == 0) if (dx+dy == 0) { if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows); - else setPixelColorXY(x0, y0, c); + else setPixelColorXY_slow(x0, y0, c); return; } @@ -734,7 +751,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 for (;;) { // if (x0 >= cols || y0 >= rows) break; // WLEDMM we hit the edge - should never happen if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows); - else setPixelColorXY(x0, y0, c); + else setPixelColorXY_slow(x0, y0, c); if (x0==x1 && y0==y1) break; int e2 = err; if (e2 >-dx) { err -= dy; x0 += sx; } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 4c43218a..faf23625 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -266,6 +266,7 @@ void Segment::resetIfRequired() { deallocateData(); next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; reset = false; // setOption(SEG_OPTION_RESET, false); + startFrame(); // WLEDMM update cached propoerties } } @@ -673,7 +674,11 @@ class JMapC { if (size > 0) return size; else +#ifndef WLEDMM_FASTPATH return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); //pixels +#else + return SEGMENT.calc_virtualWidth() * SEGMENT.calc_virtualHeight(); // calc pixel sizes +#endif } void setPixelColor(uint16_t i, uint32_t col) { updatejMapDoc(); @@ -765,7 +770,11 @@ class JMapC { jMapFile.close(); maxWidth++; maxHeight++; +#ifndef WLEDMM_FASTPATH scale = min(SEGMENT.virtualWidth() / maxWidth, SEGMENT.virtualHeight() / maxHeight); // WLEDMM use native min/max +#else + scale = min(SEGMENT.calc_virtualWidth() / maxWidth, SEGMENT.calc_virtualHeight() / maxHeight); // WLEDMM re-calc width/heiht from active settings +#endif dataSize += sizeof(jVectorMap); USER_PRINT("dataSize "); USER_PRINT(dataSize); @@ -1057,7 +1066,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT // set pixel if (x != lastX || y != lastY) { // only paint if pixel position is different if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH); - else setPixelColorXY(x, y, col); + else setPixelColorXY_slow(x, y, col); } lastX = x; lastY = y; @@ -1353,7 +1362,7 @@ void Segment::fill(uint32_t c) { // fill 2D segment for(int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { if (simpleSegment) setPixelColorXY_fast(x, y, c, scaled_col, cols, rows); - else setPixelColorXY(x, y, c); + else setPixelColorXY_slow(x, y, c); } } else { // fill 1D strip for (int x = 0; x < cols; x++) setPixelColor(x, c); @@ -1408,7 +1417,7 @@ void Segment::fade_out(uint8_t rate) { int g2 = G(color2); int b2 = B(color2); - for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) { + for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x); if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do int w1 = W(color); @@ -1426,10 +1435,12 @@ void Segment::fade_out(uint8_t rate) { rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1; gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1; bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1; + uint32_t colorNew = RGBW32(r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); // WLEDMM - //if ((wdelta == 0) && (rdelta == 0) && (gdelta == 0) && (bdelta == 0)) continue; // WLEDMM delta = zero => no change // causes problem with text overlay - if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); - else setPixelColor((uint16_t)x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); + if (colorNew != color) { // WLEDMM speedup - do not repaint the same color + if (is2D()) setPixelColorXY(x, y, colorNew); + else setPixelColor(x, colorNew); + } } } @@ -1836,6 +1847,7 @@ void WS2812FX::service() { if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB); for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]); + seg.startFrame(); // WLEDMM // effect blending (execute previous effect) // actual code may be a bit more involved as effects have runtime data including allocated memory //if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress()); diff --git a/wled00/wled.h b/wled00/wled.h index be21de04..2ff0d902 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408050 +#define VERSION 2408051 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 9ee4165dad6fefd65fedc483ef34b8a620bcf073 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:37:49 -0400 Subject: [PATCH 011/123] Freqmatrix stop identical first pixel/line --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 4cce3230..d6c5820c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7513,9 +7513,9 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch } // shift the pixels one pixel up - SEGMENT.setPixelColor(0, color); // if SEGLEN equals 1 this loop won't execute for (int i = SEGLEN - 1; i > 0; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left + SEGMENT.setPixelColor(0, color); } return FRAMETIME; From 42919f9daf8e1073840b511cbc34f1e16f5986de Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 6 Aug 2024 15:53:46 +0200 Subject: [PATCH 012/123] blob effect improvements, and a dirty hack for HUB75 double buffer * mode_2Dfloatingblobs() improvements for large panels * Segment::fillCircle() speed optimizations * HUB75 hack (disabled by default): skip first fill(BLACK) when using double buffering (as the buffer gets cleared after each frame) --- wled00/FX.cpp | 9 ++++++--- wled00/FX.h | 5 +++-- wled00/FX_2Dfcn.cpp | 30 ++++++++++++++++++++++-------- wled00/FX_fcn.cpp | 12 ++++++++++++ wled00/wled.h | 2 +- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index d6c5820c..a9bfccbb 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6271,7 +6271,10 @@ uint16_t mode_2Dfloatingblobs(void) { } SEGMENT.fadeToBlackBy(20); - bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 5); //WLEDMM + bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 6); //WLEDMM + const uint16_t minDim = min(cols, rows); // WLEDMM use smaller dimension to find good blob size + float max_grow = min(minDim/4.f,2.f); + if (minDim>=24) max_grow =(minDim/8.0f); // WLEDMM allow bigger blobs // Bounce balls around for (size_t i = 0; i < Amount; i++) { @@ -6280,13 +6283,13 @@ uint16_t mode_2Dfloatingblobs(void) { if (blob->grow[i]) { // enlarge radius until it is >= 4 blob->r[i] += (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f; - if (blob->r[i] >= min(cols/4.f,2.f)) { + if (blob->r[i] >= max_grow) { blob->grow[i] = false; } } else { // reduce radius until it is < 1 blob->r[i] -= (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f; - if (blob->r[i] < 1.f) { + if (blob->r[i] < 0.8f) { blob->grow[i] = true; } } diff --git a/wled00/FX.h b/wled00/FX.h index aa5014e2..1393d5a2 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -439,6 +439,7 @@ typedef struct Segment { bool _isSimpleSegment = false; bool _isValid2D = false; uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity + bool _firstFill = true; // dirty HACK support uint16_t _2dWidth = 0; // virtualWidth uint16_t _2dHeight = 0; // virtualHeight @@ -741,8 +742,8 @@ typedef struct Segment { void move(uint8_t dir, uint8_t delta, bool wrap = false); void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false); inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } - void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false); - inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } + void fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft); + inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX); inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index df4387db..e6587d7d 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -226,6 +226,9 @@ void Segment::startFrame(void) { // if (reverse_y) _isSimpleSegment = false; // for A/B testing _2dWidth = is2D() ? calc_virtualWidth() : virtualLength(); _2dHeight = calc_virtualHeight(); + #if 0 && defined(WLED_ENABLE_HUB75MATRIX) + _firstFill = true; // dirty HACK + #endif #endif } // WLEDMM end @@ -651,19 +654,26 @@ void Segment::drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, } // by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs -void Segment::fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, bool soft) { - if (!isActive() || radius == 0) return; // not active +void Segment::fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft) { + if (!isActive() || radius <= 0) return; // not active // draw soft bounding circle if (soft) drawCircle(cx, cy, radius, col, soft); - // fill it const int cols = virtualWidth(); const int rows = virtualHeight(); - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - if (x * x + y * y <= radius * radius && - int16_t(cx)+x>=0 && int16_t(cy)+y>=0 && - int16_t(cx)+x 3) && !soft) ? 1:0); // WLEDMM pre-compute r^2; '-1' removes spikes from bigger blobs + // WLEDMM pre-compute boundaries + const int startx = max(-radius, -int(cx)); + const int endx = min(radius, cols-1-int(cx)); + const int starty = max(-radius, -int(cy)); + const int endy = min(radius, rows-1-int(cy)); + + // fill it - WLEDMM optimized + for (int y = starty; y <= endy; y++) { + for (int x = startx; x <= endx; x++) { + if ((x * x + y * y) <= maxRadius2) { setPixelColorXY(cx + x, cy + y, col); + } } } } @@ -690,7 +700,11 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 uint32_t scaled_col = c; if (simpleSegment) { // segment brightness must be pre-calculated for the "fast" setPixelColorXY variant! + #ifdef WLEDMM_FASTPATH + uint8_t _bri_t = _brightness; + #else uint8_t _bri_t = currentBri(on ? opacity : 0); + #endif if (!_bri_t && !transitional) return; if (_bri_t < 255) scaled_col = color_fade(c, _bri_t); } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index faf23625..0e63c853 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1347,6 +1347,18 @@ void Segment::refreshLightCapabilities() { */ void Segment::fill(uint32_t c) { if (!isActive()) return; // not active + + #if 0 && defined(WLED_ENABLE_HUB75MATRIX) && defined(WLEDMM_FASTPATH) + // DIRTY HACK - this ignores the first fill(black) in each frame, knowing that HUB75 has already blanked out the display. + if (_firstFill) { + _firstFill = false; + if (c == BLACK) { + if (ledsrgb && ledsrgbSize > 0) memset(ledsrgb, 0, ledsrgbSize); + return; + } + } + #endif + const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D diff --git a/wled00/wled.h b/wled00/wled.h index 2ff0d902..34667df1 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408051 +#define VERSION 2408060 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 5778b596beb8142896cd8a008ae98adb71c6c73d Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Tue, 6 Aug 2024 10:44:44 -0400 Subject: [PATCH 013/123] ESP32-ETHERNET-KIT-VE Fix Changed eth_address from 0 to 1 based on testing with devkit as it wasn't working by default with 0 --- wled00/network.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/network.cpp b/wled00/network.cpp index 1e414d81..7e0048d8 100644 --- a/wled00/network.cpp +++ b/wled00/network.cpp @@ -89,7 +89,7 @@ const ethernet_settings ethernetBoards[] = { // ESP32-ETHERNET-KIT-VE { - 0, // eth_address, + 1, // eth_address, WLED-MM: Changed from 0 to 1 based on not working with 0 on same devkit. 5, // eth_power, 23, // eth_mdc, 18, // eth_mdio, From 273154db762f8e17c0a756c4370741f8c7acdcd4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 6 Aug 2024 18:13:59 +0200 Subject: [PATCH 014/123] drawArc speedup (Circle mapping mode) * Optimize drawArc to skip pixels that are off-screen or outside the circle's bounding box. Also move repeating calculations out of the inner loop. testcase 64x64 : 8fps --> 33 fps :-) --- wled00/FX.h | 4 ++-- wled00/FX_2Dfcn.cpp | 42 +++++++++++++++++++++++++----------------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 1393d5a2..98e934e0 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -746,8 +746,8 @@ typedef struct Segment { inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX); inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline - void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0); - inline void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline + void drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor = 0); + inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline void wu_pixel(uint32_t x, uint32_t y, CRGB c); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index e6587d7d..71fb0cb2 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -774,27 +774,34 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 } } -void Segment::drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor) { - if (!isActive()) return; // not active - // float step = degrees / (2.85f*MAX(radius,1)); - // for (float rad = 0.0f; rad <= degrees+step/2; rad += step) { - // // may want to try float version as well (with or without antialiasing) - // int x = roundf(sin_t(rad) * radius); - // int y = roundf(cos_t(rad) * radius); - // setPixelColorXY(x+x0, y+y0, c); - // } - float minradius = radius - .5; - float maxradius = radius + .5; - for (int x=0; x= minradius * minradius && newX*newX + newY*newY <= maxradius * maxradius) + for (int x=startx; x= minradius2) && (distance2 <= maxradius2)) { setPixelColorXY(x, y, color); + } else { if (fillColor != 0) - if (newX*newX + newY*newY < minradius * minradius) + if (distance2 < minradius2) setPixelColorXY(x, y, fillColor); + } } } @@ -890,10 +897,11 @@ void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel // multiply the intensities by the colour, and saturating-add them to the pixels for (int i = 0; i < 4; i++) { CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1)); + CRGB oldLed = led; led.r = qadd8(led.r, c.r * wu[i] >> 8); led.g = qadd8(led.g, c.g * wu[i] >> 8); led.b = qadd8(led.b, c.b * wu[i] >> 8); - setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led); + if (led != oldLed) setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led); // WLEDMM don't repaint same color } } #undef WU_WEIGHT From 7f9da309c9d37a27226b0a2e247e47494fafa50b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:58:38 +0200 Subject: [PATCH 015/123] const const const adding hints for the compiler for optimization. In case your custom build complains about "const", just remove the keyword. based on https://github.com/Aircoookie/WLED/commit/e82f38e277b6ad3d7b943b8868c3f88cb7c53382, but going further :-) * "const" class functions : function does not modify any class attributes ( --> "this" becomes const) * __attribute__((pure)) : function return value depends only on the parameters and/or global variables. The function does not modify any global or static variables. * __attribute__((const)) : function only examines arguments (no globals), and has no effects except the return value. This slightly more strict than "pure" * hot: tells the compiler "this functions is called very often" * cold: the opposite of hot --- usermods/audioreactive/audio_reactive.h | 2 +- wled00/FX.h | 74 ++++++++++---------- wled00/FX_2Dfcn.cpp | 8 +-- wled00/FX_fcn.cpp | 36 +++++----- wled00/bus_manager.cpp | 34 +++++----- wled00/bus_manager.h | 90 ++++++++++++------------- wled00/colors.cpp | 14 ++-- wled00/fcn_declare.h | 15 +++-- wled00/led.cpp | 2 +- wled00/pin_manager.cpp | 4 +- wled00/pin_manager.h | 4 +- wled00/src/dependencies/time/TimeLib.h | 2 +- wled00/wled.h | 6 +- wled00/wled00.ino | 2 + 14 files changed, 148 insertions(+), 145 deletions(-) diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index f7c91594..709a5960 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -285,7 +285,7 @@ static volatile float micReal_max2 = 0.0f; // MicIn data max afte // some prototypes, to ensure consistent interfaces static float mapf(float x, float in_min, float in_max, float out_min, float out_max); // map function for float static float fftAddAvg(int from, int to); // average of several FFT result bins -void FFTcode(void * parameter); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results +void FFTcode(void * parameter) __attribute__((noreturn)); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results static void runMicFilter(uint16_t numSamples, float *sampleBuffer); // pre-filtering of raw samples (band-pass) static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels, bool i2sFastpath); // post-processing and post-amp of GEQ channels diff --git a/wled00/FX.h b/wled00/FX.h index 98e934e0..387b9e55 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -33,7 +33,7 @@ bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.cpp -bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.cpp +bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented in FX_fcn.cpp #define FASTLED_INTERNAL //remove annoying pragma messages #define USE_GET_MILLISECOND_TIMER @@ -640,7 +640,7 @@ typedef struct Segment { void setPixelColor(float i, uint32_t c, bool aa = true); inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); } inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); } - uint32_t __attribute__((pure)) getPixelColor(int i); // WLEDMM attribute added + uint32_t __attribute__((pure)) getPixelColor(int i) const; // WLEDMM attribute added // 1D support functions (some implement 2D as well) void blur(uint8_t, bool smear = false); void fill(uint32_t c); @@ -652,7 +652,7 @@ typedef struct Segment { inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline void fadePixelColor(uint16_t n, uint8_t fade); - uint8_t get_random_wheel_index(uint8_t pos); + uint8_t get_random_wheel_index(uint8_t pos) const; uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255); uint32_t __attribute__((pure)) color_wheel(uint8_t pos); @@ -693,7 +693,7 @@ typedef struct Segment { void deletejMap(); //WLEDMM jMap #ifndef WLED_DISABLE_2D - inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed + inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) const { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed uint_fast16_t width = max(uint16_t(1), virtualWidth()); // segment width in logical pixels -- softhack007 avoid div/0 uint_fast16_t height = max(uint16_t(1), virtualHeight()); // segment height in logical pixels -- softhack007 avoid div/0 return (x%width) + (y%height) * width; @@ -726,7 +726,7 @@ typedef struct Segment { inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); } inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); } //#endif - uint32_t __attribute__((pure)) getPixelColorXY(int x, int y); + uint32_t __attribute__((pure)) getPixelColorXY(int x, int y) const; // 2D support functions void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend); inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); } @@ -792,7 +792,7 @@ typedef struct Segment { inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) {} inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {} #endif - uint8_t * getAudioPalette(int pal); //WLEDMM netmindz ar palette + uint8_t * getAudioPalette(int pal) const; //WLEDMM netmindz ar palette } segment; //static int segSize = sizeof(Segment); @@ -915,64 +915,64 @@ class WS2812FX { // 96 bytes bool checkSegmentAlignment(void), - hasRGBWBus(void), - hasCCTBus(void), + hasRGBWBus(void) const, + hasCCTBus(void) const, // return true if the strip is being sent pixel updates - isUpdating(void), + isUpdating(void) const, deserializeMap(uint8_t n=0), useLedsArray = false; - inline bool isServicing(void) { return _isServicing; } - inline bool hasWhiteChannel(void) {return _hasWhiteChannel;} - inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;} + inline bool isServicing(void) const { return _isServicing; } + inline bool hasWhiteChannel(void) const {return _hasWhiteChannel;} + inline bool isOffRefreshRequired(void) const {return _isOffRefreshRequired;} uint8_t paletteFade, paletteBlend, milliampsPerLed, cctBlending, - getActiveSegmentsNum(void), - getFirstSelectedSegId(void), - getLastActiveSegmentId(void), - getActiveSegsLightCapabilities(bool selectedOnly = false), + getActiveSegmentsNum(void) const, + getFirstSelectedSegId(void) __attribute__((pure)), + getLastActiveSegmentId(void) const, + getActiveSegsLightCapabilities(bool selectedOnly = false) __attribute__((pure)), setPixelSegment(uint8_t n); - inline uint8_t getBrightness(void) { return _brightness; } - inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) - inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present segments - inline uint8_t getCurrSegmentId(void) { return _segment_index; } - inline uint8_t getMainSegmentId(void) { return _mainSegment; } - inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count - inline uint8_t getTargetFps() { return _targetFps; } - inline uint8_t getModeCount() { return _modeCount; } + inline uint8_t getBrightness(void) const { return _brightness; } + inline uint8_t getMaxSegments(void) const { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) + inline uint8_t getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments + inline uint8_t getCurrSegmentId(void) const { return _segment_index; } + inline uint8_t getMainSegmentId(void) const { return _mainSegment; } + inline uint8_t getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count + inline uint8_t getTargetFps() const { return _targetFps; } + inline uint8_t getModeCount() const { return _modeCount; } uint16_t ablMilliampsMax, currentMilliamps, - getLengthPhysical(void), - __attribute__((pure)) getLengthTotal(void), // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added - getFps(); + getLengthPhysical(void) const, + __attribute__((pure)) getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added + getFps() const; - inline uint16_t getFrameTime(void) { return _frametime; } - inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; } - inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H - inline uint16_t getTransition(void) { return _transitionDur; } + inline uint16_t getFrameTime(void) const { return _frametime; } + inline uint16_t getMinShowDelay(void) const { return MIN_SHOW_DELAY; } + inline uint16_t getLength(void) const { return _length; } // 2D matrix may have less pixels than W*H + inline uint16_t getTransition(void) const { return _transitionDur; } uint32_t now, timebase; - uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t); // WLEDMM attribute pure = does not have side-effects + uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t) const; // WLEDMM attribute pure = does not have side-effects - inline uint32_t getLastShow(void) { return _lastShow; } - inline uint32_t segColor(uint8_t i) { return _colors_t[i]; } + inline uint32_t getLastShow(void) const { return _lastShow; } + inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } const char * - getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); } + getModeData(uint8_t id = 0) const { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); } const char ** getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data - Segment& getSegment(uint8_t id); + Segment& getSegment(uint8_t id) __attribute__((pure)); inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; } inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; } inline Segment* getSegments(void) { return &(_segments[0]); } @@ -1039,7 +1039,7 @@ class WS2812FX { // 96 bytes inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } uint32_t - getPixelColorXY(uint16_t, uint16_t); + getPixelColorXY(uint16_t, uint16_t) const; // end 2D support diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 71fb0cb2..e966381a 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -177,7 +177,7 @@ void WS2812FX::setUpMatrix() { } // absolute matrix version of setPixelColor(), without error checking -void IRAM_ATTR WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally { uint_fast16_t index = y * Segment::maxWidth + x; if (index < customMappingSize) index = customMappingTable[index]; @@ -200,7 +200,7 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM } // returns RGBW values of pixel -uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) { +uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) const { #ifndef WLED_DISABLE_2D uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types #else @@ -239,7 +239,7 @@ void Segment::startFrame(void) { // Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing // * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight() -void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM +void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM { unsigned i = UINT_MAX; bool sameColor = false; @@ -406,7 +406,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast } // returns RGBW values of pixel -uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) { +uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { if (x<0 || y<0 || !isActive()) return 0; // not active or out-of range if (ledsrgb) { int i = XY(x,y); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 0e63c853..8a9533cd 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -882,7 +882,7 @@ uint16_t Segment::virtualLength() const { } //WLEDMM used for M12_sBlock -void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) { +static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) { float i2; if (i<=SEGLEN*0.25) { //top, left to right i2 = i/(SEGLEN*0.25); @@ -907,7 +907,7 @@ void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, } -void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally { if (!isActive()) return; // not active #ifndef WLED_DISABLE_2D @@ -1171,7 +1171,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa) } } -uint32_t Segment::getPixelColor(int i) +uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const { if (!isActive()) return 0; // not active #ifndef WLED_DISABLE_2D @@ -1345,7 +1345,7 @@ void Segment::refreshLightCapabilities() { /* * Fills segment with color - WLEDMM using faster sPC if possible */ -void Segment::fill(uint32_t c) { +void __attribute__((hot)) Segment::fill(uint32_t c) { if (!isActive()) return; // not active #if 0 && defined(WLED_ENABLE_HUB75MATRIX) && defined(WLEDMM_FASTPATH) @@ -1457,7 +1457,7 @@ void Segment::fade_out(uint8_t rate) { } // fades all pixels to black using nscale8() -void Segment::fadeToBlackBy(uint8_t fadeBy) { +void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) { if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D @@ -1480,7 +1480,7 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) { /* * blurs segment content, source: FastLED colorutils.cpp */ -void Segment::blur(uint8_t blur_amount, bool smear) { +void __attribute__((hot)) Segment::blur(uint8_t blur_amount, bool smear) { if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur" #ifndef WLED_DISABLE_2D if (is2D()) { @@ -1541,7 +1541,7 @@ uint32_t Segment::color_wheel(uint8_t pos) { /* * Returns a new, random wheel index with a minimum distance of 42 from pos. */ -uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int types, use native min/max +uint8_t Segment::get_random_wheel_index(uint8_t pos) const { // WLEDMM use fast int types, use native min/max uint_fast8_t r = 0, x = 0, y = 0, d = 0; while(d < 42) { @@ -1562,7 +1562,7 @@ uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int ty * @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling) * @returns Single color from palette */ -uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types +uint32_t __attribute__((hot)) Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types { // default palette or no RGB support on segment if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) { @@ -1582,7 +1582,7 @@ uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, u } //WLEDMM netmindz ar palette -uint8_t * Segment::getAudioPalette(int pal) { +uint8_t * Segment::getAudioPalette(int pal) const { // https://forum.makerforums.info/t/hi-is-it-possible-to-define-a-gradient-palette-at-runtime-the-define-gradient-palette-uses-the/63339 um_data_t *um_data; @@ -1891,7 +1891,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col) busses.setPixelColor(i, col); } -uint32_t WS2812FX::getPixelColor(uint_fast16_t i) // WLEDMM fast int types +uint32_t WS2812FX::getPixelColor(uint_fast16_t i) const // WLEDMM fast int types { if (i < customMappingSize) i = customMappingTable[i]; if (i >= _length) return 0; @@ -2029,7 +2029,7 @@ void WS2812FX::show(void) { * Returns a true value if any of the strips are still being updated. * On some hardware (ESP32), strip updates are done asynchronously. */ -bool WS2812FX::isUpdating() { +bool WS2812FX::isUpdating() const { return !busses.canAllShow(); } @@ -2037,7 +2037,7 @@ bool WS2812FX::isUpdating() { * Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough. * Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accuracy varies */ -uint16_t WS2812FX::getFps() { +uint16_t WS2812FX::getFps() const { if (millis() - _lastShow > 2000) return 0; #ifdef ARDUINO_ARCH_ESP32 return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding @@ -2128,14 +2128,14 @@ void WS2812FX::setMainSegmentId(uint8_t n) { return; } -uint8_t WS2812FX::getLastActiveSegmentId(void) { +uint8_t WS2812FX::getLastActiveSegmentId(void) const { for (size_t i = _segments.size() -1; i > 0; i--) { if (_segments[i].isActive()) return i; } return 0; } -uint8_t WS2812FX::getActiveSegmentsNum(void) { +uint8_t WS2812FX::getActiveSegmentsNum(void) const { uint8_t c = 0; for (size_t i = 0; i < _segments.size(); i++) { if (_segments[i].isActive()) c++; @@ -2143,13 +2143,13 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) { return c; } -uint16_t WS2812FX::getLengthTotal(void) { // WLEDMM fast int types +uint16_t WS2812FX::getLengthTotal(void) const { // WLEDMM fast int types uint_fast16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D if (isMatrix && _length > len) len = _length; // for 2D with trailing strip return len; } -uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types +uint16_t WS2812FX::getLengthPhysical(void) const { // WLEDMM fast int types uint_fast16_t len = 0; for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types Bus *bus = busses.getBus(b); @@ -2162,7 +2162,7 @@ uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types //used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw. //returns if there is an RGBW bus (supports RGB and White, not only white) //not influenced by auto-white mode, also true if white slider does not affect output white channel -bool WS2812FX::hasRGBWBus(void) { +bool WS2812FX::hasRGBWBus(void) const { for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types Bus *bus = busses.getBus(b); if (bus == nullptr || bus->getLength()==0) break; @@ -2171,7 +2171,7 @@ bool WS2812FX::hasRGBWBus(void) { return false; } -bool WS2812FX::hasCCTBus(void) { +bool WS2812FX::hasCCTBus(void) const { if (cctFromRgb && !correctWB) return false; for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types Bus *bus = busses.getBus(b); diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 604a92c5..c8e42c57 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -86,7 +86,7 @@ uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaul } -uint32_t Bus::autoWhiteCalc(uint32_t c) { +uint32_t Bus::autoWhiteCalc(uint32_t c) const { uint8_t aWM = _autoWhiteMode; if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM; if (aWM == RGBW_MODE_MANUAL_ONLY) return c; @@ -139,7 +139,7 @@ void BusDigital::show() { PolyBus::show(_busPtr, _iType); } -bool BusDigital::canShow() { +bool BusDigital::canShow() const { return PolyBus::canShow(_busPtr, _iType); } @@ -182,7 +182,7 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) { PolyBus::setPixelColor(_busPtr, _iType, pix, c, co); } -uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) { +uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) const { if (reversed) pix = _len - pix -1; else pix += _skip; uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder); @@ -200,7 +200,7 @@ uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) { return PolyBus::getPixelColor(_busPtr, _iType, pix, co); } -uint8_t BusDigital::getPins(uint8_t* pinArray) { +uint8_t BusDigital::getPins(uint8_t* pinArray) const { uint8_t numPins = IS_2PIN(_type) ? 2 : 1; for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i]; return numPins; @@ -317,7 +317,7 @@ void BusPwm::setPixelColor(uint16_t pix, uint32_t c) { } //does no index check -uint32_t BusPwm::getPixelColor(uint16_t pix) { +uint32_t BusPwm::getPixelColor(uint16_t pix) const { if (!_valid) return 0; #if 1 // WLEDMM stick with the old code - we don't have cctICused @@ -356,7 +356,7 @@ void BusPwm::show() { } } -uint8_t BusPwm::getPins(uint8_t* pinArray) { +uint8_t BusPwm::getPins(uint8_t* pinArray) const { if (!_valid) return 0; uint8_t numPins = NUM_PWM_PINS(_type); for (uint8_t i = 0; i < numPins; i++) { @@ -408,7 +408,7 @@ void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) { _data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0; } -uint32_t BusOnOff::getPixelColor(uint16_t pix) { +uint32_t BusOnOff::getPixelColor(uint16_t pix) const { if (!_valid) return 0; return RGBW32(_data, _data, _data, _data); } @@ -418,7 +418,7 @@ void BusOnOff::show() { digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data); } -uint8_t BusOnOff::getPins(uint8_t* pinArray) { +uint8_t BusOnOff::getPins(uint8_t* pinArray) const { if (!_valid) return 0; pinArray[0] = _pin; return 1; @@ -467,7 +467,7 @@ void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) { if (_rgbw) _data[offset+3] = W(c); } -uint32_t BusNetwork::getPixelColor(uint16_t pix) { +uint32_t BusNetwork::getPixelColor(uint16_t pix) const { if (!_valid || pix >= _len) return 0; uint16_t offset = pix * _UDPchannels; return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0); @@ -480,7 +480,7 @@ void BusNetwork::show() { _broadcastLock = false; } -uint8_t BusNetwork::getPins(uint8_t* pinArray) { +uint8_t BusNetwork::getPins(uint8_t* pinArray) const { for (uint8_t i = 0; i < 4; i++) { pinArray[i] = _client[i]; } @@ -698,7 +698,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh USER_PRINTLN("MatrixPanel_I2S_DMA started"); } -void BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { +void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { if (!_valid || pix >= _len) return; #ifndef NO_CIE1931 c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction @@ -823,7 +823,7 @@ void BusManager::setStatusPixel(uint32_t c) { } } -void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) { +void IRAM_ATTR __attribute__((hot)) BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) { if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) { // WLEDMM same bus as last time - no need to search again lastBus->setPixelColor(pix - laststart, c); @@ -851,7 +851,7 @@ void BusManager::setBrightness(uint8_t b, bool immediate) { } } -void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) { +void __attribute__((cold)) BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) { if (cct > 255) cct = 255; if (cct >= 0) { //if white balance correction allowed, save as kelvin value instead of 0-255 @@ -860,7 +860,7 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) { Bus::setCCT(cct); } -uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR +uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) { // WLEDMM same bus as last time - no need to search again return lastBus->getPixelColor(pix - laststart); @@ -881,20 +881,20 @@ uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM return 0; } -bool BusManager::canAllShow() { +bool BusManager::canAllShow() const { for (uint8_t i = 0; i < numBusses; i++) { if (!busses[i]->canShow()) return false; } return true; } -Bus* BusManager::getBus(uint8_t busNr) { +Bus* BusManager::getBus(uint8_t busNr) const { if (busNr >= numBusses) return nullptr; return busses[busNr]; } //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit()) -uint16_t BusManager::getTotalLength() { +uint16_t BusManager::getTotalLength() const { uint_fast16_t len = 0; for (uint_fast8_t i=0; igetLength(); // WLEDMM use fast native types return len; diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 40fc0061..18337026 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -113,35 +113,35 @@ class Bus { virtual bool canShow() { return true; } virtual void setStatusPixel(uint32_t c) {} virtual void setPixelColor(uint16_t pix, uint32_t c) = 0; - virtual uint32_t getPixelColor(uint16_t pix) { return 0; } + virtual uint32_t getPixelColor(uint16_t pix) const { return 0; } virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; }; virtual void cleanup() = 0; - virtual uint8_t getPins(uint8_t* pinArray) { return 0; } - virtual uint16_t getLength() { return _len; } + virtual uint8_t getPins(uint8_t* pinArray) const { return 0; } + virtual uint16_t getLength() const { return _len; } virtual void setColorOrder() {} - virtual uint8_t getColorOrder() { return COL_ORDER_RGB; } + virtual uint8_t getColorOrder() const { return COL_ORDER_RGB; } virtual uint8_t skippedLeds() { return 0; } - virtual uint16_t getFrequency() { return 0U; } - inline uint16_t getStart() { return _start; } + virtual uint16_t getFrequency() const { return 0U; } + inline uint16_t getStart() const { return _start; } inline void setStart(uint16_t start) { _start = start; } - inline uint8_t getType() { return _type; } - inline bool isOk() { return _valid; } - inline bool isOffRefreshRequired() { return _needsRefresh; } - bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; } - virtual uint16_t getMaxPixels() { return MAX_LEDS_PER_BUS; }; + inline uint8_t getType() const { return _type; } + inline bool isOk() const { return _valid; } + inline bool isOffRefreshRequired() const { return _needsRefresh; } + bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start+_len; } + virtual uint16_t getMaxPixels() const { return MAX_LEDS_PER_BUS; }; - virtual bool hasRGB() { + virtual bool hasRGB() const { if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false; return true; } - virtual bool hasWhite() { return Bus::hasWhite(_type); } + virtual bool hasWhite() const { return Bus::hasWhite(_type); } static bool hasWhite(uint8_t type) { if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904) return true; // digital types with white channel if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel return false; } - virtual bool hasCCT() { + virtual bool hasCCT() const { if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA || _type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true; return false; @@ -158,7 +158,7 @@ class Bus { #endif } inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; } - inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; } + inline uint8_t getAutoWhiteMode() const { return _autoWhiteMode; } inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; } inline static uint8_t getGlobalAWMode() { return _gAWM; } @@ -176,7 +176,7 @@ class Bus { static int16_t _cct; static uint8_t _cctBlend; - uint32_t autoWhiteCalc(uint32_t c); + uint32_t autoWhiteCalc(uint32_t c) const; }; @@ -186,7 +186,7 @@ class BusDigital : public Bus { inline void show(); - bool canShow(); + bool canShow() const; void setBrightness(uint8_t b, bool immediate); @@ -194,25 +194,25 @@ class BusDigital : public Bus { void setPixelColor(uint16_t pix, uint32_t c); - uint32_t getPixelColor(uint16_t pix); + uint32_t getPixelColor(uint16_t pix) const; - uint8_t getColorOrder() { + uint8_t getColorOrder() const { return _colorOrder; } - uint16_t getLength() { + uint16_t getLength() const { return _len - _skip; } - uint8_t getPins(uint8_t* pinArray); + uint8_t getPins(uint8_t* pinArray) const; void setColorOrder(uint8_t colorOrder); - uint8_t skippedLeds() { + uint8_t skippedLeds() const { return _skip; } - uint16_t getFrequency() { return _frequencykHz; } + uint16_t getFrequency() const { return _frequencykHz; } void reinit(); @@ -240,13 +240,13 @@ class BusPwm : public Bus { void setPixelColor(uint16_t pix, uint32_t c); //does no index check - uint32_t getPixelColor(uint16_t pix); + uint32_t getPixelColor(uint16_t pix) const; void show(); - uint8_t getPins(uint8_t* pinArray); + uint8_t getPins(uint8_t* pinArray) const; - uint16_t getFrequency() { return _frequency; } + uint16_t getFrequency() const { return _frequency; } void cleanup() { deallocatePins(); @@ -274,11 +274,11 @@ class BusOnOff : public Bus { void setPixelColor(uint16_t pix, uint32_t c); - uint32_t getPixelColor(uint16_t pix); + uint32_t getPixelColor(uint16_t pix) const; void show(); - uint8_t getPins(uint8_t* pinArray); + uint8_t getPins(uint8_t* pinArray) const; void cleanup() { pinManager.deallocatePin(_pin, PinOwner::BusOnOff); @@ -298,24 +298,24 @@ class BusNetwork : public Bus { public: BusNetwork(BusConfig &bc); - uint16_t getMaxPixels() override { return 4096; }; - bool hasRGB() { return true; } - bool hasWhite() { return _rgbw; } + uint16_t getMaxPixels() const override { return 4096; }; + bool hasRGB() const { return true; } + bool hasWhite() const { return _rgbw; } void setPixelColor(uint16_t pix, uint32_t c); - uint32_t __attribute__((pure)) getPixelColor(uint16_t pix); // WLEDMM attribute added + uint32_t __attribute__((pure)) getPixelColor(uint16_t pix) const; // WLEDMM attribute added void show(); - bool canShow() { + bool canShow() const { // this should be a return value from UDP routine if it is still sending data out return !_broadcastLock; } - uint8_t getPins(uint8_t* pinArray); + uint8_t getPins(uint8_t* pinArray) const; - uint16_t getLength() { + uint16_t getLength() const { return _len; } @@ -339,10 +339,10 @@ class BusHub75Matrix : public Bus { public: BusHub75Matrix(BusConfig &bc); - uint16_t getMaxPixels() override { return 4096; }; + uint16_t getMaxPixels() const override { return 4096; }; - bool hasRGB() { return true; } - bool hasWhite() { return false; } + bool hasRGB() const { return true; } + bool hasWhite() const { return false; } void setPixelColor(uint16_t pix, uint32_t c); @@ -356,7 +356,7 @@ class BusHub75Matrix : public Bus { void setBrightness(uint8_t b, bool immediate); - uint8_t getPins(uint8_t* pinArray) { + uint8_t getPins(uint8_t* pinArray) const { pinArray[0] = mxconfig.chain_length; return 1; } // Fake value due to keep finaliseInit happy @@ -388,7 +388,7 @@ class BusManager { BusManager() {}; //utility to get the approx. memory usage of a given BusConfig - static uint32_t memUsage(BusConfig &bc); + static uint32_t memUsage(BusConfig &bc) __attribute__((pure)); int add(BusConfig &bc); @@ -407,12 +407,12 @@ class BusManager { uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added - bool canAllShow(); + bool canAllShow() const; - Bus* getBus(uint8_t busNr); + Bus* getBus(uint8_t busNr) const; //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit()) - uint16_t getTotalLength(); + uint16_t getTotalLength() const; inline void updateColorOrderMap(const ColorOrderMap &com) { memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap)); @@ -422,7 +422,7 @@ class BusManager { return colorOrderMap; } - inline uint8_t getNumBusses() { + inline uint8_t getNumBusses() const { return numBusses; } @@ -435,7 +435,7 @@ class BusManager { unsigned laststart = 0; unsigned lastend = 0; - inline uint8_t getNumVirtualBusses() { + inline uint8_t getNumVirtualBusses() const { int j = 0; for (int i=0; igetType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++; return j; diff --git a/wled00/colors.cpp b/wled00/colors.cpp index f7751861..23cf2f13 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -7,7 +7,7 @@ /* * color blend function */ -IRAM_ATTR_YN uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) { +IRAM_ATTR_YN __attribute__((hot)) uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) { if(blend == 0) return color1; if (color1 == color2) return color1; // WLEDMM shortcut const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF; @@ -71,7 +71,7 @@ IRAM_ATTR_YN uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM * if using "video" method the resulting color will never become black unless it is already black */ -IRAM_ATTR_YN uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) +IRAM_ATTR_YN __attribute__((hot)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) { if (amount == 0) return 0; // WLEDMM shortcut @@ -297,7 +297,7 @@ static float maxf (float v, float w) // WLEDMM better use standard library fmax // adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance) // called from bus manager when color correction is enabled! -uint32_t IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN +uint32_t __attribute__((hot)) IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN { //remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor() static byte correctionRGB[4] = {0,0,0,0}; @@ -406,7 +406,7 @@ static void calcInvGammaTable(float gamma) gammaTinv[i] = (int)(powf((float)i / 255.0f, gammaInv) * 255.0f + 0.5f); } } -uint8_t unGamma8(uint8_t value) { +uint8_t __attribute__((hot)) unGamma8(uint8_t value) { //if (!gammaCorrectCol || (value == 0) || (value == 255)) return value; if ((value == 0) || (value == 255)) return value; if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value; @@ -414,7 +414,7 @@ uint8_t unGamma8(uint8_t value) { return gammaTinv[value]; } -uint32_t unGamma24(uint32_t c) { +uint32_t __attribute__((hot)) unGamma24(uint32_t c) { if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return c; if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal); return RGBW32(gammaTinv[R(c)], gammaTinv[G(c)], gammaTinv[B(c)], W(c)); @@ -438,13 +438,13 @@ void calcGammaTable(float gamma) } // used for individual channel or brightness gamma correction -IRAM_ATTR_YN uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN +IRAM_ATTR_YN __attribute__((hot)) uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN { return gammaT[b]; } // used for color gamma correction -uint32_t gamma32(uint32_t color) +uint32_t __attribute__((hot)) gamma32(uint32_t color) { if (!gammaCorrectCol) return color; uint8_t w = W(color); diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index a0713d0f..09f9724b 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -250,7 +250,7 @@ void refreshNodeList(); void sendSysInfoUDP(); //network.cpp -int getSignalQuality(int rssi); +int getSignalQuality(int rssi) __attribute__((const)); void WiFiEvent(WiFiEvent_t event); //um_manager.cpp @@ -369,7 +369,7 @@ bool oappendi(int i); // append new number to temp buffer efficiently void sappend(char stype, const char* key, int val); void sappends(char stype, const char* key, char* val); void prepareHostname(char* hostname); -bool isAsterisksOnly(const char* str, byte maxLen); +bool isAsterisksOnly(const char* str, byte maxLen) __attribute__((pure)); bool requestJSONBufferLock(uint8_t module=255); void releaseJSONBufferLock(); uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen); @@ -410,13 +410,14 @@ void clearEEPROM(); //wled_math.cpp #ifndef WLED_USE_REAL_MATH template T atan_t(T x); - float cos_t(float phi); - float sin_t(float x); - float tan_t(float x); + float cos_t(float phi) __attribute__((const)); + float sin_t(float x) __attribute__((const)); + float tan_t(float x) __attribute__((const)); float acos_t(float x); float asin_t(float x); - float floor_t(float x); - float fmod_t(float num, float denom); + float atan_t(float x) __attribute__((const)); + float floor_t(float x) __attribute__((const)); + float fmod_t(float num, float denom) __attribute__((const)); #else #include // WLEDMM use "float" variants #define sin_t sinf diff --git a/wled00/led.cpp b/wled00/led.cpp index 70863396..74520147 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -68,7 +68,7 @@ void toggleOnOff() //scales the brightness with the briMultiplier factor -IRAM_ATTR_YN byte scaledBri(byte in) // WLEDMM added IRAM_ATTR_YN +IRAM_ATTR_YN __attribute__((hot)) byte scaledBri(byte in) // WLEDMM added IRAM_ATTR_YN { if (briMultiplier == 100) return(in); // WLEDMM shortcut uint_fast16_t val = ((uint_fast16_t)in*(uint_fast16_t)briMultiplier)/100; // WLEDMM diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index a9c31bde..d1e7a18b 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -723,7 +723,7 @@ bool PinManagerClass::joinWire(int8_t pinSDA, int8_t pinSCL) { */ // Check if supplied GPIO is ok to use -bool PinManagerClass::isPinOk(byte gpio, bool output) +bool PinManagerClass::isPinOk(byte gpio, bool output) const { #ifdef ESP32 if (digitalPinIsValid(gpio)) { @@ -757,7 +757,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) return false; } -PinOwner PinManagerClass::getPinOwner(byte gpio) { +PinOwner PinManagerClass::getPinOwner(byte gpio) const { if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access if (!isPinOk(gpio, false)) return PinOwner::None; return ownerTag[gpio]; diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h index cb107f49..23d8d951 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -125,9 +125,9 @@ class PinManagerClass { // will return true for reserved pins bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None); // will return false for reserved pins - bool isPinOk(byte gpio, bool output = true); + bool isPinOk(byte gpio, bool output = true) const; - PinOwner getPinOwner(byte gpio); + PinOwner getPinOwner(byte gpio) const; // WLEDMM begin String getOwnerText(PinOwner tag); // WLEDMM - return PIN owner tag as text diff --git a/wled00/src/dependencies/time/TimeLib.h b/wled00/src/dependencies/time/TimeLib.h index 5004f071..a4388a03 100644 --- a/wled00/src/dependencies/time/TimeLib.h +++ b/wled00/src/dependencies/time/TimeLib.h @@ -116,7 +116,7 @@ char* dayShortStr(uint8_t day); /* low level functions to convert to and from system time */ void breakTime(time_t time, tmElements_t &tm); // break time_t into elements -time_t makeTime(tmElements_t &tm); // convert time elements into time_t +time_t makeTime(tmElements_t &tm) __attribute__((pure)); // convert time elements into time_t } // extern "C++" #endif // __cplusplus diff --git a/wled00/wled.h b/wled00/wled.h index 34667df1..1ea73805 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408060 +#define VERSION 2408070 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ @@ -928,9 +928,9 @@ public: } // boot starts here - void setup(); + void setup() __attribute__((used)); - void loop(); + void loop() __attribute__((used)); void reset(); void beginStrip(); diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 056d8f28..b19441a2 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -61,6 +61,7 @@ void esp_heap_trace_free_hook(void* ptr) unsigned long lastMillis = 0; //WLEDMM unsigned long loopCounter = 0; //WLEDMM +void setup() __attribute__((used)); // needed for -flto void setup() { #ifdef WLED_DEBUG_HEAP esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook); @@ -68,6 +69,7 @@ void setup() { WLED::instance().setup(); } +void loop() __attribute__((used)); // needed for -flto void loop() { //WLEDMM show loops per second loopCounter++; From b2844645c6c3d4d505dcfe3429d26c623c786f71 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:53:25 +0200 Subject: [PATCH 016/123] pinwheel mapping XXL - no holes at 64x64 --- wled00/FX_fcn.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 8a9533cd..35ed815e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -812,10 +812,13 @@ constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50 constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL" constexpr int Pinwheel_Steps_XL = 368; +constexpr int Pinwheel_Size_XL = 58; // larger than this -> use "XXL" +constexpr int Pinwheel_Steps_XXL = 456; constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians +constexpr float Int_to_Rad_XXL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XXL; // conversion: from 0...456 to Radians constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) @@ -825,8 +828,9 @@ static float getPinwheelAngle(int i, int vW, int vH) { if (maxXY <= Pinwheel_Size_Small) return float(i) * Int_to_Rad_Small; if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med; if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big; + if (maxXY <= Pinwheel_Size_XL) return float(i) * Int_to_Rad_XL; // else - return float(i) * Int_to_Rad_XL; + return float(i) * Int_to_Rad_XXL; } // Pinwheel helper function: matrix dimensions to number of rays static int getPinwheelLength(int vW, int vH) { @@ -834,8 +838,9 @@ static int getPinwheelLength(int vW, int vH) { if (maxXY <= Pinwheel_Size_Small) return Pinwheel_Steps_Small; if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium; if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big; + if (maxXY <= Pinwheel_Size_XL) return Pinwheel_Steps_XL; // else - return Pinwheel_Steps_XL; + return Pinwheel_Steps_XXL; } #endif From fb2402fb9766665f5f75d4a249791609c39b5ec5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:02:46 +0200 Subject: [PATCH 017/123] HUB75 optimization (double buffer only) In double duffer mode, the screen is blanked at each show(). So we can drop setPixelColor(BLACK) calls until we receive a pixel with different color. --- wled00/bus_manager.cpp | 6 +++++- wled00/bus_manager.h | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index c8e42c57..0f892f5f 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -503,7 +503,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh _valid = false; mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory - + isBlack = false; fourScanPanel = nullptr; @@ -671,6 +671,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh } else { _valid = true; + display->clearScreen(); // initially clear the screen buffer + isBlack = true; } switch(bc.type) { @@ -700,6 +702,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { if (!_valid || pix >= _len) return; + if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() #ifndef NO_CIE1931 c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction #endif @@ -719,6 +722,7 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t int y = pix / pxwidth; display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } + isBlack = false; } void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 18337026..cfea2674 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -351,6 +351,7 @@ class BusHub75Matrix : public Bus { display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels) // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. display->clearScreen(); // Now clear the back-buffer + isBlack = true; } } @@ -369,6 +370,7 @@ class BusHub75Matrix : public Bus { // delete fourScanPanel; delete display; _valid = false; + isBlack = false; } ~BusHub75Matrix() { @@ -379,6 +381,7 @@ class BusHub75Matrix : public Bus { MatrixPanel_I2S_DMA *display = nullptr; VirtualMatrixPanel *fourScanPanel = nullptr; HUB75_I2S_CFG mxconfig; + bool isBlack = false; }; #endif From 6e415dfbbeedc968eb47b678c130e1d4782cc5bd Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 7 Aug 2024 18:31:06 +0200 Subject: [PATCH 018/123] HUB75 hack HUB75 is very memory hungry - this hack deletes the mapping table when its not needed --> frees 8Kb with a 64x64 panel. --- wled00/FX_2Dfcn.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index e966381a..9660df63 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -171,6 +171,24 @@ void WS2812FX::setUpMatrix() { //WLEDMM: no resetSegments here, only do it in set.cpp/handleSettingsSet - as we want t0 maintain the segment settings after setup has changed } } + +#ifdef WLED_ENABLE_HUB75MATRIX + // softhack007 hack: delete mapping table in case it only contains "identity" + if (customMappingTable != nullptr && customMappingTableSize > 0) { + bool isIdentity = true; + for (size_t i = 0; (i< customMappingSize) && isIdentity; i++) { //WLEDMM use customMappingTableSize + if (customMappingTable[i] != (uint16_t)i ) isIdentity = false; + } + if (isIdentity) { + free(customMappingTable); customMappingTable = nullptr; + USER_PRINTF("!setupmatrix: customMappingTable is not needed. Dropping %d bytes.\n", customMappingTableSize * sizeof(uint16_t)); + customMappingTableSize = 0; + customMappingSize = 0; + loadedLedmap = 0; //WLEDMM + } + } +#endif + #else isMatrix = false; // no matter what config says #endif From 90dd04887848803cee976239e9fe94d57fa5c22a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:41:05 +0200 Subject: [PATCH 019/123] revert fadeToBlackBy optimization causes problems with overlay text (scrolling text) --- wled00/FX_fcn.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 35ed815e..0f6eb6da 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1473,7 +1473,8 @@ void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) { for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { uint32_t cc = getPixelColorXY(x,y); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion uint32_t cc2 = color_fade(cc, scaledown); // fade - if (cc2 != cc) setPixelColorXY((uint16_t)x, (uint16_t)y, cc2); // WLEDMM only re-paint if faded color is different + //if (cc2 != cc) // WLEDMM only re-paint if faded color is different - disabled - causes problem with text overlay + setPixelColorXY((uint16_t)x, (uint16_t)y, cc2); } } else { for (uint_fast16_t x = 0; x < cols; x++) { From c66a8af85cfa91055be56802d1eed8865683943e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:44:13 +0200 Subject: [PATCH 020/123] reduce WiFi disconnects HUB75 is very heap-hungry - use a more relaxed metric for triggering "low heap emergency" actions --- wled00/wled.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 171be5c7..dfc7e75c 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -1220,7 +1220,7 @@ void WLED::handleConnection() #ifdef ARDUINO_ARCH_ESP32 // reconnect WiFi to clear stale allocations if heap gets too low if ((!strip.isUpdating()) && (now - heapTime > 5000)) { // WLEDMM: updated with better logic for small heap available by block, not total. // WLEDMM trying to use a moment when the strip is idle -#if defined(ARDUINO_ARCH_ESP32S2) +#if defined(ARDUINO_ARCH_ESP32S2) || defined(WLED_ENABLE_HUB75MATRIX) uint32_t heap = ESP.getFreeHeap(); // WLEDMM works better on -S2 #else uint32_t heap = heap_caps_get_largest_free_block(0x1800); // WLEDMM: This is a better metric for free heap. From 5b7345ef39e9a22c5429457b9927b254284e3e22 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 18:48:49 +0200 Subject: [PATCH 021/123] HUB75 refactoring * move HUB75 implementation into bus_manager.cpp * add "override" keyword * include FastLED.h if not included previously * move RGB macros into bus_manager.h --- wled00/bus_manager.cpp | 30 +++++++++++++++++++++--------- wled00/bus_manager.h | 42 +++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 0f892f5f..8ba2c6ca 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -49,13 +49,6 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte #include "wled.h" #endif -//color mangling macros -#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b)))) -#define R(c) (byte((c) >> 16)) -#define G(c) (byte((c) >> 8)) -#define B(c) (byte(c)) -#define W(c) (byte((c) >> 24)) - void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) { if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) { @@ -696,11 +689,12 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh break; } + USER_PRINT(F("MatrixPanel_I2S_DMA ")); + USER_PRINTF("%sstarted.\n", _valid? "":"not "); - USER_PRINTLN("MatrixPanel_I2S_DMA started"); } -void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { +void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { if (!_valid || pix >= _len) return; if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() #ifndef NO_CIE1931 @@ -729,6 +723,24 @@ void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { this->display->setBrightness(b); } +void __attribute__((hot)) BusHub75Matrix::show(void) { + if(mxconfig.double_buff) { + display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels) + // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. + display->clearScreen(); // Now clear the back-buffer + isBlack = true; + } +} + +void BusHub75Matrix::cleanup() { + deallocatePins(); + fourScanPanel = nullptr; + // delete fourScanPanel; + delete display; + _valid = false; + isBlack = false; +} + void BusHub75Matrix::deallocatePins() { pinManager.deallocatePin(mxconfig.gpio.r1, PinOwner::HUB75); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index cfea2674..b85bf5a6 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -12,6 +12,20 @@ #include "const.h" +#if !defined(FASTLED_VERSION) // only pull in FastLED if we don't have it yet + #define FASTLED_INTERNAL + #include +#endif + +//color mangling macros +#if !defined(RGBW32) + #define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b)))) + #define R(c) (byte((c) >> 16)) + #define G(c) (byte((c) >> 8)) + #define B(c) (byte(c)) + #define W(c) (byte((c) >> 24)) +#endif + #define GET_BIT(var,bit) (((var)>>(bit))&0x01) #define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit))) #define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit)))) @@ -341,37 +355,23 @@ class BusHub75Matrix : public Bus { uint16_t getMaxPixels() const override { return 4096; }; - bool hasRGB() const { return true; } - bool hasWhite() const { return false; } + bool hasRGB() const override { return true; } + bool hasWhite() const override { return false; } - void setPixelColor(uint16_t pix, uint32_t c); + void setPixelColor(uint16_t pix, uint32_t c) override; - void show() { - if(mxconfig.double_buff) { - display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels) - // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. - display->clearScreen(); // Now clear the back-buffer - isBlack = true; - } - } + void show(void) override; - void setBrightness(uint8_t b, bool immediate); + void setBrightness(uint8_t b, bool immediate) override; - uint8_t getPins(uint8_t* pinArray) const { + uint8_t getPins(uint8_t* pinArray) const override { pinArray[0] = mxconfig.chain_length; return 1; } // Fake value due to keep finaliseInit happy void deallocatePins(); - void cleanup() { - deallocatePins(); - fourScanPanel = nullptr; - // delete fourScanPanel; - delete display; - _valid = false; - isBlack = false; - } + void cleanup(void) override; ~BusHub75Matrix() { cleanup(); From b5d97cca9399cebb0646f163f8acafe574525c65 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 18:56:12 +0200 Subject: [PATCH 022/123] HUB75 leds buffer with dirty bit acceleration Instead of using the memory-hungry driver double buffer, this implements a LEDS buffer inside the BusHub75Matrix class. --> up to 50% faster --> uses one "dirty" bit per pixel, to only re-transmit pixels that changed after the last "show" --- wled00/bus_manager.cpp | 145 ++++++++++++++++++++++++++++++++++------- wled00/bus_manager.h | 11 +++- 2 files changed, 133 insertions(+), 23 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 8ba2c6ca..8fb12639 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -9,6 +9,36 @@ #include "bus_wrapper.h" #include "bus_manager.h" +// WLEDMM functions to get/set bits in an array - based on functions created by Brandon for GOL +// toDo : make this a class that's completely defined in a header file +bool getBitFromArray(const uint8_t* byteArray, size_t position) { // get bit value + size_t byteIndex = position / 8; + unsigned bitIndex = position % 8; + uint8_t byteValue = byteArray[byteIndex]; + return (byteValue >> bitIndex) & 1; +} + +void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr + if (byteArray == nullptr) return; + size_t byteIndex = position / 8; + unsigned bitIndex = position % 8; + if (value) + byteArray[byteIndex] |= (1 << bitIndex); + else + byteArray[byteIndex] &= ~(1 << bitIndex); +} + +size_t getBitArrayBytes(size_t num_bits) { // number of bytes needed for an array with num_bits bits + return (num_bits + 7) / 8; +} + +void setBitArray(uint8_t* byteArray, size_t numBits, bool value) { // set all bits to same value + if (byteArray == nullptr) return; + size_t len = getBitArrayBytes(numBits); + if (value) memset(byteArray, 0xFF, len); + else memset(byteArray, 0x00, len); +} + //WLEDMM: #define DEBUGOUT(x) netDebugEnabled?NetDebug.print(x):Serial.print(x) not supported in this file as netDebugEnabled not in scope #if 0 //colors.cpp @@ -665,6 +695,16 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh else { _valid = true; display->clearScreen(); // initially clear the screen buffer + + if (_ledBuffer) free(_ledBuffer); // should not happen + if (_ledsDirty) free(_ledsDirty); // should not happen + if(mxconfig.double_buff == false) { + _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) + _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits + //_ledsDirty = nullptr; + setBitArray(_ledsDirty, _len, false); // reset dirty bits + } + isBlack = true; } @@ -692,31 +732,58 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh USER_PRINT(F("MatrixPanel_I2S_DMA ")); USER_PRINTF("%sstarted.\n", _valid? "":"not "); + if (mxconfig.double_buff == true) USER_PRINTLN(F("MatrixPanel_I2S_DMA driver native double-buffering enabled.")); + if (_ledBuffer != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS buffer enabled.")); + if (_ledsDirty != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS dirty bit optimization enabled.")); + if ((_ledBuffer != nullptr) || (_ledsDirty != nullptr)) { + USER_PRINT(F("MatrixPanel_I2S_DMA LEDS buffer uses ")); + USER_PRINT((_ledBuffer? _len*sizeof(CRGB) :0) + (_ledsDirty? getBitArrayBytes(_len) :0)); + USER_PRINTLN(F(" bytes.")); + } } void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { if (!_valid || pix >= _len) return; - if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() -#ifndef NO_CIE1931 - c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction -#endif - uint8_t r = R(c); - uint8_t g = G(c); - uint8_t b = B(c); + // if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT - if(fourScanPanel != nullptr) { - int pxwidth = fourScanPanel->width(); - int x = pix % pxwidth; - int y = pix / pxwidth; - fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + if (_ledBuffer) { + CRGB fastled_col = CRGB(c); + if (_ledBuffer[pix] != fastled_col) { + _ledBuffer[pix] = fastled_col; + setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty" + isBlack = false; + } } else { - int pxwidth = display->width(); - int x = pix % pxwidth; - int y = pix / pxwidth; - display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + //if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() + #ifndef NO_CIE1931 + c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction + #endif + uint8_t r = R(c); + uint8_t g = G(c); + uint8_t b = B(c); + + if(fourScanPanel != nullptr) { + unsigned width = fourScanPanel->width(); + int x = pix % width; + int y = pix / width; + fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + } else { + unsigned width = display->width(); + int x = pix % width; + int y = pix / width; + display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + } + isBlack = false; } - isBlack = false; +} + +uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { + if (!_valid || pix >= _len) return BLACK; + if (_ledBuffer) + return uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; + else + return BLACK; } void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { @@ -724,8 +791,36 @@ void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { } void __attribute__((hot)) BusHub75Matrix::show(void) { + if (!_valid) return; + if (_ledBuffer) { + // write out buffered LEDs + bool haveDirtyBits = (_ledsDirty != nullptr); + bool isFourScan = (fourScanPanel != nullptr); + unsigned width = isFourScan ? fourScanPanel->width() : display->width(); + unsigned height = isFourScan ? fourScanPanel->height() : display->height(); + + //while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. + + size_t pix = 0; // running pixel index + for (int y=0; ydrawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + else display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + } + pix ++; + } + if (haveDirtyBits) setBitArray(_ledsDirty, _len, false); // reset dirty bits + } + if(mxconfig.double_buff) { - display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels) + display->flipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels) // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. display->clearScreen(); // Now clear the back-buffer isBlack = true; @@ -733,12 +828,18 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { } void BusHub75Matrix::cleanup() { - deallocatePins(); - fourScanPanel = nullptr; - // delete fourScanPanel; - delete display; + if (display && _valid) display->stopDMAoutput(); // terminate DMA driver (display goes black) _valid = false; + deallocatePins(); + USER_PRINTLN("HUB75 output ended."); + + //if (fourScanPanel != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior + delete display; + display = nullptr; + fourScanPanel = nullptr; isBlack = false; + if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr; + if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr; } void BusHub75Matrix::deallocatePins() { diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index b85bf5a6..93d5eb46 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -26,6 +26,13 @@ #define W(c) (byte((c) >> 24)) #endif +// WLEDMM bitarray utilities +void setBitInArray(uint8_t* byteArray, size_t position, bool value); // set bit +bool getBitFromArray(const uint8_t* byteArray, size_t position) __attribute__((pure)); // get bit value +size_t getBitArrayBytes(size_t num_bits) __attribute__((const)); // number of bytes needed for an array with num_bits bits +void setBitArray(uint8_t* byteArray, size_t numBits, bool value); // set all bits to same value + + #define GET_BIT(var,bit) (((var)>>(bit))&0x01) #define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit))) #define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit)))) @@ -359,6 +366,7 @@ class BusHub75Matrix : public Bus { bool hasWhite() const override { return false; } void setPixelColor(uint16_t pix, uint32_t c) override; + uint32_t getPixelColor(uint16_t pix) const override; void show(void) override; @@ -382,7 +390,8 @@ class BusHub75Matrix : public Bus { VirtualMatrixPanel *fourScanPanel = nullptr; HUB75_I2S_CFG mxconfig; bool isBlack = false; - + CRGB *_ledBuffer = nullptr; + byte *_ledsDirty = nullptr; }; #endif From 1b098b9863b823cedc74eb0be33ec6dae8690fd4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 19:00:19 +0200 Subject: [PATCH 023/123] fixie --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 8fb12639..183c89b8 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -755,7 +755,7 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c } } else { - //if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() + if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() #ifndef NO_CIE1931 c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction #endif From bad923570bc18a5bd9386375d535a8fe08ab8dd7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 19:04:10 +0200 Subject: [PATCH 024/123] double buffer off (MatrixPortal S3) `mxconfig.double_buff = true` should not be necessary any more. --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 183c89b8..08743552 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -570,7 +570,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh USER_PRINTLN("MatrixPanel_I2S_DMA - Matrix Portal S3 config"); - mxconfig.double_buff = true; // <------------- Turn on double buffer + //mxconfig.double_buff = true; // <------------- Turn on double buffer mxconfig.gpio.r1 = 42; mxconfig.gpio.g1 = 41; From f8154a8c7870a06a12edefdf9137e9da7f40c250 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 19:08:34 +0200 Subject: [PATCH 025/123] Update wled.h - build 2408080 --- wled00/wled.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.h b/wled00/wled.h index 1ea73805..c1f56732 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408070 +#define VERSION 2408080 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 56e72ef22db4de414ae7bcf7dbf14d3a408ad1e7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:57:15 +0200 Subject: [PATCH 026/123] HUB75 live preview --- wled00/bus_manager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 08743552..ced434a4 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -695,6 +695,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh else { _valid = true; display->clearScreen(); // initially clear the screen buffer + display->setBrightness8(127); // range is 0-255, 0 - 0%, 255 - 100% + _bri = 127; if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen @@ -781,13 +783,14 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { if (!_valid || pix >= _len) return BLACK; if (_ledBuffer) - return uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; + return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours else return BLACK; } void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { this->display->setBrightness(b); + _bri = b; } void __attribute__((hot)) BusHub75Matrix::show(void) { From 28db9bfcfdb161b952fb9a1ece0c751e56f8f6c7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 22:03:49 +0200 Subject: [PATCH 027/123] waverly effect speedup * faster math * limit height to visible area --- wled00/FX.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a9bfccbb..0f6653bd 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6667,13 +6667,19 @@ uint16_t mode_2DWaverly(void) { long t = strip.now / 2; for (int i = 0; i < cols; i++) { - uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code - uint16_t thisMax = map(thisVal, 0, 512, 0, rows); + //uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code + unsigned thisVal = unsigned(volumeSmth*SEGMENT.intensity) * inoise8(i * 45 , t , t) / (64*64); // WLEDMM same result but more accurate - for (int j = 0; j < thisMax; j++) { + //int thisMax = map(thisVal, 0, 512, 0, rows); + int thisMax = (thisVal * rows) / 512; // WLEDMM same result, just faster + int thisMax2 = min(int(rows), thisMax); // WLEDMM limit height to visible are + + for (int j = 0; j < thisMax2; j++) { + //int jmap = map(j, 0, thisMax, 250, 0); + int jmap = 250 - ((j * 250) / thisMax); // WLEDMM same result, just faster if (!SEGENV.check1) - SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND)); - SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND)); + SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND)); + SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND)); } } SEGMENT.blur(16); From d00b3147b463a3471ed18bb11970ad908c140943 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 8 Aug 2024 22:28:14 +0200 Subject: [PATCH 028/123] Waverly: better slider names Slider names were misleading. First slider: fade speed (low values means longer hold times) Second slider: signal gain (i.e. amplification) --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 0f6653bd..a541983e 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6686,7 +6686,7 @@ uint16_t mode_2DWaverly(void) { return FRAMETIME; } // mode_2DWaverly() -static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Amplification,Sensitivity,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin +static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Fade Rate,Amplification,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin #endif // WLED_DISABLE_2D From 89412b999d74288cc6b5ecd1ddbfd5d2aa478c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Mon, 29 Jul 2024 07:31:33 +0200 Subject: [PATCH 029/123] Merge pull request #4078 from apanteleev/fire-blur-control Add a parameter for blur amount in the Fire 2012 effect --- wled00/FX.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a541983e..bffcc455 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2156,14 +2156,17 @@ uint16_t mode_fire_2012() { for (int stripNr=0; stripNr> 2; + SEGMENT.blur(blurAmount); + } if (it != SEGENV.step) SEGENV.step = it; return FRAMETIME; } -static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,,Boost;;!;1.5d;sx=64,ix=160,m12=1"; // bars WLEDMM 1.5d, +static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1.5d;sx=64,ix=160,c2=128,m12=1"; // bars WLEDMM 1.5d, // ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb From a44aa92c753013e28b01fa826608d2b1e14f6e44 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 9 Aug 2024 12:53:41 +0200 Subject: [PATCH 030/123] playing with Fire2012 * speedup: add functions to only blur rows or columns (50% faster) * fire2012: tinkering with bur options. Vertical blur only when slider < 64 (faster); extra blur for slider values >192 (bush burn) --- wled00/FX.cpp | 6 ++++-- wled00/FX.h | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index bffcc455..3d00dbb8 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2148,7 +2148,7 @@ uint16_t mode_fire_2012() { // Step 4. Map from heat cells to LED colors for (int j = 0; j < SEGLEN; j++) { - SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j],byte(240)), 255, NOBLEND)); + SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j], byte(240)), 255, NOBLEND)); } } }; @@ -2158,7 +2158,9 @@ uint16_t mode_fire_2012() { if (SEGMENT.is2D()) { uint8_t blurAmount = SEGMENT.custom2 >> 2; - SEGMENT.blur(blurAmount); + if (blurAmount > 48) blurAmount += blurAmount-48; // extra blur when slider > 192 (bush burn) + if (blurAmount < 16) SEGMENT.blurCols(SEGMENT.custom2 >> 1); // no side-burn when slider < 64 (faster) + else SEGMENT.blur(blurAmount); } if (it != SEGENV.step) diff --git a/wled00/FX.h b/wled00/FX.h index 387b9e55..b61cdf72 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -656,6 +656,16 @@ typedef struct Segment { uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255); uint32_t __attribute__((pure)) color_wheel(uint8_t pos); + // 2D Blur: shortcuts for bluring columns or rows only (50% faster than full 2D blur) + inline void blurCols(fract8 blur_amount, bool smear = false) { // blur all columns + const unsigned cols = virtualWidth(); + for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount, smear); + } + inline void blurRows(fract8 blur_amount, bool smear = false) { // blur all rows + const unsigned rows = virtualHeight(); + for ( unsigned i = 0; i < rows; i++) blurRow(i, blur_amount, smear); + } + // 2D matrix #ifndef WLEDMM_FASTPATH inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline From 2934739ebf3156eb69b4471adadd61d2cee52bd2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:46:14 +0200 Subject: [PATCH 031/123] HUB75 cleanup, double buffer improvement * code cleanup, removing some unneeded sanity checks * use dirty bits in double buffer mode, too -> only not-black pixels are drawn into the back-buffer (20%-30% faster) --- wled00/bus_manager.cpp | 39 +++++++++++++++++++++------------------ wled00/bus_manager.h | 1 - 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index ced434a4..f5ecb5d6 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -19,7 +19,7 @@ bool getBitFromArray(const uint8_t* byteArray, size_t position) { // get bit val } void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr - if (byteArray == nullptr) return; + //if (byteArray == nullptr) return; size_t byteIndex = position / 8; unsigned bitIndex = position % 8; if (value) @@ -526,7 +526,6 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh _valid = false; mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory - isBlack = false; fourScanPanel = nullptr; @@ -700,14 +699,20 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen - if(mxconfig.double_buff == false) { - _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) - _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - //_ledsDirty = nullptr; - setBitArray(_ledsDirty, _len, false); // reset dirty bits - } + _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - isBlack = true; + if (_ledsDirty == nullptr) { + display->stopDMAoutput(); + delete display; display = nullptr; + _valid = false; + USER_PRINTLN(F("MatrixPanel_I2S_DMA not started - not enough memory for dirty bits!")); + return; // fail is we cannot get memory for the buffer + } + setBitArray(_ledsDirty, _len, false); // reset dirty bits + + if (mxconfig.double_buff == false) { + _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) + } } switch(bc.type) { @@ -753,11 +758,12 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c if (_ledBuffer[pix] != fastled_col) { _ledBuffer[pix] = fastled_col; setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty" - isBlack = false; } } else { - if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen() + if ((c == BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black + setBitInArray(_ledsDirty, pix, c != BLACK); // dirty = true means "color is not BLACK" + #ifndef NO_CIE1931 c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction #endif @@ -776,7 +782,6 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c int y = pix / width; display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } - isBlack = false; } } @@ -785,7 +790,7 @@ uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { if (_ledBuffer) return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours else - return BLACK; + return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not } void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { @@ -797,7 +802,6 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { if (!_valid) return; if (_ledBuffer) { // write out buffered LEDs - bool haveDirtyBits = (_ledsDirty != nullptr); bool isFourScan = (fourScanPanel != nullptr); unsigned width = isFourScan ? fourScanPanel->width() : display->width(); unsigned height = isFourScan ? fourScanPanel->height() : display->height(); @@ -806,7 +810,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { size_t pix = 0; // running pixel index for (int y=0; yflipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels) // while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. display->clearScreen(); // Now clear the back-buffer - isBlack = true; + setBitArray(_ledsDirty, _len, false); // dislay buffer is blank - reset all dirty bits } } @@ -840,7 +844,6 @@ void BusHub75Matrix::cleanup() { delete display; display = nullptr; fourScanPanel = nullptr; - isBlack = false; if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr; if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr; } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 93d5eb46..96aba376 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -389,7 +389,6 @@ class BusHub75Matrix : public Bus { MatrixPanel_I2S_DMA *display = nullptr; VirtualMatrixPanel *fourScanPanel = nullptr; HUB75_I2S_CFG mxconfig; - bool isBlack = false; CRGB *_ledBuffer = nullptr; byte *_ledsDirty = nullptr; }; From e90f8e7f0de268210f905194fc9530168d304656 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Tue, 30 Jul 2024 19:15:08 +0100 Subject: [PATCH 032/123] DMX Input - reinstate loggers for connection state change --- wled00/dmx_input.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 821481e5..3be973cc 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -187,6 +187,9 @@ void DMXInput::updateInternal() unsigned long now = millis(); if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) { if (!packet.err) { + if(!connected) { + USER_PRINTLN("DMX Input - connected"); + } connected = true; identify = isIdentifyOn(); if (!packet.is_rdm) { @@ -199,6 +202,9 @@ void DMXInput::updateInternal() } } else { + if(connected) { + USER_PRINTLN("DMX Input - disconnected"); + } connected = false; } } From a257e49bb4430be72560425f37ac17439b9afa07 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:20:15 +0200 Subject: [PATCH 033/123] HUB75 trying to reduce glitches the HUB75 driver seems to randomly produce glitches, especially on hight contrast edges. * roll back to HUB75 version 3.0.10 (known good) * limit max brightness to 238 (=92%) * add short delay after starting the driver --- platformio.ini | 3 ++- wled00/bus_manager.cpp | 23 ++++++++++++++++------- wled00/bus_manager.h | 1 + 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/platformio.ini b/platformio.ini index ec1a387d..93ca4974 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1038,7 +1038,8 @@ HUB75_build_flags = -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips ;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30) ;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... -HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11 +HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... +;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11 HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) NetDebug_build_flags = diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index f5ecb5d6..189b779a 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -685,17 +685,18 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh USER_PRINTLN("MatrixPanel_I2S_DMA created"); // let's adjust default brightness display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100% + _bri = 25; + delay(24); // experimental // Allocate memory and start DMA display if( not display->begin() ) { USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********"); return; } else { + delay(18); // experiment - give the driver a moment (~ one full frame @ 60hz) to settle _valid = true; display->clearScreen(); // initially clear the screen buffer - display->setBrightness8(127); // range is 0-255, 0 - 0%, 255 - 100% - _bri = 127; if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen @@ -736,8 +737,12 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh break; } + if (_valid) { + _panelWidth = fourScanPanel ? fourScanPanel->width() : display->width(); // cache width - it will never change + } + USER_PRINT(F("MatrixPanel_I2S_DMA ")); - USER_PRINTF("%sstarted.\n", _valid? "":"not "); + USER_PRINTF("%sstarted, width=%u, %u pixels.\n", _valid? "":"not ", _panelWidth, _len); if (mxconfig.double_buff == true) USER_PRINTLN(F("MatrixPanel_I2S_DMA driver native double-buffering enabled.")); if (_ledBuffer != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS buffer enabled.")); @@ -772,12 +777,12 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c uint8_t b = B(c); if(fourScanPanel != nullptr) { - unsigned width = fourScanPanel->width(); + int width = _panelWidth; int x = pix % width; int y = pix / width; fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } else { - unsigned width = display->width(); + int width = _panelWidth; int x = pix % width; int y = pix / width; display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); @@ -794,16 +799,19 @@ uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { } void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { - this->display->setBrightness(b); _bri = b; + if (_bri > 238) _bri=238; + display->setBrightness(_bri); } void __attribute__((hot)) BusHub75Matrix::show(void) { if (!_valid) return; + display->setBrightness(_bri); + if (_ledBuffer) { // write out buffered LEDs bool isFourScan = (fourScanPanel != nullptr); - unsigned width = isFourScan ? fourScanPanel->width() : display->width(); + //if (isFourScan) fourScanPanel->setRotation(0); unsigned height = isFourScan ? fourScanPanel->height() : display->height(); //while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. @@ -837,6 +845,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { void BusHub75Matrix::cleanup() { if (display && _valid) display->stopDMAoutput(); // terminate DMA driver (display goes black) _valid = false; + _panelWidth = 0; deallocatePins(); USER_PRINTLN("HUB75 output ended."); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 96aba376..2379f430 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -389,6 +389,7 @@ class BusHub75Matrix : public Bus { MatrixPanel_I2S_DMA *display = nullptr; VirtualMatrixPanel *fourScanPanel = nullptr; HUB75_I2S_CFG mxconfig; + unsigned _panelWidth = 0; CRGB *_ledBuffer = nullptr; byte *_ledsDirty = nullptr; }; From a77520aa05f7e18c10eea2eeab65ad1e860326fc Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:36:45 +0200 Subject: [PATCH 034/123] bugfix forgot to commit one line ... --- wled00/bus_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 189b779a..66cbd7f3 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -813,6 +813,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { bool isFourScan = (fourScanPanel != nullptr); //if (isFourScan) fourScanPanel->setRotation(0); unsigned height = isFourScan ? fourScanPanel->height() : display->height(); + unsigned width = _panelWidth; //while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker. From 5610548652505e289a1dadbd547465f6a8aa712c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:52:19 +0200 Subject: [PATCH 035/123] HUB75 clock phase `mxconfig.clkphase = false;` seems to help reduce flicker on some panels. @netmindz I think we should add a checkbox to the UI - something like "clocked on positive edge" (default = checked) which means clkphase = true. when unchecked, we set clkphase = false. --- wled00/bus_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 66cbd7f3..8783730e 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -623,6 +623,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz //mxconfig.min_refresh_rate = 90; //mxconfig.min_refresh_rate = 120; + // mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. #else USER_PRINTLN("MatrixPanel_I2S_DMA - Default pins"); From 38d30723a067606f2e0aa75770d7cc297d4f1273 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:09:10 -0400 Subject: [PATCH 036/123] 2D Audio Reactive Paintbrush Effect --- wled00/FX.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 6 ++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 4f89af77..9a6ba980 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -8550,6 +8550,88 @@ static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fil #endif // WLED_DISABLE_2D +/* + @title MoonModules WLED - Painbrush Effect + @file included in FX.cpp + @repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED + @Authors https://github.com/MoonModules/WLED/commits/mdev/ + @Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) + @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + + This function is part of the MoonModules WLED fork also known as "WLED-MM". + WLED-MM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + WLED-MM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with WLED-MM. If not, see . +*/ + +/////////////////////// +// 2D Paintbrush // +/////////////////////// +uint16_t mode_2DPaintbrush() { + + // Author: @TroyHacks + // @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + + if (!strip.isMatrix) return mode_static(); // not a 2D set-up + + const uint16_t cols = SEGMENT.virtualWidth(); + const uint16_t rows = SEGMENT.virtualHeight(); + + if (!SEGENV.allocateData(4)) return mode_static(); //allocation failed + + if (SEGENV.call == 0) { + SEGMENT.setUpLeds(); + SEGMENT.fill(BLACK); + SEGENV.aux0 = 0; + } + + bool phase_chaos = SEGMENT.check3; + bool soft = SEGMENT.check2; + bool color_chaos = SEGMENT.check1; + CRGB color; + + byte numLines = map8(SEGMENT.intensity,1,16); + + SEGENV.aux0++; // hue + SEGMENT.fadeToBlackBy(map8(SEGENV.custom1,10,128)); + + um_data_t *um_data; + if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + // add support for no audio + um_data = simulateSound(SEGMENT.soundSim); + } + uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; + + SEGENV.aux1 = phase_chaos?random8():0; + + for (size_t i = 0; i < numLines; i++) { + byte bin = map(i,0,numLines,0,15); + + byte x1 = beatsin8(max(16,int(SEGMENT.speed))/16*1 + fftResult[0]/16, 0, (cols-1), fftResult[bin], SEGENV.aux1); + byte x2 = beatsin8(max(16,int(SEGMENT.speed))/16*2 + fftResult[0]/16, 0, (cols-1), fftResult[bin], SEGENV.aux1); + byte y1 = beatsin8(max(16,int(SEGMENT.speed))/16*3 + fftResult[0]/16, 0, (rows-1), fftResult[bin], SEGENV.aux1); + byte y2 = beatsin8(max(16,int(SEGMENT.speed))/16*4 + fftResult[0]/16, 0, (rows-1), fftResult[bin], SEGENV.aux1); + + int length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); + length = map8(fftResult[bin],0,length); + + if (length > max(1,int(SEGMENT.custom3))) { + if (color_chaos) { + color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND); + } else { + uint16_t colorIndex = map(i,0,numLines,0,255); + color = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0); + } + SEGMENT.drawLine(x1,y1,x2,y2,color,soft,length); + } + } + return FRAMETIME; +} // mode_2DPaintbrush() +static const char _data_FX_MODE_2DPAINTBRUSH[] PROGMEM = "Paintbrush@Oscillator Offset,# of lines,Fade Rate,,Min Length,Color Chaos,Anti-aliasing,Phase Chaos;!,,Peaks;!;2f;sx=160,ix=255,c1=80,c2=255,c3=0,pal=11,o1=0,o2=1,o3=0"; ////////////////////////////////////////////////////////////////////////////////////////// // mode data @@ -8796,6 +8878,8 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_GEQLASER, &mode_GEQLASER, _data_FX_MODE_GEQLASER); // audio + addEffect(FX_MODE_2DPAINTBRUSH, &mode_2DPaintbrush, _data_FX_MODE_2DPAINTBRUSH); // audio + #endif // WLED_DISABLE_2D } diff --git a/wled00/FX.h b/wled00/FX.h index af707b41..c32c3b47 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -348,9 +348,9 @@ bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn. #define FX_MODE_STARBURST_AR 192 // WLED-SR audioreactive fireworks starburst // #define FX_MODE_PALETTE_AR 193 // WLED-SR audioreactive palette #define FX_MODE_FIREWORKS_AR 194 // WLED-SR audioreactive fireworks -#define FX_MODE_GEQLASER 195 // WLED-MM GEQ Laser - -#define MODE_COUNT 196 +#define FX_MODE_GEQLASER 195 // WLED-MM GEQ Laser +#define FX_MODE_2DPAINTBRUSH 196 // WLED-MM GEQ Laser +#define MODE_COUNT 197 typedef enum mapping1D2D { M12_Pixels = 0, From 9e65ab3be42cebb956d74ca8bb5801d7dc4380c2 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:53:35 -0400 Subject: [PATCH 037/123] Stop issue playlist continuing when disabling AutoPlaylist If you use the "music" playlist on boot, it'll keep it going even when you manually override to something else. This seems to fix this condition. --- usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h | 1 + 1 file changed, 1 insertion(+) diff --git a/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h b/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h index adb5b37e..4cc50671 100644 --- a/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h +++ b/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h @@ -303,6 +303,7 @@ class AutoPlaylistUsermod : public Usermod { #ifdef USERMOD_AUTO_PLAYLIST_DEBUG USER_PRINTF("AutoPlaylist: disable due to manual change of playlist from %u to %d, preset:%u\n", lastAutoPlaylist, currentPlaylist, currentPreset); #endif + suspendPlaylist(); functionality_enabled = false; } else if (currentPlaylist == musicPlaylist) { #ifdef USERMOD_AUTO_PLAYLIST_DEBUG From 3b551a40f3ea32bca5674b53f1028b14339edeb3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 15 Aug 2024 09:08:57 +0100 Subject: [PATCH 038/123] Remove repeating code to fetch audio data --- wled00/FX.cpp | 190 +++++++----------------------------------- wled00/fcn_declare.h | 1 + wled00/um_manager.cpp | 8 ++ 3 files changed, 41 insertions(+), 158 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 3d00dbb8..b8edaf85 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1994,11 +1994,7 @@ uint16_t mode_partyjerk() { * step: pos */ - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; SEGENV.aux0++; @@ -6519,11 +6515,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Ripple* ripples = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; #ifdef ESP32 float FFT_MajorPeak = *(float*) um_data->u_data[4]; @@ -6619,11 +6611,7 @@ uint16_t mode_2DSwirl(void) { uint8_t nj = (cols - 1) - j; uint16_t ms = strip.now; - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg??? int16_t volumeRaw = *(int16_t*) um_data->u_data[1]; @@ -6656,11 +6644,7 @@ uint16_t mode_2DWaverly(void) { SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; float soundPressure = *(float*) um_data->u_data[9]; float agcSensitivity= *(float*) um_data->u_data[10]; @@ -6714,11 +6698,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; //SEGMENT.fade_out(240); @@ -6766,11 +6746,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; // printUmData(); @@ -6817,11 +6793,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline. if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; // int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; //WLEDMM: this variable not used here float soundPressure = *(float*) um_data->u_data[9]; @@ -6894,11 +6866,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter ☾@Rate of f // * JUGGLES // ////////////////////// uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -6921,11 +6889,7 @@ static const char _data_FX_MODE_JUGGLES[] PROGMEM = "Juggles@!,# of balls;!,!;!; uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. With some enhancements by @softhack007 // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; float volumeSmth = *(float*) um_data->u_data[0]; float soundPressure = *(float*) um_data->u_data[9]; @@ -6977,11 +6941,7 @@ static const char _data_FX_MODE_MATRIPIX[] PROGMEM = "Matripix ☾@!,Brightness, uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline. // Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) { @@ -7020,11 +6980,7 @@ uint16_t mode_noisefire(void) { // Noisefire. By Andrew Tuline. CRGB::DarkOrange, CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) SEGMENT.fill(BLACK); @@ -7048,11 +7004,7 @@ static const char _data_FX_MODE_NOISEFIRE[] PROGMEM = "Noisefire@!,!;;;01v;m12=2 /////////////////////// uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -7090,11 +7042,7 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline. SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; uint8_t secondHand = micros()/(256-SEGMENT.speed)/500+1 % 16; @@ -7128,11 +7076,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline. if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed Plasphase* plasmoip = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) { @@ -7171,11 +7115,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline. uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254); uint16_t pos = random16(SEGLEN); // Set a random starting position. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; uint8_t *maxVol = (uint8_t*)um_data->u_data[6]; uint8_t *binNum = (uint8_t*)um_data->u_data[7]; @@ -7223,11 +7163,7 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline. } SEGMENT.fade_out(fadeVal); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; if (volumeRaw > 1) { @@ -7252,10 +7188,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline. if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed uint8_t *myVals = reinterpret_cast(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -7285,11 +7218,7 @@ static const char _data_FX_MODE_PIXELS[] PROGMEM = "Pixels@Fade rate,# of pixels uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; if (SEGENV.call == 0) { @@ -7319,11 +7248,7 @@ static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz@Fade rate,Blur;!,Color uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. // Hint: Looks best with segment brightness set to max (use global brightness to reduce brightness) // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7371,11 +7296,7 @@ uint16_t mode_DJLight(void) { // Written by Stefan Petrick, Ad // No need to prevent from executing on single led strips, only mid will be set (mid = 0) const int mid = SEGLEN / 2; - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7441,11 +7362,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. // Start frequency = 60 Hz and log10(60) = 1.78 // End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10 - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[SEGENV.check1 ? 8:4]; // WLEDMM may use FFT_MajorPeakSmth float my_magnitude = *(float*)um_data->u_data[5] / 4.0f; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7486,11 +7403,7 @@ static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting /////////////////////// uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung. // No need to prevent from executing on single led strips, we simply change pixel 0 each time and avoid the shift - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7545,11 +7458,7 @@ static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound e // SEGMENT.speed select faderate // SEGMENT.intensity select colour index uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float my_magnitude = *(float*)um_data->u_data[5] / 16.0f; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7592,11 +7501,7 @@ static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Sta // Depending on the music stream you have you might find it useful to change the frequency mapping. uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung. With some enhancements by @softhack007 // As before, this effect can also work on single pixels, we just lose the shifting effect - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7666,11 +7571,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline. if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7719,11 +7620,7 @@ static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq ☾@Rate of fall, // ** Noisemove // ////////////////////// uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7752,11 +7649,7 @@ static const char _data_FX_MODE_NOISEMOVE[] PROGMEM = "Noisemove@Speed of perlin // ** Rocktaves // ////////////////////// uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); float FFT_MajorPeak = *(float*) um_data->u_data[8]; // WLEDMM use FFT_MajorPeakSmth float my_magnitude = *(float*) um_data->u_data[5] / 16.0f; @@ -7800,11 +7693,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin // effect can work on single pixels, we just lose the shifting effect if (SEGENV.call == 0) SEGMENT.fill(BLACK); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; float FFT_MajorPeak = *(float*) um_data->u_data[4]; uint8_t *maxVol = (uint8_t*)um_data->u_data[6]; @@ -7865,11 +7754,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed uint16_t *previousBarHeight = reinterpret_cast(SEGENV.data); //array of previous bar heights per frequency band - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7976,11 +7861,7 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil bandInc = (NUMB_BANDS / cols); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -8069,10 +7950,7 @@ uint16_t mode_2DAkemi(void) { const float lightFactor = 0.15f; const float normalFactor = 0.4f; - um_data_t *um_data = nullptr; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values float base = fftResult[0]/255.0f; @@ -8458,11 +8336,7 @@ uint16_t mode_GEQLASER(void) { uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0); uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser") - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = usermods.getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; uint8_t heights[NUM_GEQ_CHANNELS] = { 0 }; diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 09f9724b..854fdb4e 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -332,6 +332,7 @@ class UsermodManager { void handleOverlayDraw(); bool handleButton(uint8_t b); bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods + um_data_t *getAudioData(); void setup(); void connected(); // void appendConfigData(); //WLEDMM not used diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 2fe44db9..8013433f 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -23,6 +23,14 @@ bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) { } return false; } +um_data_t* UsermodManager::getAudioData() { + um_data_t *um_data; + if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + // add support for no audio + um_data = simulateSound(SEGMENT.soundSim); + } + return um_data; +} void UsermodManager::addToJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); } void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); } void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); } From b0b3e75556c09fd72dd1fb2df692a504f57b7614 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 15 Aug 2024 16:22:24 +0100 Subject: [PATCH 039/123] Move getAudioData to static --- wled00/FX.cpp | 72 ++++++++++++++++++++++++------------------- wled00/fcn_declare.h | 1 - wled00/um_manager.cpp | 8 ----- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b8edaf85..a6ac03f7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -98,6 +98,14 @@ static long map2(long x, long in_min, long in_max, long out_min, long out_max) } +static um_data_t* getAudioData() { + um_data_t *um_data; + if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + // add support for no audio + um_data = simulateSound(SEGMENT.soundSim); + } + return um_data; +} // effect functions /* @@ -1994,7 +2002,7 @@ uint16_t mode_partyjerk() { * step: pos */ - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; SEGENV.aux0++; @@ -6515,7 +6523,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Ripple* ripples = reinterpret_cast(SEGENV.data); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; #ifdef ESP32 float FFT_MajorPeak = *(float*) um_data->u_data[4]; @@ -6611,7 +6619,7 @@ uint16_t mode_2DSwirl(void) { uint8_t nj = (cols - 1) - j; uint16_t ms = strip.now; - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg??? int16_t volumeRaw = *(int16_t*) um_data->u_data[1]; @@ -6644,7 +6652,7 @@ uint16_t mode_2DWaverly(void) { SEGMENT.fill(BLACK); } - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; float soundPressure = *(float*) um_data->u_data[9]; float agcSensitivity= *(float*) um_data->u_data[10]; @@ -6698,7 +6706,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. SEGMENT.fill(BLACK); } - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; //SEGMENT.fade_out(240); @@ -6746,7 +6754,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew SEGMENT.fill(BLACK); } - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; // printUmData(); @@ -6793,7 +6801,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline. if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; // int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; //WLEDMM: this variable not used here float soundPressure = *(float*) um_data->u_data[9]; @@ -6866,7 +6874,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter ☾@Rate of f // * JUGGLES // ////////////////////// uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline. - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -6889,7 +6897,7 @@ static const char _data_FX_MODE_JUGGLES[] PROGMEM = "Juggles@!,# of balls;!,!;!; uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. With some enhancements by @softhack007 // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; float volumeSmth = *(float*) um_data->u_data[0]; float soundPressure = *(float*) um_data->u_data[9]; @@ -6941,7 +6949,7 @@ static const char _data_FX_MODE_MATRIPIX[] PROGMEM = "Matripix ☾@!,Brightness, uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline. // Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1. - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) { @@ -6980,7 +6988,7 @@ uint16_t mode_noisefire(void) { // Noisefire. By Andrew Tuline. CRGB::DarkOrange, CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) SEGMENT.fill(BLACK); @@ -7004,7 +7012,7 @@ static const char _data_FX_MODE_NOISEFIRE[] PROGMEM = "Noisefire@!,!;;;01v;m12=2 /////////////////////// uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline. - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -7042,7 +7050,7 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline. SEGMENT.fill(BLACK); } - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; uint8_t secondHand = micros()/(256-SEGMENT.speed)/500+1 % 16; @@ -7076,7 +7084,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline. if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed Plasphase* plasmoip = reinterpret_cast(SEGENV.data); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) { @@ -7115,7 +7123,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline. uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254); uint16_t pos = random16(SEGLEN); // Set a random starting position. - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; uint8_t *maxVol = (uint8_t*)um_data->u_data[6]; uint8_t *binNum = (uint8_t*)um_data->u_data[7]; @@ -7163,7 +7171,7 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline. } SEGMENT.fade_out(fadeVal); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; if (volumeRaw > 1) { @@ -7188,7 +7196,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline. if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed uint8_t *myVals = reinterpret_cast(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low. - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -7218,7 +7226,7 @@ static const char _data_FX_MODE_PIXELS[] PROGMEM = "Pixels@Fade rate,# of pixels uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; if (SEGENV.call == 0) { @@ -7248,7 +7256,7 @@ static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz@Fade rate,Blur;!,Color uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. // Hint: Looks best with segment brightness set to max (use global brightness to reduce brightness) // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7296,7 +7304,7 @@ uint16_t mode_DJLight(void) { // Written by Stefan Petrick, Ad // No need to prevent from executing on single led strips, only mid will be set (mid = 0) const int mid = SEGLEN / 2; - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7362,7 +7370,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. // Start frequency = 60 Hz and log10(60) = 1.78 // End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10 - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[SEGENV.check1 ? 8:4]; // WLEDMM may use FFT_MajorPeakSmth float my_magnitude = *(float*)um_data->u_data[5] / 4.0f; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7403,7 +7411,7 @@ static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting /////////////////////// uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung. // No need to prevent from executing on single led strips, we simply change pixel 0 each time and avoid the shift - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7458,7 +7466,7 @@ static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound e // SEGMENT.speed select faderate // SEGMENT.intensity select colour index uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline. - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float my_magnitude = *(float*)um_data->u_data[5] / 16.0f; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7501,7 +7509,7 @@ static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Sta // Depending on the music stream you have you might find it useful to change the frequency mapping. uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung. With some enhancements by @softhack007 // As before, this effect can also work on single pixels, we just lose the shifting effect - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7571,7 +7579,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline. if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7620,7 +7628,7 @@ static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq ☾@Rate of fall, // ** Noisemove // ////////////////////// uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7649,7 +7657,7 @@ static const char _data_FX_MODE_NOISEMOVE[] PROGMEM = "Noisemove@Speed of perlin // ** Rocktaves // ////////////////////// uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*) um_data->u_data[8]; // WLEDMM use FFT_MajorPeakSmth float my_magnitude = *(float*) um_data->u_data[5] / 16.0f; @@ -7693,7 +7701,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin // effect can work on single pixels, we just lose the shifting effect if (SEGENV.call == 0) SEGMENT.fill(BLACK); - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; float FFT_MajorPeak = *(float*) um_data->u_data[4]; uint8_t *maxVol = (uint8_t*)um_data->u_data[6]; @@ -7754,7 +7762,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed uint16_t *previousBarHeight = reinterpret_cast(SEGENV.data); //array of previous bar heights per frequency band - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7861,7 +7869,7 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil bandInc = (NUMB_BANDS / cols); } - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7950,7 +7958,7 @@ uint16_t mode_2DAkemi(void) { const float lightFactor = 0.15f; const float normalFactor = 0.4f; - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values float base = fftResult[0]/255.0f; @@ -8336,7 +8344,7 @@ uint16_t mode_GEQLASER(void) { uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0); uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser") - um_data_t *um_data = usermods.getAudioData(); + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; uint8_t heights[NUM_GEQ_CHANNELS] = { 0 }; diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 854fdb4e..09f9724b 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -332,7 +332,6 @@ class UsermodManager { void handleOverlayDraw(); bool handleButton(uint8_t b); bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods - um_data_t *getAudioData(); void setup(); void connected(); // void appendConfigData(); //WLEDMM not used diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 8013433f..2fe44db9 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -23,14 +23,6 @@ bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) { } return false; } -um_data_t* UsermodManager::getAudioData() { - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } - return um_data; -} void UsermodManager::addToJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); } void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); } void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); } From f7e3f35c0c30f00e2350cab78348bdb90a75c456 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 15 Aug 2024 20:35:16 +0200 Subject: [PATCH 040/123] my favourite HUB75 buildenv [env:esp32_4MB_V4_HUB75_forum] --- platformio.ini | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 2 ++ 2 files changed, 66 insertions(+) diff --git a/platformio.ini b/platformio.ini index 93ca4974..94bb35e7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -187,6 +187,7 @@ build_flags = -D DECODE_SONY=true -D DECODE_SAMSUNG=true -D DECODE_LG=true + -D FASTLED_NO_FASTLED ;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this breaks framework code on ESP32-C3 and ESP32-S2 -DWLED_USE_MY_CONFIG ; -D USERMOD_SENSORSTOMQTT @@ -240,6 +241,8 @@ upload_speed = 115200 lib_compat_mode = strict lib_deps = fastled/FastLED @ 3.6.0 + ;; fastled/FastLED @ 3.7.1 + ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 IRremoteESP8266 @ 2.8.2 ;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections ;;https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7 @@ -1602,6 +1605,67 @@ lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation ; RAM: [=== ] 28.1% (used 91960 bytes from 327680 bytes) ; Flash: [==========] 97.8% (used 1537777 bytes from 1572864 bytes) + +;; softhack007: my favourite HUB75 buildenv - fastest possible +[env:esp32_4MB_V4_HUB75_forum] +extends = esp32_4MB_V4_S_base +platform_packages = ${esp32_4MB_V4_S_base.platform_packages} +;; toolchain-xtensa-esp32@~11.2 ;; for trying out newer gcc @11.2.0+2022r1 ;; 25fps -> 30fps;; FastLED 3.7.1 required !! + +build_unflags = ${esp32_4MB_V4_S_base.build_unflags} + ${Speed_Flags.build_unflags} ;; to override -Os + ;; -D WLED_ENABLE_DMX_INPUT + -DARDUINO_EVENT_RUNNING_CORE=1 + ;;-DCORE_DEBUG_LEVEL=0 + ;; -D NDEBUG + -D NO_CIE1931 ;; Do use LED brightness compensation described in CIE 1931 + +build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} + ;; -Wsuggest-attribute=const -Wsuggest-attribute=pure + ;; -Wmissing-noreturn -Wmissing-return + ;; -Wall -Wextra + -Wno-unused-value -Wno-format -Wno-type-limits + -D WLED_RELEASE_NAME=esp32_4MB_V4_HUB75 + ${Speed_Flags.build_flags} ;; -O2 -> optimize for speed instead of size + ;; -D DEBUG + -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET + -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup + -D WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions. + -D WLED_DISABLE_LOXONE + -D WLED_DISABLE_ALEXA + -D WLED_DISABLE_HUESYNC + -D WLED_DISABLE_MQTT + -D WLED_DISABLE_INFRARED + -D WLED_DISABLE_ADALIGHT + ;; -D WLED_DEBUG + ;; -D SR_DEBUG + -D WLED_BOOTUPDELAY=350 + -D WLED_ENABLE_HUB75MATRIX -DESP32_FORUM_PINOUT + ;; -D HUB75_NO_DOUBLEBUFFER ;; -D PIXEL_COLOUR_DEPTH_BITS=12 + ${common_mm.animartrix_build_flags} + ;;-DARDUINO_EVENT_RUNNING_CORE=0 ;; assign Wifi to core0, to have more CPU on core#1 (arduino loop) + ;;-DARDUINO_RUNNING_CORE=1 ;; should be default, but does not hurt + -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - seems to move more buffers into PSRAM + ;; -D CONFIG_ESP32_REV_MIN=3 ;; disables PSRAM bug workarounds in the core, reducing the code size and improving overall performance. + -D JSON_BUFFER_SIZE=18432 -D MIN_HEAP_SIZE=6144 + -D MAX_SEGMENT_DATA=40960 ;; default 32767 + -D WLEDMM_SAVE_FLASH + -D WLED_DISABLE_BROWNOUT_DET + ;;-DCORE_DEBUG_LEVEL=1 + ;;-D WLED_DISABLE_PARTICLESYSTEM1D + ;;-D WLED_DISABLE_PARTICLESYSTEM2D + ;;-D WLED_DISABLE_PARTICLESYSTEM_BUFFER + +lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} + ${common_mm.animartrix_lib_deps} +lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + ;; ${common_mm.DMXin_lib_ignore} + +board_build.partitions = ${esp32.big_partitions} +board_build.f_flash = 80000000L ; use full 80MHz speed for flash (default = 40Mhz) +board_build.flash_mode = qio ; (dio = dual i/o; more compatible than qio = quad i/o) + + ; compiled with ESP-IDF 4.4.1 [env:esp32_4MB_V4_M] extends = esp32_4MB_V4_M_base diff --git a/wled00/FX.h b/wled00/FX.h index b61cdf72..a2f51cf4 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -87,11 +87,13 @@ bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented #ifndef MAX_NUM_SEGMENTS #define MAX_NUM_SEGMENTS 32 #endif + #ifndef MAX_SEGMENT_DATA #if defined(ARDUINO_ARCH_ESP32S2) #define MAX_SEGMENT_DATA 24576 #else #define MAX_SEGMENT_DATA 32767 #endif + #endif #endif /* How much data bytes each segment should max allocate to leave enough space for other segments, From f287143cc3bbc00664143a9b550af63fcdd40e04 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 15 Aug 2024 20:36:09 +0200 Subject: [PATCH 041/123] build 2408150 --- wled00/wled.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.h b/wled00/wled.h index c1f56732..c185bc46 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408080 +#define VERSION 2408150 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 030a7cee537e99f9b5db1e3f7bf69874f3908211 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 16 Aug 2024 17:54:11 +0200 Subject: [PATCH 042/123] another small speedup, and segment stability improvement * removed a few sanity check that are done again later in getPixelColor * stability: prevent crashes when changing segments settings or effect options --- wled00/FX.h | 1 + wled00/FX_2Dfcn.cpp | 18 +++++++++++------- wled00/FX_fcn.cpp | 39 +++++++++++++++++++++++++++++++++++---- wled00/wled.h | 2 +- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index a2f51cf4..4ab04a9f 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -439,6 +439,7 @@ typedef struct Segment { #ifdef WLEDMM_FASTPATH // WLEDMM cache some values that won't change while drawing a frame bool _isSimpleSegment = false; + bool _isSuperSimpleSegment = false; bool _isValid2D = false; uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity bool _firstFill = true; // dirty HACK support diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9660df63..b7e5357a 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -241,6 +241,7 @@ void Segment::startFrame(void) { _isValid2D = isActive() && is2D(); _brightness = currentBri(on ? opacity : 0); _isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved + _isSuperSimpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); // fastest - we only draw one pixel per call // if (reverse_y) _isSimpleSegment = false; // for A/B testing _2dWidth = is2D() ? calc_virtualWidth() : virtualLength(); _2dHeight = calc_virtualHeight(); @@ -279,7 +280,8 @@ void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, // set the requested pixel strip.setPixelColorXY_fast(start + x, startY + y, scaled_col); - bool simpleSegment = !mirror && !mirror_y; + //bool simpleSegment = !mirror && !mirror_y; + bool simpleSegment = _isSuperSimpleSegment; if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed // handle mirroring @@ -306,7 +308,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY_slow(int x, int y, uint32_t col) //WL void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally #endif { - if (Segment::maxHeight==1) return; // not a matrix set-up + if ((Segment::maxHeight==1) || !isActive()) return; // not a matrix set-up const int_fast16_t cols = virtualWidth(); // WLEDMM optimization const int_fast16_t rows = virtualHeight(); @@ -335,7 +337,8 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed // WLEDMM shortcut when no grouping/spacing used - bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + //bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + bool simpleSegment = _isSuperSimpleSegment; if (simpleSegment) { strip.setPixelColorXY(start + x, startY + y, col); return; @@ -441,20 +444,21 @@ uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { // Blends the specified color with the existing pixel color. void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { - setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); + if (blend == UINT8_MAX) setPixelColorXY(x, y, color); + else setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); } // Adds the specified color with the existing pixel color perserving color balance. void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) { - if (!isActive()) return; // not active - if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit + // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY + // if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit //WLEDMM uint32_t col = getPixelColorXY(x,y); col = color_add(col, color, fast); setPixelColorXY(x, y, col); } void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { - if (!isActive()) return; // not active + // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade); setPixelColorXY(x, y, pix); } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 0f6eb6da..b5e84039 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -102,6 +102,12 @@ Segment::Segment(const Segment &orig) { DEBUG_PRINTLN(F("-- Copy segment constructor --")); memcpy((void*)this, (void*)&orig, sizeof(Segment)); //WLEDMM copy to this transitional = false; // copied segment cannot be in transition +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to the new segment + // _isValid2D = false; + _isSimpleSegment = false; + _isSuperSimpleSegment = false; +#endif name = nullptr; data = nullptr; _dataLen = 0; @@ -143,8 +149,17 @@ void Segment::allocLeds() { // move constructor --> moves everything (including buffer) from orig to this Segment::Segment(Segment &&orig) noexcept { DEBUG_PRINTLN(F("-- Move segment constructor --")); +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment + orig._isSimpleSegment = false; + orig._isSuperSimpleSegment = false; +#endif memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.transitional = false; // old segment cannot be in transition any more +#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any draw calls to old segment + orig._isValid2D = false; +#endif orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -169,6 +184,12 @@ Segment& Segment::operator= (const Segment &orig) { // copy source memcpy((void*)this, (void*)&orig, sizeof(Segment)); transitional = false; +#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any fast draw calls to this segment until the next frame starts + //_isValid2D = false; + _isSimpleSegment = false; + _isSuperSimpleSegment = false; +#endif // erase pointers to allocated data name = nullptr; data = nullptr; @@ -196,7 +217,16 @@ Segment& Segment::operator= (Segment &&orig) noexcept { deallocateData(); // free old runtime data if (_t) { delete _t; _t = nullptr; } if (ledsrgb && !Segment::_globalLeds) free(ledsrgb); //WLEDMM: not needed anymore as we will use leds from copy. no need to nullify ledsrgb as it gets new value in memcpy +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment + orig._isSimpleSegment = false; + orig._isSuperSimpleSegment = false; +#endif memcpy((void*)this, (void*)&orig, sizeof(Segment)); +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any draw calls to old segment + orig._isValid2D = false; +#endif orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -956,8 +986,8 @@ void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t co float rad = 0.0f; for (unsigned count = 0; count < numSteps; count++) { // may want to try float version as well (with or without antialiasing) - int x = roundf(sinf(rad) * radius); - int y = roundf(cosf(rad) * radius); + int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); + int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); setPixelColorXY(x, y, col); if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM rad += step; @@ -1388,7 +1418,8 @@ void __attribute__((hot)) Segment::fill(uint32_t c) { // Blends the specified color with the existing pixel color. void Segment::blendPixelColor(int n, uint32_t color, uint8_t blend) { - setPixelColor(n, color_blend(getPixelColor(n), color, blend)); + if (blend == UINT8_MAX) setPixelColor(n, color); + else setPixelColor(n, color_blend(getPixelColor(n), color, blend)); } // Adds the specified color with the existing pixel color perserving color balance. @@ -1420,7 +1451,7 @@ void Segment::fadePixelColor(uint16_t n, uint8_t fade) { /* * fade out function, higher rate = quicker fade */ -void Segment::fade_out(uint8_t rate) { +void __attribute__((hot)) Segment::fade_out(uint8_t rate) { if (!isActive()) return; // not active const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D diff --git a/wled00/wled.h b/wled00/wled.h index c185bc46..ed232910 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408150 +#define VERSION 2408160 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From b9007f2dc65f8c455d54f76645c48f23cd928afd Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 16 Aug 2024 18:02:25 +0200 Subject: [PATCH 043/123] bugfix fix compiler error on non-fastpath builds --- wled00/FX_2Dfcn.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index b7e5357a..bb0b1861 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -280,8 +280,11 @@ void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, // set the requested pixel strip.setPixelColorXY_fast(start + x, startY + y, scaled_col); - //bool simpleSegment = !mirror && !mirror_y; + #ifdef WLEDMM_FASTPATH bool simpleSegment = _isSuperSimpleSegment; + #else + bool simpleSegment = !mirror && !mirror_y; + #endif if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed // handle mirroring @@ -337,8 +340,11 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed // WLEDMM shortcut when no grouping/spacing used - //bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + #ifdef WLEDMM_FASTPATH bool simpleSegment = _isSuperSimpleSegment; + #else + bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + #endif if (simpleSegment) { strip.setPixelColorXY(start + x, startY + y, col); return; From 7bb351b185a8a38c13fa5fd4c01dc732023f4b19 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Sat, 17 Aug 2024 08:15:27 -0400 Subject: [PATCH 044/123] Minor updates to Paintbrush --- wled00/FX.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index bd95e060..1fbc74e6 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -8497,11 +8497,7 @@ uint16_t mode_2DPaintbrush() { SEGENV.aux0++; // hue SEGMENT.fadeToBlackBy(map8(SEGENV.custom1,10,128)); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; SEGENV.aux1 = phase_chaos?random8():0; @@ -8529,7 +8525,7 @@ uint16_t mode_2DPaintbrush() { } return FRAMETIME; } // mode_2DPaintbrush() -static const char _data_FX_MODE_2DPAINTBRUSH[] PROGMEM = "Paintbrush@Oscillator Offset,# of lines,Fade Rate,,Min Length,Color Chaos,Anti-aliasing,Phase Chaos;!,,Peaks;!;2f;sx=160,ix=255,c1=80,c2=255,c3=0,pal=11,o1=0,o2=1,o3=0"; +static const char _data_FX_MODE_2DPAINTBRUSH[] PROGMEM = "Paintbrush ☾@Oscillator Offset,# of lines,Fade Rate,,Min Length,Color Chaos,Anti-aliasing,Phase Chaos;!,,Peaks;!;2f;sx=160,ix=255,c1=80,c2=255,c3=0,pal=72,o1=0,o2=1,o3=0"; ////////////////////////////////////////////////////////////////////////////////////////// // mode data From f23df9dfbc5bdc4bbc01d3a49df94a027a37f17f Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Sat, 17 Aug 2024 08:28:08 -0400 Subject: [PATCH 045/123] Revert functionality change to M12_pArc Left the new code in for reference --- wled00/FX_fcn.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b5e84039..9092e3f7 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -986,8 +986,10 @@ void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t co float rad = 0.0f; for (unsigned count = 0; count < numSteps; count++) { // may want to try float version as well (with or without antialiasing) - int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); - int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); + // int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); + // int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); + int x = roundf(sinf(rad) * radius); + int y = roundf(cosf(rad) * radius); setPixelColorXY(x, y, col); if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM rad += step; From 1ef13c207703dd32dc34f5472e87939759b9827b Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Sat, 17 Aug 2024 13:05:23 -0400 Subject: [PATCH 046/123] Arc 1D Expand uses drawArc if the segment is not "super simple" WLEDMM: drawArc() is faster if it's NOT "super simple" as the regular M12_pArc code can do "useSymmetry" to speed things along on larger 2D layouts, but a more "complicated" segment likely uses mirroring which generates a symmetry speed-up, or other things which mean less pixels are calculated. --- wled00/FX_fcn.cpp | 77 ++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 9092e3f7..f8f2269e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -971,44 +971,51 @@ void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t co if (i==0) setPixelColorXY(0, 0, col); else { - //WLEDMM: drawArc(0, 0, i, col); could work as alternative + if (!_isSuperSimpleSegment) { + // WLEDMM: drawArc() is faster if it's NOT "super simple" as the regular M12_pArc + // can do "useSymmetry" to speed things along, but a more complicated segment likey + // uses mirroring which generates a symmetry speed-up, or other things which mean + // less pixels are calculated. + drawArc(0, 0, i, col); + } else { + //WLEDMM: some optimizations for the drawing loop + // pre-calculate loop limits, exploit symmetry at 45deg + float radius = float(i); + + // float step = HALF_PI / (2.85f * radius); // upstream uses this + float step = HALF_PI / (M_PI * radius); // WLEDMM we use the correct circumference + bool useSymmetry = (max(vH, vW) > 20); // for segments wider than 20 pixels, we exploit symmetry + unsigned numSteps; + if (useSymmetry) numSteps = 1 + ((HALF_PI/2.0f + step/2.0f) / step); // with symmetry + else numSteps = 1 + ((HALF_PI + step/2.0f) / step); // without symmetry - //WLEDMM: some optimizations for the drawing loop - // pre-calculate loop limits, exploit symmetry at 45deg - float radius = float(i); - // float step = HALF_PI / (2.85f * radius); // upstream uses this - float step = HALF_PI / (M_PI * radius); // WLEDMM we use the correct circumference - bool useSymmetry = (max(vH, vW) > 20); // for segments wider than 20 pixels, we exploit symmetry - unsigned numSteps; - if (useSymmetry) numSteps = 1 + ((HALF_PI/2.0f + step/2.0f) / step); // with symmetry - else numSteps = 1 + ((HALF_PI + step/2.0f) / step); // without symmetry + float rad = 0.0f; + for (unsigned count = 0; count < numSteps; count++) { + // may want to try float version as well (with or without antialiasing) + // int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); + // int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); + int x = roundf(sinf(rad) * radius); + int y = roundf(cosf(rad) * radius); + setPixelColorXY(x, y, col); + if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM + rad += step; + } - float rad = 0.0f; - for (unsigned count = 0; count < numSteps; count++) { - // may want to try float version as well (with or without antialiasing) - // int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); - // int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); - int x = roundf(sinf(rad) * radius); - int y = roundf(cosf(rad) * radius); - setPixelColorXY(x, y, col); - if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM - rad += step; + // // Bresenham’s Algorithm (may not fill every pixel) + // int d = 3 - (2*i); + // int y = i, x = 0; + // while (y >= x) { + // setPixelColorXY(x, y, col); + // setPixelColorXY(y, x, col); + // x++; + // if (d > 0) { + // y--; + // d += 4 * (x - y) + 10; + // } else { + // d += 4 * x + 6; + // } + // } } - - // Bresenham’s Algorithm (may not fill every pixel) - //int d = 3 - (2*i); - //int y = i, x = 0; - //while (y >= x) { - // setPixelColorXY(x, y, col); - // setPixelColorXY(y, x, col); - // x++; - // if (d > 0) { - // y--; - // d += 4 * (x - y) + 10; - // } else { - // d += 4 * x + 6; - // } - //} } break; case M12_pCorner: { From b47c55db90e6c39fbbf103c51d64e0989c901200 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 18 Aug 2024 13:21:55 +0200 Subject: [PATCH 047/123] fix 8266 builds wled00/FX_fcn.cpp:974:16: error: '_isSuperSimpleSegment' was not declared in this scope --- wled00/FX.h | 4 ++-- wled00/FX_2Dfcn.cpp | 5 +++-- wled00/FX_fcn.cpp | 15 +++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 546e8b98..17e70021 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -436,10 +436,10 @@ typedef struct Segment { static size_t _usedSegmentData; // WLEDMM uint16_t is too small void setPixelColorXY_fast(int x, int y,uint32_t c, uint32_t scaled_col, int cols, int rows); // set relative pixel within segment with color - faster, but no error checking!!! + bool _isSimpleSegment = false; // simple = no grouping or spacing - mirror, transpose or reverse allowed + bool _isSuperSimpleSegment = false; // superSimple = no grouping or spacing, no mirror - only transpose or reverse allowed #ifdef WLEDMM_FASTPATH // WLEDMM cache some values that won't change while drawing a frame - bool _isSimpleSegment = false; - bool _isSuperSimpleSegment = false; bool _isValid2D = false; uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity bool _firstFill = true; // dirty HACK support diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index bb0b1861..4518bdff 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -237,11 +237,12 @@ uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) // WLEDMM cache some values so we don't need to re-calc then for each pixel void Segment::startFrame(void) { + _isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved + _isSuperSimpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); // fastest - we only draw one pixel per call + #ifdef WLEDMM_FASTPATH _isValid2D = isActive() && is2D(); _brightness = currentBri(on ? opacity : 0); - _isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved - _isSuperSimpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); // fastest - we only draw one pixel per call // if (reverse_y) _isSimpleSegment = false; // for A/B testing _2dWidth = is2D() ? calc_virtualWidth() : virtualLength(); _2dHeight = calc_virtualHeight(); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index f8f2269e..c4b1a459 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -102,12 +102,11 @@ Segment::Segment(const Segment &orig) { DEBUG_PRINTLN(F("-- Copy segment constructor --")); memcpy((void*)this, (void*)&orig, sizeof(Segment)); //WLEDMM copy to this transitional = false; // copied segment cannot be in transition -#ifdef WLEDMM_FASTPATH // WLEDMM temporarily prevent any fast draw calls to the new segment // _isValid2D = false; _isSimpleSegment = false; _isSuperSimpleSegment = false; -#endif + name = nullptr; data = nullptr; _dataLen = 0; @@ -149,11 +148,11 @@ void Segment::allocLeds() { // move constructor --> moves everything (including buffer) from orig to this Segment::Segment(Segment &&orig) noexcept { DEBUG_PRINTLN(F("-- Move segment constructor --")); -#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment orig._isSimpleSegment = false; orig._isSuperSimpleSegment = false; -#endif + memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.transitional = false; // old segment cannot be in transition any more #ifdef WLEDMM_FASTPATH @@ -184,12 +183,12 @@ Segment& Segment::operator= (const Segment &orig) { // copy source memcpy((void*)this, (void*)&orig, sizeof(Segment)); transitional = false; -#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any fast draw calls to this segment until the next frame starts //_isValid2D = false; _isSimpleSegment = false; _isSuperSimpleSegment = false; -#endif + // erase pointers to allocated data name = nullptr; data = nullptr; @@ -217,11 +216,11 @@ Segment& Segment::operator= (Segment &&orig) noexcept { deallocateData(); // free old runtime data if (_t) { delete _t; _t = nullptr; } if (ledsrgb && !Segment::_globalLeds) free(ledsrgb); //WLEDMM: not needed anymore as we will use leds from copy. no need to nullify ledsrgb as it gets new value in memcpy -#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment orig._isSimpleSegment = false; orig._isSuperSimpleSegment = false; -#endif + memcpy((void*)this, (void*)&orig, sizeof(Segment)); #ifdef WLEDMM_FASTPATH // WLEDMM temporarily prevent any draw calls to old segment From 9e24a634c2353e65920213c8540dfee78f8911ae Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:43:59 -0400 Subject: [PATCH 048/123] ESP32 Dual Booting --- wled00/wled.cpp | 5 +++-- wled00/wled_serial.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index dfc7e75c..04f16bf8 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -2,7 +2,7 @@ #include "wled.h" #include "wled_ethernet.h" #include - +#include "esp_ota_ops.h" #warning WLED-MM GPL-v3. By installing WLED MM you implicitly accept the terms! #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) @@ -501,7 +501,8 @@ void WLED::setup() #ifdef WLED_RELEASE_NAME USER_PRINTF(" WLEDMM_%s %s, build %s.\n", versionString, releaseString, TOSTRING(VERSION)); // WLEDMM specific #endif - + const esp_partition_t *boot_partition = esp_ota_get_running_partition(); + USER_PRINTF("Booted from: %s which is %u bytes and type %u subtype %u at address %x\n",boot_partition->label,boot_partition->size,boot_partition->type,boot_partition->subtype,boot_partition->address); #ifdef ARDUINO_ARCH_ESP32 DEBUG_PRINT(F("esp32 ")); DEBUG_PRINTLN(ESP.getSdkVersion()); diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index 9361891b..2e2165b1 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -1,4 +1,5 @@ #include "wled.h" +#include "esp_ota_ops.h" /* * Adalight and TPM2 handler @@ -119,6 +120,30 @@ void handleSerial() } else if (next == 'v') { Serial.print("WLED"); Serial.write(' '); Serial.println(VERSION); + } else if (next == '^') { + esp_err_t err; + const esp_partition_t *boot_partition = esp_ota_get_boot_partition(); + const esp_partition_t *running_partition = esp_ota_get_running_partition(); + USER_PRINTF("Running on %s and we should have booted from %s. This %s\n",running_partition->label,boot_partition->label,(String(running_partition->label) == String(boot_partition->label))?"is what we expect.":"means OTA messed up!"); + if (String(running_partition->label) == String(boot_partition->label)) { + esp_partition_iterator_t new_boot_partition_iterator = NULL; + if (boot_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) { + new_boot_partition_iterator = esp_partition_find(ESP_PARTITION_TYPE_APP,ESP_PARTITION_SUBTYPE_APP_OTA_1,"app1"); + } else { + new_boot_partition_iterator = esp_partition_find(ESP_PARTITION_TYPE_APP,ESP_PARTITION_SUBTYPE_APP_OTA_0,"app0"); + } + const esp_partition_t* new_boot_partition = esp_partition_get(new_boot_partition_iterator); + err = esp_ota_set_boot_partition(new_boot_partition); + if (err == ESP_OK) { + USER_PRINTF("Switching boot partitions from %s to %s in 3 seconds!\n",boot_partition->label,new_boot_partition->label); + delay(3000); + esp_restart(); + } else { + USER_PRINTF("Looks like the other app partition (%s) is invalid. Ignoring.\n",new_boot_partition->label); + } + } else { + USER_PRINTF("Looks like the other partion is invalid as we exepected %s but we booted failsafe to %s. Ignoring boot change.\n",boot_partition->label,running_partition->label); + } } else if (next == 'X') { forceReconnect = true; // WLEDMM - force reconnect via Serial } else if (next == 0xB0) {updateBaudRate( 115200); From 0a26aa918c7542fbeb5e6cb68ddbf293a8f21f4b Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:51:58 -0400 Subject: [PATCH 049/123] Fixes for non-ESP32 boards --- wled00/wled.cpp | 2 ++ wled00/wled_serial.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 04f16bf8..fd3b18f3 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -2,7 +2,9 @@ #include "wled.h" #include "wled_ethernet.h" #include +#ifdef ARDUINO_ARCH_ESP32 #include "esp_ota_ops.h" +#endif #warning WLED-MM GPL-v3. By installing WLED MM you implicitly accept the terms! #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index 2e2165b1..91efb9c0 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -1,5 +1,7 @@ #include "wled.h" +#ifdef ARDUINO_ARCH_ESP32 #include "esp_ota_ops.h" +#endif /* * Adalight and TPM2 handler @@ -121,6 +123,7 @@ void handleSerial() Serial.print("WLED"); Serial.write(' '); Serial.println(VERSION); } else if (next == '^') { + #ifdef ARDUINO_ARCH_ESP32 esp_err_t err; const esp_partition_t *boot_partition = esp_ota_get_boot_partition(); const esp_partition_t *running_partition = esp_ota_get_running_partition(); @@ -144,6 +147,9 @@ void handleSerial() } else { USER_PRINTF("Looks like the other partion is invalid as we exepected %s but we booted failsafe to %s. Ignoring boot change.\n",boot_partition->label,running_partition->label); } + #else + USER_PRINTLN("This function is only for ESP32 and newer boards."); + #endif } else if (next == 'X') { forceReconnect = true; // WLEDMM - force reconnect via Serial } else if (next == 0xB0) {updateBaudRate( 115200); From ef6bedee766fccd68bfb09bc2f2f573175263af7 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:53:14 -0400 Subject: [PATCH 050/123] Minor tidy --- wled00/wled_serial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index 91efb9c0..dfa0bba4 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -148,7 +148,7 @@ void handleSerial() USER_PRINTF("Looks like the other partion is invalid as we exepected %s but we booted failsafe to %s. Ignoring boot change.\n",boot_partition->label,running_partition->label); } #else - USER_PRINTLN("This function is only for ESP32 and newer boards."); + USER_PRINTLN("Boot partition switching is only available for ESP32 and newer boards."); #endif } else if (next == 'X') { forceReconnect = true; // WLEDMM - force reconnect via Serial From 01e51e5751a074135be20028d5fc36a0c263e004 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:57:58 -0400 Subject: [PATCH 051/123] More fixes for non-ESP32 boards --- wled00/wled.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index fd3b18f3..688d5ec1 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -503,8 +503,10 @@ void WLED::setup() #ifdef WLED_RELEASE_NAME USER_PRINTF(" WLEDMM_%s %s, build %s.\n", versionString, releaseString, TOSTRING(VERSION)); // WLEDMM specific #endif + #ifdef ARDUINO_ARCH_ESP32 const esp_partition_t *boot_partition = esp_ota_get_running_partition(); USER_PRINTF("Booted from: %s which is %u bytes and type %u subtype %u at address %x\n",boot_partition->label,boot_partition->size,boot_partition->type,boot_partition->subtype,boot_partition->address); + #endif #ifdef ARDUINO_ARCH_ESP32 DEBUG_PRINT(F("esp32 ")); DEBUG_PRINTLN(ESP.getSdkVersion()); From b12b23d02c783c0038c9cd3083f5b11198163493 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:59:03 -0400 Subject: [PATCH 052/123] Boot log clarification. --- wled00/wled.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 688d5ec1..0922ec14 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -504,8 +504,8 @@ void WLED::setup() USER_PRINTF(" WLEDMM_%s %s, build %s.\n", versionString, releaseString, TOSTRING(VERSION)); // WLEDMM specific #endif #ifdef ARDUINO_ARCH_ESP32 - const esp_partition_t *boot_partition = esp_ota_get_running_partition(); - USER_PRINTF("Booted from: %s which is %u bytes and type %u subtype %u at address %x\n",boot_partition->label,boot_partition->size,boot_partition->type,boot_partition->subtype,boot_partition->address); + const esp_partition_t *running_partition = esp_ota_get_running_partition(); + USER_PRINTF("Running from: %s which is %u bytes and type %u subtype %u at address %x\n",boot_partition->label,boot_partition->size,boot_partition->type,boot_partition->subtype,boot_partition->address); #endif #ifdef ARDUINO_ARCH_ESP32 DEBUG_PRINT(F("esp32 ")); From aa38c113e3942a6c04a39302797830910deaedcd Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:01:11 -0400 Subject: [PATCH 053/123] More boot log clarity --- wled00/wled.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 0922ec14..9d54631f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -505,7 +505,7 @@ void WLED::setup() #endif #ifdef ARDUINO_ARCH_ESP32 const esp_partition_t *running_partition = esp_ota_get_running_partition(); - USER_PRINTF("Running from: %s which is %u bytes and type %u subtype %u at address %x\n",boot_partition->label,boot_partition->size,boot_partition->type,boot_partition->subtype,boot_partition->address); + USER_PRINTF("Running from: %s which is %u bytes and type %u subtype %u at address %x\n",running_partition->label,running_partition->size,running_partition->type,running_partition->subtype,running_partition->address); #endif #ifdef ARDUINO_ARCH_ESP32 DEBUG_PRINT(F("esp32 ")); From 0d1182755285cfae7e1ac16fe86e38f438d65497 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 21 Aug 2024 22:40:40 +0100 Subject: [PATCH 054/123] Add pinout for HD-WF2 --- wled00/bus_manager.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 8783730e..ea48d6e6 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -588,6 +588,31 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.d = 35; mxconfig.gpio.e = 21; +#elif defined(CONFIG_IDF_TARGET_ESP32S3) // ESP32-S3 + + // Huidu HD-WF2 ESP32-S3 + // https://www.aliexpress.com/item/1005002258734810.html + // https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/issues/433 + + USER_PRINTLN("MatrixPanel_I2S_DMA - HD-WF2 S3 config"); + + mxconfig.gpio.r1 = 2; + mxconfig.gpio.g1 = 6; + mxconfig.gpio.b1 = 10; + mxconfig.gpio.r2 = 3; + mxconfig.gpio.g2 = 7; + mxconfig.gpio.b2 = 11; + + mxconfig.gpio.lat = 33; + mxconfig.gpio.oe = 35; + mxconfig.gpio.clk = 34; + + mxconfig.gpio.a = 39; + mxconfig.gpio.b = 38; + mxconfig.gpio.c = 37; + mxconfig.gpio.d = 36; + mxconfig.gpio.e = 21; + #elif defined(ESP32_FORUM_PINOUT) // Common format for boards designed for SmartMatrix USER_PRINTLN("MatrixPanel_I2S_DMA - ESP32_FORUM_PINOUT"); From a5600950b569406904ba991a1a24ddc7b4ff99e6 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 21 Aug 2024 23:34:11 +0100 Subject: [PATCH 055/123] Enable HUB75 for the esp32S3_8MB_M for HD-WF2 --- platformio.ini | 3 +++ wled00/bus_manager.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 94bb35e7..742b8f0d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1866,6 +1866,7 @@ build_unflags = build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation ${common_mm.build_flags_S} ${common_mm.build_flags_M} + ${common_mm.HUB75_build_flags} ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM -D WLED_RELEASE_NAME=esp32S3_8MB_M -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip @@ -1893,6 +1894,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ; -D SR_DEBUG ; -D MIC_LOGGER lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M} + ${common_mm.HUB75_lib_deps} + ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation board_build.partitions = tools/WLED_ESP32_8MB.csv board_build.flash_mode = qio diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index ea48d6e6..a3174357 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -557,7 +557,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh } if(mxconfig.mx_height >= 64 && (bc.pins[0] > 1)) { - USER_PRINT("WARNING, only single panel can be used of 64 pixel boards due to memory") + USER_PRINT("WARNING, only single panel can be used of 64 pixel boards due to memory"); mxconfig.chain_length = 1; } From 1e693b5c9d090e0c05e99740610968ddfb93eca1 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 21 Aug 2024 23:35:36 +0100 Subject: [PATCH 056/123] Add new build esp32S3_4MB_S the Huidu HD-WF2 should be 8M, but formatting fails where as 4M works --- platformio.ini | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/platformio.ini b/platformio.ini index 742b8f0d..cb24513a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -72,6 +72,7 @@ default_envs = esp32_pico_4MB_M esp32_4MB_PSRAM_S ; esp32_4MB_PSRAM_REV3_S ;; experimental, optimized for WROVER-E with "revision3" chip + esp32S3_4MB_S esp32S3_8MB_S ;; experimental, optimized for speed esp32S3_8MB_M esp32S3_4MB_PSRAM_S ;; for lolin s3 mini, S3 zero, S3 super mini - optimized for speed @@ -1852,6 +1853,37 @@ lib_deps = ${esp32_4MB_V4_M_base.esp32_lib_deps} # ------------------------------------------------------------------------------ # esp32-S3 environments # ------------------------------------------------------------------------------ +[env:esp32S3_4MB_S] +extends = esp32_4MB_V4_M_base +board = esp32-s3-devkitc-1 +build_unflags = + -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) + -D USE_ALT_DISPLAY ;; four line display seems to have problems with I2C - it hangs during usermod setup + -D USERMOD_FOUR_LINE_DISPLAY ;; see above + -D USERMOD_ROTARY_ENCODER_UI ;; see above + -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) + +build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation + ${common_mm.build_flags_S} + ${common_mm.HUB75_build_flags} + ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM + -D WLED_RELEASE_NAME=esp32S3_4MB_S + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode + ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) + -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 + ; -D U8X8_HAVE_2ND_HW_I2C ;; experimental - tells U8g2 lib that a second HW I2C unit exists + -D WLED_DISABLE_LOXONE ; FLASH 1272 bytes + -D WLED_DISABLE_ALEXA ; RAM 116 bytes; FLASH 13524 bytes + ; -D WLED_DISABLE_MQTT ; RAM 216 bytes; FLASH 16496 bytes + ; -D WLED_DISABLE_HUESYNC ;RAM 122 bytes; FLASH 6308 bytes + ; -D WLED_DISABLE_INFRARED ;RAM 136 bytes; FLASH 24492 bytes + ;;-D WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions. + ; -D WLED_DEBUG + ; -D SR_DEBUG + ; -D MIC_LOGGER +lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} + ${common_mm.HUB75_lib_deps} [env:esp32S3_8MB_M] From 1e6cdc2c5bebe5bf9fb998b409d7e0eedc696da4 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 22 Aug 2024 20:41:23 +0100 Subject: [PATCH 057/123] HD-WF1 pinout --- wled00/bus_manager.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a3174357..5f10ec77 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -613,6 +613,30 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.d = 36; mxconfig.gpio.e = 21; +#elif defined(CONFIG_IDF_TARGET_ESP32S2) // ESP32-S2 + + // Huidu HD-WF1 ESP32-S2 + // https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/issues/433 + + USER_PRINTLN("MatrixPanel_I2S_DMA - HD-WF1 S2 config"); + + mxconfig.gpio.r1 = 2; + mxconfig.gpio.g1 = 6; + mxconfig.gpio.b1 = 3; + mxconfig.gpio.r2 = 4; + mxconfig.gpio.g2 = 8; + mxconfig.gpio.b2 = 5; + + mxconfig.gpio.lat = 33; + mxconfig.gpio.oe = 35; + mxconfig.gpio.clk = 34; + + mxconfig.gpio.a = 39; + mxconfig.gpio.b = 38; + mxconfig.gpio.c = 37; + mxconfig.gpio.d = 36; + mxconfig.gpio.e = 12; + #elif defined(ESP32_FORUM_PINOUT) // Common format for boards designed for SmartMatrix USER_PRINTLN("MatrixPanel_I2S_DMA - ESP32_FORUM_PINOUT"); From 9c21d3fc7206641475211ffc30f502178a7f55ad Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Fri, 23 Aug 2024 12:22:01 +0100 Subject: [PATCH 058/123] Add *untested* HD-WF1 build --- platformio.ini | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/platformio.ini b/platformio.ini index cb24513a..58961dfd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2208,6 +2208,44 @@ monitor_filters = esp32_exception_decoder ; RAM: [== ] 21.8% (used 71304 bytes from 327680 bytes) ; Flash: [======== ] 84.0% (used 1596970 bytes from 1900544 bytes) +[env:HD-WF1] +extends = esp32_4MB_V4_S_base +platform = ${esp32s2.platform} ;; using 5.2.0, due to massive connectivity problems on -S2 with 5.3.0 +platform_packages = ${esp32s2.platform_packages} + +board = nodemcu-32s2 +upload_speed = 256000 ;; 921600 +build_unflags = ${common.build_unflags} + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_DFU_ON_BOOT=0 + -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) + -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) + -D WLED_ENABLE_DMX_INPUT ;; needs more testing + -DWLEDMM_FASTPATH ;; needs more testing on -S2 + -DBOARD_HAS_PSRAM +build_flags = ${common.build_flags} ${esp32s2.build_flags} + ;; ${Debug_Flags.build_flags} + -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 + ${common_mm.build_flags_S} + ${common_mm.HUB75_build_flags} + -Wno-misleading-indentation -Wno-format-truncation + -D WLED_RELEASE_NAME=esp32s2_HD_WF1_4MB_M + -DLOLIN_WIFI_FIX -DWLEDMM_WIFI_POWERON_HACK ;; seems to work much better with this + -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 + -D WLED_DISABLE_ADALIGHT ;; disables serial protocols, as the board only has CDC USB + -D WLED_DISABLE_INFRARED ;; save flash space + -D WLED_DISABLE_ALEXA ;; save flash space + -D WLED_DISABLE_HUESYNC ;; save flash space + -D WLED_DISABLE_LOXONE ;; save flash space + -D WLEDMM_SAVE_FLASH + +lib_deps = ${esp32s2.lib_deps} ${common_mm.lib_deps_S} + ${common_mm.HUB75_lib_deps} + +lib_ignore = + IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + OneWire ; not needed as we don't include USERMOD_DALLASTEMPERATURE +monitor_filters = esp32_exception_decoder # ------------------------------------------------------------------------------ # esp32-C3 environments From 818b3f192894f24e082e1ebad2a6690031253a94 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 25 Aug 2024 16:40:15 +0100 Subject: [PATCH 059/123] Add animartrix to S3 builds with HUB75 support --- platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platformio.ini b/platformio.ini index 58961dfd..134429bb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1866,6 +1866,7 @@ build_unflags = build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation ${common_mm.build_flags_S} ${common_mm.HUB75_build_flags} + ${common_mm.animartrix_build_flags} ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM -D WLED_RELEASE_NAME=esp32S3_4MB_S -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip @@ -1884,6 +1885,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ; -D MIC_LOGGER lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.HUB75_lib_deps} + ${common_mm.animartrix_lib_deps} [env:esp32S3_8MB_M] @@ -1899,6 +1901,7 @@ build_unflags = build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation ${common_mm.build_flags_S} ${common_mm.build_flags_M} ${common_mm.HUB75_build_flags} + ${common_mm.animartrix_build_flags} ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM -D WLED_RELEASE_NAME=esp32S3_8MB_M -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip @@ -1927,6 +1930,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ; -D MIC_LOGGER lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M} ${common_mm.HUB75_lib_deps} + ${common_mm.animartrix_lib_deps} ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation board_build.partitions = tools/WLED_ESP32_8MB.csv From 69baef126f4bf11aa87a892743848d0e34e117ba Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 25 Aug 2024 20:37:22 +0200 Subject: [PATCH 060/123] athom_music buildenv updates (solves #159) disabled some usermods for athom, to bring back MQTT. --- platformio.ini | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 94bb35e7..967a9a19 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2461,12 +2461,17 @@ board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for ;https://www.athom.tech/blank-1/wled-esp32-music-addressable-led-strip-controller [env:athom_music_esp32_4MB_M] extends = esp32_4MB_M_base +build_unflags = ${common.build_unflags} + -D USERMOD_ARTIFX ;; disabled to save some program space in flash + -D USERMOD_DALLASTEMPERATURE ;; disabled - flash space is too tight for this + -D USERMOD_ROTARY_ENCODER_UI ;; see above build_flags = ${esp32_4MB_M_base.build_flags} ${Athom_PDMmic.build_flags} -D WLED_AP_SSID_UNIQUE -D WLED_RELEASE_NAME=athom_music_esp32_4MB_M -D ABL_MILLIAMPS_DEFAULT=14500 ; max 15A - -D WLED_DISABLE_MQTT -D WLED_DISABLE_LOXONE + ; -D WLED_DISABLE_MQTT + -D WLED_DISABLE_LOXONE -D WLED_DISABLE_ADALIGHT ;to get 4ld working -D BTNPIN=0 -D RLYPIN=2 -D IRPIN=25 -D IRTYPE=9 -D LEDPIN=18 -D AUDIOPIN=-1 @@ -2478,8 +2483,9 @@ build_flags = ${esp32_4MB_M_base.build_flags} ; -D PIR_SENSOR_PIN=-1 ; -D PWM_PIN=-1 ; -D WLED_USE_MY_CONFIG -; RAM: [=== ] 25.9% (used 84948 bytes from 327680 bytes) -; Flash: [==========] 95.9% (used 1509113 bytes from 1572864 bytes) + -D WLEDMM_SAVE_FLASH +; RAM: [=== ] 26.3% (used 86204 bytes from 327680 bytes) +; Flash: [========= ] 93.6% (used 1471681 bytes from 1572864 bytes) ;https://shop.myhome-control.de/Elektronik/ [env:abc_wled_controller_v43_S] From c5aa6b963bf9bdcc85a4805e3d109e03174f962c Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 29 Aug 2024 21:13:54 +0100 Subject: [PATCH 061/123] Default to hub75 32x32 --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 134429bb..13cee381 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2242,6 +2242,7 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_DISABLE_HUESYNC ;; save flash space -D WLED_DISABLE_LOXONE ;; save flash space -D WLEDMM_SAVE_FLASH + -D DEFAULT_LED_TYPE=101 ;; hub75 32x32 lib_deps = ${esp32s2.lib_deps} ${common_mm.lib_deps_S} ${common_mm.HUB75_lib_deps} From d1782519dbd780df692d06a6fb55e1bccc4c2b0c Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 31 Aug 2024 17:06:39 +0100 Subject: [PATCH 062/123] HD-WF1 - too low memory to be of used for hub75 --- platformio.ini | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/platformio.ini b/platformio.ini index 13cee381..16f758cb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2212,46 +2212,6 @@ monitor_filters = esp32_exception_decoder ; RAM: [== ] 21.8% (used 71304 bytes from 327680 bytes) ; Flash: [======== ] 84.0% (used 1596970 bytes from 1900544 bytes) -[env:HD-WF1] -extends = esp32_4MB_V4_S_base -platform = ${esp32s2.platform} ;; using 5.2.0, due to massive connectivity problems on -S2 with 5.3.0 -platform_packages = ${esp32s2.platform_packages} - -board = nodemcu-32s2 -upload_speed = 256000 ;; 921600 -build_unflags = ${common.build_unflags} - -DARDUINO_USB_CDC_ON_BOOT=1 - -DARDUINO_USB_DFU_ON_BOOT=0 - -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) - -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) - -D WLED_ENABLE_DMX_INPUT ;; needs more testing - -DWLEDMM_FASTPATH ;; needs more testing on -S2 - -DBOARD_HAS_PSRAM -build_flags = ${common.build_flags} ${esp32s2.build_flags} - ;; ${Debug_Flags.build_flags} - -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 - ${common_mm.build_flags_S} - ${common_mm.HUB75_build_flags} - -Wno-misleading-indentation -Wno-format-truncation - -D WLED_RELEASE_NAME=esp32s2_HD_WF1_4MB_M - -DLOLIN_WIFI_FIX -DWLEDMM_WIFI_POWERON_HACK ;; seems to work much better with this - -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 - -D WLED_DISABLE_ADALIGHT ;; disables serial protocols, as the board only has CDC USB - -D WLED_DISABLE_INFRARED ;; save flash space - -D WLED_DISABLE_ALEXA ;; save flash space - -D WLED_DISABLE_HUESYNC ;; save flash space - -D WLED_DISABLE_LOXONE ;; save flash space - -D WLEDMM_SAVE_FLASH - -D DEFAULT_LED_TYPE=101 ;; hub75 32x32 - -lib_deps = ${esp32s2.lib_deps} ${common_mm.lib_deps_S} - ${common_mm.HUB75_lib_deps} - -lib_ignore = - IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation - OneWire ; not needed as we don't include USERMOD_DALLASTEMPERATURE -monitor_filters = esp32_exception_decoder - # ------------------------------------------------------------------------------ # esp32-C3 environments # ------------------------------------------------------------------------------ From 6d83adae3c96b8b8c5e7dffd28f7aa1627555003 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Wed, 4 Sep 2024 21:17:21 +0200 Subject: [PATCH 063/123] Mirroring bugfix. --- wled00/FX_2Dfcn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 4518bdff..56d81443 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -300,7 +300,7 @@ void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, else strip.setPixelColorXY_fast(start + x, startY + hei_ - y - 1, scaled_col); } if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel - strip.setPixelColorXY_fast(wid_ - x - 1, hei_ - y - 1, scaled_col); + strip.setPixelColorXY_fast(start + wid_ - x - 1, startY + hei_ - y - 1, scaled_col); } } @@ -376,7 +376,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: else strip.setPixelColorXY(start + xX, startY + hei_ - yY - 1, col); } if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel - strip.setPixelColorXY(wid_ - xX - 1, hei_ - yY - 1, col); + strip.setPixelColorXY(start + wid_ - xX - 1, startY + hei_ - yY - 1, col); } } } From bef964dcba7895f70b27913ee9a43c48bc2c4fbf Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 6 Sep 2024 12:54:27 +0200 Subject: [PATCH 064/123] bugfix: prevent clearing of segment settings when changing effects in multi-segment setups, the segment options reverse, reverseY, mirror, and mirrorY were accidentally overwritten when changing effects. --- wled00/FX_fcn.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index c4b1a459..a7b9b2eb 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -599,10 +599,6 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { static int16_t oldMap = -1; static int16_t oldSim = -1; static int16_t oldPalette = -1; - static byte oldReverse = -1; - static byte oldMirror = -1; - static byte oldReverse_y = -1; - static byte oldMirror_y = -1; // if we have a valid mode & is not reserved if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) { if (fx != mode) { @@ -624,10 +620,10 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { //WLEDMM: return to old setting if not explicitly set sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) {if (oldMap==-1) oldMap = map1D2D; map1D2D = constrain(sOpt, 0, 7);} else {if (oldMap!=-1) map1D2D = oldMap; oldMap = -1;} sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) {if (oldSim==-1) oldSim = soundSim; soundSim = constrain(sOpt, 0, 1);} else {if (oldSim!=-1) soundSim = oldSim; oldSim = -1;} - sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) {if (oldReverse==-1) oldReverse = reverse; reverse = (bool)sOpt;} else {if (oldReverse!=-1) reverse = oldReverse==1; oldReverse = -1;} - sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) {if (oldMirror==-1) oldMirror = mirror; mirror = (bool)sOpt;} else {if (oldMirror!=-1) mirror = oldMirror==1; oldMirror = -1;} // NOTE: setting this option is a risky business - sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) {if (oldReverse_y==-1) oldReverse_y = reverse_y; reverse_y = (bool)sOpt;} else {if (oldReverse_y!=-1) reverse_y = oldReverse_y==1; oldReverse_y = -1;} - sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) {if (oldMirror_y==-1) oldMirror_y = mirror_y; mirror_y = (bool)sOpt;} else {if (oldMirror_y!=-1) mirror_y = oldMirror_y==1; oldMirror_y = -1;} // NOTE: setting this option is a risky business + sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt; + sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business + sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt; + sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) {if (oldPalette==-1) oldPalette = palette; setPalette(sOpt);} else {if (oldPalette!=-1) setPalette(oldPalette); oldPalette = -1;} } if (!fadeTransition) markForReset(); // WLEDMM quickfix for effect "double startup" bug. -> only works when "Crossfade" is disabled (led settings) From fc2e1263cbf4ee591faf9babafddccc496aca5ab Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 6 Sep 2024 13:06:28 +0200 Subject: [PATCH 065/123] new option don't use effect-specific palette or mapping modes * new setting in UI page: "Don't use effect palette and segment parameters" - only meaningful when "Use effect default parameters" is enabled, too. --> effect slider defaults will still be applied, however palette, 1D2D mapping mode and other segment settings will not change. --- wled00/FX.h | 2 +- wled00/FX_fcn.cpp | 20 +++++++++++--------- wled00/data/index.js | 4 ++-- wled00/data/settings_ui.htm | 3 ++- wled00/data/simple.js | 2 +- wled00/json.cpp | 2 +- wled00/set.cpp | 2 +- wled00/wled.h | 2 +- 8 files changed, 20 insertions(+), 17 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 17e70021..a0f3e90f 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -594,7 +594,7 @@ typedef struct Segment { void setCCT(uint16_t k); void setOpacity(uint8_t o); void setOption(uint8_t n, bool val); - void setMode(uint8_t fx, bool loadDefaults = false); + void setMode(uint8_t fx, bool loadDefaults = false, bool sliderDefaultsOnly = false); void setPalette(uint8_t pal); uint8_t differs(Segment& b) const; void refreshLightCapabilities(void); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index a7b9b2eb..1f086fe0 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -594,7 +594,7 @@ void Segment::setOption(uint8_t n, bool val) { if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET || n == SEG_OPTION_TRANSITIONAL)) stateChanged = true; // send UDP/WS broadcast } -void Segment::setMode(uint8_t fx, bool loadDefaults) { +void Segment::setMode(uint8_t fx, bool loadDefaults, bool sliderDefaultsOnly) { //WLEDMM: return to old setting if not explicitly set static int16_t oldMap = -1; static int16_t oldSim = -1; @@ -617,14 +617,16 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { sOpt = extractModeDefaults(fx, "o1"); check1 = (sOpt >= 0) ? (bool)sOpt : false; sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false; sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false; - //WLEDMM: return to old setting if not explicitly set - sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) {if (oldMap==-1) oldMap = map1D2D; map1D2D = constrain(sOpt, 0, 7);} else {if (oldMap!=-1) map1D2D = oldMap; oldMap = -1;} - sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) {if (oldSim==-1) oldSim = soundSim; soundSim = constrain(sOpt, 0, 1);} else {if (oldSim!=-1) soundSim = oldSim; oldSim = -1;} - sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt; - sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business - sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt; - sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business - sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) {if (oldPalette==-1) oldPalette = palette; setPalette(sOpt);} else {if (oldPalette!=-1) setPalette(oldPalette); oldPalette = -1;} + if (!sliderDefaultsOnly) { + //WLEDMM: return to old setting if not explicitly set + sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) {if (oldMap==-1) oldMap = map1D2D; map1D2D = constrain(sOpt, 0, 7);} else {if (oldMap!=-1) map1D2D = oldMap; oldMap = -1;} + sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) {if (oldSim==-1) oldSim = soundSim; soundSim = constrain(sOpt, 0, 1);} else {if (oldSim!=-1) soundSim = oldSim; oldSim = -1;} + sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt; + sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business + sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt; + sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business + sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) {if (oldPalette==-1) oldPalette = palette; setPalette(sOpt);} else {if (oldPalette!=-1) setPalette(oldPalette); oldPalette = -1;} + } } if (!fadeTransition) markForReset(); // WLEDMM quickfix for effect "double startup" bug. -> only works when "Crossfade" is disabled (led settings) stateChanged = true; // send UDP/WS broadcast diff --git a/wled00/data/index.js b/wled00/data/index.js index 61480d5e..1a6ba618 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -27,7 +27,7 @@ var cfg = { theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}}, comp :{colors:{picker: true, rgb: false, quick: true, hex: false}, labels:true, pcmbot:false, pid:true, seglen:false, segpwr:false, segexp:true, - css:true, hdays:false, fxdef:true} //WLEDMM segexp true as default + css:true, hdays:false, fxdef:true, fxdef2:false} //WLEDMM segexp true as default, fxdef2 added }; var hol = [ [0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas @@ -2856,7 +2856,7 @@ function setFX(ind = null) } else { d.querySelector(`#fxlist input[name="fx"][value="${ind}"]`).checked = true; } - var obj = {"seg": {"fx": parseInt(ind), "fxdef": cfg.comp.fxdef}}; // fxdef sets effect parameters to default values + var obj = {"seg": {"fx": parseInt(ind), "fxdef": cfg.comp.fxdef, "fxdef2": cfg.comp.fxdef2}}; // fxdef sets effect parameters to default values; WLEDMM fxdef2 only set slider defaults requestJson(obj); } diff --git a/wled00/data/settings_ui.htm b/wled00/data/settings_ui.htm index dfafb9d9..285632d3 100644 --- a/wled00/data/settings_ui.htm +++ b/wled00/data/settings_ui.htm @@ -26,7 +26,8 @@ "segexp" : "Always expand first segment", "css": "Enable custom CSS", "hdays": "Enable custom Holidays list", - "fxdef": "Use effect default parameters" + "fxdef": "Use effect default parameters", + "fxdef2": "Don't use effect palette and segment parameters" }, "theme":{ "alpha": { diff --git a/wled00/data/simple.js b/wled00/data/simple.js index 8e3d2914..aa4fb22c 100644 --- a/wled00/data/simple.js +++ b/wled00/data/simple.js @@ -1135,7 +1135,7 @@ function setSegBri(s) function setEffect(ind = 0) { tglFxDropdown(); - var obj = {"seg": {"fx": parseInt(ind), "fxdef":true}}; // fxdef sets effect parameters to default values, TODO add client setting + var obj = {"seg": {"fx": parseInt(ind), "fxdef":true, "fxdef2":false}}; // fxdef sets effect parameters to default values, TODO add client setting requestJson(obj); } diff --git a/wled00/json.cpp b/wled00/json.cpp index f672f53d..f0f189b2 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -302,7 +302,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) // end fix if (getVal(elem["fx"], &fx, 0, last)) { //load effect ('r' random, '~' inc/dec, 0-255 exact value, 5~10r pick random between 5 & 10) if (!presetId && currentPlaylist>=0) unloadPlaylist(); - if (fx != seg.mode) seg.setMode(fx, elem[F("fxdef")]); + if (fx != seg.mode) seg.setMode(fx, elem[F("fxdef")], elem[F("fxdef2")]); // WLEDMM fxdef2 added } //getVal also supports inc/decrementing and random diff --git a/wled00/set.cpp b/wled00/set.cpp index 044b6e77..6c9b57c2 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -1062,7 +1062,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) { Segment& seg = strip.getSegment(i); if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all - if (fxModeChanged) seg.setMode(effectIn, req.indexOf(F("FXD="))>0); // apply defaults if FXD= is specified + if (fxModeChanged) seg.setMode(effectIn, req.indexOf(F("FXD="))>0, req.indexOf(F("FXD2="))>0); // apply defaults if FXD= is specified if (speedChanged) seg.speed = speedIn; if (intensityChanged) seg.intensity = intensityIn; if (paletteChanged) seg.setPalette(paletteIn); diff --git a/wled00/wled.h b/wled00/wled.h index ed232910..9bfd7dd1 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408160 +#define VERSION 2409060 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From eb3ae13fab304c52fdfc813a847e77848c7a824d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 6 Sep 2024 15:35:00 +0200 Subject: [PATCH 066/123] 0.14.1-b32.41.dev -> "dev" for developer build this is a valid "semantic version". checked by https://jubianchi.github.io/semver-check/#/version/0.14.1-b32.41.dev --- package-lock.json | 4 ++-- package.json | 2 +- wled00/improv.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index dce951b8..aa060721 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wled", - "version": "0.14.1-b32.41", + "version": "0.14.1-b32.41.dev", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wled", - "version": "0.14.1-b32.41", + "version": "0.14.1-b32.41.dev", "license": "GPL-3.0-or-later", "dependencies": { "clean-css": "^4.2.3", diff --git a/package.json b/package.json index 2faab264..c73dd26f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wled", - "version": "0.14.1-b32.41", + "version": "0.14.1-b32.41.dev", "description": "Tools for WLED project", "main": "tools/cdata.js", "directories": { diff --git a/wled00/improv.cpp b/wled00/improv.cpp index d0b97182..afcbbbb2 100644 --- a/wled00/improv.cpp +++ b/wled00/improv.cpp @@ -211,7 +211,7 @@ void sendImprovInfoResponse() { //Use serverDescription if it has been changed from the default "WLED", else mDNS name bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0); char vString[32]; - snprintf_P(vString, sizeof(vString)-1, PSTR("0.14.1-b32.40/%i"),VERSION); + snprintf_P(vString, sizeof(vString)-1, PSTR("0.14.1-b32.41/%i"),VERSION); const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription}; sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str); From dbb8683ad66ebb3a637ef962e904dff31d81c194 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 6 Sep 2024 15:59:55 +0200 Subject: [PATCH 067/123] Update index.js - shorten .bin name --- wled00/data/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index 1a6ba618..05aaee05 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -696,7 +696,7 @@ function populateInfo(i) if (i.ver.includes("0.14.0-b15.22")) vcn = "Lupo"; if (i.ver.includes("0.14.1-b3")) vcn = "Fried Chicken"; // final line of "One Vision" by Queen if (i.ver.includes("0.14.3-b")) vcn = "Fried Chicken"; - cn += `v${i.ver}  "${vcn}"

(WLEDMM_${i.ver} ${i.rel}.bin)

build ${i.vid}

+ cn += `v${i.ver}  "${vcn}"

(WLEDMM ${i.rel}.bin)

build ${i.vid}

${urows} ${urows===""?'':''} ${i.opt&0x100?inforow("Net Print ☾",""):''} From 37a3141f881312542c657596bd81fbafadb219e3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 13:34:09 +0100 Subject: [PATCH 068/123] HD-WF2 tweaks --- platformio.ini | 19 ++++++------------- wled00/bus_manager.cpp | 6 +++++- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/platformio.ini b/platformio.ini index 69024166..b5b93187 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1042,8 +1042,8 @@ HUB75_build_flags = -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips ;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30) ;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... -HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... -;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11 +;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... +HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11 HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) NetDebug_build_flags = @@ -1853,7 +1853,7 @@ lib_deps = ${esp32_4MB_V4_M_base.esp32_lib_deps} # ------------------------------------------------------------------------------ # esp32-S3 environments # ------------------------------------------------------------------------------ -[env:esp32S3_4MB_S] +[env:esp32S3_4MB_S] ;; Use for HD-WF2 extends = esp32_4MB_V4_M_base board = esp32-s3-devkitc-1 build_unflags = @@ -1867,22 +1867,15 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ${common_mm.build_flags_S} ${common_mm.HUB75_build_flags} ${common_mm.animartrix_build_flags} - ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM -D WLED_RELEASE_NAME=esp32S3_4MB_S -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode - ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) + -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 - ; -D U8X8_HAVE_2ND_HW_I2C ;; experimental - tells U8g2 lib that a second HW I2C unit exists - -D WLED_DISABLE_LOXONE ; FLASH 1272 bytes - -D WLED_DISABLE_ALEXA ; RAM 116 bytes; FLASH 13524 bytes - ; -D WLED_DISABLE_MQTT ; RAM 216 bytes; FLASH 16496 bytes - ; -D WLED_DISABLE_HUESYNC ;RAM 122 bytes; FLASH 6308 bytes - ; -D WLED_DISABLE_INFRARED ;RAM 136 bytes; FLASH 24492 bytes - ;;-D WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions. + ${common_mm.build_disable_sync_interfaces} + -D WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions. ; -D WLED_DEBUG ; -D SR_DEBUG - ; -D MIC_LOGGER lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.HUB75_lib_deps} ${common_mm.animartrix_lib_deps} diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 5f10ec77..464dc29b 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -744,14 +744,18 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh return; } else { + USER_PRINTLN("MatrixPanel_I2S_DMA begin ok"); delay(18); // experiment - give the driver a moment (~ one full frame @ 60hz) to settle _valid = true; display->clearScreen(); // initially clear the screen buffer + USER_PRINTLN("MatrixPanel_I2S_DMA clear ok"); if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen + USER_PRINTLN("MatrixPanel_I2S_DMA allocate memory"); _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - + USER_PRINTLN("MatrixPanel_I2S_DMA allocate memory ok"); + if (_ledsDirty == nullptr) { display->stopDMAoutput(); delete display; display = nullptr; From 8c0fcaa0fd19bc0ea4b947b8fe5ec9e8b2f2fef4 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:19:46 +0100 Subject: [PATCH 069/123] hub75 - mxconfig.clkphase = false --- wled00/bus_manager.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 464dc29b..9b228f00 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -666,14 +666,6 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.d = 21; mxconfig.gpio.e = 12; - // mxconfig.double_buff = true; // <------------- Turn on double buffer - // mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver - //mxconfig.latch_blanking = 3; - // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz - //mxconfig.min_refresh_rate = 90; - //mxconfig.min_refresh_rate = 120; - // mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. - #else USER_PRINTLN("MatrixPanel_I2S_DMA - Default pins"); /* @@ -704,6 +696,15 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #endif + // mxconfig.double_buff = true; // <------------- Turn on double buffer + // mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver + //mxconfig.latch_blanking = 3; + // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz + //mxconfig.min_refresh_rate = 90; + //mxconfig.min_refresh_rate = 120; + mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. + + mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length); From cb9fb8ddd420ff793d9a1c3a25a11964787f7945 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:29:09 +0100 Subject: [PATCH 070/123] Update actions/upload-artifact --- .github/workflows/wled-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index d9933bd3..3ac09572 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -61,13 +61,13 @@ jobs: env: WLED_RELEASE: True run: pio run -e ${{ matrix.environment }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: firmware-${{ matrix.environment }} path: | build_output/firmware/*.bin build_output/firmware/*.gz - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 if: startsWith(github.ref, 'refs/tags/') with: name: firmware-release From 908481a55ad054ffe54ce4a5db20ab61c32e6810 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:47:00 +0100 Subject: [PATCH 071/123] Tweak github caching --- .github/workflows/wled-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index 3ac09572..236c569d 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -51,6 +51,9 @@ jobs: with: path: ~/.platformio key: ${{ runner.os }}-${{ matrix.environment}}-${{ hashFiles('platformio.ini') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.environment}} + - name: Set up Python uses: actions/setup-python@v4 with: From fff7a47ab54d0fa17dc7ff79f31366913317ddc4 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:53:49 +0100 Subject: [PATCH 072/123] Update actions/checkout action --- .github/workflows/wled-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index 236c569d..bce567bc 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -8,7 +8,7 @@ jobs: name: Gather Environments runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Cache pip uses: actions/cache@v3 with: @@ -38,7 +38,7 @@ jobs: matrix: environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Cache pip uses: actions/cache@v3 with: From ebbd06800e335fa569ee05e95ccd855ec7d4a9d3 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:55:12 +0100 Subject: [PATCH 073/123] Update actions/setup-python action --- .github/workflows/wled-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index bce567bc..c57a4d93 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -16,7 +16,7 @@ jobs: key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.9' - name: Install PlatformIO From dabda3a02c3994040cb46bd4e2c69f36b16ebef0 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:56:00 +0100 Subject: [PATCH 074/123] Update actions/cache action --- .github/workflows/wled-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index c57a4d93..b9b77423 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Cache pip - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} @@ -40,14 +40,14 @@ jobs: steps: - uses: actions/checkout@v4 - name: Cache pip - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - name: Cache PlatformIO - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.platformio key: ${{ runner.os }}-${{ matrix.environment}}-${{ hashFiles('platformio.ini') }} From 1e04f4bdb793514bd54bd88cf5e484056eb64c72 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 17:59:53 +0100 Subject: [PATCH 075/123] Update actions/setup-python action --- .github/workflows/wled-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index b9b77423..62cee507 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -55,7 +55,7 @@ jobs: ${{ runner.os }}-${{ matrix.environment}} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.9' - name: Install PlatformIO From d08b4a51fa842919e23328cc40b8150e371432bc Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 18:07:48 +0100 Subject: [PATCH 076/123] Fix artifact upload --- .github/workflows/wled-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index 62cee507..dcd92b6c 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -64,12 +64,13 @@ jobs: env: WLED_RELEASE: True run: pio run -e ${{ matrix.environment }} + - name: Rename Bin + run: mv .pio/build/${{ matrix.environment }}/firmware.bin firmware-${{ matrix.environment }}.bin - uses: actions/upload-artifact@v4 with: name: firmware-${{ matrix.environment }} path: | - build_output/firmware/*.bin - build_output/firmware/*.gz + .pio/build/${{ matrix.environment }}/firmware.bin - uses: actions/upload-artifact@v4 if: startsWith(github.ref, 'refs/tags/') with: From 3f674aeaa352223d7b82028006948a3d259c1b8d Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 18:11:31 +0100 Subject: [PATCH 077/123] Fix artifact upload --- .github/workflows/wled-ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index dcd92b6c..91f94d1b 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -65,12 +65,11 @@ jobs: WLED_RELEASE: True run: pio run -e ${{ matrix.environment }} - name: Rename Bin - run: mv .pio/build/${{ matrix.environment }}/firmware.bin firmware-${{ matrix.environment }}.bin + run: mv -v .pio/build/${{ matrix.environment }}/firmware.bin firmware-${{ matrix.environment }}.bin - uses: actions/upload-artifact@v4 with: name: firmware-${{ matrix.environment }} - path: | - .pio/build/${{ matrix.environment }}/firmware.bin + path: firmware-${{ matrix.environment }}.bin - uses: actions/upload-artifact@v4 if: startsWith(github.ref, 'refs/tags/') with: From 678243f5ca904648cce5ffd0cdb18377cfbf540d Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 18:23:30 +0100 Subject: [PATCH 078/123] Fix artifact upload --- .github/workflows/wled-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index 91f94d1b..e78c1c73 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -73,7 +73,7 @@ jobs: - uses: actions/upload-artifact@v4 if: startsWith(github.ref, 'refs/tags/') with: - name: firmware-release + name: firmware-release-${{ matrix.environment }} path: build_output/release/*.bin release: name: Create Release From 163ba3aaf6a175e89c819c5d9e165787e7706a16 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 18:32:22 +0100 Subject: [PATCH 079/123] Update actions/download-artifct action --- .github/workflows/wled-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index e78c1c73..829eeeca 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -81,7 +81,7 @@ jobs: needs: [get_default_envs, build] if: startsWith(github.ref, 'refs/tags/') steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: name: firmware-release - name: Create draft release From 2276080c67d9ca705b2de0f87fd7c52f43077754 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 7 Sep 2024 18:56:59 +0100 Subject: [PATCH 080/123] Fix artifact upload --- .github/workflows/wled-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wled-ci.yml b/.github/workflows/wled-ci.yml index 829eeeca..e875ca18 100644 --- a/.github/workflows/wled-ci.yml +++ b/.github/workflows/wled-ci.yml @@ -83,7 +83,9 @@ jobs: steps: - uses: actions/download-artifact@v4 with: - name: firmware-release + name: firmware-release-* + - name: List Artifacts + run: find ./ - name: Create draft release uses: softprops/action-gh-release@v1 with: From c2adb5be34240183678e2db64477b08d6c3596c2 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:47:49 -0400 Subject: [PATCH 081/123] HUB75 PSRAM Buffers --- wled00/bus_manager.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ wled00/bus_manager.h | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 5f10ec77..a214e901 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -588,6 +588,29 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.d = 35; mxconfig.gpio.e = 21; +#elif defined(CONFIG_IDF_TARGET_ESP32S3) && defined(HUB75_TROYHACKS) // ESP32-S3 + + // TroyHacks HUB75 + + USER_PRINTLN("MatrixPanel_I2S_DMA - TroyHacks with PSRAM"); + + mxconfig.gpio.r1 = 1; + mxconfig.gpio.g1 = 2; + mxconfig.gpio.b1 = 42; + // 4th pin is GND + mxconfig.gpio.r2 = 41; + mxconfig.gpio.g2 = 40; + mxconfig.gpio.b2 = 39; + mxconfig.gpio.e = 38; + mxconfig.gpio.a = 45; + mxconfig.gpio.b = 48; + mxconfig.gpio.c = 47; + mxconfig.gpio.d = 21; // this says GND but should be the "D" pin + mxconfig.gpio.clk = 20; + mxconfig.gpio.lat = 19; + mxconfig.gpio.oe = 0; + // 16th pin is GND + #elif defined(CONFIG_IDF_TARGET_ESP32S3) // ESP32-S3 // Huidu HD-WF2 ESP32-S3 @@ -704,6 +727,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #endif + mxconfig.clkphase = false; mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length); @@ -750,7 +774,16 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen + + #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) + if (psramFound()){ + _ledsDirty = (byte*) ps_malloc(getBitArrayBytes(_len)); // create LEDs dirty bits + } else { + _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits + } + #else _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits + #endif if (_ledsDirty == nullptr) { display->stopDMAoutput(); @@ -762,7 +795,15 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh setBitArray(_ledsDirty, _len, false); // reset dirty bits if (mxconfig.double_buff == false) { + #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) + if (psramFound()){ + _ledBuffer = (CRGB*) ps_calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) + } else { + _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) + } + #else _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) + #endif } } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 2379f430..b3360881 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -360,7 +360,7 @@ class BusHub75Matrix : public Bus { public: BusHub75Matrix(BusConfig &bc); - uint16_t getMaxPixels() const override { return 4096; }; + uint16_t getMaxPixels() const override { return MAX_LEDS; }; bool hasRGB() const override { return true; } bool hasWhite() const override { return false; } From 3ee05a74b4263c15a9a6520e356840ae6e55cda5 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:11:17 -0400 Subject: [PATCH 082/123] PSRAM buffer fixes as per SoftHack007 --- wled00/bus_manager.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index bbae989d..a29ae468 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -719,7 +719,12 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #endif - mxconfig.clkphase = false; + // mxconfig.double_buff = true; // <------------- Turn on double buffer + // mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver + // mxconfig.latch_blanking = 3; + // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz + // mxconfig.min_refresh_rate = 90; + mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length); @@ -769,15 +774,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh if (_ledBuffer) free(_ledBuffer); // should not happen if (_ledsDirty) free(_ledsDirty); // should not happen - #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) - if (psramFound()){ - _ledsDirty = (byte*) ps_malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - } else { - _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - } - #else _ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits - #endif if (_ledsDirty == nullptr) { display->stopDMAoutput(); @@ -789,7 +786,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh setBitArray(_ledsDirty, _len, false); // reset dirty bits if (mxconfig.double_buff == false) { - #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) + #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) && defined(CONFIG_SPIRAM_MODE_OCT) if (psramFound()){ _ledBuffer = (CRGB*) ps_calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) } else { From 645b45a22d8540ca7203f2cea605e6b952a17a17 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:19:06 -0400 Subject: [PATCH 083/123] Added WLEDMM_NO_MAP_RESET Allows use of ledmaps with segments without messing with the segments. LEDs can remain remapped even with segments on top of them. (For Dom) --- wled00/FX_fcn.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 1f086fe0..95e0028c 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -2558,6 +2558,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { uint16_t maxHeight = atoi(cleanUpName(fileName)); //DEBUG_PRINTF(" (\"height\": %s) \n", fileName) + #ifndef WLEDMM_NO_MAP_RESET //WLEDMM: support ledmap file properties width and height: if found change segment if (maxWidth * maxHeight > 0) { Segment::maxWidth = maxWidth; @@ -2566,6 +2567,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { } else setUpMatrix(); //reset segment sizes to panels + #endif } USER_PRINTF("deserializeMap %d x %d\n", Segment::maxWidth, Segment::maxHeight); From 9fc279a3a6b5bd7ba4f2d70d6e5e2968f7b203bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Sat, 14 Sep 2024 22:51:19 +0200 Subject: [PATCH 084/123] Merge pull request #4142 from willmmiles/fix-webserver-pin Fix AsyncWebServer version pin --- platformio.ini | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b5b93187..34b118e7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -248,7 +248,7 @@ lib_deps = ;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections ;;https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7 ;; https://github.com/lost-hope/ESPAsyncWebServer.git#master ;; WLEDMM to display .log and .wled files in /edit - https://github.com/Aircoookie/ESPAsyncWebServer.git @ 2.2.1 ;; newer with bugfixes and stability improvements + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 ;; newer with bugfixes and stability improvements #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #TFT_eSPI #For compatible OLED display uncomment following @@ -297,6 +297,37 @@ lib_deps = makuna/NeoPixelBus @ 2.7.5 ${env.lib_deps} +;; compatibilty flags - same as 0.14.0 which seems to work better on some 8266 boards. Not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 +build_flags_compat = + -DESP8266 + -DFP_IN_IROM + ;;-Wno-deprecated-declarations + -Wno-misleading-indentation + ;;-Wno-attributes ;; silence warnings about unknown attribute 'maybe_unused' in NeoPixelBus + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 + -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH + -DVTABLES_IN_FLASH + -DMIMETYPE_MINIMAL + -DWLED_SAVE_IRAM ;; needed to prevent linker error + +;; this platform version was used for WLED 0.14.0 +platform_compat = espressif8266@4.2.0 +platform_packages_compat = + platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502 + platformio/tool-esptool #@ ~1.413.0 + platformio/tool-esptoolpy #@ ~1.30000.0 + +;; experimental - for using older NeoPixelBus 2.7.9 +lib_deps_compat = + ESPAsyncTCP @ 1.2.2 + ESPAsyncUDP + ESP8266PWM + fastled/FastLED @ 3.6.0 + IRremoteESP8266 @ 2.8.2 + makuna/NeoPixelBus @ 2.7.9 + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 + + [esp32] #platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip platform = espressif32@3.5.0 From 08c2446f61ce8f8d185f83ed2b96f42f53b46039 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:11:06 +0200 Subject: [PATCH 085/123] better PSRAM flags handling (minor) in MM, we can have WLED_USE_PSRAM_JSON instead of WLED_USE_PSRAM. --- wled00/bus_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a29ae468..0811ea5d 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -786,8 +786,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh setBitArray(_ledsDirty, _len, false); // reset dirty bits if (mxconfig.double_buff == false) { - #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) && defined(CONFIG_SPIRAM_MODE_OCT) - if (psramFound()){ + #if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM) && (defined(WLED_USE_PSRAM) || defined(WLED_USE_PSRAM_JSON)) + if (psramFound()) { _ledBuffer = (CRGB*) ps_calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) } else { _ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK) From 22bd52198f16a5a2e560dd034a852be7cbbd9bcb Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 21 Sep 2024 15:59:35 +0100 Subject: [PATCH 086/123] Cleanup Hub75 config --- wled00/bus_manager.cpp | 51 ++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 0811ea5d..2c5f0b37 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -525,10 +525,32 @@ void BusNetwork::cleanup() { BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { _valid = false; - mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory - fourScanPanel = nullptr; + mxconfig.double_buff = false; // Use our own memory-optimised buffer rather than the driver's own double-buffer + + // mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver + // mxconfig.latch_blanking = 3; + // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz + // mxconfig.min_refresh_rate = 90; + mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. + + // How many panels we have connected, cap at sane value + mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory + + #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM) + if(bc.pins[0] > 4) { + USER_PRINT("WARNING, chain limited to 4"); + } + # else + // Disable this check if you are want to try bigger setups and accept you + // might need to do full erase to recover from memory relayed boot-loop if you push too far + if(mxconfig.mx_height >= 64 && (bc.pins[0] > 1)) { + USER_PRINT("WARNING, only single panel can be used of 64 pixel boards due to memory"); + mxconfig.chain_length = 1; + } + #endif + switch(bc.type) { case 101: mxconfig.mx_width = 32; @@ -556,21 +578,12 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh break; } - if(mxconfig.mx_height >= 64 && (bc.pins[0] > 1)) { - USER_PRINT("WARNING, only single panel can be used of 64 pixel boards due to memory"); - mxconfig.chain_length = 1; - } - - // mxconfig.driver = HUB75_I2S_CFG::SHIFTREG; - #if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3 // https://www.adafruit.com/product/5778 USER_PRINTLN("MatrixPanel_I2S_DMA - Matrix Portal S3 config"); - //mxconfig.double_buff = true; // <------------- Turn on double buffer - mxconfig.gpio.r1 = 42; mxconfig.gpio.g1 = 41; mxconfig.gpio.b1 = 40; @@ -588,11 +601,9 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.d = 35; mxconfig.gpio.e = 21; -#elif defined(CONFIG_IDF_TARGET_ESP32S3) && defined(HUB75_TROYHACKS) // ESP32-S3 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM)// ESP32-S3 - // TroyHacks HUB75 - - USER_PRINTLN("MatrixPanel_I2S_DMA - TroyHacks with PSRAM"); + USER_PRINTLN("MatrixPanel_I2S_DMA - S3 with PSRAM"); mxconfig.gpio.r1 = 1; mxconfig.gpio.g1 = 2; @@ -719,14 +730,6 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #endif - // mxconfig.double_buff = true; // <------------- Turn on double buffer - // mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver - // mxconfig.latch_blanking = 3; - // mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz - // mxconfig.min_refresh_rate = 90; - mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. - mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory - USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length); // OK, now we can create our matrix object @@ -996,7 +999,7 @@ int BusManager::add(BusConfig &bc) { busses[numBusses] = new BusHub75Matrix(bc); USER_PRINTLN("[BusHub75Matrix] "); #else - USER_PRINTLN("[unsupported! BusHub75Matrix] "); + USER_PRINTLN("[unsupported! BusHub75Matrix - add flag -D WLED_ENABLE_HUB75MATRIX] "); return -1; #endif } else if (IS_DIGITAL(bc.type)) { From 2781be375f6458970416f91a98f2d28e49b1773c Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 21 Sep 2024 16:52:32 +0100 Subject: [PATCH 087/123] Swap pins used for S3 with PSRAM to avoid conflict --- wled00/bus_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 2c5f0b37..287f3b51 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -617,8 +617,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.b = 48; mxconfig.gpio.c = 47; mxconfig.gpio.d = 21; // this says GND but should be the "D" pin - mxconfig.gpio.clk = 20; - mxconfig.gpio.lat = 19; + mxconfig.gpio.clk = 18; + mxconfig.gpio.lat = 8; mxconfig.gpio.oe = 0; // 16th pin is GND From 24d2a43767dff331f3b388a10e21d122c7d9ce34 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 21 Sep 2024 16:53:13 +0100 Subject: [PATCH 088/123] Enable HUB75 for esp32S3_8MB_PSRAM_M --- platformio.ini | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 34b118e7..05be0617 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1974,6 +1974,7 @@ board_build.flash_mode = qio ;; use "dio" if your board gets unstable with "qio" build_unflags = ${env:esp32S3_8MB_M.build_unflags} ;; use the same as "normal" S3 buildenv build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation ${common_mm.build_flags_S} ${common_mm.build_flags_M} + ${common_mm.HUB75_build_flags} -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_RELEASE_NAME=esp32S3_8MB_PSRAM_M -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip @@ -1998,10 +1999,12 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ; -D SR_DEBUG ; -D MIC_LOGGER lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M} + ${common_mm.HUB75_lib_deps} + ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation board_build.partitions = tools/WLED_ESP32_8MB.csv -; RAM: [==== ] 36.3% (used 118828 bytes from 327680 bytes) -; Flash: [======= ] 70.7% (used 1483465 bytes from 2097152 bytes) +; RAM: [== ] 21.1% (used 69156 bytes from 327680 bytes) +; Flash: [======== ] 75.9% (used 1591817 bytes from 2097152 bytes) ;; MM for ESP32-S3 boards - FASTPATH + optimize for speed [env:esp32S3_8MB_S] From 095d18bca59bc076e441eba212b2917e96a640c8 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:27:17 +0200 Subject: [PATCH 089/123] board definition for T7-S3 (LILYGO / TTGO) --- boards/lilygo-t7-s3.json | 47 ++++++++++++++++++++++++++++++++++++++++ wled00/pin_manager.cpp | 7 ++++++ 2 files changed, 54 insertions(+) create mode 100644 boards/lilygo-t7-s3.json diff --git a/boards/lilygo-t7-s3.json b/boards/lilygo-t7-s3.json new file mode 100644 index 00000000..4bf071fc --- /dev/null +++ b/boards/lilygo-t7-s3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_TTGO_T7_S3", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0X303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LILYGO T3-S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.aliexpress.us/item/3256804591247074.html", + "vendor": "LILYGO" +} \ No newline at end of file diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index d1e7a18b..07b5d42d 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -120,6 +120,13 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in if (gpio > 32 && gpio < 38) return (F("(reserved) Octal PSRAM or Octal Flash")); #endif //if (gpio == 0 || gpio == 3 || gpio == 45 || gpio == 46) return (F("(strapping pin)")); + #ifdef ARDUINO_TTGO_T7_S3 + // experimental: a few special pins of the T7-S3 board + if (gpio == 2) return (F("(reserved) _VBAT voltage monitoring")); + if (gpio == 17) return (F("onboard LED")); + //if (gpio == 3) return (F("(cross-connected to pin 3-1)")); // WLEDMM experimental + //if (gpio == 12) return (F("(cross-connected to pin 12-1)")); // WLEDMM experimental + #endif #elif defined(CONFIG_IDF_TARGET_ESP32S2) // ESP32-S2 From 569ba1c6267280fd3d246c38f618d50d6e78e8b2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:29:28 +0200 Subject: [PATCH 090/123] s3: better handling of PSRAM pins --- wled00/pin_manager.cpp | 16 ++++++++++------ wled00/wled.cpp | 12 +++++++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 07b5d42d..b9d90a7d 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -113,10 +113,8 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in #ifdef ARDUINO_ARCH_ESP32 #if defined(CONFIG_IDF_TARGET_ESP32S3) // ESP32-S3 - if (gpio > 18 && gpio < 21) return (F("USB (CDC) / JTAG")); - #if !defined(BOARD_HAS_PSRAM) - if (gpio > 32 && gpio < 38) return (F("(optional) Octal Flash or PSRAM")); - #else + if (gpio > 18 && gpio < 21) return (F("USB (CDC) or JTAG")); + #if CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM) if (gpio > 32 && gpio < 38) return (F("(reserved) Octal PSRAM or Octal Flash")); #endif //if (gpio == 0 || gpio == 3 || gpio == 45 || gpio == 46) return (F("(strapping pin)")); @@ -136,7 +134,7 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in #elif defined(CONFIG_IDF_TARGET_ESP32C3) // ESP32-C3 - if (gpio > 17 && gpio < 20) return (F("USB (CDC) / JTAG")); + if (gpio > 17 && gpio < 20) return (F("USB (CDC) or JTAG")); //if (gpio == 2 || gpio == 8 || gpio == 9) return (F("(strapping pin)")); #else @@ -737,12 +735,18 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) const #if defined(CONFIG_IDF_TARGET_ESP32C3) // strapping pins: 2, 8, & 9 if (gpio > 11 && gpio < 18) return false; // 11-17 SPI FLASH + #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 if (gpio > 17 && gpio < 20) return false; // 18-19 USB-JTAG + #endif #elif defined(CONFIG_IDF_TARGET_ESP32S3) // 00 to 18 are for general use. Be careful about straping pins GPIO0 and GPIO3 - these may be pulled-up or pulled-down on your board. + #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses. + #endif if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH - //if (gpio > 32 && gpio < 38) return false; // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM + // #if CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM) + // if (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM + // #endif // 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board. #elif defined(CONFIG_IDF_TARGET_ESP32S2) // strapping pins: 0, 45 & 46 diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 9d54631f..52eb569a 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -594,9 +594,11 @@ void WLED::setup() #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) //psramInit(); //WLEDMM?? softhack007: not sure if explicit init is really needed ... lets disable it here and see if that works #if defined(CONFIG_IDF_TARGET_ESP32S3) - // S3: reserve GPIO 33-37 for "octal" PSRAM - managed_pin_type pins[] = { {33, true}, {34, true}, {35, true}, {36, true}, {37, true} }; - pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM); + #if CONFIG_SPIRAM_MODE_OCT && defined(BOARD_HAS_PSRAM) + // S3: reserve GPIO 33-37 for "octal" PSRAM + managed_pin_type pins[] = { {33, true}, {34, true}, {35, true}, {36, true}, {37, true} }; + pinManager.allocateMultiplePins(pins, sizeof(pins)/sizeof(managed_pin_type), PinOwner::SPI_RAM); + #endif #elif defined(CONFIG_IDF_TARGET_ESP32S2) // S2: reserve GPIO 26-32 for PSRAM (may fail due to isPinOk() but that will also prevent other allocation) //managed_pin_type pins[] = { {26, true}, {27, true}, {28, true}, {29, true}, {30, true}, {31, true}, {32, true} }; @@ -815,7 +817,11 @@ void WLED::setup() USER_PRINTLN(F("\nGPIO\t| Assigned to\t\t| Info")); USER_PRINTLN(F("--------|-----------------------|------------")); for(int pinNr = 0; pinNr < WLED_NUM_PINS; pinNr++) { // 49 = highest PIN on ESP32-S3 +#if defined(CONFIG_IDF_TARGET_ESP32S3) + if((pinManager.isPinOk(pinNr, false)) || (pinNr > 18 && pinNr < 21)) { // softhack007: list USB pins +#else if(pinManager.isPinOk(pinNr, false)) { +#endif //if ((!pinManager.isPinAllocated(pinNr)) && (pinManager.getPinSpecialText(pinNr).length() == 0)) continue; // un-comment to hide no-name,unused GPIO pins bool is_inOut = pinManager.isPinOk(pinNr, true); #if 0 // for testing From 80a2f2b85b096c49e6bc24dd4b317f9865b9e031 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:41:51 +0200 Subject: [PATCH 091/123] minor corrections * fix some override problems bus_manager (canShow() must not be const!!!) * fixing some "comparing integer with different signedness" warnings --- wled00/FX_2Dfcn.cpp | 6 +++--- wled00/FX_fcn.cpp | 18 +++++++++--------- wled00/bus_manager.h | 28 ++++++++++++++-------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 56d81443..ea5c4307 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -351,9 +351,9 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: return; } - const int_fast16_t glen_ = groupLength(); // WLEDMM optimization - const int_fast16_t wid_ = width(); - const int_fast16_t hei_ = height(); + const uint_fast16_t glen_ = groupLength(); // WLEDMM optimization + const uint_fast16_t wid_ = width(); + const uint_fast16_t hei_ = height(); x *= glen_; // expand to physical pixels y *= glen_; // expand to physical pixels diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 95e0028c..e2250a47 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1413,12 +1413,12 @@ void __attribute__((hot)) Segment::fill(uint32_t c) { if (_bri_t < 255) scaled_col = color_fade(c, _bri_t); } // fill 2D segment - for(int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { + for(unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) { if (simpleSegment) setPixelColorXY_fast(x, y, c, scaled_col, cols, rows); else setPixelColorXY_slow(x, y, c); } } else { // fill 1D strip - for (int x = 0; x < cols; x++) setPixelColor(x, c); + for (unsigned x = 0; x < cols; x++) setPixelColor(int(x), c); } } @@ -1471,8 +1471,8 @@ void __attribute__((hot)) Segment::fade_out(uint8_t rate) { int g2 = G(color2); int b2 = B(color2); - for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { - uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x); + for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) { + uint32_t color = is2D() ? getPixelColorXY(int(x), int(y)) : getPixelColor(int(x)); if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do int w1 = W(color); int r1 = R(color); @@ -1492,8 +1492,8 @@ void __attribute__((hot)) Segment::fade_out(uint8_t rate) { uint32_t colorNew = RGBW32(r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); // WLEDMM if (colorNew != color) { // WLEDMM speedup - do not repaint the same color - if (is2D()) setPixelColorXY(x, y, colorNew); - else setPixelColor(x, colorNew); + if (is2D()) setPixelColorXY(int(x), int(y), colorNew); + else setPixelColor(int(x), colorNew); } } } @@ -1507,11 +1507,11 @@ void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) { // WLEDMM minor optimization if(is2D()) { - for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) { - uint32_t cc = getPixelColorXY(x,y); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion + for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) { + uint32_t cc = getPixelColorXY(int(x),int(y)); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion uint32_t cc2 = color_fade(cc, scaledown); // fade //if (cc2 != cc) // WLEDMM only re-paint if faded color is different - disabled - causes problem with text overlay - setPixelColorXY((uint16_t)x, (uint16_t)y, cc2); + setPixelColorXY(int(x), int(y), cc2); } } else { for (uint_fast16_t x = 0; x < cols; x++) { diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index b3360881..b7a50cf0 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -65,7 +65,7 @@ struct BusConfig { else if (type > 47) nPins = 2; else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type); else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0; - for (uint8_t i = 0; i < nPins; i++) pins[i] = ppins[i]; + for (uint8_t i = 0; i < min(unsigned(nPins),5U); i++) pins[i] = ppins[i]; //softhack007 fix for potential array out-of-bounds access } //validates start and length and extends total if needed @@ -135,21 +135,21 @@ class Bus { virtual void setStatusPixel(uint32_t c) {} virtual void setPixelColor(uint16_t pix, uint32_t c) = 0; virtual uint32_t getPixelColor(uint16_t pix) const { return 0; } - virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; }; + virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; } virtual void cleanup() = 0; virtual uint8_t getPins(uint8_t* pinArray) const { return 0; } - virtual uint16_t getLength() const { return _len; } + virtual inline uint16_t getLength() const { return _len; } virtual void setColorOrder() {} virtual uint8_t getColorOrder() const { return COL_ORDER_RGB; } - virtual uint8_t skippedLeds() { return 0; } + virtual uint8_t skippedLeds() const { return 0; } virtual uint16_t getFrequency() const { return 0U; } inline uint16_t getStart() const { return _start; } inline void setStart(uint16_t start) { _start = start; } inline uint8_t getType() const { return _type; } inline bool isOk() const { return _valid; } inline bool isOffRefreshRequired() const { return _needsRefresh; } - bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start+_len; } - virtual uint16_t getMaxPixels() const { return MAX_LEDS_PER_BUS; }; + //inline bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start+_len; } // WLEDMM not used, plus wrong - it does not consider skipped pixels + virtual uint16_t getMaxPixels() const { return MAX_LEDS_PER_BUS; } virtual bool hasRGB() const { if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false; @@ -207,7 +207,7 @@ class BusDigital : public Bus { inline void show(); - bool canShow() const; + bool canShow() override; void setBrightness(uint8_t b, bool immediate); @@ -215,13 +215,13 @@ class BusDigital : public Bus { void setPixelColor(uint16_t pix, uint32_t c); - uint32_t getPixelColor(uint16_t pix) const; + uint32_t getPixelColor(uint16_t pix) const override; uint8_t getColorOrder() const { return _colorOrder; } - uint16_t getLength() const { + uint16_t getLength() const override { return _len - _skip; } @@ -229,11 +229,11 @@ class BusDigital : public Bus { void setColorOrder(uint8_t colorOrder); - uint8_t skippedLeds() const { + uint8_t skippedLeds() const override { return _skip; } - uint16_t getFrequency() const { return _frequencykHz; } + uint16_t getFrequency() const override { return _frequencykHz; } void reinit(); @@ -267,7 +267,7 @@ class BusPwm : public Bus { uint8_t getPins(uint8_t* pinArray) const; - uint16_t getFrequency() const { return _frequency; } + uint16_t getFrequency() const override { return _frequency; } void cleanup() { deallocatePins(); @@ -329,14 +329,14 @@ class BusNetwork : public Bus { void show(); - bool canShow() const { + bool canShow() override { // this should be a return value from UDP routine if it is still sending data out return !_broadcastLock; } uint8_t getPins(uint8_t* pinArray) const; - uint16_t getLength() const { + uint16_t getLength() const override { return _len; } From 087f156d35aa89185524f3fe039ef7446d120311 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 21 Sep 2024 18:51:55 +0100 Subject: [PATCH 092/123] Reset ESP32-HUB75-MatrixPanel-DMA library version back to one with the S3_LCD_DIV_NUM fix --- platformio.ini | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index 05be0617..57f0337d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1071,10 +1071,7 @@ HUB75_build_flags = -D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size -D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips -;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30) -;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... -;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ... -HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11 +HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#aa28e2a9 ;; S3_LCD_DIV_NUM fix HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) NetDebug_build_flags = From 3669946a09206816160aaf683672c481e276443c Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 21 Sep 2024 18:54:38 +0100 Subject: [PATCH 093/123] Swap pins used for S3 to avoid gpio0 --- wled00/bus_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 287f3b51..d0fc80fa 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -616,10 +616,10 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.gpio.a = 45; mxconfig.gpio.b = 48; mxconfig.gpio.c = 47; - mxconfig.gpio.d = 21; // this says GND but should be the "D" pin + mxconfig.gpio.d = 21; mxconfig.gpio.clk = 18; mxconfig.gpio.lat = 8; - mxconfig.gpio.oe = 0; + mxconfig.gpio.oe = 3; // 16th pin is GND #elif defined(CONFIG_IDF_TARGET_ESP32S3) // ESP32-S3 From 28fe5cbd8b5eb70cc5eb725b1cf718ac5d9a1f3e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:04:06 +0200 Subject: [PATCH 094/123] forgot one --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index d0fc80fa..61cc90fb 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -162,7 +162,7 @@ void BusDigital::show() { PolyBus::show(_busPtr, _iType); } -bool BusDigital::canShow() const { +bool BusDigital::canShow() { return PolyBus::canShow(_busPtr, _iType); } From e100a2d69a36b4f08bc7d76a44efa4909bcc1cc7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:07:52 +0200 Subject: [PATCH 095/123] switch off brightness reduction this was added due to a recommendation from MrF (HUB75) but it seems to work without, too. --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 61cc90fb..e0e875e3 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -885,7 +885,7 @@ uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { _bri = b; - if (_bri > 238) _bri=238; + // if (_bri > 238) _bri=238; // not strictly needed. Enable this line if you see glitches at highest brightness. display->setBrightness(_bri); } From f1088bb5c0376e8a6d2e954cb5fda02694359db6 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:41:05 +0200 Subject: [PATCH 096/123] (experimental) loop2 to get fresh audio just before drawing * introducing usermod::loop2() - runs just before strip.service() --> expecting to reduce lagging between audio and visual to an absolute minimum. --- usermods/audioreactive/audio_reactive.h | 5 +++++ wled00/fcn_declare.h | 2 ++ wled00/um_manager.cpp | 1 + wled00/wled.cpp | 13 +++++++++++++ wled00/wled.h | 2 +- 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index 709a5960..1c46e33a 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -2352,6 +2352,11 @@ class AudioReactive : public Usermod { #endif } +#if defined(_MoonModules_WLED_) && defined(WLEDMM_FASTPATH) + void loop2(void) { + loop(); + } +#endif bool getUMData(um_data_t **data) { diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 09f9724b..31b82293 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -299,6 +299,7 @@ class Usermod { virtual ~Usermod() { if (um_data) delete um_data; } virtual void setup() = 0; // pure virtual, has to be overriden virtual void loop() = 0; // pure virtual, has to be overriden + virtual void loop2() {} // WLEDMM called just before effects will be processed virtual void handleOverlayDraw() {} // called after all effects have been processed, just before strip.show() virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects] @@ -329,6 +330,7 @@ class UsermodManager { public: void loop(); + void loop2(); // WLEDMM loop just before drawing effects (presets and everything already handled) void handleOverlayDraw(); bool handleButton(uint8_t b); bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 2fe44db9..45647d60 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -9,6 +9,7 @@ void UsermodManager::connected() { for (byte i = 0; i < numMods; i++) um void UsermodManager::loop() { for (byte i = 0; i < numMods; i++) ums[i]->loop(); } void UsermodManager::handleOverlayDraw() { for (byte i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); } // void UsermodManager::appendConfigData() { for (byte i = 0; i < numMods; i++) ums[i]->appendConfigData(); } //WLEDMM not used +void UsermodManager::loop2() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop2(); } bool UsermodManager::handleButton(uint8_t b) { bool overrideIO = false; for (byte i = 0; i < numMods; i++) { diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 52eb569a..41e04d1a 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -213,6 +213,19 @@ void WLED::loop() handlePresets(); yield(); +#if defined(_MoonModules_WLED_) && defined(WLEDMM_FASTPATH) + #ifdef WLED_DEBUG + unsigned long usermod2Millis = millis(); + #endif + usermods.loop2(); + #ifdef WLED_DEBUG + usermod2Millis = millis() - usermod2Millis; + avgUsermodMillis += usermod2Millis; + if (usermod2Millis > maxUsermodMillis) maxUsermodMillis = usermod2Millis; + #endif + yield(); +#endif + #ifdef WLED_DEBUG unsigned long stripMillis = millis(); #endif diff --git a/wled00/wled.h b/wled00/wled.h index 9bfd7dd1..82116ee6 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2409060 +#define VERSION 2409210 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 18b35d11f8ed27cb507511ce7a6152ffb5d1089d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 21 Sep 2024 20:42:03 +0200 Subject: [PATCH 097/123] usermod manager - small optimization * use native types only (faster, smaller) --- wled00/fcn_declare.h | 2 +- wled00/um_manager.cpp | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 31b82293..694e9c9f 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -326,7 +326,7 @@ class Usermod { class UsermodManager { private: Usermod* ums[WLED_MAX_USERMODS]; - byte numMods = 0; + unsigned numMods = 0; public: void loop(); diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 45647d60..7c6153f5 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -4,50 +4,50 @@ */ //Usermod Manager internals -void UsermodManager::setup() { for (byte i = 0; i < numMods; i++) ums[i]->setup(); } -void UsermodManager::connected() { for (byte i = 0; i < numMods; i++) ums[i]->connected(); } -void UsermodManager::loop() { for (byte i = 0; i < numMods; i++) ums[i]->loop(); } -void UsermodManager::handleOverlayDraw() { for (byte i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); } -// void UsermodManager::appendConfigData() { for (byte i = 0; i < numMods; i++) ums[i]->appendConfigData(); } //WLEDMM not used +void UsermodManager::setup() { for (unsigned i = 0; i < numMods; i++) ums[i]->setup(); } +void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); } +void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); } void UsermodManager::loop2() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop2(); } +void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); } +// void UsermodManager::appendConfigData() { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(); } //WLEDMM not used bool UsermodManager::handleButton(uint8_t b) { bool overrideIO = false; - for (byte i = 0; i < numMods; i++) { + for (unsigned i = 0; i < numMods; i++) { if (ums[i]->handleButton(b)) overrideIO = true; } return overrideIO; } bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) { - for (byte i = 0; i < numMods; i++) { + for (unsigned i = 0; i < numMods; i++) { if (mod_id > 0 && ums[i]->getId() != mod_id) continue; // only get data form requested usermod if provided if (ums[i]->getUMData(data)) return true; // if usermod does provide data return immediately (only one usermod can provide data at one time) } return false; } -void UsermodManager::addToJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); } -void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); } -void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); } -void UsermodManager::addToConfig(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToConfig(obj); } +void UsermodManager::addToJsonState(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToJsonState(obj); } +void UsermodManager::addToJsonInfo(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToJsonInfo(obj); } +void UsermodManager::readFromJsonState(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); } +void UsermodManager::addToConfig(JsonObject& obj) { for (unsigned i = 0; i < numMods; i++) ums[i]->addToConfig(obj); } bool UsermodManager::readFromConfig(JsonObject& obj) { bool allComplete = true; - for (byte i = 0; i < numMods; i++) { + for (unsigned i = 0; i < numMods; i++) { if (!ums[i]->readFromConfig(obj)) allComplete = false; } return allComplete; } -void UsermodManager::onMqttConnect(bool sessionPresent) { for (byte i = 0; i < numMods; i++) ums[i]->onMqttConnect(sessionPresent); } +void UsermodManager::onMqttConnect(bool sessionPresent) { for (unsigned i = 0; i < numMods; i++) ums[i]->onMqttConnect(sessionPresent); } bool UsermodManager::onMqttMessage(char* topic, char* payload) { - for (byte i = 0; i < numMods; i++) if (ums[i]->onMqttMessage(topic, payload)) return true; + for (unsigned i = 0; i < numMods; i++) if (ums[i]->onMqttMessage(topic, payload)) return true; return false; } -void UsermodManager::onUpdateBegin(bool init) { for (byte i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin -void UsermodManager::onStateChange(uint8_t mode) { for (byte i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed +void UsermodManager::onUpdateBegin(bool init) { for (unsigned i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin +void UsermodManager::onStateChange(uint8_t mode) { for (unsigned i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed /* * Enables usermods to lookup another Usermod. */ Usermod* UsermodManager::lookup(uint16_t mod_id) { - for (byte i = 0; i < numMods; i++) { + for (unsigned i = 0; i < numMods; i++) { if (ums[i]->getId() == mod_id) { return ums[i]; } @@ -58,7 +58,7 @@ Usermod* UsermodManager::lookup(uint16_t mod_id) { //WLEDMM: used by Usermods in xml.cpp Usermod* UsermodManager::lookupName(const char *mod_name) { //WLEDMM: hack to get the usermod object with the mod_name (better would be to store the usermod name in the class but that requires change to all usermods) - for (byte i = 0; i < numMods; i++) { + for (unsigned i = 0; i < numMods; i++) { // StaticJsonDocument <1024> docx; JsonObject um = doc.createNestedObject("um"); //WLEDMM reuse the global doc variable here From 3a638bb396b68d13d84867bf4342981eca645e76 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 22 Sep 2024 16:22:53 +0200 Subject: [PATCH 098/123] busmanger cannot handle more than 5 pins (hardcoded) sizeof(pins)/sizeof(pins[0]) is the number of array elements in pins[]. --- wled00/bus_manager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index b7a50cf0..eb431333 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -54,7 +54,7 @@ struct BusConfig { uint8_t skipAmount; bool refreshReq; uint8_t autoWhite; - uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255}; + uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255}; // WLEDMM warning: this means that BusConfig cannot handle nore than 5 pins per bus! uint16_t frequency; BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U) { refreshReq = (bool) GET_BIT(busType,7); @@ -65,7 +65,7 @@ struct BusConfig { else if (type > 47) nPins = 2; else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type); else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0; - for (uint8_t i = 0; i < min(unsigned(nPins),5U); i++) pins[i] = ppins[i]; //softhack007 fix for potential array out-of-bounds access + for (uint8_t i = 0; i < min(unsigned(nPins), sizeof(pins)/sizeof(pins[0])); i++) pins[i] = ppins[i]; //softhack007 fix for potential array out-of-bounds access } //validates start and length and extends total if needed From ffc9ec3cfbd11034dd345add23cb8875c69279ca Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 22 Sep 2024 17:07:26 +0200 Subject: [PATCH 099/123] exclude HUB75 from auto brightness limiter For a 64x64 panel, ABL assumes 4A of standby current. This does not make any sense. --- wled00/FX.h | 1 + wled00/FX_fcn.cpp | 18 ++++++++++++++++-- wled00/const.h | 2 ++ wled00/json.cpp | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index a0f3e90f..505721c7 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -963,6 +963,7 @@ class WS2812FX { // 96 bytes ablMilliampsMax, currentMilliamps, getLengthPhysical(void) const, + getLengthPhysical2(void) const, // WLEDMM total length including HUB75, network busses excluded __attribute__((pure)) getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added getFps() const; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e2250a47..9e2368ab 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1985,7 +1985,8 @@ void WS2812FX::estimateCurrentAndLimitBri() { for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) { Bus *bus = busses.getBus(bNum); - if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses + auto btype = bus->getType(); + if (EXCLUDE_FROM_ABL(btype)) continue; // WLEDMM exclude non-ABL and network busses uint16_t len = bus->getLength(); uint32_t busPowerSum = 0; for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED @@ -2196,7 +2197,20 @@ uint16_t WS2812FX::getLengthPhysical(void) const { // WLEDMM fast int types uint_fast16_t len = 0; for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types Bus *bus = busses.getBus(b); - if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses + auto btype = bus->getType(); + if (EXCLUDE_FROM_ABL(btype)) continue; //exclude HUB75, and non-physical network busses + len += bus->getLength(); + } + return len; +} + +//WLEDMM - getLengthPhysical plus plysical busses not supporting ABL (i.e. HUB75) +uint16_t WS2812FX::getLengthPhysical2(void) const { + uint_fast16_t len = 0; + for (unsigned b = 0; b < busses.getNumBusses(); b++) { + Bus *bus = busses.getBus(b); + auto btype = bus->getType(); + if (IS_VIRTUAL(btype)) continue; len += bus->getLength(); } return len; diff --git a/wled00/const.h b/wled00/const.h index ff8b0371..2792f158 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -257,6 +257,8 @@ #define IS_PWM(t) ((t) > 40 && (t) < 46) #define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only #define IS_2PIN(t) ((t) > 47) +#define IS_VIRTUAL(t) ( ((t) <= TYPE_RESERVED) || (((t) >= TYPE_NET_DDP_RGB) && ((t) < (TYPE_NET_DDP_RGB + 16))) ) // WLEDMM 80..95 are network "virtual" busses +#define EXCLUDE_FROM_ABL(t) ( IS_VIRTUAL(t) || ( (t) >= (TYPE_HUB75MATRIX + 10) && (t) < (TYPE_HUB75MATRIX + 10))) // WLEDMM do not apply ato-brightness-limiter on these bus types //Color orders #define COL_ORDER_GRB 0 //GRB(w),defaut diff --git a/wled00/json.cpp b/wled00/json.cpp index f0f189b2..f3a84061 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -904,7 +904,7 @@ void serializeInfo(JsonObject root) JsonObject leds = root.createNestedObject("leds"); leds[F("count")] = strip.getLengthTotal(); - leds[F("countP")] = strip.getLengthPhysical(); //WLEDMM + leds[F("countP")] = strip.getLengthPhysical2(); //WLEDMM - getLengthPhysical plus plysical busses not supporting ABL (i.e. HUB75) leds[F("pwr")] = strip.currentMilliamps; leds["fps"] = strip.getFps(); leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; From c5a0ab33eabe469650804371412fe6956b34da39 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 22 Sep 2024 17:10:21 +0200 Subject: [PATCH 100/123] clean up BusConfig nPins chaos still very confusing logic, but documented in a better way. --- wled00/bus_manager.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index eb431333..089020a0 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -60,11 +60,11 @@ struct BusConfig { refreshReq = (bool) GET_BIT(busType,7); type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh) count = len; start = pstart; colorOrder = pcolorOrder; reversed = rev; skipAmount = skip; autoWhite = aw; frequency = clock_kHz; - uint8_t nPins = 1; - if (type >= TYPE_NET_DDP_RGB && type < 96) nPins = 4; //virtual network bus. 4 "pins" store IP address - else if (type > 47) nPins = 2; - else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type); - else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0; + uint8_t nPins = 1; // default = only one pin (clockless LEDs like WS281x) + if ((type >= TYPE_NET_DDP_RGB) && (type < (TYPE_NET_DDP_RGB + 16))) nPins = 4; // virtual network bus. 4 "pins" store IP address + else if ((type > 47) && (type < 63)) nPins = 2; // (data + clock / SPI) busses - two pins + else if (IS_PWM(type)) nPins = NUM_PWM_PINS(type); // PWM needs 1..5 pins + else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0; // HUB75 does not use LED pins for (uint8_t i = 0; i < min(unsigned(nPins), sizeof(pins)/sizeof(pins[0])); i++) pins[i] = ppins[i]; //softhack007 fix for potential array out-of-bounds access } From 0a0192675858e5aed2340587e820a008d832b8e4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 22 Sep 2024 17:13:34 +0200 Subject: [PATCH 101/123] docu --- wled00/const.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wled00/const.h b/wled00/const.h index 2792f158..fe9b9ca6 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -245,7 +245,9 @@ #define TYPE_P9813 53 #define TYPE_LPD6803 54 +// WLEDMM additional types #define TYPE_HUB75MATRIX 100 // 100 - 110 +// WLEDMM caution - do not use bus types > 127 //Network types (master broadcast) (80-95) #define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus) From 1ddc9e38a25428ba01f3c913fbb30c6ab69b3d3f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:55:40 +0200 Subject: [PATCH 102/123] HUB75 bugfix - preserve chain length parameter chain length was always replaced with "4" --- wled00/bus_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 089020a0..80488b6a 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -64,7 +64,7 @@ struct BusConfig { if ((type >= TYPE_NET_DDP_RGB) && (type < (TYPE_NET_DDP_RGB + 16))) nPins = 4; // virtual network bus. 4 "pins" store IP address else if ((type > 47) && (type < 63)) nPins = 2; // (data + clock / SPI) busses - two pins else if (IS_PWM(type)) nPins = NUM_PWM_PINS(type); // PWM needs 1..5 pins - else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0; // HUB75 does not use LED pins + else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 1; // HUB75 does not use LED pins, but we need to preserve the "chain length" parameter for (uint8_t i = 0; i < min(unsigned(nPins), sizeof(pins)/sizeof(pins[0])); i++) pins[i] = ppins[i]; //softhack007 fix for potential array out-of-bounds access } From bc11ec4b4e99a3f81c31a886a31f57aff08b0d8e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:33:40 +0200 Subject: [PATCH 103/123] HUB75 bugfixes * exclude HUB75 from ABL (bad macro in const.h; "pwr" item in json.cpp) * show HUB75 as "physical" (LEDs preferences) * minor corrections --- wled00/bus_manager.cpp | 2 +- wled00/const.h | 2 +- wled00/data/settings_leds.htm | 2 +- wled00/json.cpp | 2 +- wled00/wled.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index e0e875e3..963409c6 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -536,7 +536,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh mxconfig.clkphase = false; // can help in case that the leftmost column is invisible, or pixels on the right side "bleeds out" to the left. // How many panels we have connected, cap at sane value - mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory + mxconfig.chain_length = max((uint8_t) 1, min(bc.pins[0], (uint8_t) 4)); // prevent bad data preventing boot due to low memory #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM) if(bc.pins[0] > 4) { diff --git a/wled00/const.h b/wled00/const.h index fe9b9ca6..55f9f780 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -260,7 +260,7 @@ #define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only #define IS_2PIN(t) ((t) > 47) #define IS_VIRTUAL(t) ( ((t) <= TYPE_RESERVED) || (((t) >= TYPE_NET_DDP_RGB) && ((t) < (TYPE_NET_DDP_RGB + 16))) ) // WLEDMM 80..95 are network "virtual" busses -#define EXCLUDE_FROM_ABL(t) ( IS_VIRTUAL(t) || ( (t) >= (TYPE_HUB75MATRIX + 10) && (t) < (TYPE_HUB75MATRIX + 10))) // WLEDMM do not apply ato-brightness-limiter on these bus types +#define EXCLUDE_FROM_ABL(t) ( IS_VIRTUAL(t) || ( (t) >= (TYPE_HUB75MATRIX) && (t) < (TYPE_HUB75MATRIX + 10))) // WLEDMM do not apply auto-brightness-limiter on these bus types //Color orders #define COL_ORDER_GRB 0 //GRB(w),defaut diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 6d7c36c9..1fd0e4ba 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -250,7 +250,7 @@ if (s+c > sLC) sLC = s+c; //update total count if(c>maxLC)maxLC=c; //max per output var t = parseInt(d.getElementsByName("LT"+n)[0].value); // LED type SELECT - if (t<80) sPC+=c; //virtual out busses do not count towards physical LEDs + if ((t<128) && ((t<80) || ((t>99)))) sPC+=c; //virtual out busses do not count towards physical LEDs //WLEDMM include HUB75 (>=100) } // increase led count continue; } diff --git a/wled00/json.cpp b/wled00/json.cpp index f3a84061..a2b9514b 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -905,7 +905,7 @@ void serializeInfo(JsonObject root) JsonObject leds = root.createNestedObject("leds"); leds[F("count")] = strip.getLengthTotal(); leds[F("countP")] = strip.getLengthPhysical2(); //WLEDMM - getLengthPhysical plus plysical busses not supporting ABL (i.e. HUB75) - leds[F("pwr")] = strip.currentMilliamps; + leds[F("pwr")] = strip.currentMilliamps > 100 ? strip.currentMilliamps : 0; // WLEDMM show "not calculated" for HUB75, or when all LEDs are out leds["fps"] = strip.getFps(); leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds[F("maxseg")] = strip.getMaxSegments(); diff --git a/wled00/wled.h b/wled00/wled.h index 82116ee6..74deeace 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2409210 +#define VERSION 2409260 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 0ca3f136b12b560d95be671cad57720c9fbf4641 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:06:48 +0200 Subject: [PATCH 104/123] ws error printing improvement * limit to 3 messages per second * print size when alloc failed --- wled00/ws.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wled00/ws.cpp b/wled00/ws.cpp index 22c5afd2..85bad64d 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -215,7 +215,11 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static" if ((bufSize < 1) || (used < 1)) return(false); // WLEDMM should not happen AsyncWebSocketBuffer wsBuf(bufSize); if (!wsBuf) { - USER_PRINTLN(F("WS buffer allocation failed.")); + static unsigned long last_err_time = 0; + if (millis() - last_err_time > 300) { // WLEDMM limit to 3 messages per second + USER_PRINTF("WS buffer allocation failed (!wsBuf %u bytes).\n", bufSize); + last_err_time = millis(); + } errorFlag = ERR_LOW_WS_MEM; return false; //out of memory } From 3a506aded272cb8de323078d2aa94082fac497e7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:12:53 +0200 Subject: [PATCH 105/123] trying to keep scrolling text readable the problem (partly solved) is that scrolling text does not erase any previous text, but simply paints pixels in addition. * add a "shadow" area around each letter, which is explicitly painted black * only possible when Trail=0, and overlay option selected --- wled00/FX.cpp | 5 +++-- wled00/FX.h | 2 +- wled00/FX_2Dfcn.cpp | 35 ++++++++++++++++++++++++++++------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 1fbc74e6..ea5b7415 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6371,7 +6371,7 @@ uint16_t mode_2Dscrollingtext(void) { if (SEGMENT.name) for (size_t i=0,j=0; i31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i]; const bool zero = strchr(text, '0') != nullptr; - if (!strlen(text) || !strncmp_P(text,PSTR("#F"),2) || !strncmp_P(text,PSTR("#P"),2) || !strncmp_P(text,PSTR("#DATE"),5) || !strncmp_P(text,PSTR("#DDMM"),5) || !strncmp_P(text,PSTR("#MMDD"),5) || !strncmp_P(text,PSTR("#TIME"),5) || !strncmp_P(text,PSTR("#HH"),3) || !strncmp_P(text,PSTR("#MM"),3)) { // fallback if empty segment name: display date and time + if (!strlen(text) || !strncmp_P(text,PSTR("#F"),2) || !strncmp_P(text,PSTR("#P"),2) || !strncmp_P(text,PSTR("#A"),2) || !strncmp_P(text,PSTR("#DATE"),5) || !strncmp_P(text,PSTR("#DDMM"),5) || !strncmp_P(text,PSTR("#MMDD"),5) || !strncmp_P(text,PSTR("#TIME"),5) || !strncmp_P(text,PSTR("#HH"),3) || !strncmp_P(text,PSTR("#MM"),3)) { // fallback if empty segment name: display date and time char sec[5]= {'\0'}; byte AmPmHour = hour(localTime); boolean isitAM = true; @@ -6404,6 +6404,7 @@ uint16_t mode_2Dscrollingtext(void) { SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1)); } } + bool drawShadow = (SEGMENT.check2) && (SEGMENT.custom1 == 0); for (int i = 0; i < numberOfLetters; i++) { if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0); @@ -6412,7 +6413,7 @@ uint16_t mode_2Dscrollingtext(void) { col1 = SEGCOLOR(0); col2 = SEGCOLOR(2); } - SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2); + SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2, drawShadow); } return FRAMETIME; diff --git a/wled00/FX.h b/wled00/FX.h index 505721c7..677005f2 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -761,7 +761,7 @@ typedef struct Segment { inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline void drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor = 0); inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline - void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0); + void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline void wu_pixel(uint32_t x, uint32_t y, CRGB c); //void blur1d(fract8 blur_amount); // blur all rows in 1 dimension diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index ea5c4307..7a090416 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -880,7 +880,7 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { // draws a raster font character on canvas // only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM -void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) { +void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported chr -= 32; // align with font table entries @@ -890,6 +890,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, CRGB col = CRGB(color); CRGBPalette16 grad = CRGBPalette16(col, col2 ? CRGB(col2) : col); + uint32_t bgCol = SEGCOLOR(1); //if (w<5 || w>6 || h!=8) return; for (int i = 0; i= rows) break; // drawing off-screen uint8_t bits = 0; + uint8_t bits_up = 0; // WLEDMM this is the previous line: font[(chr * h) + i -1] switch (font) { - case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); break; // 5x8 font - case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); break; // 5x8 font - case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); break; // 6x8 font - case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); break; // 7x9 font - case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); break; // 5x12 font + case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); + break; // 5x8 font + case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]); + break; // 5x8 font + case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]); + break; // 6x8 font + case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]); + break; // 7x9 font + case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]); + break; // 5x12 font default: return; } col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND); for (int j = 0; j= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen + if ((x0 >= 0) || (x0 < cols)) { + if ((bits>>(j+(8-w))) & 0x01) { // bit set & drawing on-screen setPixelColorXY(x0, y0, col); + } else { + if (drawShadow) { + // WLEDMM + if ((j < (w-1)) && (bits>>(j+(8-w) +1)) & 0x01) setPixelColorXY(x0, y0, bgCol); // blank when pixel to the right is set + else if ((j > 0) && (bits>>(j+(8-w) -1)) & 0x01) setPixelColorXY(x0, y0, bgCol);// blank when pixel to the left is set + else if ((bits_up>>(j+(8-w))) & 0x01) setPixelColorXY(x0, y0, bgCol); // blank when pixel above is set + } + } } } } From 8338b58b8846954f92ad7196edcc81b2cc993457 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:15:41 +0200 Subject: [PATCH 106/123] HUB75 memory usage info on serial --- wled00/bus_manager.cpp | 15 +++++++++++---- wled00/wled.cpp | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 963409c6..fa205c44 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -523,6 +523,7 @@ void BusNetwork::cleanup() { #warning "HUB75 driver enabled (experimental)" BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { + size_t lastHeap = ESP.getFreeHeap(); _valid = false; fourScanPanel = nullptr; @@ -540,14 +541,14 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM) if(bc.pins[0] > 4) { - USER_PRINT("WARNING, chain limited to 4"); + USER_PRINTLN("WARNING, chain limited to 4"); } # else // Disable this check if you are want to try bigger setups and accept you // might need to do full erase to recover from memory relayed boot-loop if you push too far if(mxconfig.mx_height >= 64 && (bc.pins[0] > 1)) { - USER_PRINT("WARNING, only single panel can be used of 64 pixel boards due to memory"); - mxconfig.chain_length = 1; + USER_PRINTLN("WARNING, only single panel can be used of 64 pixel boards due to memory"); + //mxconfig.chain_length = 1; } #endif @@ -730,7 +731,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #endif - USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length); + USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u (type %u) length: %u, %u bits/pixel.\n", mxconfig.mx_width, mxconfig.mx_height, bc.type, mxconfig.chain_length, mxconfig.getPixelColorDepthBits() * 3); + DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap()); lastHeap = ESP.getFreeHeap(); // OK, now we can create our matrix object display = new MatrixPanel_I2S_DMA(mxconfig); @@ -762,13 +764,16 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh _bri = 25; delay(24); // experimental + DEBUG_PRINT(F("heap usage: ")); DEBUG_PRINTLN(lastHeap - ESP.getFreeHeap()); // Allocate memory and start DMA display if( not display->begin() ) { USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********"); + USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap()); return; } else { USER_PRINTLN("MatrixPanel_I2S_DMA begin ok"); + USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap()); delay(18); // experiment - give the driver a moment (~ one full frame @ 60hz) to settle _valid = true; display->clearScreen(); // initially clear the screen buffer @@ -784,6 +789,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh delete display; display = nullptr; _valid = false; USER_PRINTLN(F("MatrixPanel_I2S_DMA not started - not enough memory for dirty bits!")); + USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap()); return; // fail is we cannot get memory for the buffer } setBitArray(_ledsDirty, _len, false); // reset dirty bits @@ -837,6 +843,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh USER_PRINT((_ledBuffer? _len*sizeof(CRGB) :0) + (_ledsDirty? getBitArrayBytes(_len) :0)); USER_PRINTLN(F(" bytes.")); } + USER_PRINT(F("heap usage: ")); USER_PRINTLN(lastHeap - ESP.getFreeHeap()); } void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 41e04d1a..5858f800 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -876,6 +876,7 @@ void WLED::setup() USER_PRINTLN(F("\n")); #endif + USER_PRINT(F("Free heap ")); USER_PRINTLN(ESP.getFreeHeap());USER_PRINTLN(); USER_PRINTLN(F("WLED initialization done.\n")); delay(50); // repeat Ada prompt From 0555b8e5f258415e7d038689c6636cbd659bdffe Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:18:24 +0200 Subject: [PATCH 107/123] HUB75: avoid allocating ledMap based on an idea by @troyhacks : fight heap fragmentation by avoiding to allocate ledMap when not needed. --- wled00/FX_2Dfcn.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 7a090416..73c7bf77 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -66,9 +66,26 @@ void WS2812FX::setUpMatrix() { USER_PRINTF("setUpMatrix %d x %d\n", Segment::maxWidth, Segment::maxHeight); + // WLEDMM check if mapping table is necessary (avoiding heap fragmentation) +#if defined(WLED_ENABLE_HUB75MATRIX) + bool needLedMap = (loadedLedmap >0); // ledmap loaded + needLedMap |= WLED_FS.exists(F("/2d-gaps.json")); // gapFile found + needLedMap |= panel.size() > 1; // 2D config: more than one panel + if (panel.size() == 1) { + Panel &p = panel[0]; + needLedMap |= p.serpentine; // panel serpentine + needLedMap |= p.vertical; // panel not horizotal + needLedMap |= p.bottomStart | p.rightStart; // panel not top left, or not left->light + needLedMap |= (p.xOffset > 0) || (p.yOffset > 0); // panel does not start at (0,0) + } +#else + bool needLedMap = true; // always use ledMaps on non-HUB75 builds +#endif + //WLEDMM recreate customMappingTable if more space needed if (Segment::maxWidth * Segment::maxHeight > customMappingTableSize) { size_t size = max(ledmapMaxSize, size_t(Segment::maxWidth * Segment::maxHeight)); // TroyHacks + if (!needLedMap) size = 0; // softhack007 USER_PRINTF("setupmatrix customMappingTable alloc %d from %d\n", size, customMappingTableSize); //if (customMappingTable != nullptr) delete[] customMappingTable; //customMappingTable = new uint16_t[size]; @@ -88,8 +105,9 @@ void WS2812FX::setUpMatrix() { if (customMappingTable != nullptr) customMappingTableSize = size; } - if (customMappingTable != nullptr) { + if ((customMappingTable != nullptr) || (!needLedMap)) { // softhack007 customMappingSize = Segment::maxWidth * Segment::maxHeight; + if (!needLedMap) customMappingSize = 0; // softhack007 // fill with empty in case we don't fill the entire matrix for (size_t i = 0; i< customMappingTableSize; i++) { //WLEDMM use customMappingTableSize @@ -130,6 +148,7 @@ void WS2812FX::setUpMatrix() { releaseJSONBufferLock(); } + if (needLedMap && customMappingTable != nullptr) { // softhack007 uint16_t x, y, pix=0; //pixel for (size_t pan = 0; pan < panel.size(); pan++) { Panel &p = panel[pan]; @@ -146,6 +165,7 @@ void WS2812FX::setUpMatrix() { } } } + } // delete gap array as we no longer need it if (gapTable) {delete[] gapTable; gapTable=nullptr;} // softhack prevent dangling pointer From b245112d2a80b0df5534fc957be09f6799bf374b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:19:53 +0200 Subject: [PATCH 108/123] some drawing speedups * speedups for addPixelColorXY, fadePixelColorXY, fadeToBlackBy --- wled00/FX.cpp | 3 +++ wled00/FX_2Dfcn.cpp | 16 +++++++++------- wled00/FX_fcn.cpp | 4 +++- wled00/wled.h | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ea5b7415..9e7a25cf 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -37,6 +37,9 @@ #define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16)) +// WLEDMM replace abs8 by abs, as abs8 does not work for numbers >127 +#define abs8(x) abs(x) + // effect utility functions static uint8_t sin_gap(uint16_t in) { if (in & 0x100) return 0; diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 73c7bf77..9ac62e1d 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -463,8 +463,9 @@ uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { if (reverse ) x = virtualWidth() - x - 1; if (reverse_y) y = virtualHeight() - y - 1; if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed - x *= groupLength(); // expand to physical pixels - y *= groupLength(); // expand to physical pixels + const uint_fast16_t groupLength_ = groupLength(); // WLEDMM small optimization + x *= groupLength_; // expand to physical pixels + y *= groupLength_; // expand to physical pixels if (x >= width() || y >= height()) return 0; return strip.getPixelColorXY(start + x, startY + y); } @@ -479,15 +480,16 @@ void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) { // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY // if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit //WLEDMM - uint32_t col = getPixelColorXY(x,y); - col = color_add(col, color, fast); - setPixelColorXY(x, y, col); + uint32_t oldCol = getPixelColorXY(x,y); + uint32_t col = color_add(oldCol, color, fast); + if (col != oldCol) setPixelColorXY(x, y, col); } void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY - CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade); - setPixelColorXY(x, y, pix); + CRGB oldPix = CRGB(getPixelColorXY(x,y)); + CRGB pix = oldPix.nscale8_video(fade); + if (pix != oldPix) setPixelColorXY(int(x), int(y), pix); } // blurRow: perform a blur on a row of a rectangular matrix diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 9e2368ab..51087562 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1510,7 +1510,9 @@ void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) { for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) { uint32_t cc = getPixelColorXY(int(x),int(y)); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion uint32_t cc2 = color_fade(cc, scaledown); // fade - //if (cc2 != cc) // WLEDMM only re-paint if faded color is different - disabled - causes problem with text overlay +#ifdef WLEDMM_FASTPATH + if (cc2 != cc) // WLEDMM only re-paint if faded color is different - normally disabled - causes problem with text overlay +#endif setPixelColorXY(int(x), int(y), cc2); } } else { diff --git a/wled00/wled.h b/wled00/wled.h index 74deeace..33174183 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2409260 +#define VERSION 2409280 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 2aa0d4703687c5c61d8786bb9986753c483b61da Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:43:12 +0200 Subject: [PATCH 109/123] adding getPixelColorRestored() similar to getPixelColor, but returns the original pixel without brightness adjustments. * getPixelColorRestored is used by segment::sPC and segment::gPC * getPixelColor is still used by ABL (auto brightness limiter) --- wled00/FX.h | 3 +++ wled00/FX_2Dfcn.cpp | 13 ++++++++++++- wled00/FX_fcn.cpp | 8 +++++++- wled00/bus_manager.cpp | 29 +++++++++++++++++++++++++++++ wled00/bus_manager.h | 16 ++++++++++++++++ wled00/ws.cpp | 1 + 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 677005f2..4e408254 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -976,6 +976,7 @@ class WS2812FX { // 96 bytes now, timebase; uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t) const; // WLEDMM attribute pure = does not have side-effects + uint32_t __attribute__((pure)) getPixelColorRestored(uint_fast16_t i) const;// WLEDMM gets the original color from the driver (without downscaling by _bri) inline uint32_t getLastShow(void) const { return _lastShow; } inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } @@ -1068,6 +1069,8 @@ class WS2812FX { // 96 bytes std::vector _segments; friend class Segment; + uint32_t getPixelColorXYRestored(uint16_t x, uint16_t y) const; // WLEDMM gets the original color from the driver (without downscaling by _bri) + private: uint16_t _length; uint8_t _brightness; diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9ac62e1d..0803ad1a 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -249,6 +249,17 @@ uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) return busses.getPixelColor(index); } +uint32_t __attribute__((hot)) WS2812FX::getPixelColorXYRestored(uint16_t x, uint16_t y) const { // WLEDMM gets the original color from the driver (without downscaling by _bri) + #ifndef WLED_DISABLE_2D + uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types + #else + uint16_t index = x; + #endif + if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return 0; + return busses.getPixelColorRestored(index); +} + /////////////////////////////////////////////////////////// // Segment:: routines /////////////////////////////////////////////////////////// @@ -467,7 +478,7 @@ uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { x *= groupLength_; // expand to physical pixels y *= groupLength_; // expand to physical pixels if (x >= width() || y >= height()) return 0; - return strip.getPixelColorXY(start + x, startY + y); + return strip.getPixelColorXYRestored(start + x, startY + y); } // Blends the specified color with the existing pixel color. diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 51087562..f2ed3e20 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1304,7 +1304,7 @@ uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const if (offset < INT16_MAX) i += offset; // WLEDMM if ((i >= stop) && (stop>0)) i -= length(); // WLEDMM avoid negative index (stop = 0 is a possible value) if (i<0) i=0; // WLEDMM just to be 100% sure - return strip.getPixelColor(i); + return strip.getPixelColorRestored(i); } uint8_t Segment::differs(Segment& b) const { @@ -1943,6 +1943,12 @@ uint32_t WS2812FX::getPixelColor(uint_fast16_t i) const // WLEDMM fast int types return busses.getPixelColor(i); } +uint32_t WS2812FX::getPixelColorRestored(uint_fast16_t i) const // WLEDMM gets the original color from the driver (without downscaling by _bri) +{ + if (i < customMappingSize) i = customMappingTable[i]; + if (i >= _length) return 0; + return busses.getPixelColorRestored(i); +} //DISCLAIMER //The following function attemps to calculate the current LED power usage, diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index fa205c44..66a417e8 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -890,6 +890,14 @@ uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const { return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not } +uint32_t __attribute__((hot)) BusHub75Matrix::getPixelColorRestored(uint16_t pix) const { + if (!_valid || pix >= _len) return BLACK; + if (_ledBuffer) + return uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; + else + return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not +} + void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) { _bri = b; // if (_bri > 238) _bri=238; // not strictly needed. Enable this line if you see glitches at highest brightness. @@ -1106,6 +1114,27 @@ uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColor(uint_fast16_t return 0; } +uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColorRestored(uint_fast16_t pix) { // WLEDMM uses bus::getPixelColorRestored() + if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) { + // WLEDMM same bus as last time - no need to search again + return lastBus->getPixelColorRestored(pix - laststart); + } + + for (uint_fast8_t i = 0; i < numBusses; i++) { + Bus* b = busses[i]; + uint_fast16_t bstart = b->getStart(); + if (pix < bstart || pix >= bstart + b->getLength()) continue; + else { + // WLEDMM remember last Bus we took + lastBus = b; + laststart = bstart; + lastend = bstart + b->getLength(); + return b->getPixelColorRestored(pix - bstart); + } + } + return 0; +} + bool BusManager::canAllShow() const { for (uint8_t i = 0; i < numBusses; i++) { if (!busses[i]->canShow()) return false; diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 80488b6a..677e71de 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -135,6 +135,7 @@ class Bus { virtual void setStatusPixel(uint32_t c) {} virtual void setPixelColor(uint16_t pix, uint32_t c) = 0; virtual uint32_t getPixelColor(uint16_t pix) const { return 0; } + virtual uint32_t getPixelColorRestored(uint16_t pix) const { return restore_Color_Lossy(getPixelColor(pix), _bri); } // override in case your bus has a lossless buffer (HUB75, FastLED, Art-Net) virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; } virtual void cleanup() = 0; virtual uint8_t getPins(uint8_t* pinArray) const { return 0; } @@ -183,6 +184,17 @@ class Bus { inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; } inline static uint8_t getGlobalAWMode() { return _gAWM; } + inline uint32_t restore_Color_Lossy(uint32_t c, uint8_t restoreBri) const { // shamelessly grabbed from upstream, who grabbed from NPB, who .. + if (restoreBri < 255) { + uint8_t* chan = (uint8_t*) &c; + for (uint_fast8_t i=0; i<4; i++) { + uint_fast16_t val = chan[i]; + chan[i] = ((val << 8) + restoreBri) / (restoreBri + 1); //adding _bri slightly improves recovery / stops degradation on re-scale + } + } + return c; + } + bool reversed = false; protected: @@ -296,6 +308,7 @@ class BusOnOff : public Bus { void setPixelColor(uint16_t pix, uint32_t c); uint32_t getPixelColor(uint16_t pix) const; + uint32_t getPixelColorRestored(uint16_t pix) const override { return getPixelColor(pix);} // WLEDMM BusOnOff ignores brightness void show(); @@ -326,6 +339,7 @@ class BusNetwork : public Bus { void setPixelColor(uint16_t pix, uint32_t c); uint32_t __attribute__((pure)) getPixelColor(uint16_t pix) const; // WLEDMM attribute added + uint32_t __attribute__((pure)) getPixelColorRestored(uint16_t pix) const override { return getPixelColor(pix);} // WLEDMM BusNetwork ignores brightness void show(); @@ -367,6 +381,7 @@ class BusHub75Matrix : public Bus { void setPixelColor(uint16_t pix, uint32_t c) override; uint32_t getPixelColor(uint16_t pix) const override; + uint32_t getPixelColorRestored(uint16_t pix) const override; // lossless getPixelColor supported void show(void) override; @@ -418,6 +433,7 @@ class BusManager { void setSegmentCCT(int16_t cct, bool allowWBCorrection = false); uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added + uint32_t __attribute__((pure)) getPixelColorRestored(uint_fast16_t pix); // WLEDMM bool canAllShow() const; diff --git a/wled00/ws.cpp b/wled00/ws.cpp index 85bad64d..f6c1e862 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -251,6 +251,7 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static" } #endif uint32_t c = restoreColorLossy(strip.getPixelColor(i), stripBrightness); // WLEDMM full bright preview - does _not_ recover ABL reductions + //uint32_t c = strip.getPixelColorRestored(i); // WLEDMM begin: preview with color gamma correction if (gammaCorrectPreview) { uint8_t w = W(c); // not sure why, but it looks better if using "white" without corrections From 59ca792c9d7bc6b90f04ae640c6e2827ea826f15 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:45:16 +0200 Subject: [PATCH 110/123] HUB75: trade bit depth against memory needs gradually reduce bitdepts on esp32 --- wled00/bus_manager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 66a417e8..cb3d8fac 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -579,6 +579,14 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh break; } +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)// classic esp32, or esp32-s2: reduce bitdepth for large panels + if (mxconfig.mx_height >= 64) { + if (mxconfig.chain_length * mxconfig.mx_width > 192) mxconfig.setPixelColorDepthBits(3); + else if (mxconfig.chain_length * mxconfig.mx_width > 64) mxconfig.setPixelColorDepthBits(4); + else mxconfig.setPixelColorDepthBits(8); + } else mxconfig.setPixelColorDepthBits(8); +#endif + #if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3 // https://www.adafruit.com/product/5778 From 559d86256c213c8eccb8097a39651141c2741402 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:56:46 +0200 Subject: [PATCH 111/123] live preview speedup --- wled00/ws.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wled00/ws.cpp b/wled00/ws.cpp index f6c1e862..5a7f34eb 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -10,9 +10,11 @@ static volatile unsigned long wsLastLiveTime = 0; // WLEDMM //uint8_t* wsFrameBuffer = nullptr; #if !defined(ARDUINO_ARCH_ESP32) || defined(WLEDMM_FASTPATH) // WLEDMM -#define WS_LIVE_INTERVAL 120 +#define WS_LIVE_INTERVAL_MAX 120 +#define WS_LIVE_INTERVAL_MIN 25 #else -#define WS_LIVE_INTERVAL 80 +#define WS_LIVE_INTERVAL_MAX 80 +#define WS_LIVE_INTERVAL_MIN 40 #endif void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) @@ -274,7 +276,7 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static" void handleWs() { - if ((millis() - wsLastLiveTime) > (unsigned long)(max((strip.getLengthTotal()/20), WS_LIVE_INTERVAL))) //WLEDMM dynamic nr of peek frames per second + if ((millis() - wsLastLiveTime) > (unsigned long)(max(WS_LIVE_INTERVAL_MIN, min((strip.getLengthTotal()/80), WS_LIVE_INTERVAL_MAX)))) //WLEDMM dynamic nr of peek frames per second { #ifdef ESP8266 ws.cleanupClients(3); From b650c15997193a8bf2372b37145f2ce08afcae63 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 29 Sep 2024 02:01:57 +0200 Subject: [PATCH 112/123] platformio.ini updates for HUB75 * -D WLEDMM_SLOWPATH prevents using I2S#1 for ws281x leds - matrixPortal S3: minor update to use more PSRAM (and keep more RAM availeable) --- platformio.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platformio.ini b/platformio.ini index 57f0337d..07c03129 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1071,6 +1071,7 @@ HUB75_build_flags = -D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size -D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already -D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips + -D WLEDMM_SLOWPATH ;; WLEDMM: do not use I2S for driving ws2812 LEDs (HUB75 driver needs I2S#1) HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#aa28e2a9 ;; S3_LCD_DIV_NUM fix HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes) @@ -2667,6 +2668,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D LOLIN_WIFI_FIX ;; try this in case Wifi does not work -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 -D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used + -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap + ; -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - seems to move more buffers into PSRAM ${common_mm.HUB75_build_flags} -D DEFAULT_LED_TYPE=101 lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ;; ;; do not include ${esp32.lib_depsV4} !!!! From a0f07cabcb82e5a3e8cb65d41e0eb2bf88e19505 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 29 Sep 2024 14:59:54 +0200 Subject: [PATCH 113/123] make a few getters "constexpr" as they just return a constant constexpr ensures that the compiler will replace the "getter" call with the value return, saving function call overhead. based on an idea from @blazoncek --- wled00/FX.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 4e408254..04eabe70 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -951,13 +951,13 @@ class WS2812FX { // 96 bytes setPixelSegment(uint8_t n); inline uint8_t getBrightness(void) const { return _brightness; } - inline uint8_t getMaxSegments(void) const { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) inline uint8_t getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments inline uint8_t getCurrSegmentId(void) const { return _segment_index; } inline uint8_t getMainSegmentId(void) const { return _mainSegment; } - inline uint8_t getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count inline uint8_t getTargetFps() const { return _targetFps; } inline uint8_t getModeCount() const { return _modeCount; } + inline static constexpr uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value) + inline static constexpr uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count uint16_t ablMilliampsMax, From 7e9474e78ce9caabc863eb8cb0ed62952fd152d7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 29 Sep 2024 17:51:44 +0200 Subject: [PATCH 114/123] depricate sPC(float, float) the function is already removed in upstream. You can use wu_pixel() instead, which is much faster and more accurate. --- wled00/FX.cpp | 5 ++++- wled00/FX_2Dfcn.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 9e7a25cf..931f74b2 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5539,7 +5539,10 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline float ylocn = float(cos8(phase/2 + i*2)) / 255.0f; //SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing unsigned palIndex = (256*ylocn) + phase/2 + (i* SEGMENT.speed)/64; - SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing - color follows rotation + //SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing - color follows rotation + // WLEDMM wu_pixel is 50% faster, and still lokks better + SEGMENT.wu_pixel(uint32_t(xlocn * (cols <<8)), uint32_t(ylocn * (rows <<8)), + CRGB(SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0))); } } else for (int i=0; i < 256; i ++) { diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 0803ad1a..a277c521 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -413,6 +413,8 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: } } +#if 0 +// WLEDMM setPixelColorXY(float x, float y, uint32_t col, ..) is depricated. use wu_pixel(x,y,col) instead. // anti-aliased version of setPixelColorXY() void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast) // WLEDMM some speedups due to fast int and faster sqrt16 { @@ -463,6 +465,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col); } } +#endif // returns RGBW values of pixel uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { From 3110b0a4769e3f8206258f0a8e2511b03773809e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 29 Sep 2024 18:02:39 +0200 Subject: [PATCH 115/123] fix for XL builds some usermod still seems to used sPC(float, float, c). > Linking .pio/build/esp32_4MB_XL/firmware.elf .pio/build/esp32_4MB_XL/src/usermods_list.cpp.o:(.literal._ZN7Frame3DD5Ev[Frame3D::~Frame3D()]+0x4): undefined reference to `Segment::setPixelColorXY(float, float, unsigned int, bool, bool)' --- wled00/FX_2Dfcn.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index a277c521..42865933 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -413,7 +413,6 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: } } -#if 0 // WLEDMM setPixelColorXY(float x, float y, uint32_t col, ..) is depricated. use wu_pixel(x,y,col) instead. // anti-aliased version of setPixelColorXY() void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast) // WLEDMM some speedups due to fast int and faster sqrt16 @@ -421,6 +420,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast if (Segment::maxHeight==1) return; // not a matrix set-up if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized +#if 0 // depricated const uint_fast16_t cols = virtualWidth(); const uint_fast16_t rows = virtualHeight(); @@ -464,8 +464,13 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast } else { setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col); } -} + +#else // replacement using wu_pixel + unsigned px = x * (virtualWidth() <<8); + unsigned py = y * (virtualHeight() <<8); + wu_pixel(px, py, CRGB(col)); #endif +} // returns RGBW values of pixel uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { From 63ff7205d61c4bdf7e9b952e392222e46b93e1d6 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 29 Sep 2024 18:37:18 +0200 Subject: [PATCH 116/123] wu_pixel small optimization 5% faster --- wled00/FX_2Dfcn.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 42865933..03919f8e 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -987,12 +987,14 @@ void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)}; // multiply the intensities by the colour, and saturating-add them to the pixels for (int i = 0; i < 4; i++) { - CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1)); + int wu_x = (x >> 8) + (i & 1); // WLEDMM precalculate x + int wu_y = (y >> 8) + ((i >> 1) & 1); // WLEDMM precalculate y + CRGB led = getPixelColorXY(wu_x, wu_y); CRGB oldLed = led; led.r = qadd8(led.r, c.r * wu[i] >> 8); led.g = qadd8(led.g, c.g * wu[i] >> 8); led.b = qadd8(led.b, c.b * wu[i] >> 8); - if (led != oldLed) setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led); // WLEDMM don't repaint same color + if (led != oldLed) setPixelColorXY(wu_x, wu_y, led); // WLEDMM don't repaint same color } } #undef WU_WEIGHT From 813b3705c1fb823851e8293e575c7d2d89e0d3c2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:33:25 +0200 Subject: [PATCH 117/123] Akemi bugfix for panel width > 32 due to a math accident, Akemi did not show proper GEQ bands in its hands when width>32. --- wled00/FX.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 931f74b2..2d44708d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7998,11 +7998,12 @@ uint16_t mode_2DAkemi(void) { //add geq left and right if (um_data) { - for (int x=0; x < cols/8; x++) { - uint16_t band = x * cols/8; + int xMax = cols/8; + for (int x=0; x < xMax; x++) { + size_t band = map2(x, 0, max(xMax,4), 0, 15); // map 0..cols/8 to 16 GEQ bands + CRGB color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0); band = constrain(band, 0, 15); uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32); - CRGB color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0); for (int y=0; y < barHeight; y++) { SEGMENT.setPixelColorXY(x, rows/2-y, color); From b0a7330a310ba1cf58b0f4b6715630ab4a3e6b23 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:35:14 +0200 Subject: [PATCH 118/123] Akemi memory saver lossless getPixelColor buffer is not needed for Akemi. --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2d44708d..c2b66d83 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7957,7 +7957,7 @@ uint16_t mode_2DAkemi(void) { const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); - if (SEGENV.call == 0) {SEGMENT.setUpLeds(); SEGMENT.fill(BLACK);} + if (SEGENV.call == 0) {SEGMENT.fill(BLACK);} uint16_t counter = (strip.now * ((SEGMENT.speed >> 2) +2)) & 0xFFFF; counter = counter >> 8; From 9ed787c0860bb0297a25a962cc83dcc92a9db0ff Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:35:14 +0200 Subject: [PATCH 119/123] colored burst effect bugfix (swapped XY dimensions) fixing a bug where width and height got swapped (visible on non-square panels) --- wled00/FX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c2b66d83..494d03d7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4982,8 +4982,8 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so SEGMENT.fadeToBlackBy(40); for (size_t i = 0; i < numLines; i++) { byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1)); - byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (cols - 1)); - byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 24); + byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (rows - 1)); + byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24); byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND); From 79f5db6d65a49a0252831562d763c91651999d5b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:12:48 +0200 Subject: [PATCH 120/123] fadePixelColorXY bugfix --- wled00/FX_2Dfcn.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 03919f8e..6ca95e13 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -506,8 +506,9 @@ void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fa void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY - CRGB oldPix = CRGB(getPixelColorXY(x,y)); - CRGB pix = oldPix.nscale8_video(fade); + CRGB pix = CRGB(getPixelColorXY(x,y)); + CRGB oldPix = pix; + pix = pix.nscale8_video(fade); if (pix != oldPix) setPixelColorXY(int(x), int(y), pix); } From b436a595ef042686b96d3401de974f1569d31812 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:34:36 +0200 Subject: [PATCH 121/123] bugfix for holes in 2D DNA Spiral Holes were visible at height > 32. Root cause: "lerp8x8" seems to be inaccurate --> replaced by a simple linear calculation. --- wled00/FX.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 494d03d7..01b9e517 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5067,10 +5067,12 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma if ((i + ms / 8) & 3) { // draw a gradient line between x and x1 x = x / 2; x1 = x1 / 2; - uint8_t steps = abs8(x - x1) + 1; + unsigned steps = abs8(x - x1) + 1; + bool positive = (x1 >= x); // direction of drawing for (size_t k = 1; k <= steps; k++) { - uint8_t rate = k * 255 / steps; - uint8_t dx = lerp8by8(x, x1, rate); + unsigned rate = k * 255 / steps; + //unsigned dx = lerp8by8(x, x1, rate); + unsigned dx = positive? (x + k-1) : (x - k+1); // behaves the same as "lerp8by8" but does not create holes //SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate)); SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look SEGMENT.fadePixelColorXY(dx, i, rate); From 16644f838ae4819dd5002df5ed6e239bf526d93f Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 2 Oct 2024 19:20:19 +0100 Subject: [PATCH 122/123] Remove stray commma from _data_FX_MODE_2DGAMEOFLIFE --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 01b9e517..f96deabe 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5379,7 +5379,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https: SEGENV.step = strip.now; return FRAMETIME; } // mode_2Dgameoflife() -static const char _data_FX_MODE_2DGAMEOFLIFE[] PROGMEM = "Game Of Life@!,Color Mutation ☾,Blur ☾,,,All Colors ☾,Overlay BG ☾,Wrap ☾,;!,!;!;2;sx=56,ix=2,c1=128,o1=0,o2=0,o3=1"; +static const char _data_FX_MODE_2DGAMEOFLIFE[] PROGMEM = "Game Of Life@!,Color Mutation ☾,Blur ☾,,,All Colors ☾,Overlay BG ☾,Wrap ☾;!,!;!;2;sx=56,ix=2,c1=128,o1=0,o2=0,o3=1"; ///////////////////////// // 2D Hiphotic // From 3a38d0cfed9485bb635e3c037f153a4252435f77 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Wed, 2 Oct 2024 20:15:58 +0200 Subject: [PATCH 123/123] Fix for #4005 --- wled00/wled.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 5858f800..3c86c4b0 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -308,6 +308,7 @@ void WLED::loop() delete busConfigs[i]; busConfigs[i] = nullptr; } strip.finalizeInit(); + busses.setBrightness(bri); // fix re-initialised bus' brightness #4005 loadLedmap = true; if (aligned) strip.makeAutoSegments(); else strip.fixInvalidSegments();