Merge branch 'main' into cpal

This commit is contained in:
Blaz Kristan 2023-04-14 17:16:20 +02:00
commit 3efee4a855
12 changed files with 2244 additions and 2212 deletions

View File

@ -1,5 +1,12 @@
## WLED changelog ## WLED changelog
#### Build 2304090
- updated Arduino ESP8266 core to 4.1.0 (newer compiler)
- updated NeoPixelBus to 2.7.3 (with support for UCS890x chipset)
- better support for ESP32-C3, ESP32-S2 and ESP32-S3 (Arduino ESP32 core 5.2.0)
- iPad/tablet with 1024 pixels width in landscape orientation PC mode support (#3153)
- fix for Pixel Art Converter (#3155)
#### Build 2303240 #### Build 2303240
- Peek scaling of large 2D matrices - Peek scaling of large 2D matrices
- Added 0D (1 pixel) metadata for effects & enhance 0D (analog strip) UI handling - Added 0D (1 pixel) metadata for effects & enhance 0D (analog strip) UI handling

View File

@ -234,7 +234,7 @@ default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
https://github.com/lorol/LITTLEFS.git https://github.com/lorol/LITTLEFS.git
makuna/NeoPixelBus @ 2.6.9 makuna/NeoPixelBus @ 2.7.3
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
@ -247,6 +247,7 @@ lib_deps =
platform = espressif32@5.2.0 platform = espressif32@5.2.0
platform_packages = platform_packages =
build_flags = -g build_flags = -g
-Wshadow=compatible-local ;; emit warning in case a local variable "shadows" another local one
-DARDUINO_ARCH_ESP32 -DESP32 -DARDUINO_ARCH_ESP32 -DESP32
#-DCONFIG_LITTLEFS_FOR_IDF_3_2 #-DCONFIG_LITTLEFS_FOR_IDF_3_2
-D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0
@ -314,7 +315,7 @@ build_flags = -g
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
;; NeoPixelBus 2.7.1 is the first that has official support for ESP32-S3 ;; NeoPixelBus 2.7.1 is the first that has official support for ESP32-S3
makuna/NeoPixelBus @ ~2.7.3 makuna/NeoPixelBus @ 2.7.3
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 https://github.com/pbolduc/AsyncTCP.git @ 1.2.0

View File

@ -4653,8 +4653,8 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so
byte ysteps = abs8(x2 - y2) + 1; byte ysteps = abs8(x2 - y2) + 1;
byte steps = xsteps >= ysteps ? xsteps : ysteps; byte steps = xsteps >= ysteps ? xsteps : ysteps;
//Draw gradient line //Draw gradient line
for (size_t i = 1; i <= steps; i++) { for (size_t j = 1; j <= steps; j++) {
uint8_t rate = i * 255 / steps; uint8_t rate = j * 255 / steps;
byte dx = lerp8by8(x1, y1, rate); byte dx = lerp8by8(x1, y1, rate);
byte dy = lerp8by8(x2, y2, rate); byte dy = lerp8by8(x2, y2, rate);
//SEGMENT.setPixelColorXY(dx, dy, grad ? color.nscale8_video(255-rate) : color); // use addPixelColorXY for different look //SEGMENT.setPixelColorXY(dx, dy, grad ? color.nscale8_video(255-rate) : color); // use addPixelColorXY for different look

View File

@ -1181,12 +1181,12 @@ void WS2812FX::estimateCurrentAndLimitBri() {
uint32_t powerSum = 0; uint32_t powerSum = 0;
for (uint8_t b = 0; b < busses.getNumBusses(); b++) { for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) {
Bus *bus = busses.getBus(b); Bus *bus = busses.getBus(bNum);
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
uint16_t len = bus->getLength(); uint16_t len = bus->getLength();
uint32_t busPowerSum = 0; uint32_t busPowerSum = 0;
for (uint16_t i = 0; i < len; i++) { //sum up the usage of each LED for (uint_fast16_t i = 0; i < len; i++) { //sum up the usage of each LED
uint32_t c = bus->getPixelColor(i); uint32_t c = bus->getPixelColor(i);
byte r = R(c), g = G(c), b = B(c), w = W(c); byte r = R(c), g = G(c), b = B(c), w = W(c);

View File

@ -184,9 +184,9 @@
//APA102 //APA102
#ifdef WLED_USE_ETHERNET #ifdef WLED_USE_ETHERNET
// fix for #2542 (by @BlackBird77) // fix for #2542 (by @BlackBird77)
#define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarEsp32DmaHspi5MhzMethod> //hardware HSPI with DMA (ESP32 only) #define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarHspi5MhzMethod> //hardware HSPI (was DotStarEsp32DmaHspi5MhzMethod in NPB 2.6.9)
#else #else
#define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarSpi5MhzMethod> //hardware HSPI #define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarSpi5MhzMethod> //hardware VSPI
#endif #endif
#define B_SS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarMethod> //soft SPI #define B_SS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarMethod> //soft SPI

View File

@ -151,7 +151,7 @@ button {
} }
.segt TD { .segt TD {
padding: 2px !important; padding: 2px 0 !important;
text-align: center; text-align: center;
/*text-transform: uppercase;*/ /*text-transform: uppercase;*/
} }
@ -174,7 +174,10 @@ button {
} }
.slider-icon { .slider-icon {
transform: translate(3px,3px); /*transform: translate(3px,3px);*/
position: absolute;
left: 8px;
bottom: 5px;
} }
.e-icon { .e-icon {
@ -314,14 +317,17 @@ button {
overflow: auto; overflow: auto;
height: 100%; height: 100%;
overscroll-behavior: none; overscroll-behavior: none;
padding: 0 4px;
} }
#Effects { #Effects {
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }
#segutil, #segutil2, #segcont, #putil, #pcont, #pql { #segutil, #segutil2, #segcont, #putil, #pcont, #pql, #fx, #palw,
width: 280px; .fnd {
max-width: 280px;
font-size: 19px;
} }
#putil, #segutil, #segutil2 { #putil, #segutil, #segutil2 {
@ -333,7 +339,8 @@ button {
padding-top: 12px; padding-top: 12px;
} }
#pql, #segcont, #pcont { #fx, #pql, #segcont, #pcont, #sliders, #picker, #qcs-w, #hexw, #pall, #ledmap,
.slider, .filter, .option, .segname, .pname, .fnd {
margin: 0 auto; margin: 0 auto;
} }
@ -380,8 +387,7 @@ button {
} }
#sliders { #sliders {
width: 300px; position: -webkit-sticky;
margin: 0 auto;
position: sticky; position: sticky;
bottom: 0; bottom: 0;
} }
@ -393,32 +399,44 @@ button {
.slider { .slider {
max-width: 300px; max-width: 300px;
min-width: 260px; /* margin: 5px auto; add 5px; if you want some vertical space but looks ugly */
margin: 0 auto; /* add 5px; if you want some vertical space but looks ugly */
border-radius: 24px; border-radius: 24px;
position: relative; position: relative;
padding-bottom: 2px; padding-bottom: 2px;
} }
/* Slider wrapper div */
.sliderwrap {
height: 30px;
width: 230px;
max-width: 230px;
position: relative;
z-index: 0;
}
#sliders .slider, #info .slider { #sliders .slider, #info .slider {
background-color: var(--c-2); background-color: var(--c-2);
} }
#sliders .sliderwrap, .sbs .sliderwrap {
left: 16px; /* offset for icon */
}
.filter, .option { .filter, .option {
background-color: var(--c-4); background-color: var(--c-4);
border-radius: 26px; border-radius: 26px;
height: 26px; height: 26px;
margin: 0 auto; /* add 4-8px if you want space at the bottom */ max-width: 300px;
/* margin: 0 auto 4px; add 4-8px if you want space at the bottom */
padding: 4px 2px; padding: 4px 2px;
position: relative; position: relative;
z-index: 1;
opacity: 1; opacity: 1;
transition: opacity 0.5s linear, height 0.5s, transform 0.5s; transition: opacity 0.5s linear, height 0.5s, transform 0.5s;
transform: scaleY(1); overflow: hidden;
} }
.option { .filter {
z-index: unset; z-index: 1;
} }
/* Tooltip text */ /* Tooltip text */
@ -530,6 +548,7 @@ button {
} }
.close { .close {
position: -webkit-sticky;
position: sticky; position: sticky;
top: 0; top: 0;
float: right; float: right;
@ -596,14 +615,9 @@ button {
} }
#info #imgw { #info #imgw {
/*display: inline-block;*/
margin: 8px auto; margin: 8px auto;
} }
/*
#kv, #kn {
display: inline-block;
}
*/
#lv { #lv {
max-width: 600px; max-width: 600px;
display: inline-block; display: inline-block;
@ -668,6 +682,7 @@ img {
transition: visibility 0.25s ease, opacity 0.25s ease; transition: visibility 0.25s ease, opacity 0.25s ease;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
left: 8px;
} }
output.sliderbubbleshow { output.sliderbubbleshow {
@ -725,16 +740,7 @@ input[type=range]::-moz-range-thumb {
border: 2px solid var(--c-1); border: 2px solid var(--c-1);
} }
/* Slider wrapper div */
.sliderwrap {
height: 30px;
width: 230px;
position: relative;
z-index: 0;
}
#Colors .sliderwrap { #Colors .sliderwrap {
width: 260px;
margin: 4px 0 0; margin: 4px 0 0;
} }
@ -748,18 +754,14 @@ input[type=range]::-moz-range-thumb {
} }
#briwrap { #briwrap {
min-width: 267px;
float: right; float: right;
margin-top: var(--bmt); margin-top: var(--bmt);
} }
#picker, #qcs-w, #hexw, #pall, #ledmap {
margin: 0 auto;
width: 260px;
/*background-color: unset;*/
}
#picker { #picker {
margin-top: -10px !important; margin-top: -10px !important;
max-width: 260px;
} }
/* buttons */ /* buttons */
@ -994,14 +996,12 @@ textarea {
.segname, .pname { .segname, .pname {
white-space: nowrap; white-space: nowrap;
/*cursor: pointer;*/
text-align: center; text-align: center;
overflow: clip; overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
line-height: 24px; line-height: 24px;
padding: 8px 24px; padding: 8px 24px;
max-width: 170px; max-width: 170px;
margin: 0 auto;
position: relative; position: relative;
} }
@ -1012,7 +1012,7 @@ textarea {
/* segment power wrapper */ /* segment power wrapper */
.sbs { .sbs {
padding: 4px 0 4px 8px; padding: 1px 0 1px 20px;
display: var(--sgp); display: var(--sgp);
} }
@ -1208,10 +1208,7 @@ TD .checkmark, TD .radiomark {
border: 0px solid var(--c-f); border: 0px solid var(--c-f);
text-align: left; text-align: left;
transition: background-color 0.5s; transition: background-color 0.5s;
/*filter: brightness(1);*/
font-size: 19px;
border-radius: 21px; border-radius: 21px;
/*min-width: 264px;*/
} }
.seg { .seg {
@ -1254,10 +1251,8 @@ TD .checkmark, TD .radiomark {
/* list wrapper */ /* list wrapper */
.list { .list {
position: relative; position: relative;
width: 280px;
transition: background-color 0.5s; transition: background-color 0.5s;
margin: auto auto 10px; margin: auto auto 10px;
font-size: 19px;
line-height: 24px; line-height: 24px;
} }
@ -1267,6 +1262,7 @@ TD .checkmark, TD .radiomark {
cursor: pointer; cursor: pointer;
background-color: var(--c-2); background-color: var(--c-2);
overflow: hidden; overflow: hidden;
position: -webkit-sticky;
position: sticky; position: sticky;
border-radius: 21px; border-radius: 21px;
margin: 13px auto 0; margin: 13px auto 0;
@ -1303,6 +1299,7 @@ TD .checkmark, TD .radiomark {
.lstI.selected { .lstI.selected {
top: 0; top: 0;
bottom: 0; bottom: 0;
border: 1px solid var(--c-4);
} }
.lstI.sticky, .lstI.sticky,
@ -1358,8 +1355,6 @@ TD .checkmark, TD .radiomark {
/* find/search element */ /* find/search element */
.fnd { .fnd {
width: 280px;
margin: 0 auto;
position: relative; position: relative;
} }
@ -1391,7 +1386,6 @@ TD .checkmark, TD .radiomark {
.presin { .presin {
padding: 8px; padding: 8px;
position: relative; position: relative;
width: 264px;
} }
.btn-s, .btn-s,
@ -1469,6 +1463,16 @@ TD .checkmark, TD .radiomark {
} }
} }
@media all and (max-width: 1023px) {
.top button {
width: 8%;
padding: 10px 0 8px 0;
}
#buttonPcm {
display: none;
}
}
@media all and (max-width: 335px) { @media all and (max-width: 335px) {
.sliderbubble { .sliderbubble {
display: none; display: none;
@ -1487,38 +1491,84 @@ TD .checkmark, TD .radiomark {
} }
} }
@media all and (max-width: 540px) { @media all and (max-width: 420px) {
.top button {
width: 16.6%;
padding: 8px 0 4px 0;
}
}
@media all and (min-width: 541px) and (max-width: 719px) {
.top button {
width: 14.2%;
padding: 8px 0 4px 0;
}
}
@media all and (max-width: 719px) {
.hd {
display: none !important;
}
#briwrap {
margin-top: 0px !important;
float: none;
}
}
@media all and (max-width: 798px) {
#buttonNodes { #buttonNodes {
display: none; display: none;
} }
} }
@media all and (max-width: 1249px) { @media all and (max-width: 639px) {
#buttonPcm { .top button {
width: 16.6%;
padding: 8px 0 4px 0;
}
#briwrap {
margin: 0 auto !important;
float: none;
display: inline-block;
}
.hd {
display: none !important;
}
}
@media all and (min-width: 420px) and (max-width: 639px) {
.top button {
width: 14.28%;
padding: 8px 0 4px 0;
}
}
@media all and (min-width: 640px) and (max-width: 767px) {
#buttonNodes {
display: none; display: none;
} }
} }
/* small screen & tablet "PC mode" support */
@media all and (min-width: 1024px) and (max-width: 1249px) {
#segutil, #segutil2, #segcont, #putil, #pcont, #pql, #fx, #palw, #psFind, #sliders {
width: 100%;
max-width: 280px;
font-size: 18px;
}
#picker {
width: 230px;
}
#putil .btn-s {
width: 114px;
}
#sliders .sliderbubble {
display: none;
}
.sliderwrap {
width: calc(100% - 28px);
}
#sliders .sliderwrap {
left: 12px;
}
.segname {
padding: 8px 16px;
max-width: 140px;
}
.segname, .pname {
max-width: 134px;
}
.segt TD {
padding: 0 !important;
}
input[type="number"], input[type=text], select, textarea {
font-size: 18px;
}
input[type="number"] {
width: 32px;
}
.lstIcontent {
padding-left: 8px;
}
.revchkl {
max-width: 183px;
text-overflow: ellipsis;
overflow-x: clip;
}
}

