mirror of
https://github.com/wled/WLED.git
synced 2025-12-09 01:27:51 +00:00
Compare commits
12 Commits
copilot/up
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95cbf0f32b | ||
|
|
cc5b504771 | ||
|
|
fe33709eb0 | ||
|
|
41b51edbdd | ||
|
|
e6b5429873 | ||
|
|
8cbc76540f | ||
|
|
c114ea6b30 | ||
|
|
bdea3d4959 | ||
|
|
e403f4e0d0 | ||
|
|
7b9d643dcd | ||
|
|
f70b359631 | ||
|
|
ae37f4268c |
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "NeoESP8266DMAFix",
|
||||
"build": { "libArchive": false },
|
||||
"platforms": ["espressif8266"],
|
||||
"dependencies": [
|
||||
{
|
||||
"owner": "makuna",
|
||||
"name": "NeoPixelBus",
|
||||
"version": "2.8.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user