From fd54b80cfe0e64473c5d4b1157333faf81895c2c Mon Sep 17 00:00:00 2001 From: ewowi Date: Thu, 5 Feb 2026 13:15:13 +0100 Subject: [PATCH 01/11] include latest FastLED and compile fixes - pio.ini: include latest FastLED - memcpy: (void *) on CRGB - CRGB + CRGB not defined (replaced by += workaround) - MAX -> max - D_FastLED.h: remove pun 19 and 20 from CONFIG_IDF_TARGET_ESP32S3 --- platformio.ini | 2 +- src/MoonBase/Nodes.cpp | 2 +- src/MoonLight/Layers/VirtualLayer.cpp | 6 ++--- src/MoonLight/Layers/VirtualLayer.h | 25 ++++++++++++--------- src/MoonLight/Modules/ModuleLightsControl.h | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 12 +++++----- src/MoonLight/Nodes/Drivers/D_Infrared.h | 2 +- src/MoonLight/Nodes/Effects/E_MoonLight.h | 12 +++++----- src/MoonLight/Nodes/Effects/E_WLED.h | 10 ++++----- src/MoonLight/Nodes/Modifiers/M_MoonLight.h | 4 ++-- 10 files changed, 41 insertions(+), 36 deletions(-) diff --git a/platformio.ini b/platformio.ini index c2cfb676..4b8f34ba 100644 --- a/platformio.ini +++ b/platformio.ini @@ -159,7 +159,7 @@ build_flags = -D ML_COLOR_ORDER=GRB ; define your color order here if needed (why WS2812 has GRB instead of RGB?) Only for FastLED, PD software configurable ; -D ML_RGBW=1 ; define whether to enable RGBW (1 = yes, 0 = no) ... could be derived from ML_CHIPSET??? lib_deps = - https://github.com/FastLED/FastLED.git#3.10.3 ; sept 2025 + https://github.com/FastLED/FastLED#8b4fd586ba38a6c3b67ce94f78d68e77aa505fa5 https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104) ; πŸ’« currently only enabled on s3 as esp32dev runs over 100% diff --git a/src/MoonBase/Nodes.cpp b/src/MoonBase/Nodes.cpp index 7aeb6b0a..b540909a 100644 --- a/src/MoonBase/Nodes.cpp +++ b/src/MoonBase/Nodes.cpp @@ -154,7 +154,7 @@ void LiveScriptNode::setup() { addExternal("uint32_t millis()", (void*)millis); addExternal("uint32_t now()", (void*)millis); // todo: synchronized time (sys->now) addExternal("uint16_t random16(uint16_t)", (void*)(uint16_t (*)(uint16_t))random16); - addExternal("void delay(uint32_t)", (void*)delay); + addExternal("void delay(uint32_t)", (void*)((void (*)(uint32_t))delay)); addExternal("void pinMode(uint8_t,uint8_t)", (void*)pinMode); addExternal("void digitalWrite(uint8_t,uint8_t)", (void*)digitalWrite); diff --git a/src/MoonLight/Layers/VirtualLayer.cpp b/src/MoonLight/Layers/VirtualLayer.cpp index 88bd7047..af5c59c2 100644 --- a/src/MoonLight/Layers/VirtualLayer.cpp +++ b/src/MoonLight/Layers/VirtualLayer.cpp @@ -18,8 +18,8 @@ // convenience functions to call fastled functions out of the Leds namespace (there naming conflict) void fastled_fadeToBlackBy(CRGB* leds, uint16_t num_leds, uint8_t fadeBy) { fadeToBlackBy(leds, num_leds, fadeBy); } // supports max UINT16_MAX leds ! -void fastled_fill_solid(struct CRGB* targetArray, int numToFill, const CRGB& color) { fill_solid(targetArray, numToFill, color); } -void fastled_fill_rainbow(struct CRGB* targetArray, int numToFill, uint8_t initialhue, uint8_t deltahue) { fill_rainbow(targetArray, numToFill, initialhue, deltahue); } +void fastled_fill_solid(CRGB* targetArray, int numToFill, const CRGB& color) { fill_solid(targetArray, numToFill, color); } +void fastled_fill_rainbow(CRGB* targetArray, int numToFill, uint8_t initialhue, uint8_t deltahue) { fill_rainbow(targetArray, (uint16_t)numToFill, initialhue, deltahue); } VirtualLayer::VirtualLayer() { EXT_LOGV(ML_TAG, "constructor"); } @@ -290,7 +290,7 @@ void VirtualLayer::addLight(Coord3D position) { createMappingTableAndAddOneToOne(); } - nrOfLights = MAX(nrOfLights, indexV + 1); + nrOfLights = max(nrOfLights, indexV + 1); if (!oneToOneMapping) { if (indexV < mappingTableSize) { diff --git a/src/MoonLight/Layers/VirtualLayer.h b/src/MoonLight/Layers/VirtualLayer.h index 024d0a21..d85f3af1 100644 --- a/src/MoonLight/Layers/VirtualLayer.h +++ b/src/MoonLight/Layers/VirtualLayer.h @@ -146,12 +146,12 @@ class VirtualLayer { void setRGB(const nrOfLights_t indexV, CRGB color) { if (indexV < mappingTableSize && mappingTable[indexV].mapType == m_zeroLights) { #ifdef BOARD_HAS_PSRAM - memcpy(mappingTable[indexV].rgb, &color, 3); + memcpy(mappingTable[indexV].rgb, (void*)&color, 3); #else mappingTable[indexV].rgb = ((min(color[0] + 3, 255) >> 3) << 9) + ((min(color[1] + 3, 255) >> 3) << 4) + (min(color[2] + 7, 255) >> 4); #endif } else - forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW], &color, sizeof(color)); }); + forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW], (void*)&color, sizeof(color)); }); } void setRGB(Coord3D pos, CRGB color) { setRGB(XYZ(pos), color); } @@ -198,17 +198,17 @@ class VirtualLayer { void setGobo(Coord3D pos, const uint8_t value) { setGobo(XYZ(pos), value); } void setRGB1(const nrOfLights_t indexV, CRGB color) { - if (layerP->lights.header.offsetRGBW1 != UINT8_MAX) forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW1], &color, sizeof(color)); }); + if (layerP->lights.header.offsetRGBW1 != UINT8_MAX) forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW1], (void*)&color, sizeof(color)); }); } void setRGB1(Coord3D pos, CRGB color) { setRGB1(XYZ(pos), color); } void setRGB2(const nrOfLights_t indexV, CRGB color) { - if (layerP->lights.header.offsetRGBW2 != UINT8_MAX) forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW2], &color, sizeof(color)); }); + if (layerP->lights.header.offsetRGBW2 != UINT8_MAX) forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW2], (void*)&color, sizeof(color)); }); } void setRGB2(Coord3D pos, CRGB color) { setRGB2(XYZ(pos), color); } void setRGB3(const nrOfLights_t indexV, CRGB color) { - if (layerP->lights.header.offsetRGBW3 != UINT8_MAX) forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW3], &color, sizeof(color)); }); + if (layerP->lights.header.offsetRGBW3 != UINT8_MAX) forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW3], (void*)&color, sizeof(color)); }); } void setRGB3(Coord3D pos, CRGB color) { setRGB3(XYZ(pos), color); } @@ -238,13 +238,18 @@ class VirtualLayer { #endif } else { CRGB color = CRGB::Black; - forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW], sizeof(color)); }, true); + forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy((void*)&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW], sizeof(color)); }, true); return color; } } CRGB getRGB(Coord3D pos) { return getRGB(XYZ(pos)); } - void addRGB(const Coord3D& position, const CRGB& color) { setRGB(position, getRGB(position) + color); } + void addRGB(const Coord3D& position, const CRGB& color) { + // setRGB(position, getRGB(position) + color); + not working anymore in newest FastLED ??? + CRGB result = getRGB(position); + result += color; + setRGB(position, result); + } void blendColor(const nrOfLights_t indexV, const CRGB& color, uint8_t blendAmount) { setRGB(indexV, blend(color, getRGB(indexV), blendAmount)); } void blendColor(Coord3D position, const CRGB& color, const uint8_t blendAmount) { blendColor(XYZ(position), color, blendAmount); } @@ -255,7 +260,7 @@ class VirtualLayer { CRGB getRGB1(const nrOfLights_t indexV) { if (layerP->lights.header.offsetRGBW1 == UINT8_MAX) return CRGB::Black; CRGB color = CRGB::Black; - forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW1], sizeof(color)); }, true); + forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy((void*)&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW1], sizeof(color)); }, true); return color; } CRGB getRGB1(Coord3D pos) { return getRGB1(XYZ(pos)); } @@ -263,7 +268,7 @@ class VirtualLayer { CRGB getRGB2(const nrOfLights_t indexV) { if (layerP->lights.header.offsetRGBW2 == UINT8_MAX) return CRGB::Black; CRGB color = CRGB::Black; - forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW2], sizeof(color)); }, true); + forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy((void*)&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW2], sizeof(color)); }, true); return color; } CRGB getRGB2(Coord3D pos) { return getRGB2(XYZ(pos)); } @@ -271,7 +276,7 @@ class VirtualLayer { CRGB getRGB3(const nrOfLights_t indexV) { if (layerP->lights.header.offsetRGBW3 == UINT8_MAX) return CRGB::Black; CRGB color = CRGB::Black; - forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW3], sizeof(color)); }, true); + forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy((void*)&color, &layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW3], sizeof(color)); }, true); return color; } CRGB getRGB3(Coord3D pos) { return getRGB3(XYZ(pos)); } diff --git a/src/MoonLight/Modules/ModuleLightsControl.h b/src/MoonLight/Modules/ModuleLightsControl.h index 38de4f60..773bad66 100644 --- a/src/MoonLight/Modules/ModuleLightsControl.h +++ b/src/MoonLight/Modules/ModuleLightsControl.h @@ -495,7 +495,7 @@ class ModuleLightsControl : public Module { xSemaphoreGive(swapMutex); } else if (isPositions == 0 && layerP.lights.header.nrOfLights) { // send to UI static unsigned long monitorMillis = 0; - if (millis() - monitorMillis >= MAX(20, layerP.lights.header.nrOfLights / 300)) { // 12K lights -> 40ms + if (millis() - monitorMillis >= max(20UL, layerP.lights.header.nrOfLights / 300)) { // 12K lights -> 40ms monitorMillis = millis(); if (_socket->getActiveClients() && _state.data["monitorOn"]) { diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index 3a296336..a8460eff 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -474,12 +474,12 @@ class FastLEDDriver : public Node { break; #if !ARDUINO_USB_CDC_ON_BOOT // 19 + 20 = USB-JTAG. Not recommended for other uses. - case 19: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 20: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; + // case 19: + // FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; + // break; + // case 20: + // FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; + // break; #endif case 21: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; diff --git a/src/MoonLight/Nodes/Drivers/D_Infrared.h b/src/MoonLight/Nodes/Drivers/D_Infrared.h index a856930b..c9b78dcd 100644 --- a/src/MoonLight/Nodes/Drivers/D_Infrared.h +++ b/src/MoonLight/Nodes/Drivers/D_Infrared.h @@ -367,7 +367,7 @@ class IRDriver : public Node { } else if (combined_code == codePaletteInc) { // palette increase newState["palette"] = MIN(state.data["palette"].as() + 1, 8 + 3 + 61); // 8 FastLED + 3 custom + 61 WLED palettes. to do: replace nr with max palette count } else if (combined_code == codePaletteDec) { // palette decrease - newState["palette"] = MAX(state.data["palette"].as() - 1, 0); + newState["palette"] = max(state.data["palette"].as() - 1, 0); } else if (combined_code == codePresetDec) { // next button - go to previous preset newState["preset"] = state.data["preset"]; newState["preset"]["action"] = "click"; diff --git a/src/MoonLight/Nodes/Effects/E_MoonLight.h b/src/MoonLight/Nodes/Effects/E_MoonLight.h index 277ab7c6..a9d23b40 100644 --- a/src/MoonLight/Nodes/Effects/E_MoonLight.h +++ b/src/MoonLight/Nodes/Effects/E_MoonLight.h @@ -725,7 +725,7 @@ class FreqSawsEffect : public Node { } else { // Calculate decay amount based on time to reach zero if (decreaser > 0 && bandSpeed[band] > 0) { - uint32_t decayAmount = MAX((bandSpeed[band] * deltaMs) / (decreaser * 10UL), 1); // *10 to scale decreaser range 0-255 to 0-2550ms + uint32_t decayAmount = max((bandSpeed[band] * deltaMs) / (decreaser * 10UL), 1UL); // *10 to scale decreaser range 0-255 to 0-2550ms if (decayAmount >= bandSpeed[band]) { bandSpeed[band] = 0; } else { @@ -905,9 +905,9 @@ class RubiksCubeEffect : public Node { } void drawCube(VirtualLayer* layer) { - int sizeX = MAX(layer->size.x - 1, 1); - int sizeY = MAX(layer->size.y - 1, 1); - int sizeZ = MAX(layer->size.z - 1, 1); + int sizeX = max(layer->size.x - 1, 1); + int sizeY = max(layer->size.y - 1, 1); + int sizeZ = max(layer->size.z - 1, 1); // 3 Sided Cube Cheat add 1 to led size if "panels" missing. May affect different fixture types if (layer->layerDimension == _3D) { @@ -1610,7 +1610,7 @@ class PixelMapEffect : public Node { Coord3D pos = {0, 0, 0}; - void setup() override { addControl(pos, "pos", "coord3D", 0, MAX(MAX(layer->size.x, layer->size.x), layer->size.x) - 1); } + void setup() override { addControl(pos, "pos", "coord3D", 0, max(max(layer->size.x, layer->size.x), layer->size.x) - 1); } void loop() override { layer->fill_solid(CRGB::Black); @@ -1721,7 +1721,7 @@ class AudioRingsEffect : public RingEffect { } void loop() override { - uint8_t nrOfRings = MAX(layer->size.y, 2); // height of the layer, minimal 2 + uint8_t nrOfRings = max(layer->size.y, 2); // height of the layer, minimal 2 for (int i = 0; i < nrOfRings; i++) { uint8_t band = ::map(i, 0, nrOfRings - 1, 0, NUM_GEQ_CHANNELS - 1); diff --git a/src/MoonLight/Nodes/Effects/E_WLED.h b/src/MoonLight/Nodes/Effects/E_WLED.h index 7279ee2e..7163baca 100644 --- a/src/MoonLight/Nodes/Effects/E_WLED.h +++ b/src/MoonLight/Nodes/Effects/E_WLED.h @@ -72,7 +72,7 @@ class BouncingBallsEffect : public Node { // uint32_t color = SEGCOLOR(0); // if (layerP.palette) { - // color = layer->color_wheel(i*(256/MAX(numBalls, 8))); + // color = layer->color_wheel(i*(256/max(numBalls, 8))); // } // else if (hasCol2) { // color = SEGCOLOR(i % NUM_COLORS); @@ -136,7 +136,7 @@ class BlurzEffect : public Node { if (freqMap) { // FreqMap mode : blob location by major frequency int freqLocn; - unsigned maxLen = (geqScanner) ? MAX(1, layer->size.x * layer->size.y * layer->size.z - 16) : layer->size.x * layer->size.y * layer->size.z; // usable segment length - leave 16 pixels when embedding "GEQ scan" + unsigned maxLen = (geqScanner) ? max(1, layer->size.x * layer->size.y * layer->size.z - 16) : layer->size.x * layer->size.y * layer->size.z; // usable segment length - leave 16 pixels when embedding "GEQ scan" freqLocn = roundf((log10f((float)sharedData.majorPeak) - 1.78f) * float(maxLen) / (MAX_FREQ_LOG10 - 1.78f)); // log10 frequency range is from 1.78 to 3.71. Let's scale to layer->size.x * layer->size.y * layer->size.z. // WLEDMM proper rounding if (freqLocn < 1) freqLocn = 0; // avoid underflow segLoc = (geqScanner) ? freqLocn + freqBand : freqLocn; @@ -145,7 +145,7 @@ class BlurzEffect : public Node { int bandStart = roundf(bandWidth * freqBand); segLoc = bandStart + random16(max(1, int(bandWidth))); } - segLoc = MAX(nrOfLights_t(0), MIN(nrOfLights_t(layer->size.x * layer->size.y * layer->size.z - 1), segLoc)); // fix overflows + segLoc = max(nrOfLights_t(0), MIN(nrOfLights_t(layer->size.x * layer->size.y * layer->size.z - 1), segLoc)); // fix overflows if (layer->size.x * layer->size.y * layer->size.z < 2) segLoc = 0; // WLEDMM just to be sure unsigned pixColor = (2 * sharedData.bands[freqBand] * 240) / max(1, layer->size.x * layer->size.y * layer->size.z - 1); // WLEDMM avoid uint8 overflow, and preserve pixel parameters for redraw @@ -1819,10 +1819,10 @@ class DripEffect : public Node { drops[x][j].col = sourcedrop; // brightness drops[x][j].colIndex = forming; // drop state CRGB c = ColorFromPalette(layerP.palette, random8()); // random color by MoonModules, hacked into velX of type float - memcpy(&drops[x][j].velX, &c, sizeof(CRGB)); + memcpy(&drops[x][j].velX, (void*)&c, sizeof(CRGB)); } CRGB dropColor; - memcpy(&dropColor, &drops[x][j].velX, sizeof(CRGB)); // hacked back + memcpy((void*)&dropColor, &drops[x][j].velX, sizeof(CRGB)); // hacked back layer->setRGB(Coord3D(x, 0), blend(CRGB::Black, dropColor, sourcedrop)); // water source if (drops[x][j].colIndex == forming) { diff --git a/src/MoonLight/Nodes/Modifiers/M_MoonLight.h b/src/MoonLight/Nodes/Modifiers/M_MoonLight.h index 8a5a060f..90ac44c4 100644 --- a/src/MoonLight/Nodes/Modifiers/M_MoonLight.h +++ b/src/MoonLight/Nodes/Modifiers/M_MoonLight.h @@ -294,7 +294,7 @@ class RotateModifier : public Node { void modifySize() override { if (expand) { - uint8_t size = MAX(layer->size.x, MAX(layer->size.y, layer->size.z)); + uint8_t size = max(layer->size.x, max(layer->size.y, layer->size.z)); size = sqrt(size * size * 2) + 1; Coord3D offset = Coord3D((size - layer->size.x) / 2, (size - layer->size.y) / 2, 0); @@ -310,7 +310,7 @@ class RotateModifier : public Node { void modifyPosition(Coord3D& position) override { if (expand) { - int size = MAX(modifierSize.x, MAX(modifierSize.y, modifierSize.z)); + int size = max(modifierSize.x, max(modifierSize.y, modifierSize.z)); size = sqrt(size * size * 2) + 1; Coord3D offset = Coord3D((size - modifierSize.x) / 2, (size - modifierSize.y) / 2, 0); position += offset; From 128afe0cdef4ae2fe7776c8a9938142b65e30d71 Mon Sep 17 00:00:00 2001 From: ewowi Date: Thu, 5 Feb 2026 14:33:12 +0100 Subject: [PATCH 02/11] FastLED and rabbit fixes (FastLED needs more stack!) - pio.ini: increase httpd stack 5120->6144 and drivers stack from 4096 to 5120 - FastLED: remove gpio 11 for esp32-do (part of spi flash) --- firmware/esp32-d0.ini | 3 --- lib/framework/CoreDump.cpp | 4 +++- platformio.ini | 4 ++-- src/MoonLight/Layers/VirtualLayer.cpp | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 7 ++++--- src/MoonLight/Nodes/Effects/E_MoonLight.h | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/firmware/esp32-d0.ini b/firmware/esp32-d0.ini index 2132c29b..8c8a217d 100644 --- a/firmware/esp32-d0.ini +++ b/firmware/esp32-d0.ini @@ -6,9 +6,6 @@ build_flags = ${env.build_flags} ; ${ESP32_LEDSDRIVER.build_flags} ;use the LedsDriver class only for setBrightness and setColorCorrection and LUT ${HP_ALL_DRIVERS.build_flags} ; -D ML_LIVE_MAPPING - ; -D FASTLED_RMT_BUILTIN_DRIVER=true - ; -D FASTLED_ESP32_HAS_RMT5 ; avoid flickering (on IDF 5 with WiFi) - ; -D FASTLED_RMT5=1 lib_deps = ${env.lib_deps} ${moonlight.lib_deps} ; ${livescripts.lib_deps} diff --git a/lib/framework/CoreDump.cpp b/lib/framework/CoreDump.cpp index 5667b692..ad621e29 100644 --- a/lib/framework/CoreDump.cpp +++ b/lib/framework/CoreDump.cpp @@ -19,7 +19,9 @@ #include "esp_partition.h" #include "esp_flash.h" -#define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) +#ifndef MIN // πŸŒ™ + #define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) +#endif CoreDump::CoreDump(PsychicHttpServer *server, SecurityManager *securityManager) : _server(server), diff --git a/platformio.ini b/platformio.ini index 4b8f34ba..1a39548c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -62,7 +62,7 @@ build_flags = -D FT_MOONBASE=1 - -D HTTPD_STACK_SIZE=5120 ; default 4096 but not enough for more complex read and update + -D HTTPD_STACK_SIZE=6144 ; default 4096 but not enough for more complex read and update , 5120 not enough when switching from FastLED to parallel LED driver -D SVELTEKIT_STACK_SIZE=6144 ; psramFound() ? 8 * 1024 : 6 * 1024πŸŒ™ 4096 to 8192 / 6144 ; πŸŒ™ Move ESP32SvelteKit (HTTP/WebSocket) to Core 1 (APP_CPU) to avoid WiFi preemption on Core 0 @@ -149,7 +149,7 @@ build_flags = -D FT_MOONLIGHT=1 -D FT_MONITOR=1 -D EFFECTS_STACK_SIZE=3072 ; psramFound() ? 4 * 1024 : 3 * 1024 - -D DRIVERS_STACK_SIZE=4096 ; psramFound() ? 4 * 1024 : 3 * 1024 + -D DRIVERS_STACK_SIZE=5120 ; psramFound() ? 4 * 1024 : 3 * 1024, 4096 not enough for FastLED driver ; FastLED pre-compiled settings: ; ML_CHIPSET: Used by FastLED driver.init diff --git a/src/MoonLight/Layers/VirtualLayer.cpp b/src/MoonLight/Layers/VirtualLayer.cpp index af5c59c2..a122c7f6 100644 --- a/src/MoonLight/Layers/VirtualLayer.cpp +++ b/src/MoonLight/Layers/VirtualLayer.cpp @@ -290,7 +290,7 @@ void VirtualLayer::addLight(Coord3D position) { createMappingTableAndAddOneToOne(); } - nrOfLights = max(nrOfLights, indexV + 1); + nrOfLights = max(nrOfLights, nrOfLights_t(indexV + 1)); if (!oneToOneMapping) { if (indexV < mappingTableSize) { diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index a8460eff..420de7f2 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -155,9 +155,10 @@ class FastLEDDriver : public Node { // case 8: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; // case 9: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; // case 10: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - case 11: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; + // GPIO11 (along with GPIO6–10) is part of the on-module SPI flash bus on standard ESP32 variants and cannot be used for general GPIO. + // case 11: + // FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; + // break; case 12: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; diff --git a/src/MoonLight/Nodes/Effects/E_MoonLight.h b/src/MoonLight/Nodes/Effects/E_MoonLight.h index a9d23b40..3285fb83 100644 --- a/src/MoonLight/Nodes/Effects/E_MoonLight.h +++ b/src/MoonLight/Nodes/Effects/E_MoonLight.h @@ -1610,7 +1610,7 @@ class PixelMapEffect : public Node { Coord3D pos = {0, 0, 0}; - void setup() override { addControl(pos, "pos", "coord3D", 0, max(max(layer->size.x, layer->size.x), layer->size.x) - 1); } + void setup() override { addControl(pos, "pos", "coord3D", 0, max(max(layer->size.x, layer->size.y), layer->size.z) - 1); } void loop() override { layer->fill_solid(CRGB::Black); From c2f3b98a8d59a92032c58145026b8ac8d488f67f Mon Sep 17 00:00:00 2001 From: ewowi Date: Thu, 5 Feb 2026 20:01:06 +0100 Subject: [PATCH 03/11] FastLED: Replace addLeds with FastLED.addLedChannel --- platformio.ini | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 463 ++---------------------- 2 files changed, 30 insertions(+), 435 deletions(-) diff --git a/platformio.ini b/platformio.ini index 1a39548c..16f14c70 100644 --- a/platformio.ini +++ b/platformio.ini @@ -149,7 +149,7 @@ build_flags = -D FT_MOONLIGHT=1 -D FT_MONITOR=1 -D EFFECTS_STACK_SIZE=3072 ; psramFound() ? 4 * 1024 : 3 * 1024 - -D DRIVERS_STACK_SIZE=5120 ; psramFound() ? 4 * 1024 : 3 * 1024, 4096 not enough for FastLED driver + -D DRIVERS_STACK_SIZE=4196 ; psramFound() ? 4 * 1024 : 3 * 1024 ; FastLED pre-compiled settings: ; ML_CHIPSET: Used by FastLED driver.init diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index 420de7f2..cdbf60c0 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -13,19 +13,13 @@ #if FT_MOONLIGHT - // Expand to , COLOR_ORDER if defined - #if defined(ML_COLOR_ORDER) - #define COLOR_ORDER_ARG , ML_COLOR_ORDER - #else - #define COLOR_ORDER_ARG - #endif - - // Expand to .setRgbw(RgbwDefault()) if ML_RGBW is 1 - #if ML_RGBW - #define RGBW_CALL .setRgbw(RgbwDefault()) - #else - #define RGBW_CALL - #endif +// #include "fl/channels/channel.h" +// #include "fl/channels/config.h" +// #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +// #include "platforms/esp/32/drivers/spi/channel_engine_spi.h" +// #else +// #include "platforms/esp/32/drivers/parlio/channel_engine_parlio.h" +// #endif class FastLEDDriver : public Node { public: @@ -130,436 +124,37 @@ class FastLEDDriver : public Node { CRGB* leds = (CRGB*)layerP.lights.channelsD; - switch (pins[pinIndex]) { - #if CONFIG_IDF_TARGET_ESP32 - case 0: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 1: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 2: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 3: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 4: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 5: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // case 6: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 7: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 8: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 9: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 10: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // GPIO11 (along with GPIO6–10) is part of the on-module SPI flash bus on standard ESP32 variants and cannot be used for general GPIO. - // case 11: - // FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - // break; - case 12: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 13: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 14: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 15: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #if !defined(BOARD_HAS_PSRAM) && !defined(ARDUINO_ESP32_PICO) - // 16+17 = reserved for PSRAM, or reserved for FLASH on pico-D4 - case 16: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 17: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #endif - case 18: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 19: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // case 20: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - case 21: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 22: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 23: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // case 24: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - case 25: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 26: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 27: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // case 28: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 29: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 30: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 31: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - case 32: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 33: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // 34-39 input-only - // case 34: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 35: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 36: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 37: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 38: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 39: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - #endif // CONFIG_IDF_TARGET_ESP32 + //https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md - #if CONFIG_IDF_TARGET_ESP32S2 - case 0: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 1: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 2: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 3: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 4: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 5: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 6: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 7: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 8: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 9: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 10: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 11: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 12: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 13: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 14: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 15: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 16: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 17: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 18: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #if !ARDUINO_USB_CDC_ON_BOOT - // 19 + 20 = USB HWCDC. reserved for USB port when ARDUINO_USB_CDC_ON_BOOT=1 - case 19: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 20: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #endif - case 21: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // 22 to 32: not connected, or reserved for SPI FLASH - // case 22: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 23: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 24: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 25: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - #if !defined(BOARD_HAS_PSRAM) - // 26-32 = reserved for PSRAM - case 26: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // case 27: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 28: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 29: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 30: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 31: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 32: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - #endif - case 33: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 34: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 35: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 36: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 37: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 38: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 39: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 40: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 41: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 42: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 43: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 44: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 45: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // 46 input-only - // case 46: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - #endif // CONFIG_IDF_TARGET_ESP32S2 + fl::ChipsetTimingConfig timing = fl::makeTimingConfig(); + fl::ChannelConfig config(pins[pinIndex], timing, fl::span(&leds[startLed], layerP.ledsPerPin[pinIndex]), GRB); - #if CONFIG_IDF_TARGET_ESP32C3 - case 0: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 1: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 2: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 3: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 4: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 5: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 6: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 7: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 8: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 9: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 10: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // 11-17 reserved for SPI FLASH - // case 11: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 12: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 13: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 14: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 15: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 16: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 17: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - #if !ARDUINO_USB_CDC_ON_BOOT - // 18 + 19 = USB HWCDC. reserved for USB port when ARDUINO_USB_CDC_ON_BOOT=1 - case 18: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 19: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #endif - // 20+21 = Serial RX+TX --> don't use for LEDS when serial-to-USB is needed - case 20: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 21: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #endif // CONFIG_IDF_TARGET_ESP32S2 - - #ifdef CONFIG_IDF_TARGET_ESP32S3 - case 0: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 1: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 2: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 3: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 4: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 5: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 6: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 7: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 8: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 9: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 10: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 11: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 12: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 13: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 14: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 15: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 16: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 17: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 18: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #if !ARDUINO_USB_CDC_ON_BOOT - // 19 + 20 = USB-JTAG. Not recommended for other uses. - // case 19: - // FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - // break; - // case 20: - // FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - // break; - #endif - case 21: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // // 22 to 32: not connected, or SPI FLASH - // case 22: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 23: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 24: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 25: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 26: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 27: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 28: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 29: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 30: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 31: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - // case 32: FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; break; - #if !defined(BOARD_HAS_PSRAM) - // 33 to 37: reserved if using _octal_ SPI Flash or _octal_ PSRAM - case 33: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 34: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 35: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 36: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 37: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #endif - case 38: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 39: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 40: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 41: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 42: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - // 43+44 = Serial RX+TX --> don't use for LEDS when serial-to-USB is needed - case 43: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 44: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 45: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 46: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 47: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - case 48: - FastLED.addLeds(leds, startLed, nrOfLights).setCorrection(TypicalLEDStrip) RGBW_CALL; - break; - #endif // CONFIG_IDF_TARGET_ESP32S3 + // Create channel with specific engine type + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + // fl::ChannelPtr channel = fl::Channel::create(config); + fl::ChannelPtr channel = fl::Channel::create(config); + FastLED.setExclusiveDriver("SPI"); + #else + // auto channel = fl::Channel::create(config); + fl::ChannelPtr channel = fl::Channel::create(config); + FastLED.setExclusiveDriver("PARLIO"); + #endif - default: - EXT_LOGW(ML_TAG, "FastLEDPin assignment: pin not supported %d", pins[pinIndex]); - } // switch pins[pinIndex] + // Register with FastLED + FastLED.addLedChannel(channel); startLed += layerP.ledsPerPin[pinIndex]; } // for pinIndex < nrOfPins } + // Check which drivers are available + for (size_t i = 0; i < FastLED.getDriverCount(); i++) { + auto drivers = FastLED.getDriverInfos(); + auto& info = drivers[i]; + EXT_LOGD(ML_TAG, "Driver: %s, Priority: %d, Enabled: %s", info.name.c_str(), info.priority, info.enabled ? "yes" : "no"); + } + FastLED.setMaxPowerInMilliWatts(1000 * layerP.maxPower); // 5v, 2000mA, to protect usb while developing } }; From c1d9c9a30d92927708f00dad8583bcdc7264ee13 Mon Sep 17 00:00:00 2001 From: ewowi Date: Sat, 7 Feb 2026 22:21:59 +0100 Subject: [PATCH 04/11] Latest FastLED (cleanup, FastLED.add), CarLightsLayout adjustments pio.ini / esp32-S3.ini / D-FastLED.h: cleanup old FastLED directives, include latest FastLED Layouts: correct CarLightsLayout --- firmware/esp32-s3.ini | 5 +- platformio.ini | 12 +--- src/MoonLight/Nodes/Drivers/D_FastLED.h | 81 +++++++++++------------ src/MoonLight/Nodes/Layouts/L_MoonLight.h | 14 ++-- 4 files changed, 49 insertions(+), 63 deletions(-) diff --git a/firmware/esp32-s3.ini b/firmware/esp32-s3.ini index d4863102..5a6a8164 100644 --- a/firmware/esp32-s3.ini +++ b/firmware/esp32-s3.ini @@ -10,14 +10,11 @@ build_flags = ; -D ARDUINO_USB_MSC_ON_BOOT=0 ;Mass Storage Class, disable ; -D ARDUINO_USB_DFU_ON_BOOT=0 ;download firmware update, disable ; -D ML_LIVE_MAPPING - ; Do not use the following FastLED settings! As we use the better version of this in Parallel LED Driverer - ; -D FASTLED_USES_ESP32S3_I2S ; S3 boards use the I2S driver (RMT is not supporting more then 4 outputs) - ; -DCOLOR_ORDER_RGB=1 ; not working yet, see also https://github.com/FastLED/FastLED/issues/1966, should use ML_COLOR_ORDER / FastLED.addLeds(RGB_ORDER), workaround change #define COLOR_ORDER_RBG in driver.h lib_deps = ${env.lib_deps} ${moonlight.lib_deps} ${livescripts.lib_deps} - ${HP_ALL_DRIVERS.lib_deps} ; FASTLED_USES_ESP32S3_I2S instead! + ${HP_ALL_DRIVERS.lib_deps} diff --git a/platformio.ini b/platformio.ini index 16f14c70..8e6f6b50 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,7 +56,7 @@ build_flags = -D BUILD_TARGET=\"$PIOENV\" -D APP_NAME=\"MoonLight\" ; πŸŒ™ Must only contain characters from [a-zA-Z0-9-_] as this is converted into a filename -D APP_VERSION=\"0.8.1\" ; semver compatible version string - -D APP_DATE=\"20260204\" ; πŸŒ™ + -D APP_DATE=\"20260207\" ; πŸŒ™ -D PLATFORM_VERSION=\"pioarduino-55.03.35\" ; πŸŒ™ make sure it matches with above plaftform @@ -151,15 +151,9 @@ build_flags = -D EFFECTS_STACK_SIZE=3072 ; psramFound() ? 4 * 1024 : 3 * 1024 -D DRIVERS_STACK_SIZE=4196 ; psramFound() ? 4 * 1024 : 3 * 1024 - ; FastLED pre-compiled settings: - ; ML_CHIPSET: Used by FastLED driver.init - -D ML_CHIPSET=WS2812B ; RGB, for fairy lights or https://www.waveshare.com/wiki/ESP32-S3-Matrix - ; -D ML_CHIPSET=APA106 ; for Cube202020 / some fairy curtain strings do not work with WS2812B - ; -D ML_CHIPSET=SK6812 ; 🚧 - -D ML_COLOR_ORDER=GRB ; define your color order here if needed (why WS2812 has GRB instead of RGB?) Only for FastLED, PD software configurable - ; -D ML_RGBW=1 ; define whether to enable RGBW (1 = yes, 0 = no) ... could be derived from ML_CHIPSET??? + ; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp lib_deps = - https://github.com/FastLED/FastLED#8b4fd586ba38a6c3b67ce94f78d68e77aa505fa5 + https://github.com/FastLED/FastLED#f413fee79300bb0e173e9e737aea57b32b0c371c ; master 20260207 https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104) ; πŸ’« currently only enabled on s3 as esp32dev runs over 100% diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index cdbf60c0..32209c8e 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -27,27 +27,11 @@ class FastLEDDriver : public Node { static uint8_t dim() { return _NoD; } static const char* tags() { return "☸️"; } - char chipSet[20] = TOSTRING(ML_CHIPSET); char version[20] = TOSTRING(FASTLED_VERSION); // "." TOSTRING(FASTLED_VERSION_MINOR) "." TOSTRING(FASTLED_VERSION_PATCH); - char colorOrder[20] = TOSTRING(ML_COLOR_ORDER); - #if FASTLED_USES_ESP32S3_I2S - bool usesI2S = true; - #else - bool usesI2S = false; - #endif - #if FASTLED_RMT5 - bool usesRMT5 = true; - #else - bool usesRMT5 = false; - #endif Char<32> status = "ok"; void setup() override { addControl(version, "version", "text", 0, 20, true); - addControl(chipSet, "chipSet", "text", 0, 20, true); - addControl(colorOrder, "colorOrder", "text", 0, 20, true); - addControl(usesI2S, "usesI2S", "checkbox", 0, 20, true); - addControl(usesRMT5, "usesRMT5", "checkbox", 0, 20, true); addControl(status, "status", "text", 0, 32, true); } @@ -69,7 +53,6 @@ class FastLEDDriver : public Node { CRGB correction = CRGB(layerP.lights.header.red, layerP.lights.header.green, layerP.lights.header.blue); CLEDController* pCur = CLEDController::head(); while (pCur) { - // ++x; if (pCur->getCorrection() != correction) { EXT_LOGD(ML_TAG, "setColorCorrection r:%d, g:%d, b:%d (#:%d)", layerP.lights.header.red, layerP.lights.header.green, layerP.lights.header.blue, pCur->size()); pCur->setCorrection(correction); @@ -116,43 +99,57 @@ class FastLEDDriver : public Node { updateControl("status", statusString.c_str()); moduleNodes->requestUIUpdate = true; + // https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md + fl::ChipsetTimingConfig timing = fl::makeTimingConfig(); + CRGB* leds = (CRGB*)layerP.lights.channelsD; uint16_t startLed = 0; - for (uint8_t pinIndex = 0; pinIndex < nrOfPins; pinIndex++) { - EXT_LOGD(ML_TAG, "ledPin s:%d #:%d p:%d", pinIndex, layerP.ledsPerPin[pinIndex]); - - uint16_t nrOfLights = layerP.ledsPerPin[pinIndex]; - - CRGB* leds = (CRGB*)layerP.lights.channelsD; - - //https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + FastLED.setExclusiveDriver("I2S"); + #else + FastLED.setExclusiveDriver("PARLIO"); + #endif - fl::ChipsetTimingConfig timing = fl::makeTimingConfig(); - fl::ChannelConfig config(pins[pinIndex], timing, fl::span(&leds[startLed], layerP.ledsPerPin[pinIndex]), GRB); + for (uint8_t pinIndex = 0; pinIndex < nrOfPins; pinIndex++) { + EXT_LOGD(ML_TAG, "ledPin p:%d #:%d", pins[pinIndex], layerP.ledsPerPin[pinIndex]); - // Create channel with specific engine type + fl::ChannelOptions options; #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - // fl::ChannelPtr channel = fl::Channel::create(config); - fl::ChannelPtr channel = fl::Channel::create(config); - FastLED.setExclusiveDriver("SPI"); + options.mAffinity = "I2S"; #else - // auto channel = fl::Channel::create(config); - fl::ChannelPtr channel = fl::Channel::create(config); - FastLED.setExclusiveDriver("PARLIO"); + options.mAffinity = "PARLIO"; #endif - // Register with FastLED - FastLED.addLedChannel(channel); + fl::ChannelConfig config(pins[pinIndex], timing, fl::span(&leds[startLed], layerP.ledsPerPin[pinIndex]), GRB, options); + fl::ChannelPtr channel = fl::Channel::create(config); + + FastLED.add(channel); + + // FastLED.addLeds(leds, layerP.ledsPerPin[pinIndex]); this works!!! (but this is static) startLed += layerP.ledsPerPin[pinIndex]; + CLEDController* pCur = CLEDController::head(); + EXT_LOGD(ML_TAG, "controller p:%p", pCur); + while (pCur) { + EXT_LOGD(ML_TAG, "controller %d", pCur->size()); + pCur = pCur->next(); + } + } // for pinIndex < nrOfPins - } - // Check which drivers are available - for (size_t i = 0; i < FastLED.getDriverCount(); i++) { - auto drivers = FastLED.getDriverInfos(); - auto& info = drivers[i]; - EXT_LOGD(ML_TAG, "Driver: %s, Priority: %d, Enabled: %s", info.name.c_str(), info.priority, info.enabled ? "yes" : "no"); + // Check which drivers are available + for (size_t i = 0; i < FastLED.getDriverCount(); i++) { + auto drivers = FastLED.getDriverInfos(); + auto& info = drivers[i]; + EXT_LOGD(ML_TAG, "Driver: %s, Priority: %d, Enabled: %s", info.name.c_str(), info.priority, info.enabled ? "yes" : "no"); + } + + CLEDController* pCur = CLEDController::head(); + EXT_LOGD(ML_TAG, "controller p:%p", pCur); + while (pCur) { + EXT_LOGD(ML_TAG, "controller %d", pCur->size()); + pCur = pCur->next(); + } } FastLED.setMaxPowerInMilliWatts(1000 * layerP.maxPower); // 5v, 2000mA, to protect usb while developing diff --git a/src/MoonLight/Nodes/Layouts/L_MoonLight.h b/src/MoonLight/Nodes/Layouts/L_MoonLight.h index 52c25cf9..0f9bef5f 100644 --- a/src/MoonLight/Nodes/Layouts/L_MoonLight.h +++ b/src/MoonLight/Nodes/Layouts/L_MoonLight.h @@ -539,10 +539,8 @@ class Rings16Layout : public Node { static const char* tags() { return "πŸš₯"; } uint8_t scale = 1; - - void setup() override { - addControl(scale, "scale", "slider", 1, 10); - } + + void setup() override { addControl(scale, "scale", "slider", 1, 10); } bool hasOnLayout() const override { return true; } @@ -658,7 +656,7 @@ class CarLightsLayout : public Node { uint8_t leftMargin = 9; // inner light left - ringLayout.ringCenter = {leftMargin + 11, 10, 0}; + ringLayout.ringCenter = {leftMargin + 11, 8, 0}; ringLayout.nrOfLEDs = 1; ringLayout.onLayout(); ringLayout.nrOfLEDs = 8; @@ -682,13 +680,13 @@ class CarLightsLayout : public Node { ringLayout.onLayout(); ringLayout.nrOfLEDs = 24; ringLayout.onLayout(); - ringLayout.nrOfLEDs = 34; + ringLayout.nrOfLEDs = 32; ringLayout.onLayout(); nextPin(); // inner light right - ringLayout.ringCenter = {leftMargin + 25, 10, 0}; + ringLayout.ringCenter = {leftMargin + 25, 8, 0}; ringLayout.nrOfLEDs = 1; ringLayout.onLayout(); ringLayout.nrOfLEDs = 8; @@ -712,7 +710,7 @@ class CarLightsLayout : public Node { ringLayout.onLayout(); ringLayout.nrOfLEDs = 24; ringLayout.onLayout(); - ringLayout.nrOfLEDs = 34; + ringLayout.nrOfLEDs = 32; ringLayout.onLayout(); nextPin(); From 589443a25e0f24593894555fdbdbafb63601d2d1 Mon Sep 17 00:00:00 2001 From: ewowi Date: Sun, 8 Feb 2026 11:54:46 +0100 Subject: [PATCH 05/11] FastLED driver controls FastLED driver - DriverNode subclass (lightsPreset control) - add affinity and temperature control - onUpdate lightPreset, affinity and temperature - Destructor removing channels - WIP --- platformio.ini | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 184 ++++++++++++++++++++---- 2 files changed, 159 insertions(+), 27 deletions(-) diff --git a/platformio.ini b/platformio.ini index 8e6f6b50..62e4db50 100644 --- a/platformio.ini +++ b/platformio.ini @@ -149,7 +149,7 @@ build_flags = -D FT_MOONLIGHT=1 -D FT_MONITOR=1 -D EFFECTS_STACK_SIZE=3072 ; psramFound() ? 4 * 1024 : 3 * 1024 - -D DRIVERS_STACK_SIZE=4196 ; psramFound() ? 4 * 1024 : 3 * 1024 + -D DRIVERS_STACK_SIZE=4096 ; psramFound() ? 4 * 1024 : 3 * 1024, 4096 is sufficient for now ; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp lib_deps = diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index 32209c8e..2f437e38 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -13,15 +13,7 @@ #if FT_MOONLIGHT -// #include "fl/channels/channel.h" -// #include "fl/channels/config.h" -// #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 -// #include "platforms/esp/32/drivers/spi/channel_engine_spi.h" -// #else -// #include "platforms/esp/32/drivers/parlio/channel_engine_parlio.h" -// #endif - -class FastLEDDriver : public Node { +class FastLEDDriver : public DriverNode { public: static const char* name() { return "FastLED Driver"; } static uint8_t dim() { return _NoD; } @@ -29,12 +21,157 @@ class FastLEDDriver : public Node { char version[20] = TOSTRING(FASTLED_VERSION); // "." TOSTRING(FASTLED_VERSION_MINOR) "." TOSTRING(FASTLED_VERSION_PATCH); Char<32> status = "ok"; + #if CONFIG_IDF_TARGET_ESP32S3 + uint8_t affinity = 2; // I2S + #elif CONFIG_IDF_TARGET_ESP32P4 + uint8_t affinity = 4; // parlio + #else + uint8_t affinity = 0; // auto + #endif + uint8_t temperature = 0; void setup() override { + DriverNode::setup(); // !! + + addControl(affinity, "affinity", "select"); + addControlValue("Auto"); + addControlValue("RMT"); + addControlValue("I2S"); + addControlValue("SPI"); + #if CONFIG_IDF_TARGET_ESP32P4 + addControlValue("Parlio"); + #endif + + addControl(temperature, "temperature", "select"); + addControlValue("Uncorrected"); + addControlValue("Candle"); + addControlValue("Tungsten100W"); + addControlValue("Halogen"); + addControl(version, "version", "text", 0, 20, true); addControl(status, "status", "text", 0, 32, true); } + fl::EOrder rgbOrder; + fl::ChannelOptions options; + + void onUpdate(const Char<20>& oldValue, const JsonObject& control) override { + DriverNode::onUpdate(oldValue, control); // !! + + LightsHeader* header = &layerP.lights.header; + + EXT_LOGD(ML_TAG, "%s: %s ", control["name"].as(), control["value"].as().c_str()); + + if (control["name"] == "lightPreset") { + switch (layerP.lights.header.lightPreset) { + case lightPreset_RGB: + rgbOrder = RGB; + break; + case lightPreset_RBG: + rgbOrder = RBG; + break; + case lightPreset_GRB: + rgbOrder = GRB; + break; + case lightPreset_GBR: + rgbOrder = GBR; + break; + case lightPreset_BRG: + rgbOrder = BRG; + break; + case lightPreset_BGR: + rgbOrder = BGR; + break; + case lightPreset_RGBW: + rgbOrder = RGB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W3; + break; + case lightPreset_GRBW: + rgbOrder = GRB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W3; + break; + case lightPreset_WRGB: + rgbOrder = RGB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W0; + break; + case lightPreset_GRB6: + rgbOrder = GRB; + break; + case lightPreset_RGB2040: + // RGB2040 uses standard RGB offsets but has special channel remapping + // for dual-channel-group architecture (handled in VirtualLayer) + rgbOrder = RGB; + break; + case lightPreset_RGBWYP: + rgbOrder = RGB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W3; + break; + case lightPreset_MHBeeEyes150W15: + rgbOrder = RGB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W3; + break; + case lightPreset_MHBeTopper19x15W32: + rgbOrder = RGB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W3; + break; + case lightPreset_MH19x15W24: + rgbOrder = RGB; + options.mRgbw.rgbw_mode = kRGBWExactColors; + options.mRgbw.w_placement = W3; + break; + default: + rgbOrder = GRB; + break; + } + } + + if (control["name"] == "affinity") { + switch (control["value"].as()) { + case 0: + options.mAffinity = ""; + break; // auto + case 1: + options.mAffinity = "RMT"; + break; + case 2: + options.mAffinity = "I2S"; + break; + case 3: + options.mAffinity = "SPI"; + break; + case 4: + options.mAffinity = "PARLIO"; + break; + } + FastLED.setExclusiveDriver(options.mAffinity.c_str()); + + if (control["name"] == "temperature") { + switch (control["value"].as()) { + case 0: + options.mTemperature = UncorrectedTemperature; + break; + case 1: + options.mTemperature = Candle; + break; + case 2: + options.mTemperature = Tungsten100W; + break; + case 3: + options.mTemperature = Halogen; + break; + } + } + + options.mCorrection = TypicalLEDStrip; // gamma ... + } + } + uint16_t savedMaxPower = UINT16_MAX; void loop() override { if (FastLED.count()) { @@ -103,43 +240,31 @@ class FastLEDDriver : public Node { fl::ChipsetTimingConfig timing = fl::makeTimingConfig(); CRGB* leds = (CRGB*)layerP.lights.channelsD; uint16_t startLed = 0; - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - FastLED.setExclusiveDriver("I2S"); - #else - FastLED.setExclusiveDriver("PARLIO"); - #endif for (uint8_t pinIndex = 0; pinIndex < nrOfPins; pinIndex++) { EXT_LOGD(ML_TAG, "ledPin p:%d #:%d", pins[pinIndex], layerP.ledsPerPin[pinIndex]); - fl::ChannelOptions options; - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - options.mAffinity = "I2S"; - #else - options.mAffinity = "PARLIO"; - #endif - - fl::ChannelConfig config(pins[pinIndex], timing, fl::span(&leds[startLed], layerP.ledsPerPin[pinIndex]), GRB, options); + fl::ChannelConfig config(pins[pinIndex], timing, fl::span(&leds[startLed], layerP.ledsPerPin[pinIndex]), rgbOrder, options); fl::ChannelPtr channel = fl::Channel::create(config); FastLED.add(channel); - // FastLED.addLeds(leds, layerP.ledsPerPin[pinIndex]); this works!!! (but this is static) + // FastLED.addLeds(leds, layerP.ledsPerPin[pinIndex]); // this works!!! (but this is static) startLed += layerP.ledsPerPin[pinIndex]; CLEDController* pCur = CLEDController::head(); EXT_LOGD(ML_TAG, "controller p:%p", pCur); while (pCur) { - EXT_LOGD(ML_TAG, "controller %d", pCur->size()); + EXT_LOGD(ML_TAG, "controller %d %d", pCur->size(), pCur->getEnabled()); pCur = pCur->next(); } } // for pinIndex < nrOfPins // Check which drivers are available + auto drivers = FastLED.getDriverInfos(); for (size_t i = 0; i < FastLED.getDriverCount(); i++) { - auto drivers = FastLED.getDriverInfos(); auto& info = drivers[i]; EXT_LOGD(ML_TAG, "Driver: %s, Priority: %d, Enabled: %s", info.name.c_str(), info.priority, info.enabled ? "yes" : "no"); } @@ -147,13 +272,20 @@ class FastLEDDriver : public Node { CLEDController* pCur = CLEDController::head(); EXT_LOGD(ML_TAG, "controller p:%p", pCur); while (pCur) { - EXT_LOGD(ML_TAG, "controller %d", pCur->size()); + EXT_LOGD(ML_TAG, "controller %d %d", pCur->size(), pCur->getEnabled()); pCur = pCur->next(); } } FastLED.setMaxPowerInMilliWatts(1000 * layerP.maxPower); // 5v, 2000mA, to protect usb while developing } + + ~FastLEDDriver() override { + // for (auto channel: channels) + { + // FastLED.remove(channel); + } + } }; #endif \ No newline at end of file From f4d90a5e7f1ce26b8501270caf87374fab769c8b Mon Sep 17 00:00:00 2001 From: ewowi Date: Sun, 8 Feb 2026 12:45:28 +0100 Subject: [PATCH 06/11] Add correction and dither controls --- src/MoonLight/Nodes/Drivers/D_FastLED.h | 66 +++++++++++++++++-------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index 2f437e38..866ff30f 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -29,6 +29,8 @@ class FastLEDDriver : public DriverNode { uint8_t affinity = 0; // auto #endif uint8_t temperature = 0; + bool correction = 0; + bool dither = false; void setup() override { DriverNode::setup(); // !! @@ -48,11 +50,18 @@ class FastLEDDriver : public DriverNode { addControlValue("Tungsten100W"); addControlValue("Halogen"); + addControl(correction, "correction", "select"); + addControlValue("Uncorrected"); + addControlValue("Typical LED"); + addControlValue("Typical SMD5050"); + + addControl(dither, "dither", "checkbox"); + addControl(version, "version", "text", 0, 20, true); addControl(status, "status", "text", 0, 32, true); } - fl::EOrder rgbOrder; + fl::EOrder rgbOrder = GRB; fl::ChannelOptions options; void onUpdate(const Char<20>& oldValue, const JsonObject& control) override { @@ -131,11 +140,11 @@ class FastLEDDriver : public DriverNode { } } - if (control["name"] == "affinity") { + else if (control["name"] == "affinity") { switch (control["value"].as()) { - case 0: + case 0: // auto options.mAffinity = ""; - break; // auto + break; case 1: options.mAffinity = "RMT"; break; @@ -150,25 +159,41 @@ class FastLEDDriver : public DriverNode { break; } FastLED.setExclusiveDriver(options.mAffinity.c_str()); + } - if (control["name"] == "temperature") { - switch (control["value"].as()) { - case 0: - options.mTemperature = UncorrectedTemperature; - break; - case 1: - options.mTemperature = Candle; - break; - case 2: - options.mTemperature = Tungsten100W; - break; - case 3: - options.mTemperature = Halogen; - break; - } + else if (control["name"] == "temperature") { + switch (control["value"].as()) { + case 0: + options.mTemperature = UncorrectedTemperature; + break; + case 1: + options.mTemperature = Candle; + break; + case 2: + options.mTemperature = Tungsten100W; + break; + case 3: + options.mTemperature = Halogen; + break; } + } + + else if (control["name"] == "correction") { + switch (control["value"].as()) { + case 0: + options.mCorrection = UncorrectedColor; + break; + case 1: + options.mCorrection = TypicalLEDStrip; + break; + case 2: + options.mCorrection = TypicalSMD5050; + break; + } + } - options.mCorrection = TypicalLEDStrip; // gamma ... + else if (control["name"] == "dither") { + options.mDitherMode = control["value"].as() ? BINARY_DITHER : DISABLE_DITHER; } } @@ -281,6 +306,7 @@ class FastLEDDriver : public DriverNode { } ~FastLEDDriver() override { + // TODO // for (auto channel: channels) { // FastLED.remove(channel); From 449d342d02845a0a96d1f8f7d41f12f724a8149b Mon Sep 17 00:00:00 2001 From: ewowi Date: Sun, 8 Feb 2026 21:19:31 +0100 Subject: [PATCH 07/11] FastLED tweaks : working now! pio.ini: latest FastLED master commit FastLED driver - affinity auto per default - addUpdateHandler - WIP - remove setExclusiveDriver - add channels variable - max pins 4 only for RMT - remove all channels during onLayout and destructor --- platformio.ini | 2 +- src/MoonLight/Nodes/Drivers/D_ArtnetOut.h | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 68 +++++++++++++++++------ 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/platformio.ini b/platformio.ini index 62e4db50..75641562 100644 --- a/platformio.ini +++ b/platformio.ini @@ -153,7 +153,7 @@ build_flags = ; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp lib_deps = - https://github.com/FastLED/FastLED#f413fee79300bb0e173e9e737aea57b32b0c371c ; master 20260207 + https://github.com/FastLED/FastLED#b16da863b0bd34df481177b207c998730f112afe ; master 20260208 https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104) ; πŸ’« currently only enabled on s3 as esp32dev runs over 100% diff --git a/src/MoonLight/Nodes/Drivers/D_ArtnetOut.h b/src/MoonLight/Nodes/Drivers/D_ArtnetOut.h index 0c33b0ae..689e9427 100644 --- a/src/MoonLight/Nodes/Drivers/D_ArtnetOut.h +++ b/src/MoonLight/Nodes/Drivers/D_ArtnetOut.h @@ -127,7 +127,7 @@ class ArtNetOutDriver : public DriverNode { TickType_t xLastWakeTime = xTaskGetTickCount(); void loop() override { - DriverNode::loop(); + DriverNode::loop(); // this populates the LUT tables LightsHeader* header = &layerP.lights.header; diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index 866ff30f..c9bf74e4 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -21,13 +21,13 @@ class FastLEDDriver : public DriverNode { char version[20] = TOSTRING(FASTLED_VERSION); // "." TOSTRING(FASTLED_VERSION_MINOR) "." TOSTRING(FASTLED_VERSION_PATCH); Char<32> status = "ok"; - #if CONFIG_IDF_TARGET_ESP32S3 - uint8_t affinity = 2; // I2S - #elif CONFIG_IDF_TARGET_ESP32P4 - uint8_t affinity = 4; // parlio - #else + // #if CONFIG_IDF_TARGET_ESP32S3 + // uint8_t affinity = 2; // I2S + // #elif CONFIG_IDF_TARGET_ESP32P4 + // uint8_t affinity = 4; // parlio + // #else uint8_t affinity = 0; // auto - #endif + // #endif uint8_t temperature = 0; bool correction = 0; bool dither = false; @@ -59,19 +59,34 @@ class FastLEDDriver : public DriverNode { addControl(version, "version", "text", 0, 20, true); addControl(status, "status", "text", 0, 32, true); + + moduleIO->addUpdateHandler( + [this](const String& originId) { + uint8_t nrOfPins = MIN(layerP.nrOfLedPins, layerP.nrOfAssignedPins); + + EXT_LOGD(ML_TAG, "recreate channels and configs %s %d", originId.c_str(), nrOfPins); + // do something similar as in destructor: delete existing channels + // do something similar as in onLayout: create new channels + + // should we check here for maxPower changes? + }, + false); + moduleControl->addUpdateHandler([this](const String& originId) { + // brightness changes here? + }); } fl::EOrder rgbOrder = GRB; - fl::ChannelOptions options; + fl::ChannelOptions options = fl::ChannelOptions(); void onUpdate(const Char<20>& oldValue, const JsonObject& control) override { DriverNode::onUpdate(oldValue, control); // !! - LightsHeader* header = &layerP.lights.header; - EXT_LOGD(ML_TAG, "%s: %s ", control["name"].as(), control["value"].as().c_str()); if (control["name"] == "lightPreset") { + options.mRgbw = RgbwInvalid::value(); // Reset RGBW options so RGB-only presets don't inherit stale W config + switch (layerP.lights.header.lightPreset) { case lightPreset_RGB: rgbOrder = RGB; @@ -158,7 +173,7 @@ class FastLEDDriver : public DriverNode { options.mAffinity = "PARLIO"; break; } - FastLED.setExclusiveDriver(options.mAffinity.c_str()); + // FastLED.setExclusiveDriver(options.mAffinity.c_str()); } else if (control["name"] == "temperature") { @@ -199,6 +214,8 @@ class FastLEDDriver : public DriverNode { uint16_t savedMaxPower = UINT16_MAX; void loop() override { + // DriverNode::loop(); // no need to call this as FastLED is not using ledsDriver LUT tables ... + if (FastLED.count()) { if (FastLED.getBrightness() != layerP.lights.header.brightness) { EXT_LOGD(ML_TAG, "setBrightness %d", layerP.lights.header.brightness); @@ -227,10 +244,14 @@ class FastLEDDriver : public DriverNode { } } + fl::vector channels; + bool hasOnLayout() const override { return true; } void onLayout() override { if (layerP.pass == 1 && !layerP.monitorPass) { - uint8_t nrOfPins = MIN(MIN(layerP.nrOfLedPins, layerP.nrOfAssignedPins), 4); // FastLED RMT supports max 4 pins! + uint8_t nrOfPins = MIN(layerP.nrOfLedPins, layerP.nrOfAssignedPins); + + if (affinity == 1 && nrOfPins > 4) nrOfPins == 4; // FastLED RMT supports max 4 pins!, what about SPI? if (nrOfPins == 0) return; @@ -266,13 +287,22 @@ class FastLEDDriver : public DriverNode { CRGB* leds = (CRGB*)layerP.lights.channelsD; uint16_t startLed = 0; + for (fl::ChannelPtr* channel = channels.begin(); channel != channels.end();) { + EXT_LOGD(ML_TAG, "remove channel"); + FastLED.remove(*channel); + channels.erase(channel); + continue; + ++channel; + } + for (uint8_t pinIndex = 0; pinIndex < nrOfPins; pinIndex++) { - EXT_LOGD(ML_TAG, "ledPin p:%d #:%d", pins[pinIndex], layerP.ledsPerPin[pinIndex]); + EXT_LOGD(ML_TAG, "ledPin p:%d #:%d rgb:%d aff:%s", pins[pinIndex], layerP.ledsPerPin[pinIndex], rgbOrder, options.mAffinity.c_str()); fl::ChannelConfig config(pins[pinIndex], timing, fl::span(&leds[startLed], layerP.ledsPerPin[pinIndex]), rgbOrder, options); fl::ChannelPtr channel = fl::Channel::create(config); FastLED.add(channel); + channels.push_back(channel); // FastLED.addLeds(leds, layerP.ledsPerPin[pinIndex]); // this works!!! (but this is static) @@ -302,15 +332,17 @@ class FastLEDDriver : public DriverNode { } } - FastLED.setMaxPowerInMilliWatts(1000 * layerP.maxPower); // 5v, 2000mA, to protect usb while developing + // FastLED.setMaxPowerInMilliWatts(1000 * layerP.maxPower); // 5v, 2000mA, to protect usb while developing } ~FastLEDDriver() override { - // TODO - // for (auto channel: channels) - { - // FastLED.remove(channel); - } + for (fl::ChannelPtr* channel = channels.begin(); channel != channels.end();) { + EXT_LOGD(ML_TAG, "remove channel"); + FastLED.remove(*channel); + channels.erase(channel); + continue; + ++channel; + } } }; From ad0d6fa421a6cbdf8dabda7c643ba840b774df32 Mon Sep 17 00:00:00 2001 From: ewowi Date: Mon, 9 Feb 2026 00:01:48 +0100 Subject: [PATCH 08/11] Latest FastLED master, tweaks --- platformio.ini | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/platformio.ini b/platformio.ini index 75641562..1144f79d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -153,7 +153,7 @@ build_flags = ; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp lib_deps = - https://github.com/FastLED/FastLED#b16da863b0bd34df481177b207c998730f112afe ; master 20260208 + https://github.com/FastLED/FastLED#f766d23185856612a15bcb70e5fadf625fde30a1 ; master 20260208 https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104) ; πŸ’« currently only enabled on s3 as esp32dev runs over 100% diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index c9bf74e4..d1f5dd37 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -251,7 +251,7 @@ class FastLEDDriver : public DriverNode { if (layerP.pass == 1 && !layerP.monitorPass) { uint8_t nrOfPins = MIN(layerP.nrOfLedPins, layerP.nrOfAssignedPins); - if (affinity == 1 && nrOfPins > 4) nrOfPins == 4; // FastLED RMT supports max 4 pins!, what about SPI? + if (affinity == 1 && nrOfPins > 4) nrOfPins = 4; // FastLED RMT supports max 4 pins!, what about SPI? if (nrOfPins == 0) return; @@ -287,13 +287,11 @@ class FastLEDDriver : public DriverNode { CRGB* leds = (CRGB*)layerP.lights.channelsD; uint16_t startLed = 0; - for (fl::ChannelPtr* channel = channels.begin(); channel != channels.end();) { + for (auto channel : channels) { EXT_LOGD(ML_TAG, "remove channel"); - FastLED.remove(*channel); - channels.erase(channel); - continue; - ++channel; + FastLED.remove(channel); } + channels.clear(); for (uint8_t pinIndex = 0; pinIndex < nrOfPins; pinIndex++) { EXT_LOGD(ML_TAG, "ledPin p:%d #:%d rgb:%d aff:%s", pins[pinIndex], layerP.ledsPerPin[pinIndex], rgbOrder, options.mAffinity.c_str()); @@ -304,6 +302,9 @@ class FastLEDDriver : public DriverNode { FastLED.add(channel); channels.push_back(channel); + fl::IChannelEngine* engine = channel->getChannelEngine(); + EXT_LOGD(ML_TAG, "Resolved engine: %s", engine->getName().c_str()); + // FastLED.addLeds(leds, layerP.ledsPerPin[pinIndex]); // this works!!! (but this is static) startLed += layerP.ledsPerPin[pinIndex]; @@ -336,13 +337,11 @@ class FastLEDDriver : public DriverNode { } ~FastLEDDriver() override { - for (fl::ChannelPtr* channel = channels.begin(); channel != channels.end();) { - EXT_LOGD(ML_TAG, "remove channel"); - FastLED.remove(*channel); - channels.erase(channel); - continue; - ++channel; - } + for (auto channel : channels) { + EXT_LOGD(ML_TAG, "remove channel"); + FastLED.remove(channel); + } + channels.clear(); } }; From 1d14391aa8633b2eab209ff5ce72368503215d03 Mon Sep 17 00:00:00 2001 From: ewowi Date: Mon, 9 Feb 2026 10:08:08 +0100 Subject: [PATCH 09/11] latest FastLED, min -> MIN, max -> MAX to avoid ambiguity pio.ini: latest FastLED min -> MIN, max -> MAX Uitilities: add MIN and MAX --- lib/framework/WiFiSettingsService.h | 2 +- platformio.ini | 2 +- src/MoonBase/Module.cpp | 4 +-- src/MoonBase/Utilities.h | 11 +++++- src/MoonLight/Layers/VirtualLayer.cpp | 2 +- src/MoonLight/Layers/VirtualLayer.h | 2 +- src/MoonLight/Modules/ModuleLightsControl.h | 2 +- src/MoonLight/Nodes/Drivers/D_ArtnetIn.h | 6 ++-- src/MoonLight/Nodes/Drivers/D_FastLED.h | 14 ++------ src/MoonLight/Nodes/Drivers/D_Infrared.h | 30 ++++++++-------- .../Nodes/Drivers/D_ParallelLEDDriver.h | 4 +-- src/MoonLight/Nodes/Effects/E_MoonLight.h | 26 +++++++------- src/MoonLight/Nodes/Effects/E_MoonModules.h | 6 ++-- src/MoonLight/Nodes/Effects/E_WLED.h | 36 ++++++++++--------- src/MoonLight/Nodes/Modifiers/M_MoonLight.h | 6 ++-- 15 files changed, 77 insertions(+), 76 deletions(-) diff --git a/lib/framework/WiFiSettingsService.h b/lib/framework/WiFiSettingsService.h index c28f1db3..24840114 100644 --- a/lib/framework/WiFiSettingsService.h +++ b/lib/framework/WiFiSettingsService.h @@ -92,7 +92,7 @@ class WiFiSettings root["hostname"] = settings.hostname; root["connection_mode"] = settings.staConnectionMode; root["txPower"] = settings.txPower;//(uint8_t )WiFi.getTxPower(); - root["txPowerMeasured"] = abs(WiFi.getTxPower()); + root["txPowerMeasured"] = std::abs(WiFi.getTxPower()); root["trackAnalytics"] = settings.trackAnalytics; // create JSON array from root diff --git a/platformio.ini b/platformio.ini index 1144f79d..c8adefef 100644 --- a/platformio.ini +++ b/platformio.ini @@ -153,7 +153,7 @@ build_flags = ; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp lib_deps = - https://github.com/FastLED/FastLED#f766d23185856612a15bcb70e5fadf625fde30a1 ; master 20260208 + https://github.com/FastLED/FastLED#14138827cd2f89e05c326f359d287506cb527267 ; master 20260209 https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104) ; πŸ’« currently only enabled on s3 as esp32dev runs over 100% diff --git a/src/MoonBase/Module.cpp b/src/MoonBase/Module.cpp index 93daf9e1..94cc3ea9 100644 --- a/src/MoonBase/Module.cpp +++ b/src/MoonBase/Module.cpp @@ -80,7 +80,7 @@ bool ModuleState::checkReOrderSwap(const JsonString& parent, const JsonVariant& uint8_t parkedAtIndex; uint8_t parkedFromIndex = UINT8_MAX; - // size_t minSize = min(stateArray.size(), newArray.size()); + // size_t minSize = MIN(stateArray.size(), newArray.size()); for (uint8_t stateIndex = 0; stateIndex < stateArray.size(); stateIndex++) { //} JsonObject stateObject : stateArray) { for (uint8_t newIndex = 0; newIndex < stateArray.size(); newIndex++) { //} JsonObject newObject : newArray) { if (stateIndex != newIndex && stateArray[stateIndex] == newArray[newIndex]) { @@ -160,7 +160,7 @@ bool ModuleState::compareRecursive(const JsonString& parent, const JsonVariant& // EXT_LOGD(MB_TAG, "compare %s[%d] %s = %s -> %s", parent.c_str(), index, key.c_str(), stateValue.as(), newValue.as()); - for (int i = 0; i < max(stateArray.size(), newArray.size()); i++) { // compare each item in the array + for (int i = 0; i < MAX(stateArray.size(), newArray.size()); i++) { // compare each item in the array // EXT_LOGD(MB_TAG, "compare %s[%d] %s = %s -> %s", parent.c_str(), index, key.c_str(), stateArray[i].as(), newArray[i].as()); if (i >= stateArray.size()) { // newArray has added a row // EXT_LOGD(MB_TAG, "add %s.%s[%d] (%d/%d) d: %d", parent.c_str(), key.c_str(), i, stateArray.size(), newArray.size(), depth); diff --git a/src/MoonBase/Utilities.h b/src/MoonBase/Utilities.h index 744ad456..00ebae8d 100644 --- a/src/MoonBase/Utilities.h +++ b/src/MoonBase/Utilities.h @@ -78,6 +78,15 @@ #define MB_TAG "πŸŒ™" #define ML_TAG "πŸ’«" +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + + struct Coord3D { int x; int y; @@ -134,7 +143,7 @@ struct Coord3D { return *this; } - Coord3D maximum(const Coord3D rhs) const { return Coord3D(max(x, rhs.x), max(y, rhs.y), max(z, rhs.z)); } + Coord3D maximum(const Coord3D rhs) const { return Coord3D(MAX(x, rhs.x), MAX(y, rhs.y), MAX(z, rhs.z)); } unsigned distanceSquared(const Coord3D rhs) const { Coord3D delta = (*this - rhs); diff --git a/src/MoonLight/Layers/VirtualLayer.cpp b/src/MoonLight/Layers/VirtualLayer.cpp index a122c7f6..8e4a0b55 100644 --- a/src/MoonLight/Layers/VirtualLayer.cpp +++ b/src/MoonLight/Layers/VirtualLayer.cpp @@ -290,7 +290,7 @@ void VirtualLayer::addLight(Coord3D position) { createMappingTableAndAddOneToOne(); } - nrOfLights = max(nrOfLights, nrOfLights_t(indexV + 1)); + nrOfLights = MAX(nrOfLights, indexV + 1); if (!oneToOneMapping) { if (indexV < mappingTableSize) { diff --git a/src/MoonLight/Layers/VirtualLayer.h b/src/MoonLight/Layers/VirtualLayer.h index d85f3af1..3a9ed2d8 100644 --- a/src/MoonLight/Layers/VirtualLayer.h +++ b/src/MoonLight/Layers/VirtualLayer.h @@ -148,7 +148,7 @@ class VirtualLayer { #ifdef BOARD_HAS_PSRAM memcpy(mappingTable[indexV].rgb, (void*)&color, 3); #else - mappingTable[indexV].rgb = ((min(color[0] + 3, 255) >> 3) << 9) + ((min(color[1] + 3, 255) >> 3) << 4) + (min(color[2] + 7, 255) >> 4); + mappingTable[indexV].rgb = ((MIN(color[0] + 3, 255) >> 3) << 9) + ((MIN(color[1] + 3, 255) >> 3) << 4) + (MIN(color[2] + 7, 255) >> 4); #endif } else forEachLightIndex(indexV, [&](nrOfLights_t indexP) { memcpy(&layerP->lights.channelsE[indexP * layerP->lights.header.channelsPerLight + layerP->lights.header.offsetRGBW], (void*)&color, sizeof(color)); }); diff --git a/src/MoonLight/Modules/ModuleLightsControl.h b/src/MoonLight/Modules/ModuleLightsControl.h index 773bad66..38de4f60 100644 --- a/src/MoonLight/Modules/ModuleLightsControl.h +++ b/src/MoonLight/Modules/ModuleLightsControl.h @@ -495,7 +495,7 @@ class ModuleLightsControl : public Module { xSemaphoreGive(swapMutex); } else if (isPositions == 0 && layerP.lights.header.nrOfLights) { // send to UI static unsigned long monitorMillis = 0; - if (millis() - monitorMillis >= max(20UL, layerP.lights.header.nrOfLights / 300)) { // 12K lights -> 40ms + if (millis() - monitorMillis >= MAX(20, layerP.lights.header.nrOfLights / 300)) { // 12K lights -> 40ms monitorMillis = millis(); if (_socket->getActiveClients() && _state.data["monitorOn"]) { diff --git a/src/MoonLight/Nodes/Drivers/D_ArtnetIn.h b/src/MoonLight/Nodes/Drivers/D_ArtnetIn.h index e26e8079..ac645e89 100644 --- a/src/MoonLight/Nodes/Drivers/D_ArtnetIn.h +++ b/src/MoonLight/Nodes/Drivers/D_ArtnetIn.h @@ -74,7 +74,7 @@ class ArtNetInDriver : public Node { continue; } - artnetUdp.read(packetBuffer, min(packetSize, (int)sizeof(packetBuffer))); + artnetUdp.read(packetBuffer, MIN(packetSize, sizeof(packetBuffer))); if (ddp) handleDDP(); @@ -124,7 +124,7 @@ class ArtNetInDriver : public Node { uint8_t* dmxData = packetBuffer + sizeof(ArtNetHeader); int startPixel = (universe - universeMin) * (512 / layerP.lights.header.channelsPerLight); - int numPixels = min((uint16_t)(dataLength / layerP.lights.header.channelsPerLight), (uint16_t)(layerP.lights.header.nrOfLights - startPixel)); + int numPixels = MIN(dataLength / layerP.lights.header.channelsPerLight, layerP.lights.header.nrOfLights - startPixel); for (int i = 0; i < numPixels; i++) { int ledIndex = startPixel + i; @@ -155,7 +155,7 @@ class ArtNetInDriver : public Node { uint8_t* pixelData = packetBuffer + sizeof(DDPHeader); int startPixel = offset / layerP.lights.header.channelsPerLight; - int numPixels = min((uint16_t)(dataLen / layerP.lights.header.channelsPerLight), (uint16_t)(layerP.lights.header.nrOfLights - startPixel)); + int numPixels = MIN(dataLen / layerP.lights.header.channelsPerLight, layerP.lights.header.nrOfLights - startPixel); for (int i = 0; i < numPixels; i++) { int ledIndex = startPixel + i; diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index d1f5dd37..9707c0ee 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -287,11 +287,7 @@ class FastLEDDriver : public DriverNode { CRGB* leds = (CRGB*)layerP.lights.channelsD; uint16_t startLed = 0; - for (auto channel : channels) { - EXT_LOGD(ML_TAG, "remove channel"); - FastLED.remove(channel); - } - channels.clear(); + FastLED.reset(ResetFlags::CHANNELS); for (uint8_t pinIndex = 0; pinIndex < nrOfPins; pinIndex++) { EXT_LOGD(ML_TAG, "ledPin p:%d #:%d rgb:%d aff:%s", pins[pinIndex], layerP.ledsPerPin[pinIndex], rgbOrder, options.mAffinity.c_str()); @@ -336,13 +332,7 @@ class FastLEDDriver : public DriverNode { // FastLED.setMaxPowerInMilliWatts(1000 * layerP.maxPower); // 5v, 2000mA, to protect usb while developing } - ~FastLEDDriver() override { - for (auto channel : channels) { - EXT_LOGD(ML_TAG, "remove channel"); - FastLED.remove(channel); - } - channels.clear(); - } + ~FastLEDDriver() override { FastLED.reset(ResetFlags::CHANNELS); } }; #endif \ No newline at end of file diff --git a/src/MoonLight/Nodes/Drivers/D_Infrared.h b/src/MoonLight/Nodes/Drivers/D_Infrared.h index c9b78dcd..5053b1d5 100644 --- a/src/MoonLight/Nodes/Drivers/D_Infrared.h +++ b/src/MoonLight/Nodes/Drivers/D_Infrared.h @@ -329,33 +329,33 @@ class IRDriver : public Node { moduleControl->read( [&](ModuleState& state) { if (combined_code == codeBrightnessInc) { // Brightness increase - newState["brightness"] = min(state.data["brightness"].as() + 5, 255); + newState["brightness"] = MIN(state.data["brightness"].as() + 5, 255); } else if (combined_code == codeBrightnessDec) { // Brightness decrease - newState["brightness"] = max(state.data["brightness"].as() - 5, 0); + newState["brightness"] = MAX(state.data["brightness"].as() - 5, 0); } else if (combined_code == codeRedInc) { // increase red - newState["red"] = min(state.data["red"].as() + 5, 255); + newState["red"] = MIN(state.data["red"].as() + 5, 255); } else if (combined_code == codeRedDec) { // decrease red - newState["red"] = max(state.data["red"].as() - 5, 0); + newState["red"] = MAX(state.data["red"].as() - 5, 0); } else if (combined_code == codeGreenInc) { // increase green - newState["green"] = min(state.data["green"].as() + 5, 255); + newState["green"] = MIN(state.data["green"].as() + 5, 255); } else if (combined_code == codeGreenDec) { // decrease green - newState["green"] = max(state.data["green"].as() - 5, 0); + newState["green"] = MAX(state.data["green"].as() - 5, 0); } else if (combined_code == codeBlueInc) { // increase blue - newState["blue"] = min(state.data["blue"].as() + 5, 255); + newState["blue"] = MIN(state.data["blue"].as() + 5, 255); } else if (combined_code == codeBlueDec) { // decrease blue - newState["blue"] = max(state.data["blue"].as() - 5, 0); + newState["blue"] = MAX(state.data["blue"].as() - 5, 0); } else if (combined_code == codePresetLoopInc) { - newState["presetLoop"] = min(state.data["presetLoop"].as() + 5, 255); + newState["presetLoop"] = MIN(state.data["presetLoop"].as() + 5, 255); } else if (combined_code == codePresetLoopDec) { - newState["presetLoop"] = max(state.data["presetLoop"].as() - 5, 0); + newState["presetLoop"] = MAX(state.data["presetLoop"].as() - 5, 0); } else if (combined_code == codeFirstPresetInc) { - newState["firstPreset"] = min(state.data["firstPreset"].as() + 5, 255); + newState["firstPreset"] = MIN(state.data["firstPreset"].as() + 5, 255); } else if (combined_code == codeFirstPresetDec) { - newState["firstPreset"] = max(state.data["firstPreset"].as() - 5, 0); + newState["firstPreset"] = MAX(state.data["firstPreset"].as() - 5, 0); } else if (combined_code == codeLastPresetInc) { - newState["lastPreset"] = min(state.data["lastPreset"].as() + 5, 255); + newState["lastPreset"] = MIN(state.data["lastPreset"].as() + 5, 255); } else if (combined_code == codeLastPresetDec) { - newState["lastPreset"] = max(state.data["lastPreset"].as() - 5, 0); + newState["lastPreset"] = MAX(state.data["lastPreset"].as() - 5, 0); } // find the current preset in the list, select the next @@ -367,7 +367,7 @@ class IRDriver : public Node { } else if (combined_code == codePaletteInc) { // palette increase newState["palette"] = MIN(state.data["palette"].as() + 1, 8 + 3 + 61); // 8 FastLED + 3 custom + 61 WLED palettes. to do: replace nr with max palette count } else if (combined_code == codePaletteDec) { // palette decrease - newState["palette"] = max(state.data["palette"].as() - 1, 0); + newState["palette"] = MAX(state.data["palette"].as() - 1, 0); } else if (combined_code == codePresetDec) { // next button - go to previous preset newState["preset"] = state.data["preset"]; newState["preset"]["action"] = "click"; diff --git a/src/MoonLight/Nodes/Drivers/D_ParallelLEDDriver.h b/src/MoonLight/Nodes/Drivers/D_ParallelLEDDriver.h index b221fb2b..20212e6a 100644 --- a/src/MoonLight/Nodes/Drivers/D_ParallelLEDDriver.h +++ b/src/MoonLight/Nodes/Drivers/D_ParallelLEDDriver.h @@ -56,7 +56,7 @@ class ParallelLEDDriver : public DriverNode { #ifndef CONFIG_IDF_TARGET_ESP32P4 if (ledsDriver.total_leds > 0) ledsDriver.showPixels(WAIT); #else - uint8_t nrOfPins = min(layerP.nrOfLedPins, layerP.nrOfAssignedPins); + uint8_t nrOfPins = MIN(layerP.nrOfLedPins, layerP.nrOfAssignedPins); // LUTs are accessed directly within show_parlio via extern ledsDriver // No brightness parameter needed @@ -75,7 +75,7 @@ class ParallelLEDDriver : public DriverNode { void onLayout() override { #if HP_ALL_DRIVERS if (layerP.pass == 1 && !layerP.monitorPass) { - uint8_t nrOfPins = min(layerP.nrOfLedPins, layerP.nrOfAssignedPins); + uint8_t nrOfPins = MIN(layerP.nrOfLedPins, layerP.nrOfAssignedPins); if (!lightPresetSaved || nrOfPins == 0) { //|| initDone can be done multiple times now... EXT_LOGD(ML_TAG, "return: lightpresetsaved:%d initDone:%d #:%d", lightPresetSaved, initDone, nrOfPins); diff --git a/src/MoonLight/Nodes/Effects/E_MoonLight.h b/src/MoonLight/Nodes/Effects/E_MoonLight.h index 3285fb83..13d920e6 100644 --- a/src/MoonLight/Nodes/Effects/E_MoonLight.h +++ b/src/MoonLight/Nodes/Effects/E_MoonLight.h @@ -721,11 +721,11 @@ class FreqSawsEffect : public Node { uint16_t targetSpeed = (volume * increaser * 257); if (volume > 0) { - bandSpeed[band] = max(bandSpeed[band], targetSpeed); + bandSpeed[band] = MAX(bandSpeed[band], targetSpeed); } else { // Calculate decay amount based on time to reach zero if (decreaser > 0 && bandSpeed[band] > 0) { - uint32_t decayAmount = max((bandSpeed[band] * deltaMs) / (decreaser * 10UL), 1UL); // *10 to scale decreaser range 0-255 to 0-2550ms + uint32_t decayAmount = MAX((bandSpeed[band] * deltaMs) / (decreaser * 10), 1); // *10 to scale decreaser range 0-255 to 0-2550ms if (decayAmount >= bandSpeed[band]) { bandSpeed[band] = 0; } else { @@ -905,9 +905,9 @@ class RubiksCubeEffect : public Node { } void drawCube(VirtualLayer* layer) { - int sizeX = max(layer->size.x - 1, 1); - int sizeY = max(layer->size.y - 1, 1); - int sizeZ = max(layer->size.z - 1, 1); + int sizeX = MAX(layer->size.x - 1, 1); + int sizeY = MAX(layer->size.y - 1, 1); + int sizeZ = MAX(layer->size.z - 1, 1); // 3 Sided Cube Cheat add 1 to led size if "panels" missing. May affect different fixture types if (layer->layerDimension == _3D) { @@ -940,10 +940,10 @@ class RubiksCubeEffect : public Node { int normalizedZ = constrain(round(z * scaleZ) - 1, 0, SIZE - 1); // Calculate the distance to the closest face - int distX = min(x, sizeX - x); - int distY = min(y, sizeY - y); - int distZ = min(z, sizeZ - z); - int dist = min(distX, min(distY, distZ)); + int distX = MIN(x, sizeX - x); + int distY = MIN(y, sizeY - y); + int distZ = MIN(z, sizeZ - z); + int dist = MIN(distX, MIN(distY, distZ)); if (dist == distZ && z < halfZ) layer->setRGB(led, COLOR_MAP[front[normalizedY][normalizedX]]); @@ -1570,8 +1570,8 @@ class VUMeterEffect : public Node { int y1 = y0 - round(size.y * 0.7 * sin((angle + 30) * PI / 180)); // βœ… Clamp to valid bounds - x1 = max(0, min(x1, (int)layer->size.x - 1)); - y1 = max(0, min(y1, (int)layer->size.y - 1)); + x1 = MAX(0, MIN(x1, layer->size.x - 1)); + y1 = MAX(0, MIN(y1, layer->size.y - 1)); // Draw the needle layer->drawLine(x0, y0, x1, y1, color, true); @@ -1610,7 +1610,7 @@ class PixelMapEffect : public Node { Coord3D pos = {0, 0, 0}; - void setup() override { addControl(pos, "pos", "coord3D", 0, max(max(layer->size.x, layer->size.y), layer->size.z) - 1); } + void setup() override { addControl(pos, "pos", "coord3D", 0, MAX(MAX(layer->size.x, layer->size.y), layer->size.z) - 1); } void loop() override { layer->fill_solid(CRGB::Black); @@ -1721,7 +1721,7 @@ class AudioRingsEffect : public RingEffect { } void loop() override { - uint8_t nrOfRings = max(layer->size.y, 2); // height of the layer, minimal 2 + uint8_t nrOfRings = MAX(layer->size.y, 2); // height of the layer, minimal 2 for (int i = 0; i < nrOfRings; i++) { uint8_t band = ::map(i, 0, nrOfRings - 1, 0, NUM_GEQ_CHANNELS - 1); diff --git a/src/MoonLight/Nodes/Effects/E_MoonModules.h b/src/MoonLight/Nodes/Effects/E_MoonModules.h index 4369e483..7f4048a9 100644 --- a/src/MoonLight/Nodes/Effects/E_MoonModules.h +++ b/src/MoonLight/Nodes/Effects/E_MoonModules.h @@ -433,7 +433,7 @@ class GEQ3DEffect : public Node { if (heights[i] > 1) { ledColorTemp = blend(ledColor, CRGB::Black, 255 - 32); - int pPos = max(0, linex + (cols / NUM_BANDS) - 1); + int pPos = MAX(0, linex + (cols / NUM_BANDS) - 1); for (int y = (i < NUM_BANDS - 1) ? heights[i + 1] : 0; y <= heights[i]; y++) { // don't bother drawing what we'll hide anyway if (rows - y > 0) layer->drawLine(pPos, rows - y - 1, projector, horizon, ledColorTemp, false, depth); // right side perspective } @@ -454,7 +454,7 @@ class GEQ3DEffect : public Node { uint16_t colorIndex = ::map(cols / NUM_BANDS * i, 0, cols - 1, 0, 255); CRGB ledColor = ColorFromPalette(layerP.palette, colorIndex); int linex = i * (cols / NUM_BANDS); - int pPos = max(0, linex + (cols / NUM_BANDS) - 1); + int pPos = MAX(0, linex + (cols / NUM_BANDS) - 1); if (heights[i] > 1) { ledColorTemp = blend(ledColor, CRGB::Black, 255 - 32); @@ -575,7 +575,7 @@ class PaintBrushEffect : public Node { length = map8(sharedData.bands[bin], 0, length); - if (length > max(1, (int)minLength)) { + if (length > MAX(1, minLength)) { CRGB color; if (color_chaos) color = ColorFromPalette(layerP.palette, i * 255 / numLines + ((aux0Hue) & 0xFF), 255); diff --git a/src/MoonLight/Nodes/Effects/E_WLED.h b/src/MoonLight/Nodes/Effects/E_WLED.h index 7163baca..2f500fea 100644 --- a/src/MoonLight/Nodes/Effects/E_WLED.h +++ b/src/MoonLight/Nodes/Effects/E_WLED.h @@ -72,7 +72,7 @@ class BouncingBallsEffect : public Node { // uint32_t color = SEGCOLOR(0); // if (layerP.palette) { - // color = layer->color_wheel(i*(256/max(numBalls, 8))); + // color = layer->color_wheel(i*(256/MAX(numBalls, 8))); // } // else if (hasCol2) { // color = SEGCOLOR(i % NUM_COLORS); @@ -80,7 +80,7 @@ class BouncingBallsEffect : public Node { uint8_t pos = layer->size.y - 1 - roundf(balls[x][i].height * (layer->size.y - 1)); // balls go up - CRGB color = ColorFromPalette(layerP.palette, i * (256 / max(numBalls, (uint8_t)8))); // error: no matching function for call to 'max(uint8_t&, int)' + CRGB color = ColorFromPalette(layerP.palette, i * (256 / MAX(numBalls, 8))); // error: no matching function for call to 'MAX(uint8_t&, int)' layer->setRGB(Coord3D(x, pos), color); } // balls layer->fill_solid(CRGB::White); @@ -136,20 +136,20 @@ class BlurzEffect : public Node { if (freqMap) { // FreqMap mode : blob location by major frequency int freqLocn; - unsigned maxLen = (geqScanner) ? max(1, layer->size.x * layer->size.y * layer->size.z - 16) : layer->size.x * layer->size.y * layer->size.z; // usable segment length - leave 16 pixels when embedding "GEQ scan" + unsigned maxLen = (geqScanner) ? MAX(1, layer->size.x * layer->size.y * layer->size.z - 16) : layer->size.x * layer->size.y * layer->size.z; // usable segment length - leave 16 pixels when embedding "GEQ scan" freqLocn = roundf((log10f((float)sharedData.majorPeak) - 1.78f) * float(maxLen) / (MAX_FREQ_LOG10 - 1.78f)); // log10 frequency range is from 1.78 to 3.71. Let's scale to layer->size.x * layer->size.y * layer->size.z. // WLEDMM proper rounding if (freqLocn < 1) freqLocn = 0; // avoid underflow segLoc = (geqScanner) ? freqLocn + freqBand : freqLocn; } else if (geqScanner) { // GEQ Scanner mode: blob location is defined by frequency band + random offset float bandWidth = float(layer->size.x * layer->size.y * layer->size.z) / 16.0f; int bandStart = roundf(bandWidth * freqBand); - segLoc = bandStart + random16(max(1, int(bandWidth))); + segLoc = bandStart + random16(MAX(1, bandWidth)); } - segLoc = max(nrOfLights_t(0), MIN(nrOfLights_t(layer->size.x * layer->size.y * layer->size.z - 1), segLoc)); // fix overflows + segLoc = MAX(0, MIN(layer->size.x * layer->size.y * layer->size.z - 1, segLoc)); // fix overflows if (layer->size.x * layer->size.y * layer->size.z < 2) segLoc = 0; // WLEDMM just to be sure - unsigned pixColor = (2 * sharedData.bands[freqBand] * 240) / max(1, layer->size.x * layer->size.y * layer->size.z - 1); // WLEDMM avoid uint8 overflow, and preserve pixel parameters for redraw - unsigned pixIntensity = MIN((unsigned)(2.0f * sharedData.bands[freqBand]), 255U); + unsigned pixColor = (2 * sharedData.bands[freqBand] * 240) / MAX(1, layer->size.x * layer->size.y * layer->size.z - 1); // WLEDMM avoid uint8 overflow, and preserve pixel parameters for redraw + unsigned pixIntensity = MIN(2.0f * sharedData.bands[freqBand], 255); if (sharedData.volume > 1.0f) { layer->setRGB(segLoc, ColorFromPalette(layerP.palette, pixColor)); @@ -576,7 +576,7 @@ class PacManEffect : public Node { const uint32_t ghostColors[4] = {CRGB::Red, PURPLEISH, CRGB::Cyan, ORANGEISH}; void initializePacMan() { - numPowerDots = MIN(layer->nrOfLights / 10U, numPowerDotsControl); // cap the max so packed state fits in 8 bits: ML: keep the nr visible in the UI + numPowerDots = MIN(layer->nrOfLights / 10, numPowerDotsControl); // cap the max so packed state fits in 8 bits: ML: keep the nr visible in the UI EXT_LOGD(ML_TAG, "#l:%d #pd:%d #g:%d #pd:%d", layer->nrOfLights, numPowerDotsControl, numGhosts, numPowerDots); @@ -1165,7 +1165,7 @@ class WaverlyEffect : public Node { Coord3D pos = {0, 0, 0}; // initialize z otherwise wrong results for (pos.x = 0; pos.x < layer->size.x; pos.x++) { uint16_t thisVal = sharedData.volume * amplification * inoise8(pos.x * 45, t, t) / 4096; // WLEDMM back to SR code - uint16_t thisMax = MIN(map(thisVal, 0, 512, 0, layer->size.y), (long)layer->size.y); + uint16_t thisMax = MIN(map(thisVal, 0, 512, 0, layer->size.y), layer->size.y); for (pos.y = 0; pos.y < thisMax; pos.y++) { CRGB color = ColorFromPalette(layerP.palette, ::map(pos.y, 0, thisMax, 250, 0)); @@ -1325,7 +1325,7 @@ class OctopusEffect : public Node { const uint16_t C_X = layer->size.x / 2 + (offset.x - 50) * layer->size.x / 100; const uint16_t C_Y = layer->size.y / 2 + (offset.y - 50) * layer->size.y / 100; Coord3D pos = {0, 0, 0}; - const uint8_t mapp = 180 / max(layer->size.x, layer->size.y); + const uint8_t mapp = 180 / MAX(layer->size.x, layer->size.y); for (pos.x = 0; pos.x < layer->size.x; pos.x++) { for (pos.y = 0; pos.y < layer->size.y; pos.y++) { nrOfLights_t indexV = layer->XYZUnModified(pos); @@ -1483,7 +1483,7 @@ class FireworksEffect : public Node { * Size is proportional to the height. */ uint8_t nSparks = flare->pos + random8(4); - // nSparks = std::max(nSparks, 4U); // This is not a standard constrain; numSparks is not guaranteed to be at least 4 + // nSparks = MAX(nSparks, 4); // This is not a standard constrain; numSparks is not guaranteed to be at least 4 nSparks = MIN(nSparks, numSparks); // initialize sparks @@ -1683,7 +1683,7 @@ static void mode_fireworks(VirtualLayer* layer, uint16_t x, uint16_t aux0, uint1 if (valid2) layer->setRGB(Coord3D(x, layer->size.y - 1 - aux1), sv2); if (addPixels) { // WLEDSR - for (uint16_t i = 0; i < max(1, layer->size.y / 20); i++) { + for (uint16_t i = 0; i < MAX(1, layer->size.y / 20); i++) { if (random8(my_intensity) == 0) { uint16_t index = random(layer->size.y); if (soundColor < 0) @@ -1808,7 +1808,7 @@ class DripEffect : public Node { float gravity = -(gravityControl / 800000.0f); - gravity *= max(1, layer->size.y - 1); + gravity *= MAX(1, layer->size.y - 1); int sourcedrop = 12; for (int x = 0; x < nrOfDrops; x++) { @@ -1963,9 +1963,9 @@ class DJLightEffect : public Node { CHSV hsvColor = rgb2hsv_approximate(color); hsvColor.v = constrain(hsvColor.v, 48, 204); // 48 < brightness < 204 if (candyFactory) - hsvColor.s = max(hsvColor.s, (uint8_t)204); // candy factory mode: strongly turn up color saturation (> 192) + hsvColor.s = MAX(hsvColor.s, 204); // candy factory mode: strongly turn up color saturation (> 192) else - hsvColor.s = max(hsvColor.s, (uint8_t)108); // normal mode: turn up color saturation to avoid pastels + hsvColor.s = MAX(hsvColor.s, 108); // normal mode: turn up color saturation to avoid pastels color = hsvColor; } // if (color.getLuma() > 12) color.maximizeBrightness(); // for testing @@ -2059,7 +2059,9 @@ class ColorTwinkleEffect : public Node { } } - ~ColorTwinkleEffect() { if (data) freeMB(data, "data"); } + ~ColorTwinkleEffect() { + if (data) freeMB(data, "data"); + } }; class PlasmaEffect : public Node { @@ -2224,7 +2226,7 @@ class JuliaEffect : public Node { if (showCenter) { // draw crosshair int screenX = lroundf((0.5f / maxCenter) * (julias.xcen + maxCenter) * float(cols)); int screenY = lroundf((0.5f / maxCenter) * (julias.ycen + maxCenter) * float(rows)); - int hair = min(min(cols - 1, rows - 1) / 2, 3); + int hair = MIN(MIN(cols - 1, rows - 1) / 2, 3); layer->drawLine(screenX, screenY - hair, screenX, screenY + hair, CRGB::Green, true); layer->drawLine(screenX - hair, screenY, screenX + hair, screenY, CRGB::Green, true); } diff --git a/src/MoonLight/Nodes/Modifiers/M_MoonLight.h b/src/MoonLight/Nodes/Modifiers/M_MoonLight.h index 90ac44c4..6a9c2aa0 100644 --- a/src/MoonLight/Nodes/Modifiers/M_MoonLight.h +++ b/src/MoonLight/Nodes/Modifiers/M_MoonLight.h @@ -142,7 +142,7 @@ class PinwheelModifier : public Node { void modifySize() override { if (layer->layerDimension > _1D && layer->effectDimension > _1D) { - layer->size.y = sqrt(sq(max(layer->size.x - layer->middle.x, layer->middle.x)) + sq(max(layer->size.y - layer->middle.y, layer->middle.y))) + 1; // Adjust y before x + layer->size.y = sqrt(sq(fl::max(layer->size.x - layer->middle.x, layer->middle.x)) + sq(fl::max(layer->size.y - layer->middle.y, layer->middle.y))) + 1; // Adjust y before x layer->size.x = petals; layer->size.z = 1; } else { @@ -294,7 +294,7 @@ class RotateModifier : public Node { void modifySize() override { if (expand) { - uint8_t size = max(layer->size.x, max(layer->size.y, layer->size.z)); + uint8_t size = MAX(layer->size.x, MAX(layer->size.y, layer->size.z)); size = sqrt(size * size * 2) + 1; Coord3D offset = Coord3D((size - layer->size.x) / 2, (size - layer->size.y) / 2, 0); @@ -310,7 +310,7 @@ class RotateModifier : public Node { void modifyPosition(Coord3D& position) override { if (expand) { - int size = max(modifierSize.x, max(modifierSize.y, modifierSize.z)); + int size = MAX(modifierSize.x, MAX(modifierSize.y, modifierSize.z)); size = sqrt(size * size * 2) + 1; Coord3D offset = Coord3D((size - modifierSize.x) / 2, (size - modifierSize.y) / 2, 0); position += offset; From a2741e2d0076f26604c4ea3d7a12c7abbf8c80ee Mon Sep 17 00:00:00 2001 From: ewowi Date: Mon, 9 Feb 2026 10:25:21 +0100 Subject: [PATCH 10/11] Small changes --- platformio.ini | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index c8adefef..72a516cb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,7 +56,7 @@ build_flags = -D BUILD_TARGET=\"$PIOENV\" -D APP_NAME=\"MoonLight\" ; πŸŒ™ Must only contain characters from [a-zA-Z0-9-_] as this is converted into a filename -D APP_VERSION=\"0.8.1\" ; semver compatible version string - -D APP_DATE=\"20260207\" ; πŸŒ™ + -D APP_DATE=\"20260208\" ; πŸŒ™ -D PLATFORM_VERSION=\"pioarduino-55.03.35\" ; πŸŒ™ make sure it matches with above plaftform diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index 9707c0ee..d7381273 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -29,7 +29,7 @@ class FastLEDDriver : public DriverNode { uint8_t affinity = 0; // auto // #endif uint8_t temperature = 0; - bool correction = 0; + uint8_t correction = 0; bool dither = false; void setup() override { @@ -229,12 +229,12 @@ class FastLEDDriver : public DriverNode { } // FastLED Led Controllers - CRGB correction = CRGB(layerP.lights.header.red, layerP.lights.header.green, layerP.lights.header.blue); + CRGB colorCorrection = CRGB(layerP.lights.header.red, layerP.lights.header.green, layerP.lights.header.blue); CLEDController* pCur = CLEDController::head(); while (pCur) { - if (pCur->getCorrection() != correction) { + if (pCur->getCorrection() != colorCorrection) { EXT_LOGD(ML_TAG, "setColorCorrection r:%d, g:%d, b:%d (#:%d)", layerP.lights.header.red, layerP.lights.header.green, layerP.lights.header.blue, pCur->size()); - pCur->setCorrection(correction); + pCur->setCorrection(colorCorrection); } // pCur->size(); pCur = pCur->next(); From 5be8eab6fbbb847765ddc7be14dea00e99b5f205 Mon Sep 17 00:00:00 2001 From: ewowi Date: Tue, 10 Feb 2026 09:21:50 +0100 Subject: [PATCH 11/11] Latest FastLED (20260210), add events --- lib/framework/WiFiSettingsService.h | 2 +- platformio.ini | 2 +- src/MoonLight/Nodes/Drivers/D_FastLED.h | 13 ++++++++++++- src/MoonLight/Nodes/Modifiers/M_MoonLight.h | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/framework/WiFiSettingsService.h b/lib/framework/WiFiSettingsService.h index 24840114..df570d07 100644 --- a/lib/framework/WiFiSettingsService.h +++ b/lib/framework/WiFiSettingsService.h @@ -92,7 +92,7 @@ class WiFiSettings root["hostname"] = settings.hostname; root["connection_mode"] = settings.staConnectionMode; root["txPower"] = settings.txPower;//(uint8_t )WiFi.getTxPower(); - root["txPowerMeasured"] = std::abs(WiFi.getTxPower()); + root["txPowerMeasured"] = std::abs(WiFi.getTxPower()); // πŸŒ™ std:: to avoid ambuigity root["trackAnalytics"] = settings.trackAnalytics; // create JSON array from root diff --git a/platformio.ini b/platformio.ini index 72a516cb..bb9b8022 100644 --- a/platformio.ini +++ b/platformio.ini @@ -153,7 +153,7 @@ build_flags = ; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp lib_deps = - https://github.com/FastLED/FastLED#14138827cd2f89e05c326f359d287506cb527267 ; master 20260209 + https://github.com/FastLED/FastLED#f28dc6b0b19581e4ba0d309fe3f2957412caca65 ; master 2026010 https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104) ; πŸ’« currently only enabled on s3 as esp32dev runs over 100% diff --git a/src/MoonLight/Nodes/Drivers/D_FastLED.h b/src/MoonLight/Nodes/Drivers/D_FastLED.h index d7381273..7c9e2f95 100644 --- a/src/MoonLight/Nodes/Drivers/D_FastLED.h +++ b/src/MoonLight/Nodes/Drivers/D_FastLED.h @@ -13,6 +13,9 @@ #if FT_MOONLIGHT +// using the new FastLED channel api +// https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md + class FastLEDDriver : public DriverNode { public: static const char* name() { return "FastLED Driver"; } @@ -74,6 +77,15 @@ class FastLEDDriver : public DriverNode { moduleControl->addUpdateHandler([this](const String& originId) { // brightness changes here? }); + + // Register event listeners via FastLED + auto& events = FastLED.channelEvents(); + + // Called when channel is created + events.onChannelCreated.add([](const fl::Channel& ch) { EXT_LOGD(ML_TAG, "Channel created: %s", ch.name().c_str()); }); + + // Called when channel data is enqueued to engine + events.onChannelEnqueued.add([](const fl::Channel& ch, const fl::string& engine) { EXT_LOGD(ML_TAG, "enqueued %s β†’ %s", ch.name().c_str(), engine.c_str()); }); } fl::EOrder rgbOrder = GRB; @@ -282,7 +294,6 @@ class FastLEDDriver : public DriverNode { updateControl("status", statusString.c_str()); moduleNodes->requestUIUpdate = true; - // https://github.com/FastLED/FastLED/blob/master/src/fl/channels/README.md fl::ChipsetTimingConfig timing = fl::makeTimingConfig(); CRGB* leds = (CRGB*)layerP.lights.channelsD; uint16_t startLed = 0; diff --git a/src/MoonLight/Nodes/Modifiers/M_MoonLight.h b/src/MoonLight/Nodes/Modifiers/M_MoonLight.h index 6a9c2aa0..9ccc266a 100644 --- a/src/MoonLight/Nodes/Modifiers/M_MoonLight.h +++ b/src/MoonLight/Nodes/Modifiers/M_MoonLight.h @@ -142,7 +142,7 @@ class PinwheelModifier : public Node { void modifySize() override { if (layer->layerDimension > _1D && layer->effectDimension > _1D) { - layer->size.y = sqrt(sq(fl::max(layer->size.x - layer->middle.x, layer->middle.x)) + sq(fl::max(layer->size.y - layer->middle.y, layer->middle.y))) + 1; // Adjust y before x + layer->size.y = sqrt(sq(MAX(layer->size.x - layer->middle.x, layer->middle.x)) + sq(MAX(layer->size.y - layer->middle.y, layer->middle.y))) + 1; // Adjust y before x layer->size.x = petals; layer->size.z = 1; } else {