From a947e8f35e919590616289d9399fef1a1d369b7a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:26:35 +0000 Subject: [PATCH 01/11] Initial plan From a2c1ad01da2d8ee90f0cbca334cacd9df0595764 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:29:07 +0000 Subject: [PATCH 02/11] Fix usermods.yml to only run for external fork PRs Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- .github/workflows/usermods.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/usermods.yml b/.github/workflows/usermods.yml index 9b60e400..3452ed46 100644 --- a/.github/workflows/usermods.yml +++ b/.github/workflows/usermods.yml @@ -12,6 +12,8 @@ on: jobs: get_usermod_envs: + # Run on push events, or on pull_request events only from forks (not from branches within wled/WLED) + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository name: Gather Usermods runs-on: ubuntu-latest steps: @@ -31,6 +33,8 @@ jobs: build: + # Run on push events, or on pull_request events only from forks (not from branches within wled/WLED) + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository name: Build Enviornments runs-on: ubuntu-latest needs: get_usermod_envs From 7c6a1d717dd30e39ae60ab035dee2559b0d85dc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:46:13 +0000 Subject: [PATCH 03/11] Remove push trigger, only run usermods CI for external fork PRs Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- .github/workflows/usermods.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/usermods.yml b/.github/workflows/usermods.yml index 3452ed46..e8ab6506 100644 --- a/.github/workflows/usermods.yml +++ b/.github/workflows/usermods.yml @@ -1,10 +1,6 @@ name: Usermod CI on: - push: - paths: - - usermods/** - - .github/workflows/usermods.yml pull_request: paths: - usermods/** @@ -12,8 +8,8 @@ on: jobs: get_usermod_envs: - # Run on push events, or on pull_request events only from forks (not from branches within wled/WLED) - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + # Only run for pull requests from forks (not from branches within wled/WLED) + if: github.event.pull_request.head.repo.full_name != github.repository name: Gather Usermods runs-on: ubuntu-latest steps: @@ -33,8 +29,8 @@ jobs: build: - # Run on push events, or on pull_request events only from forks (not from branches within wled/WLED) - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + # Only run for pull requests from forks (not from branches within wled/WLED) + if: github.event.pull_request.head.repo.full_name != github.repository name: Build Enviornments runs-on: ubuntu-latest needs: get_usermod_envs From f70b359631c08ae79eb4a23bfac3ccc293f98f22 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 1 Dec 2025 21:43:45 -0500 Subject: [PATCH 04/11] Revert "Fix ESP8266 DMA off-by-one" This reverts commit 4fa4bc8d4be7bc3f5a7184a0203db4a79b00dafe. --- .../include/NeoEsp8266DmaMethodFix.h | 122 ------------------ lib/NeoESP8266DMAFix/library.json | 12 -- platformio.ini | 1 - wled00/bus_wrapper.h | 3 - 4 files changed, 138 deletions(-) delete mode 100644 lib/NeoESP8266DMAFix/include/NeoEsp8266DmaMethodFix.h delete mode 100644 lib/NeoESP8266DMAFix/library.json diff --git a/lib/NeoESP8266DMAFix/include/NeoEsp8266DmaMethodFix.h b/lib/NeoESP8266DMAFix/include/NeoEsp8266DmaMethodFix.h deleted file mode 100644 index 5c5608b0..00000000 --- a/lib/NeoESP8266DMAFix/include/NeoEsp8266DmaMethodFix.h +++ /dev/null @@ -1,122 +0,0 @@ -/*------------------------------------------------------------------------- -NeoPixel library helper functions for Esp8266. - -FIXED VERSION FROM https://github.com/Makuna/NeoPixelBus/pull/894 -This library will overlay/shadow the base version from NeoPixelBus - -Written by Michael C. Miller. -Thanks to g3gg0.de for porting the initial DMA support which lead to this. -Thanks to github/cnlohr for the original work on DMA support, which opend -all our minds to a better way (located at https://github.com/cnlohr/esp8266ws2812i2s). - -I invest time and resources providing this open source code, -please support me by donating (see https://github.com/Makuna/NeoPixelBus) - -------------------------------------------------------------------------- -This file is part of the Makuna/NeoPixelBus library. - -NeoPixelBus is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as -published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -NeoPixelBus is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with NeoPixel. If not, see -. --------------------------------------------------------------------------*/ - -#pragma once - -#ifdef ARDUINO_ARCH_ESP8266 -#include "internal/methods/NeoEsp8266DmaMethod.h" - -template class NeoEsp8266Dma3StepEncodeFixed : public T_PATTERN -{ -public: - const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding - - static size_t SpacingPixelSize(size_t sizePixel) - { - return sizePixel; - } - - static void FillBuffers(uint8_t* i2sBuffer, - const uint8_t* data, - size_t sizeData, - [[maybe_unused]] size_t sizePixel) - { - const uint8_t SrcBitMask = 0x80; - const size_t BitsInSample = sizeof(uint32_t) * 8; - - uint32_t* pDma = reinterpret_cast(i2sBuffer); - uint32_t dmaValue = 0; - uint8_t destBitsLeft = BitsInSample; - - const uint8_t* pSrc = data; - const uint8_t* pEnd = pSrc + sizeData; - - while (pSrc < pEnd) - { - uint8_t value = *(pSrc++); - - for (uint8_t bitSrc = 0; bitSrc < 8; bitSrc++) - { - const uint16_t Bit = ((value & SrcBitMask) ? T_PATTERN::OneBit3Step : T_PATTERN::ZeroBit3Step); - - if (destBitsLeft > 3) - { - destBitsLeft -= 3; - dmaValue |= Bit << destBitsLeft; - -#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) - NeoUtil::PrintBin(dmaValue); - Serial.print(" < "); - Serial.println(destBitsLeft); -#endif - } - else if (destBitsLeft <= 3) - { - uint8_t bitSplit = (3 - destBitsLeft); - dmaValue |= Bit >> bitSplit; - -#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) - NeoUtil::PrintBin(dmaValue); - Serial.print(" > "); - Serial.println(bitSplit); -#endif - // next dma value, store and reset - *(pDma++) = dmaValue; - dmaValue = 0; - - destBitsLeft = BitsInSample - bitSplit; - if (bitSplit) - { - dmaValue |= Bit << destBitsLeft; - } - -#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) - NeoUtil::PrintBin(dmaValue); - Serial.print(" v "); - Serial.println(bitSplit); -#endif - } - - // Next - value <<= 1; - } - } - // store the remaining bits - if (destBitsLeft != BitsInSample) *pDma++ = dmaValue; - } -}; - -// Abuse explict specialization to overlay the methods -template<> class NeoEsp8266Dma3StepEncode : public NeoEsp8266Dma3StepEncodeFixed {}; -template<> class NeoEsp8266Dma3StepEncode : public NeoEsp8266Dma3StepEncodeFixed {}; - -#endif diff --git a/lib/NeoESP8266DMAFix/library.json b/lib/NeoESP8266DMAFix/library.json deleted file mode 100644 index 045acc7a..00000000 --- a/lib/NeoESP8266DMAFix/library.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "NeoESP8266DMAFix", - "build": { "libArchive": false }, - "platforms": ["espressif8266"], - "dependencies": [ - { - "owner": "makuna", - "name": "NeoPixelBus", - "version": "2.8.3" - } - ] -} diff --git a/platformio.ini b/platformio.ini index e0b3d973..655f0c65 100644 --- a/platformio.ini +++ b/platformio.ini @@ -220,7 +220,6 @@ lib_deps = ESPAsyncUDP ESP8266PWM ${env.lib_deps} - NeoESP8266DMAFix ;; compatibilty flags - same as 0.14.0 which seems to work better on some 8266 boards. Not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 build_flags_compat = diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index 2d68081f..b2ff9474 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -4,9 +4,6 @@ //#define NPB_CONF_4STEP_CADENCE #include "NeoPixelBus.h" -#ifdef ARDUINO_ARCH_ESP8266 -#include -#endif //Hardware SPI Pins #define P_8266_HS_MOSI 13 From 7b9d643dcdc26246ca9eca8fafe6f715cab257b7 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 1 Dec 2025 21:44:26 -0500 Subject: [PATCH 05/11] Update NeoPixelBus with DMA fix Includes bonus fix for ESP32 DMA driver, too! Replaces #5138. --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 655f0c65..98676c11 100644 --- a/platformio.ini +++ b/platformio.ini @@ -160,7 +160,7 @@ lib_compat_mode = strict lib_deps = fastled/FastLED @ 3.6.0 IRremoteESP8266 @ 2.8.2 - makuna/NeoPixelBus @ 2.8.3 + https://github.com/Makuna/NeoPixelBus.git#a0919d1c10696614625978dd6fb750a1317a14ce https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 marvinroger/AsyncMqttClient @ 0.9.0 # for I2C interface From c114ea6b300efc6f44c7b59646e04c853fa3b83d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:57:45 +0100 Subject: [PATCH 06/11] AR bugfix prevents crash in case that audioSource creation (audio startup) failed --- usermods/audioreactive/audio_reactive.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usermods/audioreactive/audio_reactive.cpp b/usermods/audioreactive/audio_reactive.cpp index 1d1825fd..2b7b25aa 100644 --- a/usermods/audioreactive/audio_reactive.cpp +++ b/usermods/audioreactive/audio_reactive.cpp @@ -1335,7 +1335,7 @@ class AudioReactive : public Usermod { disableSoundProcessing = true; } else { #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DEBUG) - if ((disableSoundProcessing == true) && (audioSyncEnabled == 0) && audioSource->isInitialized()) { // we just switched to "enabled" + if ((disableSoundProcessing == true) && (audioSyncEnabled == 0) && audioSource && audioSource->isInitialized()) { // we just switched to "enabled" DEBUG_PRINTLN(F("[AR userLoop] realtime mode ended - audio processing resumed.")); DEBUG_PRINTF_P(PSTR(" RealtimeMode = %d; RealtimeOverride = %d\n"), int(realtimeMode), int(realtimeOverride)); } @@ -1347,7 +1347,7 @@ class AudioReactive : public Usermod { if (audioSyncEnabled & 0x02) disableSoundProcessing = true; // make sure everything is disabled IF in audio Receive mode if (audioSyncEnabled & 0x01) disableSoundProcessing = false; // keep running audio IF we're in audio Transmit mode #ifdef ARDUINO_ARCH_ESP32 - if (!audioSource->isInitialized()) disableSoundProcessing = true; // no audio source + if (!audioSource || !audioSource->isInitialized()) disableSoundProcessing = true; // no audio source // Only run the sampling code IF we're not in Receive mode or realtime mode From 8cbc76540f7f16d074ee90420f705cf218e928cd Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 3 Dec 2025 06:56:38 +0100 Subject: [PATCH 07/11] adding dynamic update of LED type dropdown (#5014) * adding dynamic update of LED type dropdown, remove restriction * update LED type dropdown upon selection, credit @blazoncek --- wled00/data/settings_leds.htm | 52 +++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 109496c0..47c4f514 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -268,10 +268,10 @@ } // enable/disable LED fields + updateTypeDropdowns(); // restrict bus types in dropdowns to max allowed digital/analog buses let dC = 0; // count of digital buses (for parallel I2S) let LTs = d.Sf.querySelectorAll("#mLC select[name^=LT]"); LTs.forEach((s,i)=>{ - if (i < LTs.length-1) s.disabled = true; // prevent changing type (as we can't update options) // is the field a LED type? var n = s.name.substring(2,3); // bus number (0-Z) var t = parseInt(s.value); @@ -448,17 +448,8 @@ { var o = gEBCN("iST"); var i = o.length; - let disable = (sel,opt) => { sel.querySelectorAll(opt).forEach((o)=>{o.disabled=true;}); } var f = gId("mLC"); - let digitalB = 0, analogB = 0, twopinB = 0, virtB = 0; - f.querySelectorAll("select[name^=LT]").forEach((s)=>{ - let t = s.value; - if (isDig(t) && !isD2P(t)) digitalB++; - if (isD2P(t)) twopinB++; - if (isPWM(t)) analogB += numPins(t); // each GPIO is assigned to a channel - if (isVir(t)) virtB++; - }); if ((n==1 && i>=36) || (n==-1 && i==0)) return; // used to be i>=maxB+maxV when virtual buses were limited (now :"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") var s = chrID(i); @@ -468,7 +459,7 @@ var cn = `

${i+1}: -
+
mA/LED: } }); enLA(d.Sf["LAsel"+s],s); // update LED mA - // disable inappropriate LED types + // temporarily set to virtual (network) type to avoid "same type" exception during dropdown update let sel = d.getElementsByName("LT"+s)[0]; - // 32 & S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel - let maxDB = maxD - (is32() || isS2() || isS3() ? (!d.Sf["PR"].checked)*8 - (!isS3()) : 0); // adjust max digital buses if parallel I2S is not used - if (digitalB >= maxDB) disable(sel,'option[data-type="D"]'); // NOTE: see isDig() - if (twopinB >= 2) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P() (we will only allow 2 2pin buses) - disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM() + sel.value = sel.querySelector('option[data-type="N"]').value; + updateTypeDropdowns(); // update valid bus options including this new one sel.selectedIndex = sel.querySelector('option:not(:disabled)').index; + updateTypeDropdowns(); // update again for the newly selected type } if (n==-1) { o[--i].remove();--i; - o[i].querySelector("[name^=LT]").disabled = false; } gId("+").style.display = (i<35) ? "inline":"none"; // was maxB+maxV-1 when virtual buses were limited (now :"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") @@ -829,6 +817,34 @@ Swap: