Merge branch '0_15' of https://github.com/Aircoookie/WLED into ledmaps-realtime

This commit is contained in:
ezcGman 2023-11-29 20:14:51 +01:00
commit 4fc69c9a2c
11 changed files with 2787 additions and 2727 deletions

View File

@ -298,7 +298,7 @@ class Animated_Staircase : public Usermod {
// shorten the strip transition time to be equal or shorter than segment delay // shorten the strip transition time to be equal or shorter than segment delay
transitionDelay = segment_delay_ms; transitionDelay = segment_delay_ms;
strip.setTransition(segment_delay_ms/100); strip.setTransition(segment_delay_ms);
strip.trigger(); strip.trigger();
} else { } else {
if (togglePower && !on && offMode) toggleOnOff(); // toggle power on if off if (togglePower && !on && offMode) toggleOnOff(); // toggle power on if off

View File

@ -20,7 +20,7 @@
| `pinSourceSelect` | GPIO that is connected to SD's `SS`(source select) / `CS`(chip select) | 16 | | `pinSourceSelect` | GPIO that is connected to SD's `SS`(source select) / `CS`(chip select) | 16 |
| `pinSourceClock` | GPIO that is connected to SD's `SCLK` (source clock) / `CLK`(clock) | 14 | | `pinSourceClock` | GPIO that is connected to SD's `SCLK` (source clock) / `CLK`(clock) | 14 |
| `pinPoci` | GPIO that is connected to SD's `POCI`<sup></sup> (Peripheral-Out-Ctrl-In) / `MISO` (deprecated) | 36 | | `pinPoci` | GPIO that is connected to SD's `POCI`<sup></sup> (Peripheral-Out-Ctrl-In) / `MISO` (deprecated) | 36 |
| `pinPico` | GPIO that is connected to SD's `PICO`<sup></sup> (Peripheral-In-Ctrl-Out) / `MOSI` (deprecated) | 14 | | `pinPico` | GPIO that is connected to SD's `PICO`<sup></sup> (Peripheral-In-Ctrl-Out) / `MOSI` (deprecated) | 15 |
| `sdEnable` | Enable to read data from the SD-card | true | | `sdEnable` | Enable to read data from the SD-card | true |
<sup></sup><sub>Following new naming convention of [OSHWA](https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/)</sub> <sup></sup><sub>Following new naming convention of [OSHWA](https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/)</sub>

View File

@ -91,6 +91,7 @@ class StairwayWipeUsermod : public Usermod {
void startWipe() void startWipe()
{ {
bri = briLast; //turn on bri = briLast; //turn on
jsonTransitionOnce = true;
strip.setTransition(0); //no transition strip.setTransition(0); //no transition
effectCurrent = FX_MODE_COLOR_WIPE; effectCurrent = FX_MODE_COLOR_WIPE;
resetTimebase(); //make sure wipe starts from beginning resetTimebase(); //make sure wipe starts from beginning
@ -105,6 +106,7 @@ class StairwayWipeUsermod : public Usermod {
void turnOff() void turnOff()
{ {
jsonTransitionOnce = true;
#ifdef STAIRCASE_WIPE_OFF #ifdef STAIRCASE_WIPE_OFF
strip.setTransition(0); //turn off immediately after wipe completed strip.setTransition(0); //turn off immediately after wipe completed
#else #else

View File

@ -1714,7 +1714,7 @@ uint16_t mode_multi_comet(void) {
} }
comets[i]++; comets[i]++;
} else { } else {
if(!random(SEGLEN)) { if(!random16(SEGLEN)) {
comets[i] = 0; comets[i] = 0;
} }
} }
@ -1990,7 +1990,7 @@ uint16_t mode_fire_2012() {
// Step 1. Cool down every cell a little // Step 1. Cool down every cell a little
for (int i = 0; i < SEGLEN; i++) { for (int i = 0; i < SEGLEN; i++) {
uint8_t cool = (it != SEGENV.step) ? random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2) : random(4); uint8_t cool = (it != SEGENV.step) ? random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2) : random8(4);
uint8_t minTemp = (i<ignition) ? (ignition-i)/4 + 16 : 0; // should not become black in ignition area uint8_t minTemp = (i<ignition) ? (ignition-i)/4 + 16 : 0; // should not become black in ignition area
uint8_t temp = qsub8(heat[i], cool); uint8_t temp = qsub8(heat[i], cool);
heat[i] = temp<minTemp ? minTemp : temp; heat[i] = temp<minTemp ? minTemp : temp;
@ -4075,6 +4075,7 @@ static const char _data_FX_MODE_PHASEDNOISE[] PROGMEM = "Phased Noise@!,!;!,!;!"
uint16_t mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline. uint16_t mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline.
uint16_t prevSeed = random16_get_seed(); // save seed so we can restore it at the end of the function
random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through. random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through.
for (int i = 0; i < SEGLEN; i++) { for (int i = 0; i < SEGLEN; i++) {
@ -4084,6 +4085,7 @@ uint16_t mode_twinkleup(void) { // A very short twinkle routine
SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8()+strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri)); SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(random8()+strip.now/100, false, PALETTE_SOLID_WRAP, 0), pixBri));
} }
random16_set_seed(prevSeed); // restore original seed so other effects can use "random" PRNG
return FRAMETIME; return FRAMETIME;
} }
static const char _data_FX_MODE_TWINKLEUP[] PROGMEM = "Twinkleup@!,Intensity;!,!;!;;m12=0"; static const char _data_FX_MODE_TWINKLEUP[] PROGMEM = "Twinkleup@!,Intensity;!,!;!;;m12=0";
@ -4566,15 +4568,15 @@ class AuroraWave {
public: public:
void init(uint32_t segment_length, CRGB color) { void init(uint32_t segment_length, CRGB color) {
ttl = random(500, 1501); ttl = random16(500, 1501);
basecolor = color; basecolor = color;
basealpha = random(60, 101) / (float)100; basealpha = random8(60, 101) / (float)100;
age = 0; age = 0;
width = random(segment_length / 20, segment_length / W_WIDTH_FACTOR); //half of width to make math easier width = random16(segment_length / 20, segment_length / W_WIDTH_FACTOR); //half of width to make math easier
if (!width) width = 1; if (!width) width = 1;
center = random(101) / (float)100 * segment_length; center = random8(101) / (float)100 * segment_length;
goingleft = random(0, 2) == 0; goingleft = random8(0, 2) == 0;
speed_factor = (random(10, 31) / (float)100 * W_MAX_SPEED / 255); speed_factor = (random8(10, 31) / (float)100 * W_MAX_SPEED / 255);
alive = true; alive = true;
} }
@ -4659,7 +4661,7 @@ uint16_t mode_aurora(void) {
waves = reinterpret_cast<AuroraWave*>(SEGENV.data); waves = reinterpret_cast<AuroraWave*>(SEGENV.data);
for (int i = 0; i < SEGENV.aux1; i++) { for (int i = 0; i < SEGENV.aux1; i++) {
waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(random8(), false, false, random(0, 3)))); waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(random8(), false, false, random8(0, 3))));
} }
} else { } else {
waves = reinterpret_cast<AuroraWave*>(SEGENV.data); waves = reinterpret_cast<AuroraWave*>(SEGENV.data);
@ -4671,7 +4673,7 @@ uint16_t mode_aurora(void) {
if(!(waves[i].stillAlive())) { if(!(waves[i].stillAlive())) {
//If a wave dies, reinitialize it starts over. //If a wave dies, reinitialize it starts over.
waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(random8(), false, false, random(0, 3)))); waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(random8(), false, false, random8(0, 3))));
} }
} }
@ -5025,7 +5027,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
if (SEGENV.call == 0 || strip.now - SEGMENT.step > 3000) { if (SEGENV.call == 0 || strip.now - SEGMENT.step > 3000) {
SEGENV.step = strip.now; SEGENV.step = strip.now;
SEGENV.aux0 = 0; SEGENV.aux0 = 0;
random16_set_seed(millis()>>2); //seed the random generator //random16_set_seed(millis()>>2); //seed the random generator
//give the leds random state and colors (based on intensity, colors from palette or all posible colors are chosen) //give the leds random state and colors (based on intensity, colors from palette or all posible colors are chosen)
for (int x = 0; x < cols; x++) for (int y = 0; y < rows; y++) { for (int x = 0; x < cols; x++) for (int y = 0; y < rows; y++) {
@ -5755,7 +5757,7 @@ uint16_t mode_2Dcrazybees(void) {
uint8_t posX, posY, aimX, aimY, hue; uint8_t posX, posY, aimX, aimY, hue;
int8_t deltaX, deltaY, signX, signY, error; int8_t deltaX, deltaY, signX, signY, error;
void aimed(uint16_t w, uint16_t h) { void aimed(uint16_t w, uint16_t h) {
random16_set_seed(millis()); //random16_set_seed(millis());
aimX = random8(0, w); aimX = random8(0, w);
aimY = random8(0, h); aimY = random8(0, h);
hue = random8(); hue = random8();
@ -5842,7 +5844,7 @@ uint16_t mode_2Dghostrider(void) {
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) { if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
SEGENV.aux0 = cols; SEGENV.aux0 = cols;
SEGENV.aux1 = rows; SEGENV.aux1 = rows;
random16_set_seed(strip.now); //random16_set_seed(strip.now);
lighter->angleSpeed = random8(0,20) - 10; lighter->angleSpeed = random8(0,20) - 10;
lighter->gAngle = random16(); lighter->gAngle = random16();
lighter->Vspeed = 5; lighter->Vspeed = 5;
@ -5883,7 +5885,7 @@ uint16_t mode_2Dghostrider(void) {
if (lighter->reg[i]) { if (lighter->reg[i]) {
lighter->lightersPosY[i] = lighter->gPosY; lighter->lightersPosY[i] = lighter->gPosY;
lighter->lightersPosX[i] = lighter->gPosX; lighter->lightersPosX[i] = lighter->gPosX;
lighter->Angle[i] = lighter->gAngle + random(-10, 10); lighter->Angle[i] = lighter->gAngle + ((int)random8(20) - 10);
lighter->time[i] = 0; lighter->time[i] = 0;
lighter->reg[i] = false; lighter->reg[i] = false;
} else { } else {
@ -6744,7 +6746,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
uint16_t size = 0; uint16_t size = 0;
uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 254); uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 254);
uint16_t pos = random(SEGLEN); // Set a random starting position. uint16_t pos = random16(SEGLEN); // Set a random starting position.
um_data_t *um_data; um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {

View File

@ -469,6 +469,7 @@ button {
height: 54px; height: 54px;
line-height: 1.5; line-height: 1.5;
padding-bottom: 8px; padding-bottom: 8px;
pointer-events: none;
} }
/* New tooltip */ /* New tooltip */
@ -1240,6 +1241,7 @@ TD .checkmark, TD .radiomark {
.filter .fchkl { .filter .fchkl {
margin: 0 4px; margin: 0 4px;
min-width: 20px; min-width: 20px;
pointer-events: auto;
} }
.lbl-l { .lbl-l {

View File

@ -197,33 +197,33 @@
<div id="Effects" class="tabcontent"> <div id="Effects" class="tabcontent">
<div id="fx"> <div id="fx">
<p class="labels hd" id="modeLabel">Effect mode</p> <p class="labels hd" id="modeLabel">Effect mode</p>
<div class="staytop fnd" id="fxFind"> <div class="staytop fnd" id="fxFind" onmousedown="preventBlur(event);">
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="filterFocus(event);search(this,'fxlist');" onblur="filterFocus(event);" /> <input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="filterFocus(event);search(this,'fxlist');" onblur="filterFocus(event);">
<i class="icons clear-icon" onclick="clean(this);">&#xe38f;</i> <i class="icons clear-icon" onclick="clean(this);">&#xe38f;</i>
<i class="icons search-icon" style="cursor:pointer;">&#xe0a1;</i> <i class="icons search-icon" style="cursor:pointer;">&#xe0a1;</i>
<div id="filters" class="filter fade"> <div id="filters" class="filter fade">
<label id="filterPal" tooltip="Uses palette" class="check fchkl">&#x1F3A8; <label id="filterPal" tooltip="Uses palette" class="check fchkl">&#x1F3A8;
<input type="checkbox" data-flt="&#x1F3A8;" onchange="filterFx(this);"> <input type="checkbox" data-flt="&#x1F3A8;" onchange="filterFx();">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<label id="filter0D" tooltip="Single pixel" class="check fchkl">&#8226; <label id="filter0D" tooltip="Single pixel" class="check fchkl">&#8226;
<input type="checkbox" data-flt="&#8226;" onchange="filterFx(this);"> <input type="checkbox" data-flt="&#8226;" onchange="filterFx();">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<label id="filter1D" tooltip="1D" class="check fchkl">&#8942; <label id="filter1D" tooltip="1D" class="check fchkl">&#8942;
<input type="checkbox" data-flt="&#8942;" onchange="filterFx(this);"> <input type="checkbox" data-flt="&#8942;" onchange="filterFx();">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<label id="filter2D" tooltip="2D" class="check fchkl">&#9638; <label id="filter2D" tooltip="2D" class="check fchkl">&#9638;
<input type="checkbox" data-flt="&#9638;" onchange="filterFx(this);"> <input type="checkbox" data-flt="&#9638;" onchange="filterFx();">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<label id="filterVol" tooltip="Volume" class="check fchkl">&#9834; <label id="filterVol" tooltip="Volume" class="check fchkl">&#9834;
<input type="checkbox" data-flt="&#9834;" onchange="filterFx(this);"> <input type="checkbox" data-flt="&#9834;" onchange="filterFx();">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<label id="filterFreq" tooltip="Frequency" class="check fchkl">&#9835; <label id="filterFreq" tooltip="Frequency" class="check fchkl">&#9835;
<input type="checkbox" data-flt="&#9835;" onchange="filterFx(this);"> <input type="checkbox" data-flt="&#9835;" onchange="filterFx();">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
</div> </div>

View File

@ -232,6 +232,7 @@ function onLoad()
tooltip(); tooltip();
resetPUtil(); resetPUtil();
initFilters();
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true); if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
applyCfg(); applyCfg();
@ -2716,58 +2717,94 @@ function hideModes(txt)
} }
} }
*/ */
function search(f,l=null) function search(field, listId = null) {
{ field.nextElementSibling.style.display = (field.value !== '') ? 'block' : 'none';
f.nextElementSibling.style.display=(f.value!=='')?'block':'none'; if (!listId) return;
if (!l) return;
var el = gId(l).querySelectorAll('.lstI'); // clear filter if searching in fxlist
if (listId === 'fxlist' && field.value !== '') {
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { e.checked = false; });
}
// do not search if filter is active
if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
const listItems = gId(listId).querySelectorAll('.lstI');
// filter list items but leave (Default & Solid) always visible // filter list items but leave (Default & Solid) always visible
for (i = (l==='pcont'?0:1); i < el.length; i++) { for (i = (listId === 'pcont' ? 0 : 1); i < listItems.length; i++) {
var it = el[i]; const listItem = listItems[i];
var itT = it.querySelector('.lstIname').innerText.toUpperCase(); const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
it.style.display = (itT.indexOf(f.value.toUpperCase())<0) ? 'none' : ''; const searchIndex = listItemName.indexOf(field.value.toUpperCase());
listItem.style.display = (searchIndex < 0) ? 'none' : '';
listItem.dataset.searchIndex = searchIndex;
} }
// sort list items by search index and name
const sortedListItems = Array.from(listItems).sort((a, b) => {
const aSearchIndex = parseInt(a.dataset.searchIndex);
const bSearchIndex = parseInt(b.dataset.searchIndex);
if (aSearchIndex !== bSearchIndex) {
return aSearchIndex - bSearchIndex;
}
const aName = a.querySelector('.lstIname').innerText.toUpperCase();
const bName = b.querySelector('.lstIname').innerText.toUpperCase();
return aName.localeCompare(bName);
});
sortedListItems.forEach(item => {
gId(listId).append(item);
});
} }
function clean(c) function clean(clearButton) {
{ clearButton.style.display = 'none';
c.style.display='none'; const inputField = clearButton.previousElementSibling;
var i=c.previousElementSibling; inputField.value = '';
i.value=''; search(inputField, clearButton.parentElement.nextElementSibling.id);
i.focus();
i.dispatchEvent(new Event('input'));
if (i.parentElement.id=='fxFind') {
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{e.checked=false;});
}
} }
function filterFocus(e) function initFilters() {
{ gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { e.checked = false; });
let f = gId("filters"); }
function filterFocus(e) {
const f = gId("filters");
if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition) if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition)
// compute sticky top (with delay for transition) // compute sticky top (with delay for transition)
setTimeout(()=>{ setTimeout(() => {
let sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight; const sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight;
sCol('--sti', sti+"px"); sCol('--sti', sti + "px");
}, 252); }, 252);
if (e.type === "blur") { if (e.type === "blur") {
let t = e.relatedTarget ? e.relatedTarget : e.explicitOriginalTarget; setTimeout(() => {
do { if (e.target === document.activeElement && document.hasFocus()) return;
if (t.id && (t.id === "fxFind")) { setTimeout(()=>{t.firstElementChild.focus();},150); return; } // do not hide if filter is active
t = t.parentElement; if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
} while (t.tagName !== "BODY"); f.classList.add('fade');
setTimeout(()=>{f.classList.add('fade');},255); // wait with hiding }, 255); // wait with hiding
} }
} }
function filterFx(o) function filterFx() {
{ const inputField = gId('fxFind').children[0];
if (!o) return; inputField.value = '';
let i = gId('fxFind').children[0]; inputField.focus();
i.value=!o.checked?'':o.dataset.flt; clean(inputField.nextElementSibling);
i.focus(); const listItems = gId("fxlist").querySelectorAll('.lstI');
i.dispatchEvent(new Event('input')); for (let i = 1; i < listItems.length; i++) {
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{if(e!==o)e.checked=false;}); const listItem = listItems[i];
const listItemName = listItem.querySelector('.lstIname').innerText;
let hide = false;
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = true; });
listItem.style.display = hide ? 'none' : '';
}
}
function preventBlur(e) {
if (e.target === gId("fxFind").children[0] || e.target === gId("filters")) return;
e.preventDefault();
} }
// make sure "dur" and "transition" are arrays with at least the length of "ps" // make sure "dur" and "transition" are arrays with at least the length of "ps"

View File

@ -52,51 +52,55 @@
maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l; maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l;
} }
function pinsOK() { function pinsOK() {
var LCs = d.Sf.querySelectorAll("#mLC input[name^=L]"); // input fields var ok = true;
for (i=0; i<LCs.length; i++) { var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
var nm = LCs[i].name.substring(0,2); nList.forEach((LC,i)=>{
if (!ok) return; // prevent iteration after conflict
let nm = LC.name.substring(0,2);
let n = LC.name.substring(2);
let t = parseInt(d.Sf["LT"+n].value, 10); // LED type SELECT
// ignore IP address // ignore IP address
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3") { if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3") {
var n = LCs[i].name.substring(2); if (t>=80) return;
var t = parseInt(d.getElementsByName("LT"+n)[0].value, 10); // LED type SELECT
if (t>=80) continue;
} }
//check for pin conflicts //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")
if (LCs[i].value!="" && LCs[i].value!="-1") { if (LC.value!="" && LC.value!="-1") {
var p = d.rsvd.concat(d.um_p); // used pin array let 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 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))) { if (p.some((e)=>e==parseInt(LC.value))) {
alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`); alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`);
LCs[i].value=""; LC.value="";
LCs[i].focus(); LC.focus();
return false; ok = false;
} return;
else if (/*!(nm == "IR" || nm=="BT") &&*/ d.ro_gpio.some((e)=>e==parseInt(LCs[i].value))) { } else if (d.ro_gpio.some((e)=>e==parseInt(LC.value))) {
alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`); alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);
LCs[i].value=""; LC.value="";
LCs[i].focus(); LC.focus();
return false; ok = false;
return;
} }
for (j=i+1; j<LCs.length; j++) { for (j=i+1; j<nList.length; j++) {
var n2 = LCs[j].name.substring(0,2); let n2 = nList[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") {
if (n2.substring(0,1)==="L") { if (n2.substring(0,1)==="L") {
var m = LCs[j].name.substring(2); var m = nList[j].name.substring(2);
var t2 = parseInt(d.getElementsByName("LT"+m)[0].value, 10); var t2 = parseInt(d.Sf["LT"+m].value, 10);
if (t2>=80) continue; if (t2>=80) continue;
} }
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) { if (nList[j].value!="" && nList[i].value==nList[j].value) {
alert(`Pin conflict between ${LCs[i].name}/${LCs[j].name}!`); alert(`Pin conflict between ${LC.name}/${nList[j].name}!`);
LCs[j].value=""; nList[j].value="";
LCs[j].focus(); nList[j].focus();
return false; ok = false;
return;
} }
} }
} }
} }
} });
return true; return ok;
} }
function trySubmit(e) { function trySubmit(e) {
d.Sf.data.value = ''; d.Sf.data.value = '';
@ -206,7 +210,7 @@
// enumerate pins // enumerate pins
for (p=1; p<5; p++) { for (p=1; p<5; p++) {
var LK = d.getElementsByName("L"+p+n)[0]; // secondary pins var LK = d.Sf["L"+p+n]; // secondary pins
if (!LK) continue; 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 if (((t>=80 && t<96) && p<4) || (t>49 && p==1) || (t>41 && t < 50 && (p+40 < t))) // TYPE_xxxx values from const.h
{ {
@ -222,7 +226,7 @@
} }
if (change) { if (change) {
gId("rf"+n).checked = (gId("rf"+n).checked || t == 31); // LEDs require data in off state 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 if (t > 31 && t < 48) d.Sf["LC"+n].value = 1; // for sanity change analog count just to 1 LED
d.Sf["LA"+n].min = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? 0 : 1; d.Sf["LA"+n].min = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? 0 : 1;
d.Sf["MA"+n].min = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? 0 : 250; d.Sf["MA"+n].min = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? 0 : 250;
} }
@ -230,7 +234,7 @@
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 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("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 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 if (!(t > 28 && t < 32)) d.Sf["WO"+n].value = 0; // reset swapping
gId("dig"+n+"c").style.display = (t >= 40 && t < 48) ? "none":"inline"; // hide count for analog 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+"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+"s").style.display = ((t >= 80 && t < 96) || (t >= 40 && t < 48)) ? "none":"inline"; // hide skip 1st for virtual & analog
@ -249,75 +253,69 @@
d.Sf.AW.selectedIndex = 0; d.Sf.AW.selectedIndex = 0;
d.Sf.CR.checked = false; d.Sf.CR.checked = false;
} }
// check for pin conflicts // update start indexes, max values, calculate current, etc
var LCs = d.Sf.querySelectorAll("#mLC input[name^=L]"); // input fields var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
for (i=0; i<LCs.length; i++) { nList.forEach((LC,i)=>{
var nm = LCs[i].name.substring(0,2); // field name let nm = LC.name.substring(0,2); // field name
var n = LCs[i].name.substring(2); // bus number let n = LC.name.substring(2); // bus number
let t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
// do we have a led count field // do we have a led count field
if (nm=="LC") { if (nm=="LC") {
var c=parseInt(LCs[i].value,10); //get LED count let c = parseInt(LC.value,10); //get LED count
if (!customStarts || !startsDirty[n]) gId("ls"+n).value=sLC; //update start value if (!customStarts || !startsDirty[n]) gId("ls"+n).value=sLC; //update start value
gId("ls"+n).disabled = !customStarts; //enable/disable field editing gId("ls"+n).disabled = !customStarts; //enable/disable field editing
if(c){ if (c) {
var s = parseInt(gId("ls"+n).value); //start value let s = parseInt(gId("ls"+n).value); //start value
if (s+c > sLC) sLC = s+c; //update total count if (s+c > sLC) sLC = s+c; //update total count
if(c>maxLC)maxLC=c; //max per output if (c > maxLC) maxLC = c; //max per output
var t = parseInt(d.Sf["LT"+n].value); // LED type SELECT if (t < 80) sPC += c; //virtual out busses do not count towards physical LEDs
if (t<80) sPC+=c; //virtual out busses do not count towards physical LEDs if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) sDI += c;
if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) sDI+=c;
if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) { if (!((t >= 80 && t < 96) || (t >= 40 && t < 48))) {
let maPL = parseInt(d.Sf["LA"+n].value); let maPL = parseInt(d.Sf["LA"+n].value);
if (maPL==255) maPL = 12; if (maPL == 255) maPL = 12;
busMA += maPL*c; busMA += maPL*c;
} }
} // increase led count } // increase led count
continue; return;
} }
// do we have led pins for digital leds // do we have led pins for digital leds
if (nm=="L0" || nm=="L1") { if (nm=="L0" || nm=="L1") {
var lc=d.Sf["LC"+n]; d.Sf["LC"+n].max = maxPB; // update max led count value
lc.max=maxPB; // update max led count value
} }
// ignore IP address (stored in pins for virtual busses) // ignore IP address (stored in pins for virtual busses)
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3") { if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3") {
var t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
if (t>=80) { if (t>=80) {
LCs[i].max = 255; LC.max = 255;
LCs[i].min = 0; LC.min = 0;
LCs[i].style.color="#fff"; LC.style.color="#fff";
continue; // do not check conflicts return; // do not check conflicts
} else { } else {
LCs[i].max = d.max_gpio; LC.max = d.max_gpio;
LCs[i].min = -1; LC.min = -1;
} }
} }
// check for pin conflicts // check for pin conflicts & color fields
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")
if (LCs[i].value!="" && LCs[i].value!="-1") { if (LC.value!="" && LC.value!="-1") {
var p = d.rsvd.concat(d.um_p); // used pin array let 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 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++) { for (j=0; j<nList.length; j++) {
if (i==j) continue; if (i==j) continue;
var n2 = LCs[j].name.substring(0,2); let n2 = nList[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") {
if (n2.substring(0,1)==="L") { if (n2.substring(0,1)==="L") {
var m = LCs[j].name.substring(2); let m = nList[j].name.substring(2);
var t2 = parseInt(d.Sf["LT"+m].value, 10); let t2 = parseInt(d.Sf["LT"+m].value, 10);
if (t2>=80) continue; if (t2 >= 80) continue;
} }
if (LCs[j].value!="" && LCs[j].value!="-1") p.push(parseInt(LCs[j].value,10)); // add current pin if (nList[j].value!="" && nList[j].value!="-1") p.push(parseInt(nList[j].value,10)); // add current pin
} }
} }
// now check for conflicts // now check for conflicts
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"; if (p.some((e)=>e==parseInt(LC.value))) LC.style.color = "red";
} else LC.style.color = d.ro_gpio.some((e)=>e==parseInt(LC.value)) ? "orange" : "#fff";
// check buttons, IR & relay
//if (nm=="IR" || nm=="BT" || nm=="RL") {
// LCs[i].max = d.max_gpio;
// LCs[i].min = -1;
//}
} }
});
d.Sf.querySelectorAll("#mLC input[name^=LC]").forEach((s,n)=>{ d.Sf.querySelectorAll("#mLC input[name^=LC]").forEach((s,n)=>{
let c = parseInt(s.value,10); //get LED count let c = parseInt(s.value,10); //get LED count
let t = parseInt(d.Sf["LT"+n].value); let t = parseInt(d.Sf["LT"+n].value);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -495,6 +495,16 @@ void WLED::setup()
initServer(); initServer();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap()); DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
// Seed FastLED random functions with an esp random value, which already works properly at this point.
#if defined(ARDUINO_ARCH_ESP32)
const uint32_t seed32 = esp_random();
#elif defined(ARDUINO_ARCH_ESP8266)
const uint32_t seed32 = RANDOM_REG32;
#else
const uint32_t seed32 = random(std::numeric_limits<long>::max());
#endif
random16_set_seed((uint16_t)((seed32 & 0xFFFF) ^ (seed32 >> 16)));
#if WLED_WATCHDOG_TIMEOUT > 0 #if WLED_WATCHDOG_TIMEOUT > 0
enableWatchdog(); enableWatchdog();
#endif #endif