Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,12 @@ 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, 4096 is sufficient for now
-D DRIVERS_STACK_SIZE=6144 ; psramFound() ? 4 * 1024 : 3 * 1024, 4096 is sufficient for now. Update: due to FastLED audio I had to increase to 6144 (might want to move audio to a separate task)

; -D FASTLED_TESTING ; causes duplicate definition of initSpiHardware(); - workaround: removed implementation in spi_hw_manager_esp32.cpp.hpp
-D FASTLED_BUILD=\"20260221\"
-D FASTLED_BUILD=\"20260222\"
lib_deps =
https://github.com/FastLED/FastLED#9d0b0eb9b5e59e4093982e0c2bdcfdff72ca80cb ; master 20260221
https://github.com/FastLED/FastLED#27c99130c83ab666c4c6dbf389425fec5f27db05 ; master 20260222
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's examine the platformio.ini file around the specified lines and check for build flags
cat -n platformio.ini | head -230 | tail -50

Repository: MoonModules/MoonLight

Length of output: 3265


🏁 Script executed:

#!/bin/bash
# Search for all FastLED-related configuration flags in the repo
rg -n "FASTLED_RMT5|FASTLED_RMT4|FASTLED_BUILD|FASTLED_" --type ini --type txt --type h --type cpp

Repository: MoonModules/MoonLight

Length of output: 92


🏁 Script executed:

#!/bin/bash
# Check the exact commit details and verify build string alignment
# Find the git repository containing the pinned FastLED commit
rg -n "27c99130c83ab666c4c6dbf389425fec5f27db05" --type ini

Repository: MoonModules/MoonLight

Length of output: 92


🏁 Script executed:

#!/bin/bash
# Search for FASTLED_RMT5, FASTLED_RMT4, and related driver flags without file type restrictions
rg -n "FASTLED_RMT5|FASTLED_RMT4|FASTLED_SPI" .

Repository: MoonModules/MoonLight

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Check the complete [moonlight] section and build_flags to see all configuration
sed -n '199,211p' platformio.ini

Repository: MoonModules/MoonLight

Length of output: 811


🏁 Script executed:

#!/bin/bash
# Check all build_flags sections across the entire platformio.ini
rg -B2 -A5 "build_flags|FASTLED" platformio.ini

Repository: MoonModules/MoonLight

Length of output: 2738


🏁 Script executed:

#!/bin/bash
# Verify the commit date by examining git if available, or search related documentation
# Check if there are any comments/docs about the FastLED version and RMT configuration
rg -n "27c99130c83ab666c4c6dbf389425fec5f27db05|RMT5|RMT4|Handler detached" .

Repository: MoonModules/MoonLight

Length of output: 181


🏁 Script executed:

#!/bin/bash
# Check platform-espressif32 version 55.03.37 for ESP-IDF details
# Look for package.json or version info in typical locations
rg -n "esp-idf|ESP-IDF|5\.[0-9]" platformio.ini | head -20

Repository: MoonModules/MoonLight

Length of output: 2966


🏁 Script executed:

#!/bin/bash
# Search for any Arduino core version or framework configuration
rg -n "framework|arduino|framework-esp32idf|framework-espidf" platformio.ini

Repository: MoonModules/MoonLight

Length of output: 3009


Add -D FASTLED_RMT5=0 to force legacy RMT4 driver and prevent ISR handler degradation.

The FASTLED_BUILD string aligns correctly with the pinned commit. However, platform 55.03.37 uses ESP-IDF 5.5+ with Arduino core 3.x, which causes FastLED to default to the RMT5 driver. RMT5 has documented ISR handler lifecycle issues (see FastLED issue #1903) causing repeated "Handler detached" messages and severe performance drops (~2 FPS). Add -D FASTLED_RMT5=0 to the [moonlight] build_flags to force the stable legacy RMT4 driver.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@platformio.ini` around lines 207 - 209, Add the compiler define to force the
legacy RMT4 driver: in the platformio.ini's [moonlight] build_flags (the same
place where -D FASTLED_BUILD is set), append -D FASTLED_RMT5=0 so FastLED uses
RMT4 instead of RMT5; update the build_flags string that currently references
FASTLED_BUILD so it includes this new define to prevent the RMT5 ISR "Handler
detached" issues described.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true on newest FastLED

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🌐 Web query:

FastLED RMT5 driver fixes February 2026 handler detached

💡 Result:

I couldn’t find any FastLED change/issue (through the public repo + recent searches) specifically tied to a “handler detached” message for the ESP32 RMT5 driver in February 2026—so there doesn’t appear to be a known “Feb 2026” targeted fix labeled that way. (If you have the exact log line + platform/core version, I can search more precisely.)

