|
13 | 13 | function gT(t) { for (let type of d.ledTypes) if (t == type.i) return type; } // getType from available ledTypes |
14 | 14 | function isPWM(t) { return gT(t).t.charAt(0) === "A"; } // is PWM type |
15 | 15 | function isAna(t) { return gT(t).t === "" || isPWM(t); } // is analog type |
16 | | - function isDig(t) { return gT(t).t === "D" || isD2P(t); } // is digital type |
| 16 | + function isD1P(t) { return gT(t).t === "D"; } // is digital 1 pin type |
17 | 17 | function isD2P(t) { return gT(t).t === "2P"; } // is digital 2 pin type |
| 18 | + function isDig(t) { return isD1P(t) || isD2P(t); } // is digital type |
18 | 19 | function isNet(t) { return gT(t).t === "N"; } // is network type |
19 | 20 | function isVir(t) { return gT(t).t === "V" || isNet(t); } // is virtual type |
20 | 21 | function hasRGB(t) { return !!(gT(t).c & 0x01); } // has RGB |
|
254 | 255 | } |
255 | 256 |
|
256 | 257 | // enable/disable LED fields |
| 258 | + updateTypeDropdowns(change); |
257 | 259 | let dC = 0; // count of digital buses (for parallel I2S) |
258 | 260 | let LTs = d.Sf.querySelectorAll("#mLC select[name^=LT]"); |
259 | 261 | LTs.forEach((s,i)=>{ |
260 | | - s.disabled = (i < LTs.length-1); // prevent changing type (as we can't update options) |
261 | 262 | var n = s.name.substring(2,3); // bus number (0-Z) |
262 | 263 | var t = parseInt(s.value); |
263 | 264 | memu += getMem(t, n); // calc memory |
|
405 | 406 | function addLEDs(n,init=true) { |
406 | 407 | var o = gEBCN("iST"); |
407 | 408 | var i = o.length; |
408 | | - let disable = (sel,opt) => { sel.querySelectorAll(opt).forEach((o)=>{o.disabled=true;}); } |
409 | | - |
410 | 409 | var f = gId("mLC"); |
411 | | - let digitalB = 0, analogB = 0, twopinB = 0, virtB = 0; |
412 | | - f.querySelectorAll("select[name^=LT]").forEach((s)=>{ |
413 | | - let t = s.value; |
414 | | - if (isDig(t) && !isD2P(t)) digitalB++; |
415 | | - if (isD2P(t)) twopinB++; |
416 | | - if (isPWM(t)) analogB += numPins(t); // each GPIO is assigned to a channel |
417 | | - if (isVir(t)) virtB++; |
418 | | - }); |
419 | 410 |
|
420 | 411 | if ((n==1 && i>=36) || (n==-1 && i==0)) return; // used to be i>=maxB+maxV when virtual buses were limited (now :"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") |
421 | 412 | var s = chrID(i); |
|
424 | 415 | // npm run build has trouble minimizing spaces inside string |
425 | 416 | var cn = `<div class="iST" draggable="true" ondragstart="hDS(event)" id="l${s}" style="cursor:grab;"> |
426 | 417 | <hr class="sml"> |
427 | | -<span id="n${s}">${i+1}</span>: |
| 418 | +<span id="n${s}">${++i}</span>: |
428 | 419 | <select name="LT${s}" onchange="UI(true)"></select><br> |
429 | 420 | <div id="abl${s}"> |
430 | 421 | mA/LED: <select name="LL${s}" onchange="enLA(this);UI();"> |
|
450 | 441 | <div id="dig${s}w" style="display:none">Swap: <select name="WO${s}"><option value="0">None</option><option value="1">W & B</option><option value="2">W & G</option><option value="3">W & R</option><option data-opt="CCT" value="4">WW & CW</option></select></div> |
451 | 442 | <div id="dig${s}l" style="display:none">Clock: <select name="SP${s}"><option value="0">Slowest</option><option value="1">Slow</option><option value="2">Normal</option><option value="3">Fast</option><option value="4">Fastest</option></select></div> |
452 | 443 | <div> |
453 | | -<span id="psd${s}">Start:</span> <input type="number" name="LS${s}" id="ls${s}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required /> |
| 444 | +<span id="psd${s}">Start:</span> <input type="number" name="LS${s}" id="ls${s}" class="l starts" min="0" max="8191" value="${lastEnd(i-1)}" oninput="startsDirty[${i}]=true;UI();" required /> |
454 | 445 | <div id="dig${s}c" style="display:inline">Length: <input type="number" name="LC${s}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br> |
455 | 446 | </div> |
456 | 447 | <span id="p0d${s}">GPIO:</span><input type="number" name="L0${s}" required class="s" onchange="UI();pinUpd(this);"/> |
|
480 | 471 | } |
481 | 472 | }); |
482 | 473 | enLA(gN("LL"+s)); // update LED mA |
483 | | - // disable inappropriate LED types |
484 | 474 | let sel = gN("LT"+s); |
485 | | - // 32 & S2 supports mono I2S as well as parallel so we need to take that into account; S3 only supports parallel |
486 | | - let maxDB = maxD - (is32() || isS2() || isS3() ? (!gN("PR").checked)*8 - (!isS3()) : 0); // adjust max digital buses if parallel I2S is not used |
487 | | - if (digitalB >= maxDB) disable(sel,'option[data-type="D"]'); // NOTE: see isDig() |
488 | | - if (twopinB >= 2) disable(sel,'option[data-type="2P"]'); // NOTE: see isD2P() (we will only allow 2 2pin buses) |
489 | | - disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`); // NOTE: see isPWM() |
490 | | - sel.selectedIndex = sel.querySelector('option:not(:disabled)').index; |
| 475 | + sel.selectedIndex = sel.querySelector('option:not([data-type])').index; // select On/Off by default |
491 | 476 | } |
492 | 477 | if (n==-1) { |
493 | | - o[--i].remove();--i; |
494 | | - o[i].querySelector("[name^=LT]").disabled = false; |
| 478 | + o[--i].remove(); |
495 | 479 | } |
496 | 480 |
|
497 | | - gId("+").style.display = (i<35) ? "inline":"none"; // was maxB+maxV-1 when virtual buses were limited (now :"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") |
498 | | - gId("-").style.display = (i>0) ? "inline":"none"; |
| 481 | + gId("+").style.display = (i<36) ? "inline":"none"; // was maxB+maxV-1 when virtual buses were limited (now :"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") |
| 482 | + gId("-").style.display = (i>1) ? "inline":"none"; |
499 | 483 |
|
500 | 484 | if (!init) { |
501 | | - UI(); |
| 485 | + UI(true); |
502 | 486 | } |
503 | 487 | } |
504 | 488 |
|
|
828 | 812 | } |
829 | 813 | return opt; |
830 | 814 | } |
| 815 | + // dynamically enforce bus type availability based on current usage |
| 816 | + function updateTypeDropdowns(change=false) { |
| 817 | + let LTs = d.Sf.querySelectorAll("#mLC select[name^=LT]"); |
| 818 | + let digitalB = 0, analogB = 0, twopinB = 0, virtB = 0; |
| 819 | + // count currently used buses (including last added bus) |
| 820 | + LTs.forEach((sel,i) => { |
| 821 | + let t = parseInt(sel.value); |
| 822 | + if (isD1P(t)) digitalB++; |
| 823 | + if (isPWM(t)) analogB += numPins(t); |
| 824 | + if (isD2P(t)) twopinB++; |
| 825 | + if (isVir(t)) virtB++; |
| 826 | + }); |
| 827 | + // now enable/disable type options according to limits in dropdowns |
| 828 | + LTs.forEach((sel,i) => { |
| 829 | + const last = i == LTs.length-1; |
| 830 | + const curType = parseInt(sel.value); |
| 831 | + const disable = (q) => sel.querySelectorAll(q).forEach(o => o.disabled = true); |
| 832 | + const enable = (q) => sel.querySelectorAll(q).forEach(o => o.disabled = false); |
| 833 | + enable('option'); // reset all first |
| 834 | + // max digital count |
| 835 | + let maxDB = maxD - ((is32() || isS2() || isS3()) ? (!d.Sf["PR"].checked) * 8 - (!isS3()) : 0); |
| 836 | + // disallow adding more of a type that has reached its limit |
| 837 | + if (digitalB >= maxDB && !isD1P(curType)) disable('option[data-type="D"]'); |
| 838 | + if (twopinB >= 2 && !isD2P(curType)) disable('option[data-type="2P"]'); |
| 839 | + // determine available analog pins |
| 840 | + disable(`option[data-type^="${'A'.repeat(maxA - analogB + (isPWM(curType) ? numPins(curType) : 0) + 1)}"]`); |
| 841 | + // if last added bus has an invalid type, change it to first available |
| 842 | + if (last && sel.selectedOptions[0].disabled) sel.selectedIndex = sel.querySelector('option:not(:disabled)').index; |
| 843 | + }); |
| 844 | + } |
831 | 845 | </script> |
832 | 846 | <style>@import url("style.css");</style> |
833 | 847 | </head> |
|
0 commit comments