mirror of
https://github.com/wled/WLED.git
synced 2025-04-24 06:47:18 +00:00
Merge branch '0_15' of https://github.com/Aircoookie/WLED into ledmaps-realtime
This commit is contained in:
commit
4fc69c9a2c
@ -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
|
||||
|
@ -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) {...}
|
||||
```
|
||||
```
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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 {
|
||||
|
@ -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);"></i>
|
||||
<i class="icons search-icon" style="cursor:pointer;"></i>
|
||||
<div id="filters" class="filter fade">
|
||||
<label id="filterPal" tooltip="Uses palette" class="check fchkl">🎨
|
||||
<input type="checkbox" data-flt="🎨" onchange="filterFx(this);">
|
||||
<input type="checkbox" data-flt="🎨" onchange="filterFx();">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filter0D" tooltip="Single pixel" class="check fchkl">•
|
||||
<input type="checkbox" data-flt="•" onchange="filterFx(this);">
|
||||
<input type="checkbox" data-flt="•" onchange="filterFx();">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filter1D" tooltip="1D" class="check fchkl">⋮
|
||||
<input type="checkbox" data-flt="⋮" onchange="filterFx(this);">
|
||||
<input type="checkbox" data-flt="⋮" onchange="filterFx();">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filter2D" tooltip="2D" class="check fchkl">▦
|
||||
<input type="checkbox" data-flt="▦" onchange="filterFx(this);">
|
||||
<input type="checkbox" data-flt="▦" onchange="filterFx();">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filterVol" tooltip="Volume" class="check fchkl">♪
|
||||
<input type="checkbox" data-flt="♪" onchange="filterFx(this);">
|
||||
<input type="checkbox" data-flt="♪" onchange="filterFx();">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label id="filterFreq" tooltip="Frequency" class="check fchkl">♫
|
||||
<input type="checkbox" data-flt="♫" onchange="filterFx(this);">
|
||||
<input type="checkbox" data-flt="♫" onchange="filterFx();">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -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"
|
||||
|
@ -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
4086
wled00/html_ui.h
4086
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user