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
transitionDelay = segment_delay_ms;
strip.setTransition(segment_delay_ms/100);
strip.setTransition(segment_delay_ms);
strip.trigger();
} else {
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 |
| `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 |
| `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 |
<sup></sup><sub>Following new naming convention of [OSHWA](https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/)</sub>
@ -31,4 +31,4 @@
- checks if the specified file is available on the SD card
```cpp
bool file_onSD(const char *filepath) {...}
```
```

View File

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

View File

@ -1714,7 +1714,7 @@ uint16_t mode_multi_comet(void) {
}
comets[i]++;
} else {
if(!random(SEGLEN)) {
if(!random16(SEGLEN)) {
comets[i] = 0;
}
}
@ -1990,7 +1990,7 @@ uint16_t mode_fire_2012() {
// Step 1. Cool down every cell a little
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 temp = qsub8(heat[i], cool);
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 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.
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));
}
random16_set_seed(prevSeed); // restore original seed so other effects can use "random" PRNG
return FRAMETIME;
}
static const char _data_FX_MODE_TWINKLEUP[] PROGMEM = "Twinkleup@!,Intensity;!,!;!;;m12=0";
@ -4566,15 +4568,15 @@ class AuroraWave {
public:
void init(uint32_t segment_length, CRGB color) {
ttl = random(500, 1501);
ttl = random16(500, 1501);
basecolor = color;
basealpha = random(60, 101) / (float)100;
basealpha = random8(60, 101) / (float)100;
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;
center = random(101) / (float)100 * segment_length;
goingleft = random(0, 2) == 0;
speed_factor = (random(10, 31) / (float)100 * W_MAX_SPEED / 255);
center = random8(101) / (float)100 * segment_length;
goingleft = random8(0, 2) == 0;
speed_factor = (random8(10, 31) / (float)100 * W_MAX_SPEED / 255);
alive = true;
}
@ -4659,7 +4661,7 @@ uint16_t mode_aurora(void) {
waves = reinterpret_cast<AuroraWave*>(SEGENV.data);
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 {
waves = reinterpret_cast<AuroraWave*>(SEGENV.data);
@ -4671,7 +4673,7 @@ uint16_t mode_aurora(void) {
if(!(waves[i].stillAlive())) {
//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) {
SEGENV.step = strip.now;
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)
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;
int8_t deltaX, deltaY, signX, signY, error;
void aimed(uint16_t w, uint16_t h) {
random16_set_seed(millis());
//random16_set_seed(millis());
aimX = random8(0, w);
aimY = random8(0, h);
hue = random8();
@ -5842,7 +5844,7 @@ uint16_t mode_2Dghostrider(void) {
if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) {
SEGENV.aux0 = cols;
SEGENV.aux1 = rows;
random16_set_seed(strip.now);
//random16_set_seed(strip.now);
lighter->angleSpeed = random8(0,20) - 10;
lighter->gAngle = random16();
lighter->Vspeed = 5;
@ -5883,7 +5885,7 @@ uint16_t mode_2Dghostrider(void) {
if (lighter->reg[i]) {
lighter->lightersPosY[i] = lighter->gPosY;
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->reg[i] = false;
} else {
@ -6744,7 +6746,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
uint16_t size = 0;
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;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {

View File

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

View File

@ -197,33 +197,33 @@
<div id="Effects" class="tabcontent">
<div id="fx">
<p class="labels hd" id="modeLabel">Effect mode</p>
<div class="staytop fnd" id="fxFind">
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="filterFocus(event);search(this,'fxlist');" onblur="filterFocus(event);" />
<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);">
<i class="icons clear-icon" onclick="clean(this);">&#xe38f;</i>
<i class="icons search-icon" style="cursor:pointer;">&#xe0a1;</i>
<div id="filters" class="filter fade">
<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>
</label>
<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>
</label>
<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>
</label>
<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>
</label>
<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>
</label>
<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>
</label>
</div>

View File

@ -232,6 +232,7 @@ function onLoad()
tooltip();
resetPUtil();
initFilters();
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
applyCfg();
@ -2716,58 +2717,94 @@ function hideModes(txt)
}
}
*/
function search(f,l=null)
{
f.nextElementSibling.style.display=(f.value!=='')?'block':'none';
if (!l) return;
var el = gId(l).querySelectorAll('.lstI');
function search(field, listId = null) {
field.nextElementSibling.style.display = (field.value !== '') ? 'block' : 'none';
if (!listId) return;
// 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
for (i = (l==='pcont'?0:1); i < el.length; i++) {
var it = el[i];
var itT = it.querySelector('.lstIname').innerText.toUpperCase();
it.style.display = (itT.indexOf(f.value.toUpperCase())<0) ? 'none' : '';
for (i = (listId === 'pcont' ? 0 : 1); i < listItems.length; i++) {
const listItem = listItems[i];
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
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)
{
c.style.display='none';
var i=c.previousElementSibling;
i.value='';
i.focus();
i.dispatchEvent(new Event('input'));
if (i.parentElement.id=='fxFind') {
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{e.checked=false;});
}
function clean(clearButton) {
clearButton.style.display = 'none';
const inputField = clearButton.previousElementSibling;
inputField.value = '';
search(inputField, clearButton.parentElement.nextElementSibling.id);
}
function filterFocus(e)
{
let f = gId("filters");
function initFilters() {
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { e.checked = false; });
}
function filterFocus(e) {
const f = gId("filters");
if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition)
// compute sticky top (with delay for transition)
setTimeout(()=>{
let sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight;
sCol('--sti', sti+"px");
setTimeout(() => {
const sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight;
sCol('--sti', sti + "px");
}, 252);
if (e.type === "blur") {
let t = e.relatedTarget ? e.relatedTarget : e.explicitOriginalTarget;
do {
if (t.id && (t.id === "fxFind")) { setTimeout(()=>{t.firstElementChild.focus();},150); return; }
t = t.parentElement;
} while (t.tagName !== "BODY");
setTimeout(()=>{f.classList.add('fade');},255); // wait with hiding
setTimeout(() => {
if (e.target === document.activeElement && document.hasFocus()) return;
// do not hide if filter is active
if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
f.classList.add('fade');
}, 255); // wait with hiding
}
}
function filterFx(o)
{
if (!o) return;
let i = gId('fxFind').children[0];
i.value=!o.checked?'':o.dataset.flt;
i.focus();
i.dispatchEvent(new Event('input'));
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{if(e!==o)e.checked=false;});
function filterFx() {
const inputField = gId('fxFind').children[0];
inputField.value = '';
inputField.focus();
clean(inputField.nextElementSibling);
const listItems = gId("fxlist").querySelectorAll('.lstI');
for (let i = 1; i < listItems.length; i++) {
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"

View File

@ -52,51 +52,55 @@
maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l;
}
function pinsOK() {
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);
var ok = true;
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
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
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3") {
var n = LCs[i].name.substring(2);
var t = parseInt(d.getElementsByName("LT"+n)[0].value, 10); // LED type SELECT
if (t>=80) continue;
if (t>=80) return;
}
//check for pin conflicts
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 = d.rsvd.concat(d.um_p); // used pin array
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4")
if (LC.value!="" && LC.value!="-1") {
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
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.`);
LCs[i].value="";
LCs[i].focus();
return false;
}
else if (/*!(nm == "IR" || nm=="BT") &&*/ d.ro_gpio.some((e)=>e==parseInt(LCs[i].value))) {
LC.value="";
LC.focus();
ok = false;
return;
} else if (d.ro_gpio.some((e)=>e==parseInt(LC.value))) {
alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);
LCs[i].value="";
LCs[i].focus();
return false;
LC.value="";
LC.focus();
ok = false;
return;
}
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"*/) {
for (j=i+1; j<nList.length; j++) {
let n2 = nList[j].name.substring(0,2);
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4") {
if (n2.substring(0,1)==="L") {
var m = LCs[j].name.substring(2);
var t2 = parseInt(d.getElementsByName("LT"+m)[0].value, 10);
var m = nList[j].name.substring(2);
var t2 = parseInt(d.Sf["LT"+m].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 (nList[j].value!="" && nList[i].value==nList[j].value) {
alert(`Pin conflict between ${LC.name}/${nList[j].name}!`);
nList[j].value="";
nList[j].focus();
ok = false;
return;
}
}
}
}
}
return true;
});
return ok;
}
function trySubmit(e) {
d.Sf.data.value = '';
@ -206,7 +210,7 @@
// enumerate pins
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 (((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) {
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["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
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
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+"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
@ -249,75 +253,69 @@
d.Sf.AW.selectedIndex = 0;
d.Sf.CR.checked = false;
}
// check for pin conflicts
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); // field name
var n = LCs[i].name.substring(2); // bus number
// update start indexes, max values, calculate current, etc
var nList = d.Sf.querySelectorAll("#mLC input[name^=L]");
nList.forEach((LC,i)=>{
let nm = LC.name.substring(0,2); // field name
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
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
gId("ls"+n).disabled = !customStarts; //enable/disable field editing
if(c){
var s = parseInt(gId("ls"+n).value); //start value
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
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 && t < 96) || (t >= 40 && t < 48))) sDI+=c;
if (c > maxLC) maxLC = c; //max per output
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))) {
let maPL = parseInt(d.Sf["LA"+n].value);
if (maPL==255) maPL = 12;
if (maPL == 255) maPL = 12;
busMA += maPL*c;
}
} // increase led count
continue;
return;
}
// do we have led pins for digital leds
if (nm=="L0" || nm=="L1") {
var lc=d.Sf["LC"+n];
lc.max=maxPB; // update max led count value
d.Sf["LC"+n].max = maxPB; // update max led count value
}
// ignore IP address (stored in pins for virtual busses)
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3") {
var t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
if (t>=80) {
LCs[i].max = 255;
LCs[i].min = 0;
LCs[i].style.color="#fff";
continue; // do not check conflicts
LC.max = 255;
LC.min = 0;
LC.style.color="#fff";
return; // do not check conflicts
} else {
LCs[i].max = d.max_gpio;
LCs[i].min = -1;
LC.max = d.max_gpio;
LC.min = -1;
}
}
// check for pin conflicts
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 = d.rsvd.concat(d.um_p); // used pin array
// check for pin conflicts & color fields
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4")
if (LC.value!="" && LC.value!="-1") {
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
for (j=0; j<LCs.length; j++) {
for (j=0; j<nList.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"*/) {
let n2 = nList[j].name.substring(0,2);
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4") {
if (n2.substring(0,1)==="L") {
var m = LCs[j].name.substring(2);
var t2 = parseInt(d.Sf["LT"+m].value, 10);
if (t2>=80) continue;
let m = nList[j].name.substring(2);
let t2 = parseInt(d.Sf["LT"+m].value, 10);
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
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)=>{
let c = parseInt(s.value,10); //get LED count
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();
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
enableWatchdog();
#endif