View File

@ -72,8 +72,8 @@
</div> </div>
<div id="briwrap"> <div id="briwrap">
<p class="hd">Brightness</p> <p class="hd">Brightness</p>
<div class="il"> <div class="slider" style="left:24px;">
<i class="icons slider-icon" onclick="tglTheme()">&#xe2a6;</i> <i class="icons slider-icon" onclick="tglTheme()" style="transform: translate(-32px,5px);">&#xe2a6;</i>
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderBri" onchange="setBri()" oninput="updateTrail(this)" max="255" min="1" type="range" value="128" /> <input id="sliderBri" onchange="setBri()" oninput="updateTrail(this)" max="255" min="1" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
@ -231,6 +231,10 @@
<input type="checkbox" data-flt="&#x1F3A8;" onchange="filterFx(this)"> <input type="checkbox" data-flt="&#x1F3A8;" onchange="filterFx(this)">
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<label id="filter0D" class="check fchkl hide">&#8226;
<input type="checkbox" data-flt="&#8226;" onchange="filterFx(this)">
<span class="checkmark"></span>
</label>
<label id="filter1D" class="check fchkl">&#8942; <label id="filter1D" class="check fchkl">&#8942;
<input type="checkbox" data-flt="&#8942;" onchange="filterFx(this)"> <input type="checkbox" data-flt="&#8942;" onchange="filterFx(this)">
<span class="checkmark"></span> <span class="checkmark"></span>
@ -249,7 +253,7 @@
</label> </label>
</div> </div>
<div id="slider0" class="slider"> <div id="slider0" class="slider">
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglFreeze()">&#xe325;</i> <i class="icons slider-icon" onclick="tglFreeze()">&#xe325;</i>
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" /> <input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>
@ -258,7 +262,7 @@
<span id="sliderLabel0" class="tooltiptext">Effect speed</span> <span id="sliderLabel0" class="tooltiptext">Effect speed</span>
</div> </div>
<div id="slider1" class="slider"> <div id="slider1" class="slider">
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglLabels()">&#xe409;</i> <i class="icons slider-icon" onclick="tglLabels()">&#xe409;</i>
<div class="sliderwrap il"> <div class="sliderwrap il">
<input id="sliderIntensity" class="noslide" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" /> <input id="sliderIntensity" class="noslide" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div> <div class="sliderdisplay"></div>

