Compare commits

...

12 Commits

Author SHA1 Message Date
dependabot[bot]
95cbf0f32b Bump urllib3 from 2.5.0 to 2.6.0
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.5.0 to 2.6.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.6.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-06 04:48:08 +00:00
Frank
cc5b504771 Add cherry-picking tip to CONTRIBUTING.md
Added a tip about using cherry-picking for copying commits, especially to copy from a local working branch (e.g. ``main``) to the PR branch.
2025-12-03 20:36:08 +01:00
Frank
fe33709eb0 some clarifications
Corrected grammar and clarity in AI contribution guidelines.
2025-12-03 15:19:20 +01:00
Frank
41b51edbdd text styling 2025-12-03 15:15:27 +01:00
Frank
e6b5429873 Update CONTRIBUTING.md with AI usage guidelines
Added guidelines for contributions involving AI assistance.
2025-12-03 15:13:38 +01:00
Damian Schneider
8cbc76540f 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
2025-12-03 06:56:38 +01:00
Frank
c114ea6b30 AR bugfix
prevents crash in case that audioSource creation (audio startup) failed
2025-12-02 22:57:45 +01:00
Will Tatam
bdea3d4959 Merge pull request #5143 from wled/copilot/update-usermods-trigger-logic
Fix usermods.yml to only trigger for external fork PRs
2025-12-02 08:08:14 +00:00
Will Tatam
e403f4e0d0 Merge pull request #5147 from willmmiles/npb-894
Replace #5138 with upstream NeoPixelBus fix
2025-12-02 08:05:51 +00:00
Will Miles
7b9d643dcd Update NeoPixelBus with DMA fix
Includes bonus fix for ESP32 DMA driver, too!
Replaces #5138.
2025-12-01 21:54:04 -05:00
Will Miles
f70b359631 Revert "Fix ESP8266 DMA off-by-one"
This reverts commit 4fa4bc8d4b.
2025-12-01 21:43:45 -05:00
Frank
ae37f4268c platformio.ini: short hashes => long hashes
short hashes can cause spurious build errors, and will not be supported any more in future platform version.
2025-12-01 20:26:22 +01:00
8 changed files with 59 additions and 162 deletions

View File

@@ -26,9 +26,28 @@ Github will pick up the changes so your PR stays up-to-date.
> It has many subtle and unexpected consequences on our github reposistory.
> For example, we regularly lost review comments when the PR author force-pushes code changes. So, pretty please, do not force-push.
> [!TIP]
> use [cherry-picking](https://docs.github.com/en/desktop/managing-commits/cherry-picking-a-commit-in-github-desktop) to copy commits from one branch to another.
You can find a collection of very useful tips and tricks here: https://github.com/wled-dev/WLED/wiki/How-to-properly-submit-a-PR
### Source Code from an AI agent or bot
> [!IMPORTANT]
> Its OK if you took help from an AI for writing your source code.
>
> However, we expect a few things from you as the person making a contribution to WLED:
* Make sure you really understand the code suggested by the AI, and don't just accept it because it "seems to work".
* Don't let the AI change existing code without double-checking by you as the contributor. Often, the result will not be complete. For example, previous source code comments may be lost.
* Remember that AI are still "Often-Wrong" ;-)
* If you don't feel very confident using English, you can use AI for translating code comments and descriptions into English. AI bots are very good at understanding language. However, always check if the results is correct. The translation might still have wrong technical terms, or errors in some details.
#### best practice with AI:
* As the person who contributes source code to WLED, make sure you understand exactly what the AI generated code does
* best practice: add a comment like ``'// below section of my code was generated by an AI``, when larger parts of your source code were not written by you personally.
* always review translations and code comments for correctness
* always review AI generated source code
* If the AI has rewritten existing code, check that the change is necessary and that nothing has been lost or broken. Also check that previous code comments are still intact.
### Code style

View File

@@ -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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#pragma once
#ifdef ARDUINO_ARCH_ESP8266
#include "internal/methods/NeoEsp8266DmaMethod.h"
template<typename T_PATTERN> 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<uint32_t*>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<NeoEsp8266DmaNormalPattern> : public NeoEsp8266Dma3StepEncodeFixed<NeoEsp8266DmaNormalPattern> {};
template<> class NeoEsp8266Dma3StepEncode<NeoEsp8266DmaInvertedPattern> : public NeoEsp8266Dma3StepEncodeFixed<NeoEsp8266DmaInvertedPattern> {};
#endif