What is documented/fixed recently around ESP32 RMT5 stability:

  • FastLED 3.10.1 fixed an ESP32‑S3 RMT5 break where an internal improvement accidentally set DMA mode true, breaking RMT5. Updating beyond 3.10.1 is recommended if you hit DMA-related failures. [1]
  • Ongoing RMT5 reliability discussions (especially Wi‑Fi flicker/jitter) note RMT5’s limits and practical mitigations (e.g., raising RMT interrupt priority to the max the driver allows and increasing buffering), but these are about underruns/flicker rather than a “handler detached” teardown error. [2]
  • If you need a robust workaround today, FastLED explicitly recommends switching away from RMT5 in some cases:
    • Force legacy RMT4 with -D FASTLED_RMT5=0 (typically requires older ESP32 Arduino core / IDF4-era setups; also note RMT4 and RMT5 can’t coexist). [3]
    • Or use alternative output paths (I2S/SPI/Adafruit bridge), which users/reporting/dev notes often suggest when RMT5 is unstable under load. [3]

Most actionable next step: confirm whether your “handler detached” happens only with DMA enabled. If yes, try updating FastLED (>= 3.10.1) first. [1] If it persists, try FASTLED_RMT5=0 (RMT4) or switch to a non-RMT driver as above. [3]

Sources:
[1] FastLED releases (3.10.1 notes: DMA mode accidentally set true, breaking RMT5) https://github.com/fastled/fastled/releases
[2] FastLED issue #2082 (RMT5 + Wi‑Fi flicker; buffering/priority limits/knobs discussion) FastLED/FastLED#2082
[3] FastLED repository documentation (RMT4 vs RMT5 selection; FASTLED_RMT5=0; alternative drivers) https://github.com/FastLED/FastLED


@ewowi, thank you for the correction! I appreciate you letting me know that the RMT5 "Handler detached" issues have been resolved in the newest FastLED version.

Since you originally provided the learning about RMT5 issues (learning ID 9bb17d59-f1a1-4505-b40f-39a68c64be29) and you're now confirming it's no longer applicable with the latest FastLED, would you like me to remove that outdated learning from the knowledge base? This will prevent it from being referenced in future reviews.