View File

@ -214,6 +214,7 @@ function onLoad()
resetPUtil(); resetPUtil();
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
applyCfg(); applyCfg();
if (cfg.comp.hdays) { //load custom holiday list if (cfg.comp.hdays) { //load custom holiday list
fetch((loc?`http://${locip}`:'.') + "/holidays.json", { // may be loaded from external source fetch((loc?`http://${locip}`:'.') + "/holidays.json", { // may be loaded from external source
@ -258,9 +259,8 @@ function onLoad()
resetUtil(); resetUtil();
d.addEventListener("visibilitychange", handleVisibilityChange, false); d.addEventListener("visibilitychange", handleVisibilityChange, false);
size(); //size();
gId("cv").style.opacity=0; gId("cv").style.opacity=0;
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
var sls = d.querySelectorAll('input[type="range"]'); var sls = d.querySelectorAll('input[type="range"]');
for (var sl of sls) { for (var sl of sls) {
sl.addEventListener('touchstart', toggleBubble); sl.addEventListener('touchstart', toggleBubble);
@ -603,14 +603,19 @@ function parseInfo(i) {
syncTglRecv = i.str; syncTglRecv = i.str;
maxSeg = i.leds.maxseg; maxSeg = i.leds.maxseg;
pmt = i.fs.pmt; pmt = i.fs.pmt;
gId('buttonNodes').style.display = lastinfo.ndc > 0 ? null:"none";
// do we have a matrix set-up // do we have a matrix set-up
mw = i.leds.matrix ? i.leds.matrix.w : 0; mw = i.leds.matrix ? i.leds.matrix.w : 0;
mh = i.leds.matrix ? i.leds.matrix.h : 0; mh = i.leds.matrix ? i.leds.matrix.h : 0;
isM = mw>0 && mh>0; isM = mw>0 && mh>0;
if (!isM) { if (!isM) {
gId("filter0D").classList.remove('hide');
gId("filter1D").classList.add('hide'); gId("filter1D").classList.add('hide');
//gId("filter2D").classList.add('hide'); gId("filter2D").classList.add('hide');
hideModes("2D"); } else {
gId("filter0D").classList.add('hide');
gId("filter1D").classList.remove('hide');
gId("filter2D").classList.remove('hide');
} }
// if (i.noaudio) { // if (i.noaudio) {
// gId("filterVol").classList.add("hide"); // gId("filterVol").classList.add("hide");
@ -638,7 +643,7 @@ function parseInfo(i) {
function populateInfo(i) function populateInfo(i)
{ {
var cn=""; var cn="";
var heap = i.freeheap/1000; var heap = i.freeheap/1024;
heap = heap.toFixed(1); heap = heap.toFixed(1);
var pwr = i.leds.pwr; var pwr = i.leds.pwr;
var pwru = "Not calculated"; var pwru = "Not calculated";
@ -697,13 +702,13 @@ function populateSegments(s)
let sg = gId(`seg${i}`); let sg = gId(`seg${i}`);
let exp = sg ? (sg.classList.contains('expanded') || (i===0 && cfg.comp.segexp)) : false; let exp = sg ? (sg.classList.contains('expanded') || (i===0 && cfg.comp.segexp)) : false;
let segp = `<div id="segp${i}" class="sbs"> let segp = `<div id="segp${i}" class="sbs">`+
<i class="icons e-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})">&#xe08f;</i> `<i class="icons slider-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})">&#xe08f;</i>`+
<div class="sliderwrap il"> `<div class="sliderwrap il">`+
<input id="seg${i}bri" class="noslide" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" /> `<input id="seg${i}bri" class="noslide" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" />`+
<div class="sliderdisplay"></div> `<div class="sliderdisplay"></div>`+
</div> `</div>`+
</div>`; `</div>`;
let staX = inst.start; let staX = inst.start;
let stoX = inst.stop; let stoX = inst.stop;
let staY = inst.startY; let staY = inst.startY;
@ -715,81 +720,81 @@ function populateSegments(s)
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`; rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`;
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`; miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`;
} }
let map2D = `<div id="seg${i}map2D" data-map="map2D" class="lbl-s hide">Expand 1D FX<br> let map2D = `<div id="seg${i}map2D" data-map="map2D" class="lbl-s hide">Expand 1D FX<br>`+
<div class="sel-p"><select class="sel-p" id="seg${i}m12" onchange="setM12(${i})"> `<div class="sel-p"><select class="sel-p" id="seg${i}m12" onchange="setM12(${i})">`+
<option value="0" ${inst.m12==0?' selected':''}>Pixels</option> `<option value="0" ${inst.m12==0?' selected':''}>Pixels</option>`+
<option value="1" ${inst.m12==1?' selected':''}>Bar</option> `<option value="1" ${inst.m12==1?' selected':''}>Bar</option>`+
<option value="2" ${inst.m12==2?' selected':''}>Arc</option> `<option value="2" ${inst.m12==2?' selected':''}>Arc</option>`+
<option value="3" ${inst.m12==3?' selected':''}>Corner</option> `<option value="3" ${inst.m12==3?' selected':''}>Corner</option>`+
</select></div> `</select></div>`+
</div>`; `</div>`;
let sndSim = `<div data-snd="si" class="lbl-s hide">Sound sim<br> let sndSim = `<div data-snd="si" class="lbl-s hide">Sound sim<br>`+
<div class="sel-p"><select class="sel-p" id="seg${i}si" onchange="setSi(${i})"> `<div class="sel-p"><select class="sel-p" id="seg${i}si" onchange="setSi(${i})">`+
<option value="0" ${inst.si==0?' selected':''}>BeatSin</option> `<option value="0" ${inst.si==0?' selected':''}>BeatSin</option>`+
<option value="1" ${inst.si==1?' selected':''}>WeWillRockYou</option> `<option value="1" ${inst.si==1?' selected':''}>WeWillRockYou</option>`+
<option value="2" ${inst.si==2?' selected':''}>U10_3</option> `<option value="2" ${inst.si==2?' selected':''}>U10_3</option>`+
<option value="3" ${inst.si==3?' selected':''}>U14_3</option> `<option value="3" ${inst.si==3?' selected':''}>U14_3</option>`+
</select></div> `</select></div>`+
</div>`; `</div>`;
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}"> cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}">`+
<label class="check schkl"> `<label class="check schkl">`+
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}> `<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>`+
<span class="checkmark"></span> `<span class="checkmark"></span>`+
</label> `</label>`+
<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i> `<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>`+
<div class="segname" onclick="selSegEx(${i})"> `<div class="segname" onclick="selSegEx(${i})">`+
${inst.n ? inst.n : "Segment "+i} (inst.n ? inst.n : "Segment "+i) +
<i class="icons edit-icon flr" id="seg${i}nedit" onclick="tglSegn(${i})">&#xe2c6;</i> `<i class="icons edit-icon flr" id="seg${i}nedit" onclick="tglSegn(${i})">&#xe2c6;</i>`+
</div> `</div>`+
<i class="icons e-icon flr" id="sege${i}" onclick="expand(${i})">&#xe395;</i> `<i class="icons e-icon flr" id="sege${i}" onclick="expand(${i})">&#xe395;</i>`+
${cfg.comp.segpwr?segp:''} (cfg.comp.segpwr ? segp : '') +
<div class="segin" id="seg${i}in"> `<div class="segin" id="seg${i}in">`+
<input type="text" class="ptxt" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/> `<input type="text" class="ptxt" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>`+
<table class="infot segt"> `<table class="infot segt">`+
<tr> `<tr>`+
<td>${isM&&staX<mw*mh?'Start X':'Start LED'}</td> `<td>${isM&&staX<mw*mh?'Start X':'Start LED'}</td>`+
<td>${isM&&staX<mw*mh?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td> `<td>${isM&&staX<mw*mh?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>`+
<td>${isM&&staX<mw*mh?'':'Offset'}</td> `<td>${isM&&staX<mw*mh?'':'Offset'}</td>`+
</tr> `</tr>`+
<tr> `<tr>`+
<td><input class="segn" id="seg${i}s" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> `<td><input class="segn" id="seg${i}s" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
<td><input class="segn" id="seg${i}e" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> `<td><input class="segn" id="seg${i}e" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
<td style="text-align:revert;">${isM&&staX<mw*mh?miXck+'<br>'+rvXck:''}<input class="segn ${isM&&staX<mw*mh?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td> `<td style="text-align:revert;">${isM&&staX<mw*mh?miXck+'<br>'+rvXck:''}<input class="segn ${isM&&staX<mw*mh?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>`+
</tr> `</tr>`+
${isM&&staX<mw*mh ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+ (isM && staX<mw*mh ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
'<tr>'+ '<tr>'+
'<td><input class="segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+ '<td><input class="segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td><input class="segn" id="seg'+i+'eY" type="number" min="0" max="'+mh+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+ '<td><input class="segn" id="seg'+i+'eY" type="number" min="0" max="'+mh+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+ '<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+
'</tr>':''} '</tr>' : '') +
<tr> `<tr>`+
<td>Grouping</td> `<td>Grouping</td>`+
<td>Spacing</td> `<td>Spacing</td>`+
<td></td> `<td></td>`+
</tr> `</tr>`+
<tr> `<tr>`+
<td><input class="segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> `<td><input class="segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
<td><input class="segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> `<td><input class="segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
<td style="text-align:revert;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td> `<td style="text-align:revert;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td>`+
</tr> `</tr>`+
</table> `</table>`+
<div class="h bp" id="seg${i}len"></div> `<div class="h bp" id="seg${i}len"></div>`+
${!(isM&&staX<mw*mh)?rvXck:''} (!(isM&&staX<mw*mh) ? rvXck : '') +
${isM&&staX<mw*mh&&stoY-staY>1&&stoX-staX>1?map2D:''} (isM&&staX<mw*mh&&stoY-staY>1&&stoX-staX>1 ? map2D : '') +
${s.AudioReactive && s.AudioReactive.on ? "" : sndSim} (s.AudioReactive && s.AudioReactive.on ? "" : sndSim) +
<label class="check revchkl" id="seg${i}lbtm"> `<label class="check revchkl" id="seg${i}lbtm">`+
${isM&&staX<mw*mh?'Transpose':'Mirror effect'}${isM&&staX<mw*mh? (isM&&staX<mw*mh?'Transpose':'Mirror effect') + (isM&&staX<mw*mh ?
'<input type="checkbox" id="seg'+i+'tp" onchange="setTp('+i+')" '+(inst.tp?"checked":"")+'>': '<input type="checkbox" id="seg'+i+'tp" onchange="setTp('+i+')" '+(inst.tp?"checked":"")+'>':
'<input type="checkbox" id="seg'+i+'mi" onchange="setMi('+i+')" '+(inst.mi?"checked":"")+'>'} '<input type="checkbox" id="seg'+i+'mi" onchange="setMi('+i+')" '+(inst.mi?"checked":"")+'>') +
<span class="checkmark"></span> `<span class="checkmark"></span>`+
</label> `</label>`+
<div class="del"> `<div class="del">`+
<button class="btn btn-xs" id="segr${i}" title="Repeat until end" onclick="rptSeg(${i})"><i class="icons btn-icon">&#xe22d;</i></button> `<button class="btn btn-xs" id="segr${i}" title="Repeat until end" onclick="rptSeg(${i})"><i class="icons btn-icon">&#xe22d;</i></button>`+
<button class="btn btn-xs" id="segd${i}" title="Delete" onclick="delSeg(${i})"><i class="icons btn-icon">&#xe037;</i></button> `<button class="btn btn-xs" id="segd${i}" title="Delete" onclick="delSeg(${i})"><i class="icons btn-icon">&#xe037;</i></button>`+
</div> `</div>`+
</div> `</div>`+
${cfg.comp.segpwr?'':segp} (cfg.comp.segpwr ? '' : segp) +
</div>`; `</div>`;
} }
gId('segcont').innerHTML = cn; gId('segcont').innerHTML = cn;
@ -960,18 +965,16 @@ function genPalPrevCss(id)
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', effectPar = '') function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', effectPar = '')
{ {
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" ${effectPar===''?'':'data-opt="'+effectPar+'"'}onClick="${clickAction}(${id})"> return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" ${effectPar===''?'':'data-opt="'+effectPar+'"'}onClick="${clickAction}(${id})">`+
<label class="radio schkl" onclick="event.preventDefault()"> `<label class="radio schkl" onclick="event.preventDefault()">`+
<input type="radio" value="${id}" name="${listName}"> `<input type="radio" value="${id}" name="${listName}">`+
<span class="radiomark"></span> `<span class="radiomark"></span>`+
<div class="lstIcontent"> `<div class="lstIcontent">`+
<span class="lstIname"> `<span class="lstIname">${name}</span>`+
${name} `</div>`+
</span> `</label>`+
</div> extraHtml +
</label> `</div>`;
${extraHtml}
</div>`;
} }
function btype(b) function btype(b)
@ -1160,7 +1163,6 @@ function updateUI()
gId('buttonPower').className = (isOn) ? 'active':''; gId('buttonPower').className = (isOn) ? 'active':'';
gId('buttonNl').className = (nlA) ? 'active':''; gId('buttonNl').className = (nlA) ? 'active':'';
gId('buttonSync').className = (syncSend) ? 'active':''; gId('buttonSync').className = (syncSend) ? 'active':'';
showNodes();
updateSelectedFx(); updateSelectedFx();
updateSelectedPalette(selectedPal); // must be after updateSelectedFx() to un-hide color slots for * palettes updateSelectedPalette(selectedPal); // must be after updateSelectedFx() to un-hide color slots for * palettes
@ -1244,7 +1246,7 @@ function updateSelectedFx()
if (fx.dataset.id>0) { if (fx.dataset.id>0) {
if (segLmax==0) fx.classList.add('hide'); // none of the segments selected (hide all effects) if (segLmax==0) fx.classList.add('hide'); // none of the segments selected (hide all effects)
else { else {
if (segLmax==1 && (!opts[3] || opts[3].indexOf("0")<0)) fx.classList.add('hide'); if ((segLmax==1 && (!opts[3] || opts[3].indexOf("0")<0)) || (!isM && opts[3] && ((opts[3].indexOf("2")>=0 && opts[3].indexOf("1")<0)))) fx.classList.add('hide');
else fx.classList.remove('hide'); else fx.classList.remove('hide');
} }
} }
@ -1295,7 +1297,6 @@ function makeWS() {
var i = json.info; var i = json.info;
if (i) { if (i) {
parseInfo(i); parseInfo(i);
showNodes();
if (isInfo) populateInfo(i); if (isInfo) populateInfo(i);
} else } else
i = lastinfo; i = lastinfo;
@ -1720,29 +1721,29 @@ function makeSeg()
behavior: 'smooth', behavior: 'smooth',
block: 'start', block: 'start',
}); });
var cn = `<div class="seg lstI expanded"> var cn = `<div class="seg lstI expanded">`+
<div class="segin"> `<div class="segin">`+
<input type="text" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/> `<input type="text" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/>`+
<table class="segt"> `<table class="segt">`+
<tr> `<tr>`+
<td width="38%">${isM?'Start X':'Start LED'}</td> `<td width="38%">${isM?'Start X':'Start LED'}</td>`+
<td width="38%">${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td> `<td width="38%">${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>`+
</tr> `</tr>`+
<tr> `<tr>`+
<td><input class="segn" id="seg${lu}s" type="number" min="0" max="${isM?mw-1:ledCount-1}" value="${ns}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td> `<td><input class="segn" id="seg${lu}s" type="number" min="0" max="${isM?mw-1:ledCount-1}" value="${ns}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>`+
<td><input class="segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td> `<td><input class="segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>`+
<td><button class="btn btn-xs" onclick="setSeg(${lu});"><i class="icons bth-icon" id="segc${lu}">&#xe390;</i></button></td> `<td><button class="btn btn-xs" onclick="setSeg(${lu});"><i class="icons bth-icon" id="segc${lu}">&#xe390;</i></button></td>`+
</tr> `</tr>`+
<tr id="mkSYH" class="${isM?"":"hide"}"><td>Start Y</td><td>${cfg.comp.seglen?'Height':'Stop Y'}</td></tr> `<tr id="mkSYH" class="${isM?"":"hide"}"><td>Start Y</td><td>${cfg.comp.seglen?'Height':'Stop Y'}</td></tr>`+
<tr id="mkSYD" class="${isM?"":"hide"}"> `<tr id="mkSYD" class="${isM?"":"hide"}">`+
<td><input class="segn" id="seg${lu}sY" type="number" min="0" max="${mh-1}" value="0" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td> `<td><input class="segn" id="seg${lu}sY" type="number" min="0" max="${mh-1}" value="0" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>`+
<td><input class="segn" id="seg${lu}eY" type="number" min="0" max="${mh}" value="${isM?mh:1}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td> `<td><input class="segn" id="seg${lu}eY" type="number" min="0" max="${mh}" value="${isM?mh:1}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>`+
</tr> `</tr>`+
</table> `</table>`+
<div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div> `<div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div>`+
<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div> `<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div>`+
</div> `</div>`+
</div>`; `</div>`;
gId('segutil').innerHTML = cn; gId('segutil').innerHTML = cn;
} }
@ -2619,7 +2620,7 @@ function getPalettesData(page, callback)
showToast(error, true); showToast(error, true);
}); });
} }
/*
function hideModes(txt) function hideModes(txt)
{ {
for (let e of (gId('fxlist').querySelectorAll('.lstI')||[])) { for (let e of (gId('fxlist').querySelectorAll('.lstI')||[])) {
@ -2630,7 +2631,7 @@ function hideModes(txt)
if (f) e.classList.add('hide'); //else e.classList.remove('hide'); if (f) e.classList.add('hide'); //else e.classList.remove('hide');
} }
} }
*/
function search(f,l=null) function search(f,l=null)
{ {
f.nextElementSibling.style.display=(f.value!=='')?'block':'none'; f.nextElementSibling.style.display=(f.value!=='')?'block':'none';
@ -2795,20 +2796,16 @@ function move(e)
x0 = null; x0 = null;
} }
function showNodes() {
gId('buttonNodes').style.display = (lastinfo.ndc > 0 && (wW > 797 || (wW > 539 && wW < 720))) ? "block":"none";
}
function size() function size()
{ {
wW = window.innerWidth; wW = window.innerWidth;
showNodes();
var h = gId('top').clientHeight; var h = gId('top').clientHeight;
sCol('--th', h + "px"); sCol('--th', h + "px");
sCol('--bh', gId('bot').clientHeight + "px"); sCol('--bh', gId('bot').clientHeight + "px");
if (isLv) h -= 4; if (isLv) h -= 4;
sCol('--tp', h + "px"); sCol('--tp', h + "px");
togglePcMode(); togglePcMode();
lastw = wW;
} }
function togglePcMode(fromB = false) function togglePcMode(fromB = false)
@ -2816,19 +2813,16 @@ function togglePcMode(fromB = false)
if (fromB) { if (fromB) {
pcModeA = !pcModeA; pcModeA = !pcModeA;
localStorage.setItem('pcm', pcModeA); localStorage.setItem('pcm', pcModeA);
pcMode = pcModeA;
} }
if (wW < 1250 && !pcMode) return; pcMode = (wW >= 1024) && pcModeA;
if (!fromB && ((wW < 1250 && lastw < 1250) || (wW >= 1250 && lastw >= 1250))) return; if (cpick) cpick.resize(pcMode && wW>1023 && wW<1250 ? 230 : 260); // for tablet in landscape
if (!fromB && ((wW < 1024 && lastw < 1024) || (wW >= 1024 && lastw >= 1024))) return; // no change in size and called from size()
openTab(0, true); openTab(0, true);
if (wW < 1250) {pcMode = false;}
else if (pcModeA && !fromB) pcMode = pcModeA;
updateTablinks(0); updateTablinks(0);
gId('buttonPcm').className = (pcMode) ? "active":""; gId('buttonPcm').className = (pcMode) ? "active":"";
gId('bot').style.height = (pcMode && !cfg.comp.pcmbot) ? "0":"auto"; gId('bot').style.height = (pcMode && !cfg.comp.pcmbot) ? "0":"auto";
sCol('--bh', gId('bot').clientHeight + "px"); sCol('--bh', gId('bot').clientHeight + "px");
_C.style.width = (pcMode)?'100%':'400%'; _C.style.width = (pcMode)?'100%':'400%';
lastw = wW;
} }
function mergeDeep(target, ...sources) function mergeDeep(target, ...sources)
@ -2852,7 +2846,7 @@ function mergeDeep(target, ...sources)
size(); size();
_C.style.setProperty('--n', N); _C.style.setProperty('--n', N);
window.addEventListener('resize', size, false); window.addEventListener('resize', size, true);
_C.addEventListener('mousedown', lock, false); _C.addEventListener('mousedown', lock, false);
_C.addEventListener('touchstart', lock, false); _C.addEventListener('touchstart', lock, false);

