diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 8a3330e473..ad893359b6 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -13,8 +13,9 @@ function gT(t) { for (let type of d.ledTypes) if (t == type.i) return type; } // getType from available ledTypes function isPWM(t) { return gT(t).t.charAt(0) === "A"; } // is PWM type function isAna(t) { return gT(t).t === "" || isPWM(t); } // is analog type - function isDig(t) { return gT(t).t === "D" || isD2P(t); } // is digital type + function isD1P(t) { return gT(t).t === "D"; } // is digital 1 pin type function isD2P(t) { return gT(t).t === "2P"; } // is digital 2 pin type + function isDig(t) { return isD1P(t) || isD2P(t); } // is digital type function isNet(t) { return gT(t).t === "N"; } // is network type function isVir(t) { return gT(t).t === "V" || isNet(t); } // is virtual type function isHub75(t){ return gT(t).t === "H"; } // is HUB75 type @@ -71,7 +72,7 @@ return; } // ignore IP address - if (isNet(t)) return; + if (isNet(t)) return; //check for pin conflicts if (LC.value!="" && LC.value!="-1") { let p = d.rsvd.concat(d.um_p); // used pin array @@ -101,10 +102,10 @@ nList[j].focus(); ok = false; return; - } } } } + } }); return ok; } @@ -118,7 +119,6 @@ if (bquot > 100) msg += "\n\rToo many LEDs for me to handle properly!"; if (maxM < 10000) msg += "\n\rConsider using an ESP32."; alert(msg);} if (!d.Sf.ABL.checked || d.Sf.PPL.checked) d.Sf.MA.value = 0; // submit 0 as ABL (PPL will handle it) if (d.Sf.checkValidity()) { - d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{s.disabled=false;}); // just in case d.Sf.submit(); //https://stackoverflow.com/q/37323914 } } @@ -131,7 +131,7 @@ if (!en) { // limiter disabled d.Sf.PPL.checked = false; -// d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((e)=>{e.selectedIndex = 0;}); // select default LED mA +// d.Sf.querySelectorAll("#mLC select[name^=LL]").forEach((e)=>{e.selectedIndex = 0;}); // select default LED mA // d.Sf.querySelectorAll("#mLC input[name^=LA]").forEach((e)=>{e.min = 0; e.value = 0;}); // set min & value to 0 } UI(); @@ -160,9 +160,10 @@ if (ppl) d.Sf.MA.value = sumMA; // populate UI ABL value if PPL used } // enable and update LED Amps - function enLA(s,n) + function enLA(s) { const abl = d.Sf.ABL.checked; + const n = s.name.substring(2); // bus number (0-Z) const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT gId('LAdis'+n).style.display = s.selectedIndex==5 ? "inline" : "none"; // show/hide custom mA field if (s.value!=="0") d.Sf["LA"+n].value = s.value; // set value from select object @@ -177,9 +178,9 @@ }); d.Sf.ABL.checked = en; // select appropriate LED current - d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,x)=>{ + d.Sf.querySelectorAll("#mLC select[name^=LL]").forEach((sel)=>{ sel.value = 0; // set custom - var n = chrID(x); + var n = sel.name.substring(2); // bus number (0-Z) if (en) switch (parseInt(d.Sf["LA"+n].value)) { case 0: break; // disable ABL @@ -190,7 +191,7 @@ case 255: sel.value = 255; break; } else sel.value = 0; - enLA(sel,n); // configure individual limiter + enLA(sel); // configure individual limiter }); enABL(); gId('m1').innerHTML = maxM; @@ -214,8 +215,8 @@ mul = 2; // ESP32 RMT uses double buffer } else if ((is32() || isS2() || isS3()) && toNum(n) > (parallelI2S ? 7 : 0)) { mul = 2; // ESP32 RMT uses double buffer - } else if ((parallelI2S && toNum(n) < 8) || (n == 0 && is32())) { // I2S uses extra DMA buffer - dbl = len * ch * 3; // DMA buffer for parallel I2S (TODO: ony the bus with largst LED count should be used) + } else if ((parallelI2S && toNum(n) < 8) || (toNum(n) == 0 && is32())) { // I2S uses extra DMA buffer + dbl = len * ch * 3; // DMA buffer for parallel I2S (TODO: only the bus with largst LED count should be used) } } return len * ch * mul + dbl + pbfr; @@ -226,81 +227,22 @@ let gRGBW = false, memu = 0; let busMA = 0; let sLC = 0, sPC = 0, sDI = 0, maxLC = 0; - const abl = d.Sf.ABL.checked; - let setPinConfig = (n,t) => { - let p0d = "GPIO:"; - let p1d = ""; - let off = "Off Refresh"; - switch (gT(t).t.charAt(0)) { - case '2': // 2 pin digital - p1d = "Clock "+p0d; - // fallthrough - case 'D': // digital - p0d = "Data "+p0d; - break; - case 'A': // PWM analog - if (numPins(t) > 1) p0d = "GPIOs:"; - off = "Dithering"; - break; - case 'N': // network - p0d = "IP address:"; - break; - case 'V': // virtual/non-GPIO based - p0d = "Config:" - break; - case 'H': // HUB75 - p0d = "Panel size (width x height), Panel count:" - break; - } - gId("p0d"+n).innerText = p0d; - gId("p1d"+n).innerText = p1d; - gId("off"+n).innerText = off; - // secondary pins show/hide (type string length is equivalent to number of pins used; except for network and on/off) - let pins = Math.max(gT(t).t.length,1) + 3*isNet(t) + 2*isHub75(t); // fixes network pins to 4 - for (let p=1; p<5; p++) { - var LK = d.Sf["L"+p+n]; - if (!LK) continue; - LK.style.display = (p < pins) ? "inline" : "none"; - LK.required = (p < pins); - if (p >= pins) LK.value=""; - } - } // enable/disable LED fields + updateTypeDropdowns(change); 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); - memu += getMem(t, n); // calc memory - dC += (isDig(t) && !isD2P(t)); - setPinConfig(n,t); - gId("abl"+n).style.display = (!abl || !isDig(t)) ? "none" : "inline"; // show/hide individual ABL settings - if (change) { // did we change LED type? - gId("rf"+n).checked = (gId("rf"+n).checked || t == 31); // LEDs require data in off state (mandatory for TM1814) - if (isAna(t)) d.Sf["LC"+n].value = 1; // for sanity change analog count just to 1 LED - d.Sf["LA"+n].min = (!isDig(t) || !abl) ? 0 : 1; // set minimum value for LED mA - d.Sf["MA"+n].min = (!isDig(t)) ? 0 : 250; // set minimum value for PSU mA - } - gId("rf"+n).onclick = mustR(t) ? (()=>{return false}) : (()=>{}); // prevent change change of "Refresh" checkmark when mandatory - gRGBW |= hasW(t); // RGBW checkbox - gId("co"+n).style.display = (isVir(t) || isAna(t) || isHub75(t)) ? "none":"inline"; // hide color order for PWM - gId("dig"+n+"w").style.display = (isDig(t) && hasW(t)) ? "inline":"none"; // show swap channels dropdown - gId("dig"+n+"w").querySelector("[data-opt=CCT]").disabled = !hasCCT(t); // disable WW/CW swapping - if (!(isDig(t) && hasW(t))) d.Sf["WO"+n].value = 0; // reset swapping - gId("dig"+n+"c").style.display = (isAna(t) || isHub75(t)) ? "none":"inline"; // hide count for analog - gId("dig"+n+"r").style.display = (isVir(t)) ? "none":"inline"; // hide reversed for virtual - gId("dig"+n+"s").style.display = (isVir(t) || isAna(t) || isHub75(t)) ? "none":"inline"; // hide skip 1st for virtual & analog - gId("dig"+n+"f").style.display = (isDig(t) || (isPWM(t) && maxL>2048)) ? "inline":"none"; // hide refresh (PWM hijacks reffresh for dithering on ESP32) - gId("dig"+n+"a").style.display = (hasW(t)) ? "inline":"none"; // auto calculate white - gId("dig"+n+"l").style.display = (isD2P(t) || isPWM(t)) ? "inline":"none"; // bus clock speed / PWM speed (relative) (not On/Off) - gId("rev"+n).innerHTML = isAna(t) ? "Inverted output":"Reversed"; // change reverse text for analog else (rotated 180°) - //gId("psd"+n).innerHTML = isAna(t) ? "Index:":"Start:"; // change analog start description - gId("net"+n+"h").style.display = isNet(t) && !is8266() ? "block" : "none"; // show host field for network types except on ESP8266 - if (!isNet(t) || is8266()) d.Sf["HS"+n].value = ""; // cleart host field if not network type or ESP8266 + memu += getMem(t, n); // calc memory + dC += isD1P(t); // count digital buses + gRGBW |= hasW(t); // RGBW checkbox }); + // enable/disable add/remove buttons + gId("+").style.display = (LTs.length<36) ? "inline":"none"; // now: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".length + gId("-").style.display = (LTs.length>1) ? "inline":"none"; + // display global white channel overrides gId("wc").style.display = (gRGBW) ? 'inline':'none'; if (!gRGBW) { @@ -320,15 +262,16 @@ } // do we have a led count field if (nm=="LC") { + LC.max = isAna(t) ? 1 : (isDig(t) ? maxPB : 16384); // set max value let c = parseInt(LC.value,10); //get LED count if (!customStarts || !startsDirty[toNum(n)]) gId("ls"+n).value = sLC; //update start value gId("ls"+n).disabled = !customStarts; //enable/disable field editing if (c) { let s = parseInt(gId("ls"+n).value); //start value if (s+c > sLC) sLC = s+c; //update total count - if (c > maxLC) maxLC = c; //max per output if (!isVir(t)) sPC += c; //virtual out busses do not count towards physical LEDs if (isDig(t)) { + if (c > maxLC) maxLC = c; //max per output sDI += c; // summarize digital LED count let maPL = parseInt(d.Sf["LA"+n].value); if (maPL == 255) maPL = 12; @@ -438,8 +381,8 @@ function lastEnd(i) { if (i-- < 1) return 0; var s = chrID(i); - v = parseInt(d.getElementsByName("LS"+s)[0].value) + parseInt(d.getElementsByName("LC"+s)[0].value); - var t = parseInt(d.getElementsByName("LT"+s)[0].value); + v = parseInt(gN("LS"+s).value) + parseInt(gN("LC"+s).value); + var t = parseInt(gN("LT"+s).value); if (isPWM(t)) v = 1; //PWM busses return isNaN(v) ? 0 : v; } @@ -447,29 +390,19 @@ { 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); if (n==1) { // npm run build has trouble minimizing spaces inside string - var cn = `