2d Mapping with Matrix Gaps (#2892)

* New 2d mapping
* panel matrix generator
* add todos, fix vert/horz swap
* Fix 2d mapping to matrix in settings 2D
* add correct index mapping to pixels per panel
* fix panel bug in led layout
* formatting and change max panels
* add per panel width and height
* fix using length instead of custom mapping size
* fix: panel dimensions location

* panel[] implemented as a vector.
Removed matrixWidth & matrixHeight.
Panel structure update.
* Fixes.

Co-authored-by: Blaz Kristan <blaz@kristan-sp.si>
This commit is contained in:
Caleb Marting 2023-01-02 13:56:00 -06:00 committed by GitHub
parent 8e208bc76d
commit 187ecf511f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1445 additions and 1349 deletions

View File

@ -655,12 +655,8 @@ class WS2812FX { // 96 bytes
timebase(0), timebase(0),
isMatrix(false), isMatrix(false),
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
hPanels(1), panels(1),
vPanels(1),
panelH(8),
panelW(8),
matrix{0,0,0,0}, matrix{0,0,0,0},
panel{{0,0,0,0}},
#endif #endif
// semi-private (just obscured) used in effect functions through macros // semi-private (just obscured) used in effect functions through macros
_currentPalette(CRGBPalette16(CRGB::Black)), _currentPalette(CRGBPalette16(CRGB::Black)),
@ -697,6 +693,7 @@ class WS2812FX { // 96 bytes
_mode.clear(); _mode.clear();
_modeData.clear(); _modeData.clear();
_segments.clear(); _segments.clear();
panel.clear();
customPalettes.clear(); customPalettes.clear();
if (useLedsArray && Segment::_globalLeds) free(Segment::_globalLeds); if (useLedsArray && Segment::_globalLeds) free(Segment::_globalLeds);
} }
@ -809,22 +806,31 @@ class WS2812FX { // 96 bytes
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
#define WLED_MAX_PANELS 64 #define WLED_MAX_PANELS 64
uint8_t uint8_t
hPanels, panels;
vPanels;
uint16_t struct {
panelH, bool bottomStart : 1;
panelW; bool rightStart : 1;
bool vertical : 1;
bool serpentine : 1;
} matrix;
typedef struct panel_bitfield_t { typedef struct panel_t {
bool bottomStart : 1; // starts at bottom? uint16_t xOffset; // x offset relative to the top left of matrix in LEDs
bool rightStart : 1; // starts on right? uint16_t yOffset; // y offset relative to the top left of matrix in LEDs
bool vertical : 1; // is vertical? uint8_t width; // width of the panel
bool serpentine : 1; // is serpentine? uint8_t height; // height of the panel
union {
uint8_t options;
struct {
bool bottomStart : 1; // starts at bottom?
bool rightStart : 1; // starts on right?
bool vertical : 1; // is vertical?
bool serpentine : 1; // is serpentine?
};
};
} Panel; } Panel;
Panel std::vector<Panel> panel;
matrix,
panel[WLED_MAX_PANELS];
#endif #endif
void void

View File

@ -41,57 +41,57 @@ void WS2812FX::setUpMatrix() {
customMappingTable = nullptr; customMappingTable = nullptr;
customMappingSize = 0; customMappingSize = 0;
// important if called from set.cpp, irrelevant if called from cfg.cpp
// fix limits if not a matrix set-up (no finalizeInit() called from set.cpp)
Segment::maxWidth = _length;
Segment::maxHeight = 1;
// isMatrix is set in cfg.cpp or set.cpp // isMatrix is set in cfg.cpp or set.cpp
if (isMatrix) { if (isMatrix) {
uint16_t maxWidth = hPanels * panelW; // calculate width dynamically because it will have gaps
uint16_t maxHeight = vPanels * panelH; Segment::maxWidth = 1;
Segment::maxHeight = 1;
for (size_t i = 0; i < panel.size(); i++) {
Panel &p = panel[i];
if (p.xOffset + p.width > Segment::maxWidth) {
Segment::maxWidth = p.xOffset + p.width;
}
if (p.yOffset + p.height > Segment::maxHeight) {
Segment::maxHeight = p.yOffset + p.height;
}
}
// safety check // safety check
if (maxWidth * maxHeight > MAX_LEDS || maxWidth == 1 || maxHeight == 1) { if (Segment::maxWidth * Segment::maxHeight > MAX_LEDS || Segment::maxWidth <= 1 || Segment::maxHeight <= 1) {
DEBUG_PRINTLN(F("2D Bounds error."));
isMatrix = false; isMatrix = false;
Segment::maxWidth = _length;
Segment::maxHeight = 1;
panels = 0;
panel.clear(); // release memory allocated by panels
return; return;
} }
customMappingTable = new uint16_t[maxWidth * maxHeight]; customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight];
if (customMappingTable != nullptr) { if (customMappingTable != nullptr) {
Segment::maxWidth = maxWidth; customMappingSize = Segment::maxWidth * Segment::maxHeight;
Segment::maxHeight = maxHeight;
customMappingSize = maxWidth * maxHeight;
uint16_t startL; // index in custom mapping array (logical strip) // fill with empty in case we don't fill the entire matrix
uint16_t startP; // position of 1st pixel of panel on (virtual) strip for (size_t i = 0; i< customMappingSize; i++) {
uint16_t x, y, offset; customMappingTable[i] = (uint16_t)-1;
uint8_t h = matrix.vertical ? vPanels : hPanels; }
uint8_t v = matrix.vertical ? hPanels : vPanels;
for (uint8_t j=0, p=0; j<v; j++) { uint16_t x, y, pix=0; //pixel
for (uint8_t i=0; i<h; i++, p++) { for (size_t pan = 0; pan < panel.size(); pan++) {
y = (matrix.vertical ? matrix.rightStart : matrix.bottomStart) ? v - j - 1 : j; Panel &p = panel[pan];
x = (matrix.vertical ? matrix.bottomStart : matrix.rightStart) ? h - i - 1 : i; uint16_t h = p.vertical ? p.height : p.width;
x = matrix.serpentine && j%2 ? h - x - 1 : x; uint16_t v = p.vertical ? p.width : p.height;
for (size_t j = 0; j < v; j++){
startL = (matrix.vertical ? y : x) * panelW + (matrix.vertical ? x : y) * Segment::maxWidth * panelH; // logical index (top-left corner) for(size_t i = 0; i < h; i++, pix++) {
startP = p * panelW * panelH; // physical index (top-left corner) y = (p.vertical?p.rightStart:p.bottomStart) ? v-j-1 : j;
x = (p.vertical?p.bottomStart:p.rightStart) ? h-i-1 : i;
uint8_t H = panel[h*j + i].vertical ? panelW : panelH; x = p.serpentine && j%2 ? h-x-1 : x;
uint8_t W = panel[h*j + i].vertical ? panelH : panelW; customMappingTable[(p.yOffset + (p.vertical?x:y)) * Segment::maxWidth + p.xOffset + (p.vertical?y:x)] = pix;
for (uint16_t l=0, q=0; l<H; l++) {
for (uint16_t k=0; k<W; k++, q++) {
y = (panel[h*j + i].vertical ? panel[h*j + i].rightStart : panel[h*j + i].bottomStart) ? H - l - 1 : l;
x = (panel[h*j + i].vertical ? panel[h*j + i].bottomStart : panel[h*j + i].rightStart) ? W - k - 1 : k;
x = (panel[h*j + i].serpentine && l%2) ? (W - x - 1) : x;
offset = (panel[h*j + i].vertical ? y : x) + (panel[h*j + i].vertical ? x : y) * Segment::maxWidth;
customMappingTable[startL + offset] = startP + q;
}
} }
} }
} }
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
DEBUG_PRINT(F("Matrix ledmap:")); DEBUG_PRINT(F("Matrix ledmap:"));
for (uint16_t i=0; i<customMappingSize; i++) { for (uint16_t i=0; i<customMappingSize; i++) {
@ -101,7 +101,13 @@ void WS2812FX::setUpMatrix() {
DEBUG_PRINTLN(); DEBUG_PRINTLN();
#endif #endif
} else { // memory allocation error } else { // memory allocation error
DEBUG_PRINTLN(F("Ledmap alloc error."));
isMatrix = false; isMatrix = false;
panels = 0;
panel.clear();
Segment::maxWidth = _length;
Segment::maxHeight = 1;
return;
} }
} }
#else #else
@ -115,7 +121,7 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
if (!isMatrix) return; // not a matrix set-up if (!isMatrix) return; // not a matrix set-up
uint16_t index = y * Segment::maxWidth + x; uint16_t index = y * Segment::maxWidth + x;
if (index >= customMappingSize) return; // customMappingSize is always W * H of matrix in 2D setup if (index >= customMappingSize) return;
#else #else
uint16_t index = x; uint16_t index = x;
if (index >= _length) return; if (index >= _length) return;

View File

@ -97,32 +97,38 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
JsonObject matrix = hw_led[F("matrix")]; JsonObject matrix = hw_led[F("matrix")];
if (!matrix.isNull()) { if (!matrix.isNull()) {
strip.isMatrix = true; strip.isMatrix = true;
CJSON(strip.panelH, matrix[F("ph")]); CJSON(strip.panels, matrix[F("mpc")]);
CJSON(strip.panelW, matrix[F("pw")]);
CJSON(strip.hPanels, matrix[F("mph")]);
CJSON(strip.vPanels, matrix[F("mpv")]);
CJSON(strip.matrix.bottomStart, matrix[F("pb")]); CJSON(strip.matrix.bottomStart, matrix[F("pb")]);
CJSON(strip.matrix.rightStart, matrix[F("pr")]); CJSON(strip.matrix.rightStart, matrix[F("pr")]);
CJSON(strip.matrix.vertical, matrix[F("pv")]); CJSON(strip.matrix.vertical, matrix[F("pv")]);
CJSON(strip.matrix.serpentine, matrix["ps"]); CJSON(strip.matrix.serpentine, matrix["ps"]);
strip.panel.clear();
JsonArray panels = matrix[F("panels")]; JsonArray panels = matrix[F("panels")];
uint8_t s = 0; uint8_t s = 0;
if (!panels.isNull()) { if (!panels.isNull()) {
strip.panel.reserve(max(1U,min((size_t)strip.panels,(size_t)WLED_MAX_PANELS))); // pre-allocate memory for panels
for (JsonObject pnl : panels) { for (JsonObject pnl : panels) {
CJSON(strip.panel[s].bottomStart, pnl["b"]); WS2812FX::Panel p;
CJSON(strip.panel[s].rightStart, pnl["r"]); CJSON(p.bottomStart, pnl["b"]);
CJSON(strip.panel[s].vertical, pnl["v"]); CJSON(p.rightStart, pnl["r"]);
CJSON(strip.panel[s].serpentine, pnl["s"]); CJSON(p.vertical, pnl["v"]);
if (++s >= WLED_MAX_PANELS) break; // max panels reached CJSON(p.serpentine, pnl["s"]);
CJSON(p.xOffset, pnl["x"]);
CJSON(p.yOffset, pnl["y"]);
CJSON(p.height, pnl["h"]);
CJSON(p.width, pnl["w"]);
strip.panel.push_back(p);
if (++s >= WLED_MAX_PANELS || s >= strip.panels) break; // max panels reached
} }
} } else {
// clear remaining panels // fallback
for (; s<WLED_MAX_PANELS; s++) { WS2812FX::Panel p;
strip.panel[s].bottomStart = 0; strip.panels = 1;
strip.panel[s].rightStart = 0; p.height = p.width = 8;
strip.panel[s].vertical = 0; p.xOffset = p.yOffset = 0;
strip.panel[s].serpentine = 0; p.options = 0;
strip.panel.push_back(p);
} }
strip.setUpMatrix(); strip.setUpMatrix();
@ -700,22 +706,23 @@ void serializeConfig() {
// 2D Matrix Settings // 2D Matrix Settings
if (strip.isMatrix) { if (strip.isMatrix) {
JsonObject matrix = hw_led.createNestedObject(F("matrix")); JsonObject matrix = hw_led.createNestedObject(F("matrix"));
matrix[F("ph")] = strip.panelH; matrix[F("mpc")] = strip.panels;
matrix[F("pw")] = strip.panelW;
matrix[F("mph")] = strip.hPanels;
matrix[F("mpv")] = strip.vPanels;
matrix[F("pb")] = strip.matrix.bottomStart; matrix[F("pb")] = strip.matrix.bottomStart;
matrix[F("pr")] = strip.matrix.rightStart; matrix[F("pr")] = strip.matrix.rightStart;
matrix[F("pv")] = strip.matrix.vertical; matrix[F("pv")] = strip.matrix.vertical;
matrix["ps"] = strip.matrix.serpentine; matrix["ps"] = strip.matrix.serpentine;
JsonArray panels = matrix.createNestedArray(F("panels")); JsonArray panels = matrix.createNestedArray(F("panels"));
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) { for (uint8_t i=0; i<strip.panel.size(); i++) {
JsonObject pnl = panels.createNestedObject(); JsonObject pnl = panels.createNestedObject();
pnl["b"] = strip.panel[i].bottomStart; pnl["b"] = strip.panel[i].bottomStart;
pnl["r"] = strip.panel[i].rightStart; pnl["r"] = strip.panel[i].rightStart;
pnl["v"] = strip.panel[i].vertical; pnl["v"] = strip.panel[i].vertical;
pnl["s"] = strip.panel[i].serpentine; pnl["s"] = strip.panel[i].serpentine;
pnl["x"] = strip.panel[i].xOffset;
pnl["y"] = strip.panel[i].yOffset;
pnl["h"] = strip.panel[i].height;
pnl["w"] = strip.panel[i].width;
} }
} }
#endif #endif

View File

@ -8,6 +8,7 @@
<script> <script>
var d=document; var d=document;
var loc = false, locip; var loc = false, locip;
var maxPanels=64;
function H(){window.open("https://kno.wled.ge/features/2D");} function H(){window.open("https://kno.wled.ge/features/2D");}
function B(){window.open("/settings","_self");} function B(){window.open("/settings","_self");}
function gId(n){return d.getElementById(n);} function gId(n){return d.getElementById(n);}
@ -43,34 +44,31 @@
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
} }
var maxPanels=64; function UI(panels=1)
function UI(change=false)
{ {
gId("mpdiv").style.display = "block";
if (gId("somp").value === "0") { if (gId("somp").value === "0") {
gId("mpdiv").style.display = "none"; gId("mpdiv").style.display = "none";
resetPanels(); resetPanels();
return; return;
} }
gId("mpdiv").style.display = "block";
maxPanels = parseInt(d.Sf.MPH.value) * parseInt(d.Sf.MPV.value);
let i = gId("panels").children.length; let i = gId("panels").children.length;
if (i<maxPanels) for (let j=i; j<maxPanels; j++) addPanel(j); if (i<panels) for (let j=i; j<panels; j++) addPanel(j);
if (i>maxPanels) for (let j=i; j>maxPanels; j--) remPanel(); if (i>panels) for (let j=i; j>panels; j--) remPanel();
//btnPanel(gId("panels").children.length);
} }
function addPanels() { function addPanels() {
let h = parseInt(d.Sf.MPH.value); let c = parseInt(d.Sf.MPC.value);
let v = parseInt(d.Sf.MPV.value); for (let i=0; i<c; i++) addPanel(i);
for (let i=0; i<h*v; i++) addPanel(i);
} }
function addPanel(i=0) { function addPanel(i=0) {
let p = gId("panels"); let p = gId("panels");
if (p.children.length >= maxPanels) return; if (p.children.length >= maxPanels) return;
let b = `<div id="pnl${i}">${i===0?"":'<hr class="sml">'}Panel ${i}<br>1<sup>st</sup> LED: <select name="P${i}B"> let b = `<div id="pnl${i}"><hr class="sml">Panel ${i}<br>
1<sup>st</sup> LED: <select name="P${i}B">
<option value="0">Top</option> <option value="0">Top</option>
<option value="1">Bottom</option> <option value="1">Bottom</option>
</select><select name="P${i}R"> </select><select name="P${i}R">
@ -81,7 +79,11 @@ Orientation: <select name="P${i}V">
<option value="0">Horizontal</option> <option value="0">Horizontal</option>
<option value="1">Vertical</option> <option value="1">Vertical</option>
</select><br> </select><br>
Serpentine: <input type="checkbox" name="P${i}S"></div>`; Serpentine: <input type="checkbox" name="P${i}S"><br>
Dimensions (WxH): <input id="P${i}W" name="P${i}W" type="number" min="1" max="128" value="8"> x <input id="P${i}H" name="P${i}H" type="number" min="1" max="128" value="8"><br>
Offset X:<input id="P${i}X" name="P${i}X" type="number" min="0" max="256" value="0">
Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0"><br><i>(offset from top-left corner in # LEDs)</i>
</div>`;
p.insertAdjacentHTML("beforeend", b); p.insertAdjacentHTML("beforeend", b);
} }
@ -93,15 +95,48 @@ Serpentine: <input type="checkbox" name="P${i}S"></div>`;
} }
function resetPanels() { function resetPanels() {
d.Sf.MPH.value = 1; d.Sf.MPC.value = 1;
d.Sf.MPV.value = 1;
for (let e of gId("panels").children) e.remove(); for (let e of gId("panels").children) e.remove();
for (let e of gId("panels").children) e.remove(); // to remove any leftovers
} }
function btnPanel(i) { function btnPanel(i) {
gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none"; gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none";
gId("pnl_rem").style.display = (i>1) ? "inline":"none"; gId("pnl_rem").style.display = (i>1) ? "inline":"none";
} }
function gen() {
resetPanels();
var pansH = parseInt(d.Sf.MPH.value);
var pansV = parseInt(d.Sf.MPV.value);
var c = pansH*pansV;
//maxPanels = c;
d.Sf.MPC.value = c; // number of panels
var ps = d.Sf.PS.checked;
var pv = d.Sf.PV.value==="1";
var pb = d.Sf.PB.value==="1";
var pr = d.Sf.PR.value==="1";
var pw = parseInt(d.Sf.PW.value);
var ph = parseInt(d.Sf.PH.value);
var h = pv ? pansV : pansH;
var v = pv ? pansH : pansV;
for (let j = 0, p = 0; j < v; j++) {
for (let i = 0; i < h; i++, p++) {
if (j*i < maxPanels) addPanel(p);
var y = (pv?pr:pb) ? v-j-1: j;
var x = (pv?pb:pr) ? h-i-1 : i;
x = ps && j%2 ? h-x-1 : x;
gId("P"+p+"X").value = (pv?y:x) * pw;
gId("P"+p+"Y").value = (pv?x:y) * ph
gId("P"+p+"W").value = pw;
gId("P"+p+"H").value = ph;
}
}
}
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>
@ -118,7 +153,8 @@ Serpentine: <input type="checkbox" name="P${i}S"></div>`;
<option value="1">2D Matrix</option> <option value="1">2D Matrix</option>
</select><br> </select><br>
<div id="mpdiv" style="display:none;"> <div id="mpdiv" style="display:none;">
<h3>Panel set-up</h3> <hr class="sml">
<h3>Matrix Generator</h3>
Panel dimensions (WxH): <input name="PW" type="number" min="1" max="128" value="8"> x <input name="PH" type="number" min="1" max="128" value="8"><br> Panel dimensions (WxH): <input name="PW" type="number" min="1" max="128" value="8"> x <input name="PH" type="number" min="1" max="128" value="8"><br>
Horizontal panels: <input name="MPH" type="number" min="1" max="8" value="1" oninput="UI()"> Horizontal panels: <input name="MPH" type="number" min="1" max="8" value="1" oninput="UI()">
Vertical panels: <input name="MPV" type="number" min="1" max="8" value="1" oninput="UI()"><br> Vertical panels: <input name="MPV" type="number" min="1" max="8" value="1" oninput="UI()"><br>
@ -133,12 +169,15 @@ Serpentine: <input type="checkbox" name="P${i}S"></div>`;
<option value="0">Horizontal</option> <option value="0">Horizontal</option>
<option value="1">Vertical</option> <option value="1">Vertical</option>
</select><br> </select><br>
Serpentine: <input type="checkbox" name="PS"> Serpentine: <input type="checkbox" name="PS"><br>
<hr class="sml"> <i style="color:#fa0;">Can populate LED panel layout with pre-arranged matrix.<br>These values do not affect final layout.</i><br>
<i>A matrix is made of 1 or more physical LED panels of the same dimensions.<br> <button type="button" onclick="gen()">Populate</button>
Panels should be arranged from top-left to bottom-right order, starting with lower panel number on the left (or top if transposed).<br>
Each panel can have different LED orientation and/or starting point and/or layout.</i><br>
<hr class="sml"> <hr class="sml">
<h3>Panel set-up</h3>
Number of panels: <input name="MPC" type="number" min="1" max="64" value="1" oninput="UI(parseInt(this.value))"><br>
<i>A matrix is made of 1 or more physical LED panels.<br>
<!--Panels should be arranged from top-left to bottom-right order, starting with lower panel number on the left (or top if transposed).<br>-->
Each panel can be of different size and/or have different LED orientation and/or starting point and/or layout.</i><br>
<h3>LED panel layout</h3> <h3>LED panel layout</h3>
<div id="panels"> <div id="panels">
</div> </div>

View File

@ -1820,118 +1820,137 @@ const uint8_t PAGE_settings_um[] PROGMEM = {
// Autogenerated from wled00/data/settings_2D.htm, do not edit!! // Autogenerated from wled00/data/settings_2D.htm, do not edit!!
const uint16_t PAGE_settings_2D_length = 1745; const uint16_t PAGE_settings_2D_length = 2053;
const uint8_t PAGE_settings_2D[] PROGMEM = { const uint8_t PAGE_settings_2D[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x95, 0x58, 0x5b, 0x6f, 0xdb, 0x36, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x9d, 0x58, 0x6b, 0x53, 0xdc, 0x38,
0x14, 0x7e, 0xd7, 0xaf, 0x60, 0x88, 0xa2, 0x93, 0x5a, 0x59, 0x8e, 0xbb, 0x0b, 0x8a, 0x58, 0x52, 0x16, 0xfd, 0xee, 0x5f, 0x21, 0x34, 0xbb, 0x29, 0x3b, 0xb8, 0x5f, 0xcc, 0x4c, 0x6a, 0xaa, 0xdb,
0xd6, 0x34, 0xd9, 0x92, 0x21, 0x41, 0x83, 0xba, 0x4b, 0x31, 0xac, 0x43, 0x4b, 0x4b, 0xc7, 0x16, 0x36, 0x1b, 0x1e, 0x3b, 0xb0, 0x05, 0x9b, 0xae, 0x74, 0x16, 0x42, 0x6d, 0xb6, 0x32, 0x6a, 0xfb,
0x1b, 0x89, 0x14, 0x48, 0xca, 0x49, 0xe6, 0xe6, 0xbf, 0xef, 0x90, 0x92, 0xaf, 0x71, 0xda, 0xee, 0x1a, 0x2b, 0xd8, 0x92, 0xcb, 0x52, 0xf3, 0x18, 0xc2, 0x7f, 0xdf, 0x2b, 0xd9, 0xed, 0x7e, 0x02,
0x25, 0x36, 0xc9, 0x73, 0x3f, 0xdf, 0xb9, 0x38, 0xf1, 0xde, 0xf1, 0x9b, 0xd7, 0xef, 0xfe, 0xba, 0x9b, 0xfd, 0x02, 0x58, 0xba, 0xf7, 0xe8, 0xea, 0x3e, 0x8f, 0x08, 0x76, 0x8e, 0x3e, 0x1c, 0x7e,
0x3c, 0x21, 0x85, 0xa9, 0xca, 0x34, 0xb6, 0x7f, 0x49, 0xc9, 0xc4, 0x34, 0xa1, 0x20, 0x28, 0x9e, 0xba, 0x1a, 0x1f, 0x93, 0x4c, 0x17, 0x79, 0x14, 0x98, 0x9f, 0x24, 0x67, 0xe2, 0x3a, 0xa4, 0x20,
0x81, 0xe5, 0x69, 0x5c, 0x81, 0x61, 0x24, 0x2b, 0x98, 0xd2, 0x60, 0x12, 0xda, 0x98, 0x49, 0xef, 0x28, 0x7e, 0x03, 0x4b, 0xa2, 0xa0, 0x00, 0xcd, 0x48, 0x9c, 0xb1, 0x4a, 0x81, 0x0e, 0xe9, 0x4c,
0x25, 0xed, 0x6e, 0x3d, 0xc1, 0x2a, 0x48, 0xe8, 0x8c, 0xc3, 0x4d, 0x2d, 0x95, 0xa1, 0x24, 0x93, 0xa7, 0x9d, 0xdf, 0x68, 0xb3, 0xea, 0x08, 0x56, 0x40, 0x48, 0x6f, 0x39, 0xdc, 0x95, 0xb2, 0xd2,
0xc2, 0x80, 0x40, 0xb2, 0x1b, 0x9e, 0x9b, 0x22, 0xf9, 0x79, 0x7f, 0x7f, 0x49, 0xba, 0xf5, 0x94, 0x94, 0xc4, 0x52, 0x68, 0x10, 0x28, 0x76, 0xc7, 0x13, 0x9d, 0x85, 0xbf, 0xf6, 0xfb, 0xad, 0xe8,
0xc3, 0x8c, 0x67, 0xd0, 0x73, 0x87, 0x90, 0x0b, 0x6e, 0x38, 0x2b, 0x7b, 0x3a, 0x63, 0x25, 0x24, 0xda, 0x56, 0x02, 0xb7, 0x3c, 0x86, 0x8e, 0xfd, 0xf0, 0xb9, 0xe0, 0x9a, 0xb3, 0xbc, 0xa3, 0x62,
0x83, 0xb0, 0x62, 0xb7, 0xbc, 0x6a, 0xaa, 0xe5, 0xb9, 0xd1, 0xa0, 0xdc, 0x81, 0x8d, 0xf1, 0x2c, 0x96, 0x43, 0x38, 0xf0, 0x0b, 0x76, 0xcf, 0x8b, 0x59, 0xd1, 0x7e, 0xcf, 0x14, 0x54, 0xf6, 0x83,
0x24, 0x7d, 0xa0, 0x39, 0x8d, 0x0d, 0x37, 0x25, 0xa4, 0x2f, 0x8e, 0xc9, 0x08, 0x4c, 0xaf, 0xa9, 0x4d, 0xf1, 0x5b, 0x48, 0xba, 0x71, 0x72, 0x14, 0x68, 0xae, 0x73, 0x88, 0xf6, 0x8e, 0xc8, 0x04,
0xe3, 0x7e, 0x7b, 0x11, 0xeb, 0x4c, 0xf1, 0xda, 0xa4, 0xde, 0x8c, 0x29, 0x52, 0xca, 0x8c, 0xd7, 0x74, 0x67, 0x56, 0x06, 0xbd, 0x7a, 0x21, 0x50, 0x71, 0xc5, 0x4b, 0x1d, 0x39, 0xb7, 0xac, 0x22,
0x61, 0x9e, 0xe4, 0x32, 0x6b, 0x2a, 0x34, 0x26, 0xc4, 0x8b, 0x64, 0x6f, 0x30, 0x9c, 0x34, 0x22, 0xb9, 0x8c, 0x79, 0xe9, 0x27, 0x61, 0x22, 0xe3, 0x59, 0x81, 0xc6, 0xf8, 0xb8, 0x10, 0xee, 0xd8,
0x33, 0x5c, 0x0a, 0x72, 0xea, 0x07, 0xf3, 0x1b, 0x2e, 0x72, 0x79, 0x13, 0xc9, 0x1a, 0x84, 0x4f, 0xf3, 0xc6, 0x4c, 0x40, 0xae, 0xc2, 0x77, 0xbf, 0x8c, 0xd2, 0x99, 0x88, 0x35, 0x97, 0x82, 0x9c,
0x0b, 0x63, 0x6a, 0x7d, 0xd0, 0xef, 0x5f, 0x0b, 0x19, 0xdd, 0x94, 0x90, 0x47, 0x53, 0xe8, 0x4f, 0xb8, 0xde, 0xe3, 0x1d, 0x17, 0x89, 0xbc, 0xeb, 0xca, 0x12, 0x84, 0x4b, 0x33, 0xad, 0x4b, 0x35,
0x80, 0x99, 0x46, 0x81, 0xee, 0xbf, 0x38, 0xa6, 0xc1, 0xfd, 0x92, 0xf7, 0x68, 0x9b, 0xb7, 0x8f, 0xec, 0xf5, 0x6e, 0x84, 0xec, 0xde, 0xe5, 0x90, 0x74, 0xaf, 0xa1, 0x97, 0x02, 0xd3, 0xb3, 0x0a,
0x01, 0x33, 0x5c, 0x4c, 0x35, 0x0d, 0xe9, 0x47, 0x0d, 0xe5, 0x64, 0x9d, 0x7a, 0x7a, 0x96, 0xfb, 0x54, 0x6f, 0xef, 0x88, 0x7a, 0x4f, 0xad, 0xee, 0xc1, 0xba, 0x6e, 0x0f, 0xbd, 0xa7, 0xb9, 0xb8,
0x10, 0xcc, 0x15, 0xa0, 0x28, 0x41, 0xac, 0x5c, 0x73, 0x52, 0x82, 0x35, 0xea, 0xe8, 0xce, 0x3d, 0x56, 0xd4, 0xa7, 0x5f, 0x15, 0xe4, 0xe9, 0xb2, 0xf4, 0xf5, 0x69, 0xe2, 0x82, 0xf7, 0x58, 0x01,
0xad, 0x48, 0x4b, 0xc9, 0xf2, 0x3f, 0x46, 0x3e, 0x84, 0x22, 0xd9, 0xdb, 0x0f, 0xe6, 0x25, 0x18, 0x42, 0x09, 0x62, 0x70, 0xf5, 0x71, 0x0e, 0xc6, 0xc2, 0x83, 0x07, 0xbb, 0xb5, 0x10, 0xcd, 0x25,
0x62, 0x92, 0x3c, 0xca, 0x14, 0xda, 0x01, 0x1d, 0x93, 0x4f, 0x5b, 0x3f, 0x69, 0x30, 0x34, 0x11, 0x4b, 0xfe, 0x31, 0x71, 0xc1, 0x17, 0xe1, 0x4e, 0xdf, 0x7b, 0xcc, 0x41, 0x13, 0x1d, 0x26, 0xdd,
0xea, 0x7d, 0x65, 0x8c, 0xe2, 0xe3, 0xc6, 0x00, 0x3e, 0xa8, 0x8c, 0x86, 0x10, 0x84, 0xdb, 0xf7, 0xb8, 0x42, 0x3b, 0xa0, 0x51, 0x72, 0x69, 0x7d, 0x69, 0xea, 0x8d, 0x74, 0x17, 0xcf, 0x7d, 0xaf,
0xe6, 0xae, 0x06, 0xb4, 0xcc, 0xc0, 0xad, 0xe9, 0x7f, 0x66, 0x33, 0xb6, 0x10, 0xf0, 0x80, 0x90, 0x75, 0xc5, 0xa7, 0x33, 0x0d, 0xb8, 0x51, 0xc5, 0xd4, 0x07, 0xcf, 0x5f, 0x5f, 0xd7, 0x0f, 0x25,
0xe9, 0x3b, 0x81, 0x22, 0x44, 0x10, 0xe6, 0xd1, 0x58, 0xe6, 0x77, 0x11, 0xab, 0xd1, 0xbf, 0xfc, 0xa0, 0x65, 0x1a, 0xee, 0x75, 0xef, 0x1b, 0xbb, 0x65, 0x73, 0x80, 0x0d, 0x41, 0xa6, 0x1e, 0x04,
0x75, 0xc1, 0xcb, 0xdc, 0x37, 0x96, 0x9e, 0xe5, 0xf9, 0xc9, 0x0c, 0xad, 0x38, 0xe7, 0x1a, 0x73, 0x42, 0x08, 0xcf, 0x4f, 0xba, 0x53, 0x99, 0x3c, 0x74, 0x59, 0x89, 0xf7, 0x4b, 0x0e, 0x33, 0x9e,
0x0c, 0xca, 0xa7, 0xd6, 0x66, 0x1a, 0xfa, 0x41, 0x92, 0xce, 0x7f, 0x07, 0x73, 0xe5, 0x07, 0xe1, 0x27, 0xae, 0x36, 0xf2, 0x2c, 0x49, 0x8e, 0x6f, 0xd1, 0x8a, 0x33, 0xae, 0x30, 0xe0, 0x50, 0xb9,
0x9f, 0x67, 0x7e, 0x70, 0xbf, 0x9b, 0x18, 0x94, 0x92, 0x0a, 0x6d, 0x44, 0x62, 0x44, 0x89, 0x96, 0xd4, 0xd8, 0x4c, 0x7d, 0xd7, 0x0b, 0xa3, 0xc7, 0xdf, 0x41, 0x5f, 0xb8, 0x9e, 0xff, 0xaf, 0x53,
0x25, 0x44, 0xa5, 0x9c, 0xfa, 0xf4, 0xc4, 0xde, 0x93, 0x2e, 0x02, 0x18, 0x48, 0x32, 0xe1, 0x25, 0xd7, 0x7b, 0xda, 0x2e, 0x0c, 0x55, 0x25, 0x2b, 0xb4, 0x11, 0x85, 0x31, 0x65, 0x94, 0xcc, 0xa1,
0x38, 0x5f, 0x10, 0x16, 0x0a, 0x7d, 0x3e, 0xef, 0xee, 0xe5, 0xc4, 0x22, 0x6f, 0xc2, 0xa7, 0x8d, 0x9b, 0xcb, 0x6b, 0x97, 0x1e, 0x9b, 0x75, 0xd2, 0x78, 0x00, 0x1d, 0x49, 0x52, 0x9e, 0x83, 0xbd,
0x62, 0x2e, 0x64, 0xad, 0x2f, 0x64, 0xc2, 0xb8, 0xcd, 0xd9, 0x07, 0x71, 0x26, 0x32, 0x59, 0xd5, 0x0b, 0xe6, 0x48, 0x85, 0x77, 0x3e, 0x6b, 0xd6, 0x65, 0x6a, 0xd2, 0x30, 0xe5, 0xd7, 0xb3, 0x8a,
0x18, 0x39, 0x20, 0x35, 0x9b, 0x02, 0xc9, 0x99, 0x61, 0x7b, 0x98, 0x8e, 0xb5, 0x28, 0x8f, 0x30, 0x59, 0x97, 0xd5, 0x77, 0x21, 0x29, 0xe3, 0x26, 0x66, 0x5f, 0xc4, 0xa9, 0x88, 0x65, 0x51, 0xa2,
0x7d, 0xd4, 0x2a, 0x38, 0xa0, 0x49, 0xd2, 0xe5, 0x11, 0xe1, 0xe1, 0xe4, 0x45, 0xb5, 0x92, 0x46, 0xe7, 0x80, 0x94, 0xec, 0x1a, 0x48, 0xc2, 0x34, 0xdb, 0xc1, 0x70, 0x2c, 0x79, 0x79, 0x82, 0xe1,
0x66, 0xb2, 0x7c, 0xfa, 0xd4, 0x77, 0x90, 0xd9, 0x0f, 0x7d, 0x87, 0xa5, 0xc4, 0x52, 0x94, 0x23, 0xa3, 0xe6, 0x80, 0x21, 0x0d, 0xc3, 0x26, 0x8e, 0x98, 0x2b, 0x16, 0xaf, 0x5b, 0x56, 0x52, 0xcb,
0x23, 0x15, 0x4a, 0xb5, 0x39, 0x3c, 0x33, 0x50, 0x59, 0xef, 0xb3, 0xb3, 0x9a, 0x06, 0xc1, 0x97, 0x58, 0xe6, 0x6f, 0xde, 0xb8, 0x36, 0x7f, 0xfa, 0xbe, 0x6b, 0x13, 0x2b, 0x34, 0x12, 0xf9, 0x44,
0x2f, 0x1d, 0x19, 0xf2, 0x57, 0x35, 0x1a, 0xfc, 0x1b, 0xca, 0x27, 0x17, 0x32, 0x87, 0x88, 0x5c, 0xcb, 0x0a, 0x51, 0x4d, 0x0c, 0x4f, 0x35, 0x14, 0xe6, 0xf6, 0xf1, 0x69, 0x49, 0x3d, 0xef, 0xfb,
0x96, 0xc0, 0x34, 0x10, 0x0c, 0x04, 0x28, 0xf2, 0xfe, 0xfc, 0xe4, 0x98, 0x9c, 0x5d, 0xa2, 0x49, 0xf7, 0x46, 0x0c, 0xf5, 0x8b, 0x12, 0x0d, 0xfe, 0x3b, 0xe2, 0x93, 0x73, 0x99, 0x40, 0x97, 0x8c,
0xe1, 0x86, 0x44, 0xbd, 0x29, 0x31, 0x74, 0xd2, 0x82, 0xc0, 0x52, 0x39, 0x4c, 0x58, 0xf1, 0x87, 0x73, 0x60, 0x0a, 0x08, 0x3a, 0x02, 0x2a, 0x72, 0x79, 0x76, 0x7c, 0x44, 0x4e, 0xc7, 0x68, 0x92,
0x0e, 0xa4, 0x88, 0x51, 0xfa, 0xdc, 0x3d, 0x1f, 0x50, 0x1a, 0x3c, 0x5f, 0x81, 0xaf, 0xaf, 0xa3, 0xbf, 0x82, 0xa8, 0x56, 0x11, 0x7d, 0x8b, 0xe6, 0x79, 0x46, 0xca, 0xe6, 0x84, 0x81, 0xdf, 0xb7,
0xcf, 0xfa, 0xb0, 0x4e, 0x06, 0xfb, 0x34, 0xdc, 0x1b, 0x04, 0xf7, 0xb6, 0x0e, 0xb0, 0xbe, 0x2e, 0x49, 0x8a, 0x39, 0x4a, 0x77, 0xed, 0xf6, 0x90, 0x52, 0x6f, 0x77, 0x91, 0x7c, 0x3d, 0xd5, 0xfd,
0x99, 0x80, 0x52, 0x27, 0xbf, 0xfc, 0xb4, 0x02, 0x3f, 0x66, 0x08, 0xb0, 0x1a, 0x82, 0x39, 0x9f, 0xa6, 0xf6, 0xcb, 0x70, 0xd0, 0xa7, 0xfe, 0xce, 0x60, 0xe9, 0xc2, 0x18, 0x10, 0x2c, 0x34, 0xef,
0xf8, 0x74, 0x1f, 0xa3, 0x90, 0x58, 0x90, 0x52, 0x8d, 0xa6, 0xd3, 0x20, 0x9a, 0xb1, 0xb2, 0x81, 0x91, 0xa7, 0xae, 0x49, 0x46, 0x5a, 0x94, 0x09, 0xbf, 0xa5, 0x5e, 0x57, 0xe9, 0x07, 0x0c, 0x40,
0xa0, 0xc3, 0xab, 0x7b, 0xa8, 0xea, 0x9c, 0xcf, 0xf0, 0x45, 0x9b, 0x3b, 0xcc, 0x58, 0xce, 0x75, 0xc2, 0x55, 0x99, 0xb3, 0x87, 0x90, 0x4e, 0x11, 0xf4, 0x06, 0xf3, 0xa4, 0x8f, 0x6e, 0x09, 0xad,
0x5d, 0xb2, 0xbb, 0x84, 0x0a, 0x29, 0x30, 0x49, 0x33, 0xc9, 0x73, 0x82, 0x45, 0x02, 0xa6, 0xd5, 0xa0, 0xc2, 0xbb, 0xa0, 0xdc, 0x2d, 0xcb, 0x67, 0xe0, 0x35, 0x09, 0xfc, 0x12, 0x82, 0x90, 0x02,
0xe4, 0x07, 0xc3, 0xaf, 0x31, 0x8d, 0xd1, 0xf4, 0x6b, 0x1a, 0xae, 0x0c, 0xab, 0x6d, 0xbf, 0x39, 0xa3, 0x76, 0x2b, 0x79, 0x42, 0xb0, 0x6a, 0x40, 0xd7, 0x75, 0xe7, 0x7a, 0x23, 0x93, 0xc9, 0xa2,
0x43, 0x60, 0xe7, 0xd1, 0x68, 0x12, 0x5d, 0x5c, 0x9e, 0x76, 0x06, 0x3c, 0xdb, 0x7e, 0xb8, 0xea, 0xc6, 0x2c, 0xed, 0x1a, 0xea, 0xc6, 0x26, 0xab, 0x2a, 0x10, 0xdd, 0x1c, 0xc4, 0xb5, 0xce, 0x46,
0x1e, 0x86, 0xb6, 0x2e, 0x44, 0x6b, 0x72, 0xed, 0x64, 0xa0, 0x96, 0xcc, 0x62, 0x54, 0x81, 0x88, 0x68, 0x9d, 0x08, 0xc0, 0x4b, 0x65, 0xe5, 0xd6, 0x89, 0x2f, 0x46, 0x3a, 0x80, 0x91, 0xde, 0xdd,
0x4a, 0x10, 0x53, 0x53, 0x0c, 0xd1, 0x33, 0x11, 0x2f, 0x95, 0x04, 0x13, 0xa9, 0x7c, 0xcb, 0x86, 0xf5, 0x30, 0x91, 0x2c, 0x14, 0xe6, 0xa0, 0x15, 0x8b, 0xd6, 0xc4, 0x22, 0x14, 0xeb, 0x74, 0xd0,
0x3d, 0x65, 0x08, 0xab, 0xfb, 0x21, 0x3c, 0x7f, 0x1e, 0x20, 0x4c, 0xdd, 0x09, 0x4b, 0xd1, 0xb1, 0xc2, 0xa2, 0x16, 0x5b, 0xba, 0xfb, 0x5c, 0x15, 0xad, 0xb0, 0xf5, 0x04, 0x61, 0x69, 0x9a, 0xdd,
0xa5, 0x8f, 0xb0, 0xa5, 0x6b, 0x6c, 0xbd, 0x1e, 0x06, 0xa8, 0x6a, 0xd9, 0xd6, 0xa0, 0xb5, 0x10, 0x29, 0x16, 0x52, 0xd2, 0x9d, 0xa4, 0xdd, 0xf3, 0xf1, 0x61, 0x73, 0xbf, 0xd1, 0x1c, 0x52, 0x84,
0x85, 0x41, 0x98, 0xb7, 0x7c, 0x8f, 0x79, 0x87, 0x25, 0xfe, 0xa8, 0x7f, 0x0b, 0xad, 0x26, 0xd9, 0xfd, 0x11, 0x5a, 0x32, 0x12, 0xcb, 0x27, 0x8b, 0x2d, 0x98, 0xe8, 0xd5, 0xa6, 0x4a, 0xd7, 0xee,
0x1f, 0x9a, 0x18, 0x9e, 0x89, 0xa1, 0x59, 0x37, 0xd3, 0xec, 0x50, 0x88, 0xf9, 0xec, 0x1a, 0xc6, 0x66, 0x8d, 0x5c, 0xbf, 0x60, 0x14, 0xb6, 0x9d, 0xa8, 0xf1, 0xe5, 0xa8, 0xbe, 0xc0, 0x1f, 0x01,
0x56, 0x60, 0x9c, 0x47, 0xdb, 0xd1, 0x49, 0x93, 0x95, 0x8b, 0x6d, 0x9e, 0x87, 0xad, 0xbe, 0x4f, 0x3a, 0x93, 0xf0, 0x24, 0xa4, 0xa5, 0xc8, 0xff, 0xf2, 0x08, 0x4f, 0xa6, 0x3b, 0x57, 0x24, 0xce,
0x31, 0xe6, 0x8c, 0xf0, 0x3c, 0xa1, 0xb5, 0x28, 0x9f, 0xcc, 0xe1, 0x9e, 0xa6, 0x4f, 0xe6, 0xfb, 0x99, 0x52, 0x21, 0x55, 0x45, 0x4e, 0x23, 0xab, 0x46, 0xcc, 0x5e, 0x30, 0xad, 0xa2, 0x2f, 0x62,
0x88, 0x0f, 0x38, 0xa4, 0xf4, 0xe0, 0x87, 0xb8, 0x50, 0x24, 0x2b, 0x99, 0xd6, 0x09, 0xd5, 0x55, 0x10, 0xa8, 0x59, 0x19, 0x29, 0x1d, 0xf4, 0xcc, 0x6f, 0x82, 0x39, 0x35, 0x24, 0x01, 0x36, 0x1e,
0x49, 0xd3, 0x1f, 0xee, 0x9d, 0x10, 0x62, 0x29, 0xe3, 0xb1, 0x4a, 0x07, 0xb1, 0x6e, 0xea, 0x54, 0x88, 0xd1, 0x16, 0xdb, 0x3c, 0xc7, 0x46, 0xf8, 0x80, 0xa2, 0xec, 0x17, 0x1d, 0xc8, 0xd2, 0xda,
0x9b, 0xb8, 0x6f, 0x3f, 0x09, 0x42, 0xfd, 0x80, 0xc4, 0xd8, 0x0f, 0x21, 0x43, 0xbb, 0x5c, 0x1b, 0x6d, 0xef, 0x19, 0x62, 0x7c, 0xa3, 0x4f, 0x12, 0x7b, 0x68, 0xbd, 0xba, 0x4d, 0x62, 0x40, 0xa3,
0xbf, 0xb4, 0xa4, 0x47, 0x34, 0xfd, 0x20, 0x3e, 0x98, 0x58, 0xd6, 0xce, 0x07, 0xe7, 0x75, 0x82, 0x03, 0xa9, 0xb5, 0x2c, 0x96, 0x84, 0xf0, 0x28, 0x8b, 0x1f, 0x6d, 0x39, 0xe7, 0xe3, 0x73, 0xe7,
0x38, 0x4c, 0xdf, 0x49, 0xec, 0xe6, 0xed, 0xed, 0x2e, 0x8a, 0x01, 0x4d, 0x8f, 0xa4, 0x31, 0xb2, 0x9c, 0x41, 0xaa, 0x5f, 0x39, 0xe8, 0x23, 0xbf, 0xce, 0xf4, 0xd6, 0x73, 0xec, 0x4d, 0x3f, 0x54,
0x5a, 0x23, 0x42, 0x55, 0x4e, 0x7e, 0xba, 0x43, 0xcf, 0xdb, 0xc7, 0xf4, 0x9c, 0xc3, 0xc4, 0x7c, 0x1c, 0x0b, 0xc7, 0xd6, 0xe6, 0xd6, 0x2b, 0x5e, 0x3c, 0x77, 0xf4, 0x89, 0xac, 0xf8, 0x9f, 0x38,
0x43, 0xd1, 0x5b, 0x3e, 0x2d, 0xcc, 0x4e, 0x3d, 0xe8, 0xe7, 0x07, 0xf1, 0x46, 0x71, 0xac, 0x67, 0x96, 0x58, 0xfe, 0x8a, 0x01, 0x17, 0xd8, 0x60, 0x78, 0xbc, 0x22, 0xb6, 0x66, 0xc3, 0x04, 0x2a,
0xd7, 0x32, 0x76, 0xba, 0x78, 0xf5, 0x98, 0xea, 0x53, 0xa9, 0xf8, 0xbf, 0x38, 0x20, 0x59, 0xf9, 0x6c, 0x83, 0x58, 0x63, 0x80, 0x26, 0x70, 0x51, 0xce, 0x30, 0x6a, 0xd8, 0x52, 0x43, 0x1a, 0x67,
0x0d, 0x03, 0xae, 0xb0, 0xef, 0xf1, 0x6c, 0x83, 0x6c, 0xcb, 0x86, 0x11, 0x28, 0xec, 0xce, 0x58, 0x10, 0xdf, 0x4c, 0xe5, 0x3d, 0x5d, 0xb6, 0x68, 0x42, 0x1b, 0xb5, 0x23, 0x8e, 0xfd, 0x5a, 0x21,
0xfa, 0x80, 0x26, 0x70, 0x51, 0x37, 0x98, 0x41, 0xec, 0xf4, 0x09, 0xcd, 0x0a, 0xc8, 0xae, 0xc7, 0xa2, 0x22, 0xee, 0xe5, 0xfd, 0x89, 0xd7, 0x2a, 0x9b, 0x50, 0x5b, 0xd1, 0xcb, 0x15, 0x45, 0xfc,
0xf2, 0x96, 0xae, 0x5b, 0x34, 0xc2, 0xc9, 0xd9, 0xc7, 0xec, 0xa6, 0x9f, 0x86, 0x22, 0xe2, 0x02, 0xaa, 0x61, 0xc5, 0xac, 0x98, 0x42, 0x45, 0x49, 0xc1, 0x85, 0xb1, 0x90, 0x60, 0xde, 0xe0, 0xef,
0xe7, 0xac, 0x79, 0x95, 0x7f, 0x66, 0x19, 0x4a, 0x38, 0x7d, 0x77, 0x71, 0xee, 0xd3, 0x31, 0x20, 0xbd, 0xdf, 0xe8, 0xdc, 0x6a, 0x9c, 0xd1, 0xe4, 0x7e, 0x03, 0xed, 0x64, 0x05, 0xed, 0xe4, 0x47,
0xee, 0x00, 0xdb, 0x3d, 0x0d, 0xd7, 0x11, 0xb6, 0x82, 0x79, 0x87, 0xe8, 0xdd, 0x75, 0x37, 0xb4, 0xd0, 0x1a, 0x5f, 0xa7, 0x29, 0x16, 0x2d, 0xf9, 0x3c, 0x5c, 0x47, 0xfe, 0xbc, 0x82, 0xfc, 0x79,
0xdd, 0x46, 0x24, 0xb0, 0xa8, 0x3f, 0x11, 0x27, 0x83, 0x2f, 0x5f, 0xe0, 0x6f, 0xd1, 0x1b, 0xfc, 0x2b, 0x72, 0xbf, 0x41, 0xde, 0xfb, 0xf5, 0x1d, 0x5d, 0x0a, 0xc3, 0x17, 0x71, 0xb5, 0x01, 0x77,
0x13, 0xa1, 0x0c, 0x39, 0x03, 0x7f, 0x43, 0xea, 0x5a, 0xbf, 0x98, 0x6f, 0xd6, 0x06, 0xae, 0x01, 0xb5, 0x02, 0x77, 0xf5, 0x23, 0x70, 0xc6, 0xd0, 0x80, 0x47, 0xae, 0xac, 0x4d, 0x4d, 0xb1, 0xdb,
0x9b, 0x15, 0x91, 0x0c, 0x96, 0x25, 0x01, 0x76, 0x02, 0xec, 0xb6, 0x20, 0x80, 0x1d, 0x7a, 0xc6, 0x12, 0x2d, 0xcb, 0x4e, 0x8e, 0x89, 0x86, 0x93, 0xa1, 0xc2, 0x29, 0x43, 0xb8, 0x20, 0x3f, 0x99,
0x46, 0x2c, 0x6a, 0x7b, 0xde, 0xb2, 0x89, 0xf2, 0x23, 0x16, 0xcd, 0x83, 0xbe, 0xb4, 0xd6, 0x14, 0x92, 0x50, 0x5e, 0xd0, 0xe3, 0x36, 0x9a, 0x58, 0x5f, 0xd1, 0x1f, 0x23, 0xd1, 0xe5, 0x02, 0xb9,
0x0e, 0x29, 0x17, 0x25, 0x46, 0x95, 0x1e, 0x74, 0x1d, 0x6e, 0xc9, 0x88, 0xf2, 0x1f, 0x32, 0xa6, 0x86, 0x7e, 0x9f, 0x7c, 0x63, 0x31, 0xc6, 0xf3, 0xe4, 0xd3, 0xf9, 0x99, 0x4b, 0xa7, 0x80, 0x75,
0x83, 0x6d, 0x86, 0x7b, 0x0f, 0x33, 0xd5, 0x2e, 0x23, 0xb1, 0x23, 0x4e, 0x7f, 0xe5, 0x95, 0x5d, 0x0f, 0x38, 0xe5, 0xa8, 0xaf, 0x97, 0x6a, 0x7c, 0xd1, 0x4b, 0x9a, 0xb6, 0xb1, 0xbd, 0x79, 0x8d,
0x5e, 0x48, 0xa3, 0x4a, 0x6c, 0xb3, 0x8e, 0x3f, 0xd3, 0xb6, 0x3a, 0x91, 0xd0, 0x11, 0xc4, 0xfd, 0x0c, 0xf3, 0x10, 0x21, 0xcc, 0x9b, 0x98, 0x08, 0xc2, 0xc1, 0xf7, 0xef, 0xf0, 0x6f, 0xd1, 0x19,
0x76, 0x05, 0xb3, 0x53, 0x17, 0xe7, 0xa0, 0x6d, 0xfa, 0x09, 0xc5, 0x41, 0x85, 0x49, 0x43, 0xd7, 0xfc, 0xa7, 0x8b, 0x18, 0xf2, 0x16, 0xdc, 0x15, 0xd4, 0xa5, 0xae, 0xf8, 0xb8, 0xda, 0x80, 0xc2,
0x2b, 0xcf, 0xd5, 0xa4, 0xfd, 0xf6, 0x51, 0x2f, 0xb2, 0x3a, 0x9a, 0x50, 0x82, 0x0b, 0x57, 0x21, 0x41, 0xdb, 0x81, 0xc0, 0xcc, 0xb9, 0xed, 0x07, 0x7a, 0xd0, 0xc2, 0xfe, 0xa0, 0xf8, 0xc2, 0x8a,
0x6d, 0xb5, 0x4a, 0x6d, 0x37, 0x23, 0x5b, 0xbc, 0x5d, 0x7d, 0x1a, 0x89, 0x93, 0xe8, 0x66, 0xf3, 0xa9, 0x16, 0x4d, 0xff, 0xf2, 0x1e, 0x6b, 0x35, 0x91, 0x7f, 0xc5, 0xa6, 0xb6, 0xd1, 0xd0, 0x21,
0xae, 0x80, 0xb2, 0xc6, 0xda, 0xf3, 0x62, 0x9c, 0xf6, 0x06, 0x83, 0xd3, 0xa2, 0xa5, 0x3d, 0x50, 0x68, 0x5b, 0xd6, 0x3e, 0xe5, 0x22, 0xc7, 0x0a, 0xa0, 0xc3, 0xa6, 0xcb, 0xb7, 0x8a, 0x88, 0xbf,
0xd4, 0x9a, 0x95, 0x3c, 0xbb, 0x4e, 0xe8, 0xa9, 0x55, 0x7b, 0x18, 0xf7, 0xdb, 0x87, 0x0e, 0x35, 0xa9, 0x18, 0x0d, 0xd6, 0x15, 0x96, 0x08, 0x11, 0x52, 0x26, 0xc3, 0x87, 0x96, 0x07, 0x84, 0x71,
0xbb, 0x79, 0xbc, 0x25, 0xd3, 0x91, 0x65, 0x3a, 0x62, 0xd9, 0xf5, 0x8a, 0x6f, 0x83, 0x43, 0x37, 0xe3, 0x66, 0x6b, 0x3e, 0x69, 0x5a, 0x33, 0xf2, 0xa1, 0xf5, 0xad, 0x8b, 0xf9, 0x96, 0x0e, 0xe1,
0xe3, 0x8a, 0xa3, 0x8d, 0x23, 0x36, 0x83, 0x15, 0x49, 0xa1, 0x16, 0xe2, 0x8b, 0x17, 0xa9, 0x87, 0xad, 0x18, 0xad, 0xb9, 0x52, 0x5b, 0xc0, 0x3c, 0xb4, 0xcb, 0xe3, 0x49, 0xd7, 0x16, 0x2a, 0x24,
0x2b, 0x1d, 0xa2, 0xc2, 0x6e, 0x74, 0x78, 0x1a, 0xe1, 0x56, 0x52, 0x13, 0xdc, 0x0a, 0x5c, 0xa2, 0x3e, 0x33, 0x15, 0x80, 0xd3, 0xad, 0x5e, 0x6f, 0x30, 0x7c, 0xb9, 0xb2, 0x7a, 0xd0, 0xac, 0xf2,
0x57, 0x45, 0x66, 0x03, 0xe1, 0x06, 0xd5, 0x22, 0x0c, 0x6f, 0x2e, 0x2e, 0x5b, 0x43, 0x0a, 0xdc, 0x95, 0xd5, 0x8f, 0xcd, 0x6a, 0xb5, 0x66, 0xc9, 0xf8, 0x72, 0x6e, 0x48, 0xb9, 0xbe, 0xd3, 0x5a,
0x67, 0xf1, 0x62, 0x03, 0x5a, 0xe1, 0x5a, 0x47, 0x76, 0x8b, 0x09, 0x46, 0xe4, 0x41, 0x4d, 0x0e, 0xaf, 0x42, 0xb6, 0x2f, 0x86, 0xe0, 0xcf, 0xf0, 0x37, 0x0c, 0xc5, 0x22, 0x6e, 0x61, 0xdf, 0x37,
0x70, 0x95, 0xb4, 0xda, 0x96, 0xa5, 0xe6, 0x3d, 0x2c, 0x47, 0xb4, 0xed, 0x82, 0x21, 0xd1, 0xed, 0xc3, 0x06, 0x82, 0xd9, 0x08, 0x70, 0xd8, 0x2c, 0x66, 0x5a, 0x1f, 0x47, 0x9f, 0x32, 0xa3, 0xcf,
0x92, 0x68, 0xa3, 0x1a, 0x97, 0x7d, 0xb3, 0x9d, 0x7a, 0xc4, 0x73, 0x69, 0x4d, 0x68, 0x87, 0x92, 0x37, 0x43, 0xe8, 0x11, 0xde, 0xea, 0x45, 0x24, 0xde, 0xbc, 0x59, 0x1a, 0x4a, 0xf6, 0x9e, 0x71,
0x03, 0x87, 0x0b, 0xf4, 0xf2, 0xc7, 0xb4, 0xed, 0x98, 0xba, 0x5b, 0x5d, 0x97, 0x17, 0x39, 0xc7, 0xe8, 0xb2, 0x7d, 0x3e, 0x94, 0xde, 0xfe, 0xac, 0x03, 0x9d, 0x01, 0x9e, 0x94, 0x9a, 0x15, 0x39,
0xe5, 0x4e, 0xa3, 0x5c, 0x4d, 0xfc, 0xf7, 0xb7, 0xa7, 0xc1, 0xb2, 0xa4, 0xbb, 0xfd, 0xf7, 0xf2, 0xe4, 0xde, 0xbe, 0xea, 0x68, 0x5c, 0xd1, 0xa3, 0x34, 0x44, 0x4a, 0x03, 0x7f, 0xdd, 0xc3, 0x85,
0x3d, 0xed, 0x22, 0x29, 0x9a, 0x6a, 0x0c, 0x0a, 0x73, 0xcf, 0x85, 0xb5, 0xcc, 0x8e, 0x78, 0xfc, 0x14, 0x17, 0xd2, 0x3a, 0x7e, 0x63, 0xba, 0x2b, 0x76, 0xe9, 0xe7, 0xf9, 0x8c, 0x37, 0x5a, 0xf1,
0x7c, 0xf1, 0x92, 0x2e, 0xac, 0xc5, 0xa5, 0x9d, 0xdc, 0x2e, 0xd8, 0x3b, 0xee, 0x53, 0x34, 0xe9, 0x30, 0xf5, 0xde, 0x56, 0xcb, 0xdb, 0x57, 0xcb, 0xdb, 0xe9, 0x30, 0xf6, 0xde, 0x96, 0xcb, 0xdb,
0xfb, 0xd9, 0xad, 0x47, 0xab, 0x46, 0xd5, 0x66, 0x40, 0x6f, 0x5b, 0x74, 0x61, 0x85, 0x7e, 0x45, 0x97, 0xed, 0xf6, 0x8a, 0xd6, 0x49, 0xbb, 0x5c, 0x3e, 0x3d, 0x39, 0xd8, 0x51, 0x6b, 0xaa, 0x1e,
0xe6, 0x4a, 0xe2, 0xc0, 0x82, 0xcb, 0xf1, 0x26, 0xb4, 0xcd, 0x81, 0x47, 0x16, 0xed, 0x6d, 0x5b, 0xd8, 0x44, 0x89, 0xfe, 0xc6, 0x0b, 0x43, 0xed, 0xc9, 0xac, 0xca, 0x91, 0x66, 0xd8, 0xdc, 0x89,
0xf8, 0x42, 0xf6, 0xd5, 0xf7, 0xcb, 0xf6, 0xb6, 0x84, 0xef, 0x98, 0x44, 0x5b, 0x18, 0xea, 0x82, 0x95, 0x99, 0x9c, 0x28, 0x68, 0x05, 0x82, 0x5e, 0xfd, 0x40, 0x31, 0x34, 0x14, 0x89, 0xa1, 0x61,
0x72, 0xb4, 0x0b, 0x0c, 0x38, 0x83, 0xbc, 0x55, 0x8e, 0xbf, 0x35, 0x80, 0x1e, 0x1b, 0x3f, 0x6f, 0x41, 0x21, 0x45, 0xe6, 0x86, 0x2d, 0x00, 0xdd, 0x54, 0x38, 0xb6, 0x9b, 0x98, 0xbf, 0xbe, 0xaa,
0x57, 0xa2, 0xbd, 0x47, 0xe6, 0xce, 0xb7, 0x66, 0xce, 0x06, 0xbe, 0xbc, 0xaf, 0x0d, 0x9c, 0xab, 0x79, 0x37, 0x99, 0xa4, 0xd8, 0x33, 0x40, 0x67, 0xd2, 0x4c, 0x52, 0xa9, 0xcc, 0xbb, 0xc1, 0x0c,
0x5d, 0x7e, 0xec, 0x18, 0x34, 0xdb, 0x16, 0xed, 0x9a, 0x32, 0x1b, 0x5a, 0xbf, 0x63, 0xc2, 0x2c, 0xd6, 0x66, 0x8e, 0x62, 0x97, 0xa8, 0xe4, 0xdd, 0xea, 0x5a, 0x06, 0x79, 0x89, 0x33, 0xd2, 0x09,
0xe0, 0x69, 0xc7, 0xcb, 0xd6, 0x76, 0x10, 0xf3, 0xd4, 0x7b, 0x85, 0xf9, 0xb2, 0x55, 0x43, 0xb8, 0x90, 0xfe, 0x6a, 0xcc, 0xcc, 0xba, 0x0f, 0xd5, 0x1f, 0x14, 0x4f, 0x8d, 0x73, 0x1e, 0xdf, 0x84,
0xc6, 0x6f, 0xb9, 0x6b, 0xdf, 0x03, 0x5b, 0xd5, 0x15, 0xce, 0x1a, 0x52, 0x17, 0x77, 0xda, 0x81, 0xf4, 0xc4, 0x1c, 0xbb, 0x1f, 0xf4, 0xea, 0x8d, 0xa8, 0xee, 0x27, 0xdb, 0x75, 0x9c, 0x56, 0xe9,
0xc0, 0x2e, 0xc5, 0x2d, 0x10, 0x2c, 0x81, 0x29, 0x80, 0x68, 0x14, 0xbb, 0x56, 0x14, 0x91, 0x0b, 0xc0, 0x28, 0x1d, 0xb0, 0xf8, 0x66, 0xa1, 0xb7, 0xa2, 0xa1, 0x66, 0xd3, 0x82, 0xa3, 0x8d, 0x13,
0x42, 0x5b, 0xc9, 0x44, 0x17, 0xb2, 0x29, 0x73, 0x32, 0x06, 0xc2, 0x94, 0xb2, 0x45, 0x9f, 0x93, 0x76, 0x0b, 0x0b, 0x91, 0xac, 0x9a, 0xc3, 0x67, 0x7b, 0x91, 0x83, 0x0f, 0x1e, 0x2c, 0x12, 0xf3,
0x09, 0xae, 0xdd, 0x04, 0x7b, 0x5e, 0xaf, 0xc4, 0x10, 0xe3, 0x17, 0x32, 0x76, 0x79, 0xea, 0x29, 0xde, 0xc1, 0xaf, 0x09, 0xd2, 0xf4, 0x92, 0x20, 0x4d, 0xb6, 0x45, 0xbe, 0x18, 0x86, 0xc6, 0x11,
0x1b, 0x52, 0xd4, 0x97, 0x83, 0x0a, 0x89, 0x36, 0x4c, 0xd9, 0x4d, 0x99, 0xdc, 0x70, 0x53, 0xe0, 0x96, 0xa8, 0xcd, 0xdd, 0xf0, 0xe1, 0x7c, 0x5c, 0x1b, 0x92, 0xe1, 0x6b, 0x0f, 0x17, 0x56, 0x2a,
0x4f, 0x8d, 0x1b, 0xe8, 0xba, 0x0b, 0x69, 0x41, 0x66, 0x7f, 0x80, 0x58, 0xdd, 0x4e, 0x86, 0x8f, 0xcd, 0x5f, 0x22, 0x44, 0x96, 0xa9, 0xa3, 0x47, 0x36, 0x66, 0xe7, 0x00, 0x1f, 0x5a, 0xe6, 0xb4,
0x46, 0xa2, 0x40, 0xc2, 0xd1, 0x1e, 0x54, 0xa2, 0xb1, 0xc5, 0x42, 0x1e, 0x44, 0x9e, 0x33, 0xe4, 0x76, 0x24, 0x3a, 0x9b, 0x63, 0x13, 0x6d, 0x3b, 0x67, 0x28, 0x74, 0xdf, 0x0a, 0xad, 0x4c, 0xcd,
0x84, 0x65, 0x45, 0xc7, 0x9a, 0x31, 0x41, 0x0a, 0x6c, 0x6a, 0x68, 0xec, 0x64, 0x02, 0x38, 0x87, 0x96, 0xd3, 0xd4, 0x54, 0x91, 0x38, 0x36, 0xac, 0x21, 0x6d, 0x3a, 0xc4, 0xd0, 0xf6, 0x84, 0x0d,
0x8c, 0xf3, 0x46, 0xae, 0xf2, 0x45, 0x98, 0xc8, 0xfb, 0x28, 0x6d, 0xa9, 0xbe, 0x96, 0x1c, 0xa9, 0x9e, 0x13, 0x64, 0x3f, 0x47, 0x35, 0x2a, 0xf9, 0xdd, 0xbc, 0x18, 0x18, 0xb2, 0x63, 0xbc, 0xfc,
0xba, 0x5b, 0xec, 0x0e, 0xb2, 0x31, 0x28, 0xb7, 0xcf, 0xdb, 0x4e, 0xb2, 0x1d, 0x45, 0x6c, 0x11, 0xcf, 0x91, 0x53, 0x33, 0xa0, 0xe4, 0xb9, 0x91, 0xda, 0xcc, 0x93, 0xff, 0x61, 0x84, 0x3a, 0xdb,
0xcb, 0xf0, 0x74, 0xd4, 0xae, 0x6f, 0xac, 0x56, 0xb5, 0x76, 0x12, 0x2e, 0x3a, 0xa9, 0xfb, 0xeb, 0x66, 0x68, 0xa3, 0xfe, 0xc3, 0x33, 0xd3, 0x59, 0xb0, 0x8c, 0x3a, 0x2c, 0x6a, 0xcd, 0xa2, 0xf3,
0xb9, 0xd6, 0xfa, 0xf5, 0x3e, 0xff, 0x7f, 0x5a, 0xb6, 0xb7, 0x36, 0x0e, 0xec, 0x18, 0xc2, 0x0f, 0x57, 0x30, 0x17, 0x88, 0x03, 0x1b, 0x33, 0xab, 0x1b, 0xd2, 0x3a, 0x30, 0x64, 0x4e, 0x4d, 0x9e,
0x3b, 0xaa, 0xec, 0xdc, 0xb2, 0xff, 0x50, 0xf8, 0x0f, 0x92, 0x1e, 0x9c, 0x00, 0x60, 0x10, 0x00, 0xc3, 0xbe, 0x78, 0x0e, 0xdb, 0xd9, 0x04, 0x5f, 0xc3, 0x36, 0xd6, 0xaf, 0xb1, 0xc8, 0xb5, 0xbc,
0x00 0x6a, 0x7c, 0x62, 0xeb, 0xe3, 0x45, 0x02, 0xf9, 0x2a, 0x79, 0xdc, 0xa0, 0x8e, 0xcd, 0x03, 0x7f,
0xfc, 0x71, 0x5b, 0xf2, 0xad, 0x70, 0xc6, 0xd7, 0xf8, 0xa2, 0xb3, 0x92, 0x74, 0x2f, 0x91, 0xc5,
0x8b, 0x6d, 0x67, 0x2d, 0xc2, 0xe7, 0xbc, 0x70, 0xe4, 0x06, 0x43, 0x5c, 0x39, 0x74, 0x0b, 0x3b,
0x74, 0x9e, 0xa1, 0x87, 0x93, 0x39, 0x81, 0x21, 0x4d, 0x35, 0xe0, 0x43, 0x53, 0x56, 0xc3, 0x9f,
0x52, 0x86, 0xb6, 0x38, 0x87, 0x4c, 0x90, 0x52, 0x96, 0xb3, 0x1c, 0x1f, 0xfb, 0x86, 0xbf, 0xd4,
0x01, 0x21, 0x58, 0x2d, 0x12, 0x31, 0xef, 0xb8, 0xce, 0x48, 0x59, 0x41, 0x87, 0x55, 0x95, 0xa9,
0xeb, 0x04, 0x13, 0xc8, 0x14, 0x4a, 0xd7, 0xe6, 0xe1, 0xa7, 0x0c, 0x8b, 0xbc, 0x36, 0x59, 0x91,
0x44, 0x12, 0x21, 0x35, 0x61, 0x69, 0x6a, 0xee, 0x9f, 0x72, 0xc1, 0xe6, 0x28, 0x5d, 0xc3, 0x88,
0xac, 0x09, 0xaf, 0x74, 0x2f, 0x3b, 0xa3, 0xf1, 0xdd, 0xd1, 0x98, 0xb3, 0xdc, 0xa0, 0x36, 0x0a,
0xb6, 0x2e, 0x4d, 0xd5, 0xfc, 0x67, 0xc6, 0x14, 0xeb, 0x3f, 0x6d, 0x3a, 0x1a, 0x56, 0xf2, 0x4c,
0xe2, 0x1e, 0xbe, 0x58, 0x14, 0xef, 0x7e, 0x79, 0xb6, 0x2a, 0xda, 0x11, 0xab, 0x33, 0xae, 0x9a,
0xf9, 0xea, 0xb5, 0xb4, 0xd0, 0x79, 0xdf, 0x38, 0x85, 0x70, 0x85, 0x7f, 0x25, 0x96, 0x18, 0x0d,
0x4c, 0xcf, 0x2c, 0x90, 0xe3, 0x91, 0x32, 0x7b, 0x50, 0xb6, 0x9c, 0x5a, 0xe7, 0xaa, 0xda, 0x7b,
0xc7, 0x2c, 0xce, 0x1a, 0x6f, 0xc7, 0x18, 0x84, 0xa9, 0xd5, 0x4b, 0x38, 0xfa, 0x0f, 0x29, 0x94,
0x26, 0x8a, 0xff, 0x09, 0x84, 0x89, 0xa4, 0x87, 0x40, 0x19, 0xb6, 0xeb, 0xa5, 0x2d, 0x83, 0x24,
0x17, 0x59, 0x37, 0x97, 0x52, 0x9a, 0x55, 0xe6, 0x4d, 0x8e, 0xf1, 0xe4, 0x28, 0xd5, 0xac, 0x36,
0x31, 0x70, 0xda, 0x20, 0xa0, 0xaf, 0xd6, 0xe3, 0x6c, 0x1d, 0xb8, 0x78, 0x10, 0xd6, 0x7c, 0x6e,
0x3e, 0x13, 0x9a, 0xc9, 0xb0, 0x08, 0x9f, 0xf3, 0xcc, 0xc4, 0xfa, 0xbf, 0x86, 0x0f, 0xda, 0x65,
0x06, 0x2a, 0x1e, 0x63, 0x86, 0xae, 0x99, 0xc0, 0xe6, 0x1f, 0x87, 0xff, 0x05, 0xfe, 0x7e, 0xc2,
0xdf, 0x48, 0x14, 0x00, 0x00
}; };

File diff suppressed because it is too large Load Diff

View File

@ -643,22 +643,34 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (subPage == 10) if (subPage == 10)
{ {
strip.isMatrix = request->arg(F("SOMP")).toInt(); strip.isMatrix = request->arg(F("SOMP")).toInt();
strip.panelH = MAX(1,MIN(128,request->arg(F("PH")).toInt())); // strip.panelH = MAX(1,MIN(128,request->arg(F("PH")).toInt()));
strip.panelW = MAX(1,MIN(128,request->arg(F("PW")).toInt())); // strip.panelW = MAX(1,MIN(128,request->arg(F("PW")).toInt()));
strip.hPanels = MAX(1,MIN(8,request->arg(F("MPH")).toInt())); strip.panel.clear(); // release memory if allocated
strip.vPanels = MAX(1,MIN(8,request->arg(F("MPV")).toInt())); if (strip.isMatrix) {
strip.matrix.bottomStart = request->arg(F("PB")).toInt(); strip.panels = MAX(1,MIN(WLED_MAX_PANELS,request->arg(F("MPC")).toInt()));
strip.matrix.rightStart = request->arg(F("PR")).toInt(); strip.matrix.bottomStart = request->arg(F("PB")).toInt();
strip.matrix.vertical = request->arg(F("PV")).toInt(); strip.matrix.rightStart = request->arg(F("PR")).toInt();
strip.matrix.serpentine = request->hasArg(F("PS")); strip.matrix.vertical = request->arg(F("PV")).toInt();
for (uint8_t i=0; i<WLED_MAX_PANELS; i++) { strip.matrix.serpentine = request->hasArg(F("PS"));
char pO[8]; sprintf_P(pO, PSTR("P%d"), i); strip.panel.reserve(strip.panels); // pre-allocate memory
uint8_t l = strlen(pO); pO[l+1] = 0; for (uint8_t i=0; i<strip.panels; i++) {
pO[l] = 'B'; if (!request->hasArg(pO)) break; WS2812FX::Panel p;
pO[l] = 'B'; strip.panel[i].bottomStart = request->arg(pO).toInt(); char pO[8]; sprintf_P(pO, PSTR("P%d"), i);
pO[l] = 'R'; strip.panel[i].rightStart = request->arg(pO).toInt(); uint8_t l = strlen(pO); pO[l+1] = 0;
pO[l] = 'V'; strip.panel[i].vertical = request->arg(pO).toInt(); pO[l] = 'B'; if (!request->hasArg(pO)) break;
pO[l] = 'S'; strip.panel[i].serpentine = request->hasArg(pO); pO[l] = 'B'; p.bottomStart = request->arg(pO).toInt();
pO[l] = 'R'; p.rightStart = request->arg(pO).toInt();
pO[l] = 'V'; p.vertical = request->arg(pO).toInt();
pO[l] = 'S'; p.serpentine = request->hasArg(pO);
pO[l] = 'X'; p.xOffset = request->arg(pO).toInt();
pO[l] = 'Y'; p.yOffset = request->arg(pO).toInt();
pO[l] = 'W'; p.width = request->arg(pO).toInt();
pO[l] = 'H'; p.height = request->arg(pO).toInt();
strip.panel.push_back(p);
}
} else {
Segment::maxWidth = strip.getLengthTotal();
Segment::maxHeight = 1;
} }
strip.setUpMatrix(); // will check limits strip.setUpMatrix(); // will check limits
} }

View File

@ -726,18 +726,20 @@ void getSettingsJS(byte subPage, char* dest)
{ {
sappend('v',SET_F("SOMP"),strip.isMatrix); sappend('v',SET_F("SOMP"),strip.isMatrix);
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
oappend(SET_F("maxPanels=")); oappendi(WLED_MAX_PANELS); oappend(SET_F(";"));
oappend(SET_F("resetPanels();")); oappend(SET_F("resetPanels();"));
if (strip.isMatrix) { if (strip.isMatrix) {
sappend('v',SET_F("PH"),strip.panelH); if(strip.panels>0){
sappend('v',SET_F("PW"),strip.panelW); sappend('v',SET_F("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience
sappend('v',SET_F("MPH"),strip.hPanels); sappend('v',SET_F("PH"),strip.panel[0].height);
sappend('v',SET_F("MPV"),strip.vPanels); }
sappend('v',SET_F("MPC"),strip.panels);
sappend('v',SET_F("PB"),strip.matrix.bottomStart); sappend('v',SET_F("PB"),strip.matrix.bottomStart);
sappend('v',SET_F("PR"),strip.matrix.rightStart); sappend('v',SET_F("PR"),strip.matrix.rightStart);
sappend('v',SET_F("PV"),strip.matrix.vertical); sappend('v',SET_F("PV"),strip.matrix.vertical);
sappend('c',SET_F("PS"),strip.matrix.serpentine); sappend('c',SET_F("PS"),strip.matrix.serpentine);
// panels // panels
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) { for (uint8_t i=0; i<strip.panels; i++) {
char n[5]; char n[5];
oappend(SET_F("addPanel(")); oappend(SET_F("addPanel("));
oappend(itoa(i,n,10)); oappend(itoa(i,n,10));
@ -748,6 +750,10 @@ void getSettingsJS(byte subPage, char* dest)
pO[l] = 'R'; sappend('v',pO,strip.panel[i].rightStart); pO[l] = 'R'; sappend('v',pO,strip.panel[i].rightStart);
pO[l] = 'V'; sappend('v',pO,strip.panel[i].vertical); pO[l] = 'V'; sappend('v',pO,strip.panel[i].vertical);
pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine); pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine);
pO[l] = 'X'; sappend('v',pO,strip.panel[i].xOffset);
pO[l] = 'Y'; sappend('v',pO,strip.panel[i].yOffset);
pO[l] = 'W'; sappend('v',pO,strip.panel[i].width);
pO[l] = 'H'; sappend('v',pO,strip.panel[i].height);
} }
} }
#else #else