File diff suppressed because it is too large Load Diff

View File

@ -300,10 +300,10 @@ byte PinManagerClass::allocateLedc(byte channels)
if (ca >= channels) { //enough free channels if (ca >= channels) { //enough free channels
byte in = (i + 1) - ca; byte in = (i + 1) - ca;
for (byte j = 0; j < ca; j++) { for (byte j = 0; j < ca; j++) {
byte b = in + j; byte bChan = in + j;
byte by = b >> 3; byte byChan = bChan >> 3;
byte bi = b - 8*by; byte biChan = bChan - 8*byChan;
bitWrite(ledcAlloc[by], bi, true); bitWrite(ledcAlloc[byChan], biChan, true);
} }
return in; return in;
} }

View File

@ -821,9 +821,9 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
} }
} }
byte buffer[ART_NET_HEADER_SIZE]; byte header_buffer[ART_NET_HEADER_SIZE];
memcpy_P(buffer, ART_NET_HEADER, ART_NET_HEADER_SIZE); memcpy_P(header_buffer, ART_NET_HEADER, ART_NET_HEADER_SIZE);
ddpUdp.write(buffer, ART_NET_HEADER_SIZE); // This doesn't change. Hard coded ID, OpCode, and protocol version. ddpUdp.write(header_buffer, ART_NET_HEADER_SIZE); // This doesn't change. Hard coded ID, OpCode, and protocol version.
ddpUdp.write(sequenceNumber & 0xFF); // sequence number. 1..255 ddpUdp.write(sequenceNumber & 0xFF); // sequence number. 1..255
ddpUdp.write(0x00); // physical - more an FYI, not really used for anything. 0..3 ddpUdp.write(0x00); // physical - more an FYI, not really used for anything. 0..3
ddpUdp.write((currentPacket) & 0xFF); // Universe LSB. 1 full packet == 1 full universe, so just use current packet number. ddpUdp.write((currentPacket) & 0xFF); // Universe LSB. 1 full packet == 1 full universe, so just use current packet number.

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2303240 #define VERSION 2304090
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG