Pin dropdown updates for LED pins.
Updated pxmagic
This commit is contained in:
@@ -26,7 +26,10 @@
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
GetV();checkSi();setABL();
|
||||
GetV();
|
||||
checkSi();
|
||||
setABL();
|
||||
d.Sf.addEventListener("submit", trySubmit);
|
||||
if (d.um_p[0]==-1) d.um_p.shift();
|
||||
pinDropdowns();
|
||||
});
|
||||
@@ -50,7 +53,7 @@
|
||||
maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l;
|
||||
}
|
||||
function pinsOK() {
|
||||
var LCs = d.getElementsByTagName("input");
|
||||
var LCs = d.Sf.querySelectorAll("#mLC input[name^=L]"); // input fields
|
||||
for (i=0; i<LCs.length; i++) {
|
||||
var nm = LCs[i].name.substring(0,2);
|
||||
// ignore IP address
|
||||
@@ -60,23 +63,36 @@
|
||||
if (t>=80) continue;
|
||||
}
|
||||
//check for pin conflicts
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4"/* || nm=="RL" || nm=="BT" || nm=="IR"*/)
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
var p = []; // used pin array
|
||||
for (k=0;k<d.rsvd.length;k++) p.push(d.rsvd[k]); // fill with reservations
|
||||
for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with usermod pins
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||
else if (!(nm == "IR" || nm=="BT") && d.ro_gpio.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||
for (j=i+1; j<LCs.length; j++)
|
||||
{
|
||||
var p = d.rsvd.concat(d.um_p); // used pin array
|
||||
d.Sf.querySelectorAll("select.pin").forEach((e)=>{if(e.value>-1)p.push(parseInt(e.value));}) // buttons, IR & relay
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value))) {
|
||||
alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`);
|
||||
LCs[i].value="";
|
||||
LCs[i].focus();
|
||||
return false;
|
||||
}
|
||||
else if (/*!(nm == "IR" || nm=="BT") &&*/ d.ro_gpio.some((e)=>e==parseInt(LCs[i].value))) {
|
||||
alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);
|
||||
LCs[i].value="";
|
||||
LCs[i].focus();
|
||||
return false;
|
||||
}
|
||||
for (j=i+1; j<LCs.length; j++) {
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4" || n2=="RL" || n2=="BT" || n2=="IR") {
|
||||
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4"/* || n2=="RL" || n2=="BT" || n2=="IR"*/) {
|
||||
if (n2.substring(0,1)==="L") {
|
||||
var m = LCs[j].name.substring(2);
|
||||
var t2 = parseInt(d.getElementsByName("LT"+m)[0].value, 10);
|
||||
if (t2>=80) continue;
|
||||
}
|
||||
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) {alert(`Pin conflict between ${LCs[i].name}/${LCs[j].name}!`);LCs[j].value="";LCs[j].focus();return false;}
|
||||
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) {
|
||||
alert(`Pin conflict between ${LCs[i].name}/${LCs[j].name}!`);
|
||||
LCs[j].value="";
|
||||
LCs[j].focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +113,7 @@
|
||||
gId('abl').style.display = (en) ? 'inline':'none';
|
||||
gId('psu2').style.display = (en) ? 'inline':'none';
|
||||
if (d.Sf.LA.value > 0) setABL();
|
||||
UI();
|
||||
}
|
||||
function enLA()
|
||||
{
|
||||
@@ -118,28 +135,28 @@
|
||||
default: gId('LAdis').style.display = 'inline';
|
||||
}
|
||||
gId('m1').innerHTML = maxM;
|
||||
d.getElementsByName("Sf")[0].addEventListener("submit", trySubmit);
|
||||
UI();
|
||||
}
|
||||
//returns mem usage
|
||||
function getMem(t, n) {
|
||||
let len = parseInt(d.getElementsByName("LC"+n)[0].value);
|
||||
len += parseInt(d.getElementsByName("SL"+n)[0].value); // skipped LEDs are allocated too
|
||||
let dbl = 0;
|
||||
if (d.Sf.LD.checked) dbl = len * 3; // double buffering
|
||||
if (t < 32) {
|
||||
if (t==26 || t==29) len *= 2; // 16 bit LEDs
|
||||
if (maxM < 10000 && d.getElementsByName("L0"+n)[0].value == 3) { //8266 DMA uses 5x the mem
|
||||
if (t > 28) return len*20; //RGBW
|
||||
return len*15;
|
||||
if (t > 28) return len*20 + dbl; //RGBW
|
||||
return len*15 + dbl;
|
||||
} else if (maxM >= 10000) //ESP32 RMT uses double buffer?
|
||||
{
|
||||
if (t > 28) return len*8; //RGBW
|
||||
return len*6;
|
||||
if (t > 28) return len*8 + dbl; //RGBW
|
||||
return len*6 + dbl;
|
||||
}
|
||||
if (t > 28) return len*4; //RGBW
|
||||
return len*3;
|
||||
if (t > 28) return len*4 + dbl; //RGBW
|
||||
return len*3 + dbl;
|
||||
}
|
||||
if (t > 31 && t < 48) return 5;
|
||||
return len*3;
|
||||
if (t > 31 && t < 48) return 5; // analog
|
||||
return len*3 + dbl;
|
||||
}
|
||||
|
||||
function UI(change=false)
|
||||
@@ -152,53 +169,50 @@
|
||||
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
|
||||
|
||||
// enable/disable LED fields
|
||||
var s = d.getElementsByTagName("select");
|
||||
for (i=0; i<s.length; i++) {
|
||||
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{
|
||||
// is the field a LED type?
|
||||
if (s[i].name.substring(0,2)=="LT") {
|
||||
var n = s[i].name.substring(2);
|
||||
var t = parseInt(s[i].value,10);
|
||||
gId("p0d"+n).innerHTML = (t>=80 && t<96) ? "IP address:" : (t > 49) ? "Data GPIO:" : (t > 41) ? "GPIOs:" : "GPIO:";
|
||||
gId("p1d"+n).innerHTML = (t> 49 && t<64) ? "Clk GPIO:" : "";
|
||||
var LK = d.getElementsByName("L1"+n)[0]; // clock pin
|
||||
var n = s.name.substring(2);
|
||||
var t = parseInt(s.value);
|
||||
gId("p0d"+n).innerHTML = (t>=80 && t<96) ? "IP address:" : (t > 49) ? "Data GPIO:" : (t > 41) ? "GPIOs:" : "GPIO:";
|
||||
gId("p1d"+n).innerHTML = (t> 49 && t<64) ? "Clk GPIO:" : "";
|
||||
//var LK = d.getElementsByName("L1"+n)[0]; // clock pin
|
||||
|
||||
memu += getMem(t, n); // calc memory
|
||||
memu += getMem(t, n); // calc memory
|
||||
|
||||
// enumerate pins
|
||||
for (p=1; p<5; p++) {
|
||||
var LK = d.getElementsByName("L"+p+n)[0]; // secondary pins
|
||||
if (!LK) continue;
|
||||
if (((t>=80 && t<96) && p<4) || (t>49 && p==1) || (t>41 && t < 50 && (p+40 < t))) // TYPE_xxxx values from const.h
|
||||
{
|
||||
// display pin field
|
||||
LK.style.display = "inline";
|
||||
LK.required = true;
|
||||
} else {
|
||||
// hide pin field
|
||||
LK.style.display = "none";
|
||||
LK.required = false;
|
||||
LK.value="";
|
||||
}
|
||||
// enumerate pins
|
||||
for (p=1; p<5; p++) {
|
||||
var LK = d.getElementsByName("L"+p+n)[0]; // secondary pins
|
||||
if (!LK) continue;
|
||||
if (((t>=80 && t<96) && p<4) || (t>49 && p==1) || (t>41 && t < 50 && (p+40 < t))) // TYPE_xxxx values from const.h
|
||||
{
|
||||
// display pin field
|
||||
LK.style.display = "inline";
|
||||
LK.required = true;
|
||||
} else {
|
||||
// hide pin field
|
||||
LK.style.display = "none";
|
||||
LK.required = false;
|
||||
LK.value="";
|
||||
}
|
||||
if (change) {
|
||||
gId("rf"+n).checked = (gId("rf"+n).checked || t == 31); // LEDs require data in off state
|
||||
if (t > 31 && t < 48) d.getElementsByName("LC"+n)[0].value = 1; // for sanity change analog count just to 1 LED
|
||||
}
|
||||
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
||||
gRGBW |= isRGBW = ((t > 17 && t < 22) || (t > 28 && t < 32) || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h
|
||||
gId("co"+n).style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide color order for PWM
|
||||
gId("dig"+n+"w").style.display = (t > 28 && t < 32) ? "inline":"none"; // show swap channels dropdown
|
||||
if (!(t > 28 && t < 32)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping
|
||||
gId("dig"+n+"c").style.display = (t >= 40 && t < 48) ? "none":"inline"; // hide count for analog
|
||||
gId("dig"+n+"r").style.display = (t >= 80 && t < 96) ? "none":"inline"; // hide reversed for virtual
|
||||
gId("dig"+n+"s").style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide skip 1st for virtual & analog
|
||||
gId("dig"+n+"f").style.display = ((t >= 16 && t < 32) || (t >= 50 && t < 64)) ? "inline":"none"; // hide refresh
|
||||
gId("dig"+n+"a").style.display = (isRGBW && t != 40) ? "inline":"none"; // auto calculate white
|
||||
gId("dig"+n+"l").style.display = (t > 48 && t < 64) ? "inline":"none"; // bus clock speed
|
||||
gId("rev"+n).innerHTML = (t >= 40 && t < 48) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
||||
gId("psd"+n).innerHTML = (t >= 40 && t < 48) ? "Index:":"Start:"; // change analog start description
|
||||
}
|
||||
}
|
||||
if (change) {
|
||||
gId("rf"+n).checked = (gId("rf"+n).checked || t == 31); // LEDs require data in off state
|
||||
if (t > 31 && t < 48) d.getElementsByName("LC"+n)[0].value = 1; // for sanity change analog count just to 1 LED
|
||||
}
|
||||
gId("rf"+n).onclick = (t == 31) ? (()=>{return false}) : (()=>{}); // prevent change for TM1814
|
||||
gRGBW |= isRGBW = ((t > 17 && t < 22) || (t > 28 && t < 32) || (t > 40 && t < 46 && t != 43) || t == 88); // RGBW checkbox, TYPE_xxxx values from const.h
|
||||
gId("co"+n).style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide color order for PWM
|
||||
gId("dig"+n+"w").style.display = (t > 28 && t < 32) ? "inline":"none"; // show swap channels dropdown
|
||||
if (!(t > 28 && t < 32)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping
|
||||
gId("dig"+n+"c").style.display = (t >= 40 && t < 48) ? "none":"inline"; // hide count for analog
|
||||
gId("dig"+n+"r").style.display = (t >= 80 && t < 96) ? "none":"inline"; // hide reversed for virtual
|
||||
gId("dig"+n+"s").style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide skip 1st for virtual & analog
|
||||
gId("dig"+n+"f").style.display = ((t >= 16 && t < 32) || (t >= 50 && t < 64)) ? "inline":"none"; // hide refresh
|
||||
gId("dig"+n+"a").style.display = (isRGBW && t != 40) ? "inline":"none"; // auto calculate white
|
||||
gId("dig"+n+"l").style.display = (t > 48 && t < 64) ? "inline":"none"; // bus clock speed
|
||||
gId("rev"+n).innerHTML = (t >= 40 && t < 48) ? "Inverted output":"Reversed (rotated 180°)"; // change reverse text for analog
|
||||
gId("psd"+n).innerHTML = (t >= 40 && t < 48) ? "Index:":"Start:"; // change analog start description
|
||||
});
|
||||
// display global white channel overrides
|
||||
gId("wc").style.display = (gRGBW) ? 'inline':'none';
|
||||
if (!gRGBW) {
|
||||
@@ -206,7 +220,7 @@
|
||||
d.Sf.CR.checked = false;
|
||||
}
|
||||
// check for pin conflicts
|
||||
var LCs = d.getElementsByTagName("input");
|
||||
var LCs = d.Sf.querySelectorAll("#mLC input[name^=L]"); // input fields
|
||||
var sLC = 0, sPC = 0, maxLC = 0;
|
||||
for (i=0; i<LCs.length; i++) {
|
||||
var nm = LCs[i].name.substring(0,2); // field name
|
||||
@@ -244,15 +258,14 @@
|
||||
}
|
||||
}
|
||||
// check for pin conflicts
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4"/* || nm=="RL" || nm=="BT" || nm=="IR"*/)
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
var p = []; // used pin array
|
||||
for (k=0;k<d.rsvd.length;k++) p.push(d.rsvd[k]); // fill with reservations
|
||||
for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with usermod pins
|
||||
var p = d.rsvd.concat(d.um_p); // used pin array
|
||||
d.Sf.querySelectorAll("select.pin").forEach((e)=>{if(e.value>-1)p.push(parseInt(e.value));}) // buttons, IR & relay
|
||||
for (j=0; j<LCs.length; j++) {
|
||||
if (i==j) continue;
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4" || n2=="RL" || n2=="BT" || n2=="IR") {
|
||||
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4"/* || n2=="RL" || n2=="BT" || n2=="IR"*/) {
|
||||
if (n2.substring(0,1)==="L") {
|
||||
var m = LCs[j].name.substring(2);
|
||||
var t2 = parseInt(d.getElementsByName("LT"+m)[0].value, 10);
|
||||
@@ -262,13 +275,13 @@
|
||||
}
|
||||
}
|
||||
// now check for conflicts
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) LCs[i].style.color="red"; else LCs[i].style.color=d.ro_gpio.some((e)=>e==parseInt(LCs[i].value,10))?"orange":"#fff";
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value))) LCs[i].style.color="red"; else LCs[i].style.color=d.ro_gpio.some((e)=>e==parseInt(LCs[i].value))?"orange":"#fff";
|
||||
}
|
||||
// check buttons, IR & relay
|
||||
if (nm=="IR" || nm=="BT" || nm=="RL") {
|
||||
LCs[i].max = d.max_gpio;
|
||||
LCs[i].min = -1;
|
||||
}
|
||||
//if (nm=="IR" || nm=="BT" || nm=="RL") {
|
||||
// LCs[i].max = d.max_gpio;
|
||||
// LCs[i].min = -1;
|
||||
//}
|
||||
}
|
||||
// update total led count
|
||||
gId("lc").textContent = sLC;
|
||||
@@ -367,11 +380,11 @@ ${i+1}:
|
||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required />
|
||||
<div id="dig${i}c" style="display:inline">Length: <input type="number" name="LC${i}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br>
|
||||
</div>
|
||||
<span id="p0d${i}">GPIO:</span> <input type="number" name="L0${i}" required class="s" onchange="UI()"/>
|
||||
<span id="p1d${i}"></span><input type="number" name="L1${i}" class="s" onchange="UI()"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" class="s" onchange="UI()"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" class="s" onchange="UI()"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" class="s" onchange="UI()"/>
|
||||
<span id="p0d${i}">GPIO:</span><input type="number" name="L0${i}" required class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p1d${i}"></span><input type="number" name="L1${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div>
|
||||
<div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div>
|
||||
<div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div>
|
||||
@@ -566,6 +579,45 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
}
|
||||
}
|
||||
}
|
||||
// update select options
|
||||
d.Sf.querySelectorAll("select.pin").forEach((e)=>{pinUpd(e);});
|
||||
// add dataset values for LED GPIO pins
|
||||
d.Sf.querySelectorAll(".iST input.s[name^=L]").forEach((i)=>{
|
||||
if (i.value!=="" && i.value>=0)
|
||||
i.dataset.val = i.value;
|
||||
});
|
||||
}
|
||||
function pinUpd(e) {
|
||||
// update changed select options across all usermods
|
||||
let oldV = parseInt(e.dataset.val);
|
||||
e.dataset.val = e.value;
|
||||
let txt = e.name;
|
||||
let pins = [];
|
||||
d.Sf.querySelectorAll(".iST input.s[name^=L]").forEach((i)=>{
|
||||
if (i.value!=="" && i.value>=0 && i.max<255)
|
||||
pins.push(i.value);
|
||||
});
|
||||
let selects = d.Sf.querySelectorAll("select.pin");
|
||||
for (let sel of selects) {
|
||||
if (sel == e) continue
|
||||
Array.from(sel.options).forEach((i)=>{
|
||||
let led = pins.includes(i.value);
|
||||
if (!(i.value==oldV || i.value==e.value || led)) return;
|
||||
if (i.value == -1) {
|
||||
i.text = "unused";
|
||||
return
|
||||
}
|
||||
i.text = i.value;
|
||||
if (i.value==oldV) {
|
||||
i.disabled = false;
|
||||
}
|
||||
if (i.value==e.value || led) {
|
||||
i.disabled = true;
|
||||
i.text += ` ${led?'LED':txt}`;
|
||||
}
|
||||
if (d.ro_gpio.includes(parseInt(i.value))) i.text += " (R/O)";
|
||||
});
|
||||
}
|
||||
}
|
||||
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
||||
function addDropdown(field) {
|
||||
@@ -585,6 +637,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
}
|
||||
}
|
||||
sel.setAttribute("data-val", v);
|
||||
sel.setAttribute("onchange", "pinUpd(this)");
|
||||
// finally, replace the old input element with the new select element
|
||||
inp.parentElement.replaceChild(sel, inp);
|
||||
return sel;
|
||||
@@ -681,7 +734,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
<hr class="sml">
|
||||
Make a segment for each output: <input type="checkbox" name="MS"><br>
|
||||
Custom bus start indices: <input type="checkbox" onchange="tglSi(this.checked)" id="si"><br>
|
||||
Use global LED buffer: <input type="checkbox" name="LD"><br>
|
||||
Use global LED buffer: <input type="checkbox" name="LD" onchange="UI()"><br>
|
||||
<hr class="sml">
|
||||
<div id="color_order_mapping">
|
||||
Color Order Override:
|
||||
|
||||
Reference in New Issue
Block a user