✏️ Learnings added
Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 130
File: platformio.ini:207-209
Timestamp: 2026-02-22T12:37:03.751Z
Learning: FastLED RMT5 driver issues (ISR handler "Handler detached" messages and performance degradation) have been resolved in FastLED versions as of commit 27c99130c83ab666c4c6dbf389425fec5f27db05 (master 20260222). The `-D FASTLED_RMT5=0` workaround is no longer needed.
<!-- </add_learning>

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-02-05T13:20:46.001Z
Learning: In MoonLight with FastLED 3.11 on ESP-IDF 5.x+ (Arduino core 3.x): FastLED defaults to RMT5 driver (wraps Espressif's led_strip component), which has known ISR handler lifecycle issues causing repeated "Handler detached" messages every ~500ms and severe performance degradation (e.g., 2 FPS). RMT5 is more prone to Wi-Fi/interrupt jitter than legacy RMT4. Solution: force legacy RMT4 by adding `-D FASTLED_RMT5=0` to build flags in platformio.ini, or switch to FastLED's parallel I/O drivers which don't use RMT. RMT4 and RMT5 cannot coexist in the same binary.

Learnt from: CR
Repo: MoonModules/MoonLight PR: 0
File: misc/parking/GEMINI.md:0-0
Timestamp: 2025-11-29T16:17:30.619Z
Learning: Applies to misc/parking/**/platformio.ini : Use PlatformIO to build and upload the ESP32 backend C++ code

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-16T15:53:11.236Z
Learning: For ESP32-PICO-MINI-02 (and similar ESP32 boards with PSRAM), the critical configuration to enable PSRAM is `board_build.arduino.memory_type = qio_qspi` in platformio.ini. The board JSON may already include `-DBOARD_HAS_PSRAM` and `flash_mode: qio`, but without the memory_type setting, PSRAM won't be properly initialized, causing LoadStoreError crashes when code tries to access PSRAM addresses.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-28T18:06:23.868Z
Learning: ESP32-P4 observed lower headroom for httpd task stack in MoonLight: NodeManager rename (create new node + rebuild controls + remove old) can overflow httpd stack when onUpdate runs in httpd. Mitigation: defer only NodeManager rename heavy work to SvelteKit loop via a small pendingRenames queue; keep identity short-circuit in compareRecursive and equality-guarded controls updates. Increasing httpd stack_size for P4 builds is an optional, broader fix.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 121
File: src/MoonLight/Nodes/Drivers/D_FastLED.h:176-176
Timestamp: 2026-02-08T20:43:12.857Z
Learning: In MoonLight FastLED 3.11 driver (src/MoonLight/Nodes/Drivers/D_FastLED.h): Affinity is applied per-channel via fl::ChannelOptions.mAffinity passed to fl::ChannelConfig (not via FastLED.setExclusiveDriver). Keeping setExclusiveDriver commented out leaves all drivers available; FastLED then selects the appropriate driver for each channel based on the mAffinity preference ("RMT", "I2S", "SPI", "PARLIO", or "" for auto). This allows per-channel driver preferences rather than a global restriction.

Learnt from: CR
Repo: MoonModules/MoonLight PR: 0
File: misc/parking/GEMINI.md:0-0
Timestamp: 2025-11-29T16:17:30.619Z
Learning: Applies to misc/parking/**/factory_settings.ini : Configure default or factory-set ESP32 parameters in `factory_settings.ini`

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-18T17:07:33.344Z
Learning: FastLED library does not support direct 4-byte-per-pixel (CRGBW) buffers. It always expects CRGB (3-byte) arrays and internally generates the W channel from RGB using .setRgbw() API. Casting a 4-byte RGBW buffer to CRGB* causes misalignment (W becomes next pixel's R). For MoonLight's FastLED driver with channelsPerLight=4: must either (1) repack RGB in-place before FastLED.show() then restore after, (2) use driver-specific channelsPerLight=3 layout, or (3) allocate temporary RGB-only buffer. Option 1 (in-place repacking) is best for ESP32-D0 memory constraints.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-06T13:45:03.067Z
Learning: For MoonLight on ESP32 at extreme loads (e.g., 49K channels @ 100 fps): Task watchdog can fire when AppDrivers/AppEffects process many nodes without yielding. Even with vTaskDelay(1) at loop end, the node iteration for-loops (PhysicalLayer::loopDrivers line 108-111, PhysicalLayer::loop line 73-75) can take >5 seconds without yielding, starving IDLE task (priority 0). Solution: add taskYIELD() or vTaskDelay(1) inside the node/layer iteration loops to give IDLE task chances to run and reset watchdog. Lowering task priority won't help since IDLE is already at 0 (lowest).

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-18T12:49:07.297Z
Learning: In MoonLight channel reordering architecture: Keep rgbwBufferMapping in driver task (not effect task) because: (1) Driver has spare CPU cycles waiting for DMA/I2S/Art-Net timing; effect task is CPU-bound and starvation-prone. (2) Contiguous RGB writes in effects are cache-friendly; scattered writes at final offsets are cache-hostile for non-RGB orders (GRB, BGR, etc.). (3) forEachLightIndex already handles sparse mapping iteration; moving reordering to effects adds complexity without benefit since drivers must send full frames anyway (can't skip iteration). (4) rgbwBufferMapping does brightness/gamma LUT + white extraction + reordering—moving just reordering creates code duplication. (5) Effects should express color intent (CRGB), not hardware details (offsetRed/Green/Blue). Driver-side transformation maintains separation of concerns and task load balance for scaling to 98K+ pixels.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes remove it please

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ewowi, I've removed the outdated learning about the FastLED RMT5 driver issues. The knowledge base now reflects the current state: that RMT5 issues have been resolved in FastLED as of commit 27c99130c83ab666c4c6dbf389425fec5f27db05 (master 20260222), and the -D FASTLED_RMT5=0 workaround is no longer needed. Thank you for keeping the information up to date!

🐰💭
(Learning tidied up!)
/) /)
( •.• )
/>📝✨


⛔ Learnings removed
Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-02-05T13:20:46.001Z
Learning: In MoonLight with FastLED 3.11 on ESP-IDF 5.x+ (Arduino core 3.x): FastLED defaults to RMT5 driver (wraps Espressif's led_strip component), which has known ISR handler lifecycle issues causing repeated "Handler detached" messages every ~500ms and severe performance degradation (e.g., 2 FPS). RMT5 is more prone to Wi-Fi/interrupt jitter than legacy RMT4. Solution: force legacy RMT4 by adding `-D FASTLED_RMT5=0` to build flags in platformio.ini, or switch to FastLED's parallel I/O drivers which don't use RMT. RMT4 and RMT5 cannot coexist in the same binary.

🧠 Learnings used
Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-02-05T13:20:46.001Z
Learning: In MoonLight with FastLED 3.11 on ESP-IDF 5.x+ (Arduino core 3.x): FastLED defaults to RMT5 driver (wraps Espressif's led_strip component), which has known ISR handler lifecycle issues causing repeated "Handler detached" messages every ~500ms and severe performance degradation (e.g., 2 FPS). RMT5 is more prone to Wi-Fi/interrupt jitter than legacy RMT4. Solution: force legacy RMT4 by adding `-D FASTLED_RMT5=0` to build flags in platformio.ini, or switch to FastLED's parallel I/O drivers which don't use RMT. RMT4 and RMT5 cannot coexist in the same binary.

Learnt from: CR
Repo: MoonModules/MoonLight PR: 0
File: misc/parking/GEMINI.md:0-0
Timestamp: 2025-11-29T16:17:30.619Z
Learning: Applies to misc/parking/**/platformio.ini : Use PlatformIO to build and upload the ESP32 backend C++ code

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-16T15:53:11.236Z
Learning: For ESP32-PICO-MINI-02 (and similar ESP32 boards with PSRAM), the critical configuration to enable PSRAM is `board_build.arduino.memory_type = qio_qspi` in platformio.ini. The board JSON may already include `-DBOARD_HAS_PSRAM` and `flash_mode: qio`, but without the memory_type setting, PSRAM won't be properly initialized, causing LoadStoreError crashes when code tries to access PSRAM addresses.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-28T18:06:23.868Z
Learning: ESP32-P4 observed lower headroom for httpd task stack in MoonLight: NodeManager rename (create new node + rebuild controls + remove old) can overflow httpd stack when onUpdate runs in httpd. Mitigation: defer only NodeManager rename heavy work to SvelteKit loop via a small pendingRenames queue; keep identity short-circuit in compareRecursive and equality-guarded controls updates. Increasing httpd stack_size for P4 builds is an optional, broader fix.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 130
File: platformio.ini:207-209
Timestamp: 2026-02-22T12:37:03.751Z
Learning: FastLED RMT5 driver issues (ISR handler "Handler detached" messages and performance degradation) have been resolved in FastLED versions as of commit 27c99130c83ab666c4c6dbf389425fec5f27db05 (master 20260222). The `-D FASTLED_RMT5=0` workaround is no longer needed.
<!-- </add_learning>

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 121
File: src/MoonLight/Nodes/Drivers/D_FastLED.h:176-176
Timestamp: 2026-02-08T20:43:12.857Z
Learning: In MoonLight FastLED 3.11 driver (src/MoonLight/Nodes/Drivers/D_FastLED.h): Affinity is applied per-channel via fl::ChannelOptions.mAffinity passed to fl::ChannelConfig (not via FastLED.setExclusiveDriver). Keeping setExclusiveDriver commented out leaves all drivers available; FastLED then selects the appropriate driver for each channel based on the mAffinity preference ("RMT", "I2S", "SPI", "PARLIO", or "" for auto). This allows per-channel driver preferences rather than a global restriction.

Learnt from: CR
Repo: MoonModules/MoonLight PR: 0
File: misc/parking/GEMINI.md:0-0
Timestamp: 2025-11-29T16:17:30.619Z
Learning: Applies to misc/parking/**/factory_settings.ini : Configure default or factory-set ESP32 parameters in `factory_settings.ini`

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-18T12:49:07.297Z
Learning: In MoonLight channel reordering architecture: Keep rgbwBufferMapping in driver task (not effect task) because: (1) Driver has spare CPU cycles waiting for DMA/I2S/Art-Net timing; effect task is CPU-bound and starvation-prone. (2) Contiguous RGB writes in effects are cache-friendly; scattered writes at final offsets are cache-hostile for non-RGB orders (GRB, BGR, etc.). (3) forEachLightIndex already handles sparse mapping iteration; moving reordering to effects adds complexity without benefit since drivers must send full frames anyway (can't skip iteration). (4) rgbwBufferMapping does brightness/gamma LUT + white extraction + reordering—moving just reordering creates code duplication. (5) Effects should express color intent (CRGB), not hardware details (offsetRed/Green/Blue). Driver-side transformation maintains separation of concerns and task load balance for scaling to 98K+ pixels.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-18T17:07:33.344Z
Learning: FastLED library does not support direct 4-byte-per-pixel (CRGBW) buffers. It always expects CRGB (3-byte) arrays and internally generates the W channel from RGB using .setRgbw() API. Casting a 4-byte RGBW buffer to CRGB* causes misalignment (W becomes next pixel's R). For MoonLight's FastLED driver with channelsPerLight=4: must either (1) repack RGB in-place before FastLED.show() then restore after, (2) use driver-specific channelsPerLight=3 layout, or (3) allocate temporary RGB-only buffer. Option 1 (in-place repacking) is best for ESP32-D0 memory constraints.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2026-01-06T13:45:03.067Z
Learning: For MoonLight on ESP32 at extreme loads (e.g., 49K channels @ 100 fps): Task watchdog can fire when AppDrivers/AppEffects process many nodes without yielding. Even with vTaskDelay(1) at loop end, the node iteration for-loops (PhysicalLayer::loopDrivers line 108-111, PhysicalLayer::loop line 73-75) can take >5 seconds without yielding, starving IDLE task (priority 0). Solution: add taskYIELD() or vTaskDelay(1) inside the node/layer iteration loops to give IDLE task chances to run and reset watchdog. Lowering task priority won't help since IDLE is already at 0 (lowest).

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 84
File: src/MoonLight/Modules/ModuleLightsControl.h:367-379
Timestamp: 2025-12-28T10:28:24.157Z
Learning: In MoonLight PR `#84`: wrapping effectTask's layerP.loop() with monitorMutex while reading channelsE for monitor emission is thread-safe and prevents partial frames, but introduces serialization between effects rendering and monitor emission. Reading from channelsD (driver/front buffer) instead—with monitorMutex held only during the brief pointer swap—is superior because it maintains full parallelism (effects ║ monitor ║ driver), shows actual LED output, and minimizes mutex hold time.

Learnt from: ewowi
Repo: MoonModules/MoonLight PR: 0
File: :0-0
Timestamp: 2025-12-25T13:34:40.097Z
Learning: For the MoonLight LED system: Effects task can run on Core 0 (PRO_CPU) since it only performs computation (calculating colors, writing to channels array) without timing-critical hardware interaction. WiFi preemption is acceptable for pure computation tasks. Only the driver task (using DMA, I2S, LCD, PARLIO) requires Core 1 (APP_CPU) for uninterrupted timing-critical hardware operations.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain
🏁 Script executed:

#!/bin/bash
# First, let's examine the platformio.ini file around the specified lines and check for build flags
cat -n platformio.ini | head -230 | tail -50

Repository: MoonModules/MoonLight

Length of output: 3265

🏁 Script executed:

#!/bin/bash
# Search for all FastLED-related configuration flags in the repo
rg -n "FASTLED_RMT5|FASTLED_RMT4|FASTLED_BUILD|FASTLED_" --type ini --type txt --type h --type cpp

Repository: MoonModules/MoonLight

Length of output: 92

🏁 Script executed:

#!/bin/bash
# Check the exact commit details and verify build string alignment
# Find the git repository containing the pinned FastLED commit
rg -n "27c99130c83ab666c4c6dbf389425fec5f27db05" --type ini

Repository: MoonModules/MoonLight

Length of output: 92

🏁 Script executed:

#!/bin/bash
# Search for FASTLED_RMT5, FASTLED_RMT4, and related driver flags without file type restrictions
rg -n "FASTLED_RMT5|FASTLED_RMT4|FASTLED_SPI" .

Repository: MoonModules/MoonLight

Length of output: 47

🏁 Script executed:

#!/bin/bash
# Check the complete [moonlight] section and build_flags to see all configuration
sed -n '199,211p' platformio.ini

Repository: MoonModules/MoonLight

Length of output: 811

🏁 Script executed:

#!/bin/bash
# Check all build_flags sections across the entire platformio.ini
rg -B2 -A5 "build_flags|FASTLED" platformio.ini

Repository: MoonModules/MoonLight

Length of output: 2738

🏁 Script executed:

#!/bin/bash
# Verify the commit date by examining git if available, or search related documentation
# Check if there are any comments/docs about the FastLED version and RMT configuration
rg -n "27c99130c83ab666c4c6dbf389425fec5f27db05|RMT5|RMT4|Handler detached" .

Repository: MoonModules/MoonLight

Length of output: 181

🏁 Script executed:

#!/bin/bash
# Check platform-espressif32 version 55.03.37 for ESP-IDF details
# Look for package.json or version info in typical locations
rg -n "esp-idf|ESP-IDF|5\.[0-9]" platformio.ini | head -20

Repository: MoonModules/MoonLight

Length of output: 2966

🏁 Script executed:

#!/bin/bash
# Search for any Arduino core version or framework configuration
rg -n "framework|arduino|framework-esp32idf|framework-espidf" platformio.ini

Repository: MoonModules/MoonLight

Length of output: 3009

Add -D FASTLED_RMT5=0 to force legacy RMT4 driver and prevent ISR handler degradation.

The FASTLED_BUILD string aligns correctly with the pinned commit. However, platform 55.03.37 uses ESP-IDF 5.5+ with Arduino core 3.x, which causes FastLED to default to the RMT5 driver. RMT5 has documented ISR handler lifecycle issues (see FastLED issue #1903) causing repeated "Handler detached" messages and severe performance drops (~2 FPS). Add -D FASTLED_RMT5=0 to the [moonlight] build_flags to force the stable legacy RMT4 driver.

🤖 Prompt for AI Agents

Disabling RMT5 should not be necessary now? The RMT5 driver now allocates more memory during WIFI active mode. Please let me know if this isn't the case. RMT5 will have stress testing either this week if ai credits sustain. Otherwise post friday on refresh.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

https://github.com/ewowi/WLED-sync#25f280b5e8e47e49a95282d0b78a5ce5301af4fe ; sourceIP + fftUdp.clear() if arduino >=3 (20251104)

; 💫 currently only enabled on s3 as esp32dev runs over 100%
Expand Down
13 changes: 11 additions & 2 deletions src/MoonBase/Nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class LiveScriptNode : public Node {
// layout
void onLayout() override; // call map in LiveScript

~LiveScriptNode();
~LiveScriptNode() override;

// LiveScript functions
void compileAndRun();
Expand Down Expand Up @@ -346,6 +346,14 @@ static struct SharedData {
size_t clientListSize;

Coord3D gravity;

//FastLED Audio
bool vocalsActive = false;
float vocalConfidence = 0;
float bassLevel = 0;
float trebleLevel = 0;
bool beat = false;

} sharedData;

/**
Expand All @@ -359,7 +367,8 @@ static struct SharedData {
#include "MoonLight/Nodes/Drivers/D_ArtnetIn.h"
#include "MoonLight/Nodes/Drivers/D_ArtnetOut.h"
#include "MoonLight/Nodes/Drivers/D_AudioSync.h"
#include "MoonLight/Nodes/Drivers/D_FastLED.h"
#include "MoonLight/Nodes/Drivers/D_FastLEDDriver.h"
#include "MoonLight/Nodes/Drivers/D_FastLEDAudio.h"
#include "MoonLight/Nodes/Drivers/D_Hub75.h"
#include "MoonLight/Nodes/Drivers/D_Infrared.h"
#include "MoonLight/Nodes/Drivers/D_IMU.h"
Expand Down
4 changes: 4 additions & 0 deletions src/MoonLight/Modules/ModuleDrivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,12 @@ class ModuleDrivers : public NodeManager {
addControlValue(control, getNameAndTags<SpiralLayout>());
addControlValue(control, getNameAndTags<SingleRowLayout>());
addControlValue(control, getNameAndTags<SingleColumnLayout>());
addControlValue(control, getNameAndTags<TubesLayout>());

// Drivers, Most used first
addControlValue(control, getNameAndTags<ParallelLEDDriver>());
addControlValue(control, getNameAndTags<FastLEDDriver>());
addControlValue(control, getNameAndTags<FastLEDAudioDriver>());
addControlValue(control, getNameAndTags<ArtNetInDriver>());
addControlValue(control, getNameAndTags<ArtNetOutDriver>());
addControlValue(control, getNameAndTags<AudioSyncDriver>());
Expand Down Expand Up @@ -135,10 +137,12 @@ class ModuleDrivers : public NodeManager {
if (!node) node = checkAndAlloc<TorontoBarGourdsLayout>(name);
if (!node) node = checkAndAlloc<SingleRowLayout>(name);
if (!node) node = checkAndAlloc<SingleColumnLayout>(name);
if (!node) node = checkAndAlloc<TubesLayout>(name);

// Drivers most used first
if (!node) node = checkAndAlloc<ParallelLEDDriver>(name);
if (!node) node = checkAndAlloc<FastLEDDriver>(name);
if (!node) node = checkAndAlloc<FastLEDAudioDriver>(name);
if (!node) node = checkAndAlloc<ArtNetInDriver>(name);
if (!node) node = checkAndAlloc<ArtNetOutDriver>(name);
if (!node) node = checkAndAlloc<AudioSyncDriver>(name);
Expand Down
2 changes: 2 additions & 0 deletions src/MoonLight/Modules/ModuleEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ class ModuleEffects : public NodeManager {

// FastLED effects
addControlValue(control, getNameAndTags<RainbowEffect>());
addControlValue(control, getNameAndTags<FLAudioEffect>());

// Moving head effects, alphabetically
addControlValue(control, getNameAndTags<AmbientMoveEffect>());
Expand Down Expand Up @@ -291,6 +292,7 @@ class ModuleEffects : public NodeManager {

// FastLED
if (!node) node = checkAndAlloc<RainbowEffect>(name);
if (!node) node = checkAndAlloc<FLAudioEffect>(name);

// Moving head effects, alphabetically

Expand Down
101 changes: 101 additions & 0 deletions src/MoonLight/Nodes/Drivers/D_FastLEDAudio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
@title MoonLight
@file D_FastLEDAudio.h
@repo https://github.com/MoonModules/MoonLight, submit changes to this file as PRs
@Authors https://github.com/MoonModules/MoonLight/commits/main
@Doc https://moonmodules.org/MoonLight/moonlight/overview/
@Copyright © 2026 Github MoonLight Commit Authors
@license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
@license For non GPL-v3 usage, commercial licenses must be purchased. Contact us for more information.
**/

#pragma once

#if FT_MOONLIGHT

#include "fl/audio.h"
#include "fl/audio/audio_processor.h"
#include "fl/audio_input.h"
#include "fl/time_alpha.h"

#define I2S_CLK_PIN 6 // Serial Clock (SCK) (BLUE)
#define I2S_WS_PIN 4 // Word Select (WS) (GREEN)
#define I2S_SD_PIN 5 // Serial Data (SD) (YELLOW)
#define I2S_CHANNEL fl::Left

static fl::AudioConfigI2S i2sConfig(I2S_WS_PIN, I2S_SD_PIN, I2S_CLK_PIN, 0, I2S_CHANNEL, 44100, 16, fl::Philips);
static fl::AudioConfig config(i2sConfig);
static fl::shared_ptr<fl::IAudioInput> audioInput;

class FastLEDAudioDriver : public Node {
public:
static const char* name() { return "FastLED Audio"; }
static uint8_t dim() { return _NoD; }
static const char* tags() { return "☸️"; }

fl::AudioProcessor audioProcessor;

void setup() override {
Node::setup(); // !!

fl::string errorMsg;
audioInput = fl::IAudioInput::create(config, &errorMsg);
if (!audioInput) {
EXT_LOGE(ML_TAG, "Failed to create audio input: %s", errorMsg.c_str());
return;
}
audioInput->start();

audioProcessor.onBeat([]() {
sharedData.beat = true;
EXT_LOGD(ML_TAG, "onBeat");
});

audioProcessor.onVocalStart([]() {
sharedData.vocalsActive = true;
// EXT_LOGD(ML_TAG, "onVocalStart");
});

audioProcessor.onVocalEnd([]() {
sharedData.vocalsActive = false;
// EXT_LOGD(ML_TAG, "onVocalEnd");
});

audioProcessor.onVocalConfidence([](float confidence) {
sharedData.vocalConfidence = sharedData.vocalsActive ? confidence : 0.0;
// EXT_LOGD(ML_TAG, "onVocalConfidence %d", confidence);
});

audioProcessor.onBass([](float level) {
if (level > 0.01f) {
sharedData.bassLevel = level;
// EXT_LOGD(ML_TAG, "onBass: %f", level);
}
});

audioProcessor.onTreble([](float level) {
if (level > 0.01f) {
sharedData.trebleLevel = level;
// EXT_LOGD(ML_TAG, "onTreble: %f", level);
}
});
}

void loop20ms() override {
if (!audioInput) return;

sharedData.beat = false;

while (fl::AudioSample sample = audioInput->read()) {
audioProcessor.update(sample);
}
}

~FastLEDAudioDriver() override {
if (audioInput) {
audioInput->stop();
}
}
};

#endif
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
@title MoonLight
@file FastLED.h
@file D_FastLEDDriver.h
@repo https://github.com/MoonModules/MoonLight, submit changes to this file as PRs
@Authors https://github.com/MoonModules/MoonLight/commits/main
@Doc https://moonmodules.org/MoonLight/moonlight/overview/
Expand Down
40 changes: 40 additions & 0 deletions src/MoonLight/Nodes/Effects/E_FastLED.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,44 @@ class RainbowEffect : public Node {
}
};

class FLAudioEffect : public Node {
public:
static const char* name() { return "FLAudio"; }
static uint8_t dim() { return _2D; }
static const char* tags() { return "⚡️🎵"; }

void setup() {}

uint16_t hue = 0;
uint8_t beatLevel = 0;
float maxBass = 0;
float maxTreble = 0;
float maxVocal = 0;

void loop() override {
layer->fadeToBlackBy(70);

// maxLevels
if (sharedData.bassLevel > maxBass) maxBass = sharedData.bassLevel;
if (sharedData.trebleLevel > maxTreble) maxTreble = sharedData.trebleLevel;
if (sharedData.vocalConfidence > maxVocal) maxVocal = sharedData.vocalConfidence;

if (sharedData.beat) beatLevel = 255;

// EXT_LOGD(ML_TAG, "%f-%d %f-%d %d-%d %f-%d", sharedData.bassLevel, bassLevel, sharedData.trebleLevel, trebleLevel, sharedData.beat, beatLevel, sharedData.vocalsActive ? sharedData.vocalConfidence : 0, vocalsLevel);

layer->drawLine(0, layer->size.y - 1, 0, layer->size.y - 1 - layer->size.y * sharedData.bassLevel / maxBass, CRGB::Blue);
layer->drawLine(1, layer->size.y - 1, 1, layer->size.y - 1 - layer->size.y * sharedData.trebleLevel / maxTreble, CRGB::Orange);
layer->drawLine(2, layer->size.y - 1, 2, layer->size.y - 1 - layer->size.y * sharedData.vocalConfidence / maxVocal, CRGB::Green);
layer->drawLine(3, layer->size.y - 1, 3, layer->size.y - 1 - layer->size.y * beatLevel / 255, CRGB::Red);

//correct if lower output
if (maxBass > 0) maxBass -= 0.01;
if (maxTreble > 0) maxTreble -= 0.01;
if (maxVocal > 0) maxVocal -= 0.01;

if (beatLevel) beatLevel--;
}
};

#endif
10 changes: 7 additions & 3 deletions src/MoonLight/Nodes/Effects/E_WLED.h
Original file line number Diff line number Diff line change
Expand Up @@ -3560,14 +3560,18 @@ class WaterfallEffect : public Node {
uint8_t pixCol = (log10f(myMajorPeak) - 2.26f) * 150;
if (myMajorPeak < 182.0f) pixCol = 0;

for (int i = 0; i < layer->nrOfLights - 1; i++) layer->setRGB(i, layer->getRGB(i + 1));
for (int x = 0; x < layer->size.x; x++)
for (int z = 0; z < layer->size.z; z++)
for (int y = 0; y < layer->size.y - 1; y++) layer->setRGB(Coord3D(x, y, z), layer->getRGB(Coord3D(x, y + 1, z)));

bool peak = sharedData.volume > 128.0f;
if (peak) {
layer->setRGB(layer->nrOfLights - 1, CHSV(92, 92, 92));
for (int x = 0; x < layer->size.x; x++)
for (int z = 0; z < layer->size.z; z++) layer->setRGB(Coord3D(x, layer->size.y - 1, z), CHSV(92, 92, 92));
} else {
CRGB color = ColorFromPalette(layerP.palette, pixCol + intensity, 127 + myMagnitude / 2.0);
layer->setRGB(layer->nrOfLights - 1, color); // blend(layerP.color2, color, (int)myMagnitude));
for (int x = 0; x < layer->size.x; x++)
for (int z = 0; z < layer->size.z; z++) layer->setRGB(Coord3D(x, layer->size.y - 1, z), color); // blend(layerP.color2, color, (int)myMagnitude));
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/MoonLight/Nodes/Layouts/L_MoonLight.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
@license For non GPL-v3 usage, commercial licenses must be purchased. Contact us for more information.
**/

#pragma once

#if FT_MOONLIGHT

class HumanSizedCubeLayout : public Node {
Expand Down Expand Up @@ -437,6 +439,36 @@ class SingleColumnLayout : public Node {
}
};

class TubesLayout : public Node {
public:
static const char* name() { return "Tubes"; }
static uint8_t dim() { return _2D; }
static const char* tags() { return "🚥"; }

uint8_t nrOfTubes = 4;
uint8_t ledsPerTube = 54;
uint8_t tubeDistance = 10;
bool reversed_order = false;

void setup() override {
addControl(nrOfTubes, "nrOfTubes", "slider");
addControl(ledsPerTube, "ledsPerTube", "slider");
addControl(tubeDistance, "tubeDistance", "slider");
addControl(reversed_order, "reversed order", "checkbox");
}

bool hasOnLayout() const override { return true; }
void onLayout() override {
for (int tube = 0; tube < nrOfTubes; tube++) {
SingleColumnLayout tubeLayout;
tubeLayout.height = ledsPerTube;
tubeLayout.reversed_order = reversed_order;
tubeLayout.xposition = tube * tubeDistance;
tubeLayout.onLayout();
}
}
};

class RingLayout : public Node {
public:
static const char* name() { return "Ring"; }
Expand Down
7 changes: 4 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,10 @@ void setup() {
if (Serial) Serial.printf("Serial init wait %d\n", i * 300);
}

if (Serial) Serial.flush();

Serial.setDebugOutput(true);
if (Serial) {
Serial.flush();
// Serial.setDebugOutput(true); //causes all EXT_LOG to dissappear
}

Serial.printf("C++ Standard: %ld\n", __cplusplus); // 202002L

Expand Down