From 025be3b8724ed05be543f7979c9d16e91fc55e4c Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 21 Oct 2025 19:01:18 +0200 Subject: [PATCH 1/6] adding dynamic update of LED type dropdown, remove restriction --- wled00/data/settings_leds.htm | 49 +++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 8a3330e473..32b185338f 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -270,7 +270,8 @@ 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) + s.addEventListener('change', updateTypeDropdowns); + //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); @@ -447,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); @@ -522,18 +514,9 @@ } }); enLA(d.Sf["LAsel"+s],s); // update LED mA - // disable inappropriate LED types - 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.selectedIndex = sel.querySelector('option:not(:disabled)').index; } 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") @@ -541,6 +524,7 @@ if (!init) { UI(); + updateTypeDropdowns(); } } @@ -742,6 +726,7 @@ if (i.value!=="" && i.value>=0) i.dataset.val = i.value; }); + updateTypeDropdowns(); } function pinUpd(e) { // update changed select options across all usermods @@ -812,6 +797,32 @@ } 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 count + let maxDB = maxD - ((is32() || isS2() || isS3()) ? (!d.Sf["PR"].checked) * 8 - (!isS3()) : 0); + // disallow adding more of a type that has reached its limit + if (digitalB >= maxDB && !isDig(curType)) disable('option[data-type="D"]'); + if (twopinB >= 2 && !isD2P(curType)) disable('option[data-type="2P"]'); + disable(`option[data-type^="${'A'.repeat(maxA - analogB + (isPWM(curType)?numPins(curType):0) + 1)}"]`); + }); + } From 0e0e1ac314bb1f23676d50379c7789c0010d111c Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 22 Oct 2025 08:15:27 +0200 Subject: [PATCH 2/6] call updateTypeDropdowns() at end of UI(), bugfix fixed bug that allowed to change to 2-pin digital and then back to 1-pin digital. --- wled00/data/settings_leds.htm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 32b185338f..f5b876938a 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -270,8 +270,6 @@ let dC = 0; // count of digital buses (for parallel I2S) let LTs = d.Sf.querySelectorAll("#mLC select[name^=LT]"); LTs.forEach((s,i)=>{ - s.addEventListener('change', updateTypeDropdowns); - //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); @@ -435,6 +433,8 @@ gId('fpsNone').style.display = (d.Sf.FR.value == 0) ? 'block':'none'; gId('fpsWarn').style.display = (d.Sf.FR.value == 0) || (d.Sf.FR.value >= 80) ? 'block':'none'; gId('fpsHigh').style.display = (d.Sf.FR.value >= 80) ? 'block':'none'; + // restrict bus types in dropdowns to max allowed digital/analog buses + updateTypeDropdowns(); } function lastEnd(i) { if (i-- < 1) return 0; @@ -524,7 +524,6 @@ if (!init) { UI(); - updateTypeDropdowns(); } } @@ -726,7 +725,6 @@ if (i.value!=="" && i.value>=0) i.dataset.val = i.value; }); - updateTypeDropdowns(); } function pinUpd(e) { // update changed select options across all usermods @@ -818,7 +816,7 @@ // max digital count let maxDB = maxD - ((is32() || isS2() || isS3()) ? (!d.Sf["PR"].checked) * 8 - (!isS3()) : 0); // disallow adding more of a type that has reached its limit - if (digitalB >= maxDB && !isDig(curType)) disable('option[data-type="D"]'); + if (digitalB >= maxDB && !(isDig(curType) && !isD2P(curType))) disable('option[data-type="D"]'); if (twopinB >= 2 && !isD2P(curType)) disable('option[data-type="2P"]'); disable(`option[data-type^="${'A'.repeat(maxA - analogB + (isPWM(curType)?numPins(curType):0) + 1)}"]`); }); From 7ce356a80822462c52e901d4ce7914636de2c53e Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 22 Oct 2025 19:05:49 +0200 Subject: [PATCH 3/6] add clarifying comments --- wled00/data/settings_leds.htm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index f5b876938a..e04afb39fe 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -814,6 +814,8 @@ const enable = (q) => sel.querySelectorAll(q).forEach(o => o.disabled = false); enable('option'); // reset all first // max digital count + // 32 & S2 supports 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); // disallow adding more of a type that has reached its limit if (digitalB >= maxDB && !(isDig(curType) && !isD2P(curType))) disable('option[data-type="D"]'); From d89b7f923242116f377bd7148eea3e072f494862 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 23 Oct 2025 18:37:27 +0200 Subject: [PATCH 4/6] bugfix: dont allow additional digital buses --- wled00/data/settings_leds.htm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index e04afb39fe..e448d24b04 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -514,6 +514,11 @@ } }); enLA(d.Sf["LAsel"+s],s); // update LED mA + // temporarily set to virtual (network) type to avoid "same type" exception during dropdown update + let sel = d.getElementsByName("LT"+s)[0]; + 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; } if (n==-1) { o[--i].remove();--i; @@ -813,11 +818,10 @@ 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 count - // 32 & S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel + // 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); - // disallow adding more of a type that has reached its limit + 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(`option[data-type^="${'A'.repeat(maxA - analogB + (isPWM(curType)?numPins(curType):0) + 1)}"]`); From d0fdaf2e2d9a963bb0113249f94fc449089cd9e6 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 26 Oct 2025 19:02:02 +0100 Subject: [PATCH 5/6] move updateTypeDropdowns() --- wled00/data/settings_leds.htm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index e448d24b04..52eee44fbd 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -267,6 +267,7 @@ } // 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)=>{ @@ -433,8 +434,6 @@ gId('fpsNone').style.display = (d.Sf.FR.value == 0) ? 'block':'none'; gId('fpsWarn').style.display = (d.Sf.FR.value == 0) || (d.Sf.FR.value >= 80) ? 'block':'none'; gId('fpsHigh').style.display = (d.Sf.FR.value >= 80) ? 'block':'none'; - // restrict bus types in dropdowns to max allowed digital/analog buses - updateTypeDropdowns(); } function lastEnd(i) { if (i-- < 1) return 0; From 31c33568704893f54ad687a8c1a3746194e4311f Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 26 Oct 2025 19:09:01 +0100 Subject: [PATCH 6/6] add comment as suggested by the rabbit --- wled00/data/settings_leds.htm | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 52eee44fbd..a3b3a915d5 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -823,6 +823,7 @@ // 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)}"]`); }); }