View File

@@ -1,12 +0,0 @@
{
"name": "NeoESP8266DMAFix",
"build": { "libArchive": false },
"platforms": ["espressif8266"],
"dependencies": [
{
"owner": "makuna",
"name": "NeoPixelBus",
"version": "2.8.3"
}
]
}

View File

@@ -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
@@ -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 =
@@ -257,7 +256,7 @@ lib_deps_compat =
lib_deps =
esp32async/AsyncTCP @ 3.4.7
bitbank2/AnimatedGIF@^1.4.7
https://github.com/Aircoookie/GifDecoder#bc3af18
https://github.com/Aircoookie/GifDecoder.git#bc3af189b6b1e06946569f6b4287f0b79a860f8e
build_flags =
-D CONFIG_ASYNC_TCP_USE_WDT=0
-D CONFIG_ASYNC_TCP_STACK_SIZE=8192
@@ -301,7 +300,7 @@ build_flags = -g
-D WLED_ENABLE_DMX_INPUT
lib_deps =
${esp32_all_variants.lib_deps}
https://github.com/someweisguy/esp_dmx.git#47db25d
https://github.com/someweisguy/esp_dmx.git#47db25d8c515e76fabcf5fc5ab0b786f98eeade0
${env.lib_deps}
[esp32s2]

View File

@@ -50,7 +50,7 @@ tabulate==0.9.0
# via platformio
typing-extensions==4.12.2
# via anyio
urllib3==2.5.0
urllib3==2.6.0
# via requests
uvicorn==0.34.0
# via platformio

View File

@@ -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

View File

@@ -4,9 +4,6 @@
//#define NPB_CONF_4STEP_CADENCE
#include "NeoPixelBus.h"
#ifdef ARDUINO_ARCH_ESP8266
#include <NeoEsp8266DmaMethodFix.h>
#endif
//Hardware SPI Pins
#define P_8266_HS_MOSI 13

View File

@@ -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 = `<div class="iST">
<hr class="sml">
${i+1}:
<select name="LT${s}" onchange="UI(true)"></select><br>
<select name="LT${s}" onchange="updateTypeDropdowns();UI(true)"></select><br>
<div id="abl${s}">
mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
<option value="55" selected>55mA (typ. 5V WS281x)</option>
@@ -523,18 +514,15 @@ mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
}
});
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: <select id="xw${s}" name="XW${s}">
}
return opt;
}
// dynamically enforce bus type availability based on current usage
function updateTypeDropdowns() {
let LTs = d.Sf.querySelectorAll("#mLC select[name^=LT]");
let digitalB = 0, analogB = 0, twopinB = 0, virtB = 0;
// count currently used buses
LTs.forEach(sel => {
let t = parseInt(sel.value);
if (isDig(t) && !isD2P(t)) digitalB++;
if (isPWM(t)) analogB += numPins(t);
if (isD2P(t)) twopinB++;
if (isVir(t)) virtB++;
});
// enable/disable type options according to limits in dropdowns
LTs.forEach(sel => {
const curType = parseInt(sel.value);
const disable = (q) => sel.querySelectorAll(q).forEach(o => o.disabled = true);
const enable = (q) => sel.querySelectorAll(q).forEach(o => o.disabled = false);
enable('option'); // reset all first
// max digital buses: ESP32 & S2 support mono I2S as well as parallel so we need to take that into account; S3 only supports parallel
// supported outputs using parallel I2S/mono I2S: S2: 12/5, S3: 12/4, ESP32: 16/9
let maxDB = maxD - ((is32() || isS2() || isS3()) ? (!d.Sf["PR"].checked) * 8 - (!isS3()) : 0); // adjust max digital buses if parallel I2S is not used
// disallow adding more of a type that has reached its limit but allow changing the current type
if (digitalB >= maxDB && !(isDig(curType) && !isD2P(curType))) disable('option[data-type="D"]');
if (twopinB >= 2 && !isD2P(curType)) disable('option[data-type="2P"]');
// Disable PWM types that need more pins than available (accounting for current type's pins if PWM)
disable(`option[data-type^="${'A'.repeat(maxA - analogB + (isPWM(curType)?numPins(curType):0) + 1)}"]`);
});
}
</script>
<style>@import url("style.css");</style>
</head>