Vectors & dynamic loadJS.

- Segments
- Modes

NOTE: crashes ESP if effect is running while deleting segment.
This commit is contained in:
Blaz Kristan 2022-07-17 15:58:41 +02:00
parent 8f72e0ab83
commit 6c6849d8d7
31 changed files with 3189 additions and 2884 deletions

View File

@ -263,120 +263,60 @@ writeChunks(
name: "PAGE_settings", name: "PAGE_settings",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=0\"></script>"
)
}, },
{ {
file: "settings_wifi.htm", file: "settings_wifi.htm",
name: "PAGE_settings_wifi", name: "PAGE_settings_wifi",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=1\"></script>"
)
}, },
{ {
file: "settings_leds.htm", file: "settings_leds.htm",
name: "PAGE_settings_leds", name: "PAGE_settings_leds",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=2\"></script>"
)
}, },
{ {
file: "settings_dmx.htm", file: "settings_dmx.htm",
name: "PAGE_settings_dmx", name: "PAGE_settings_dmx",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=7\"></script>"
)
}, },
{ {
file: "settings_ui.htm", file: "settings_ui.htm",
name: "PAGE_settings_ui", name: "PAGE_settings_ui",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=3\"></script>"
)
}, },
{ {
file: "settings_sync.htm", file: "settings_sync.htm",
name: "PAGE_settings_sync", name: "PAGE_settings_sync",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=4\"></script>"
)
}, },
{ {
file: "settings_time.htm", file: "settings_time.htm",
name: "PAGE_settings_time", name: "PAGE_settings_time",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=5\"></script>"
)
}, },
{ {
file: "settings_sec.htm", file: "settings_sec.htm",
name: "PAGE_settings_sec", name: "PAGE_settings_sec",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=6\"></script>"
)
}, },
{ {
file: "settings_um.htm", file: "settings_um.htm",
name: "PAGE_settings_um", name: "PAGE_settings_um",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=8\"></script>"
)
}, },
{ {
file: "settings_2D.htm", file: "settings_2D.htm",
name: "PAGE_settings_2D", name: "PAGE_settings_2D",
method: "gzip", method: "gzip",
filter: "html-minify", filter: "html-minify",
mangle: (str) =>
str
.replace(
/function GetV().*\<\/script\>/gms,
"</script><script src=\"/settings/s.js?p=10\"></script>"
)
}, },
{ {
file: "settings_pin.htm", file: "settings_pin.htm",

View File

@ -103,25 +103,24 @@ class Animated_Staircase : public Usermod {
void updateSegments() { void updateSegments() {
mainSegmentId = strip.getMainSegmentId(); mainSegmentId = strip.getMainSegmentId();
Segment* segments = strip.getSegments(); for (int i = 0; i < strip.getActiveSegmentsNum(); i++) {
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) { Segment &seg = strip.getSegment(i);
if (!segments->isActive()) { if (!seg.isActive()) {
maxSegmentId = i - 1; maxSegmentId = i - 1;
break; break;
} }
if (i >= onIndex && i < offIndex) { if (i >= onIndex && i < offIndex) {
segments->setOption(SEG_OPTION_ON, 1, i); seg.setOption(SEG_OPTION_ON, true);
// We may need to copy mode and colors from segment 0 to make sure // We may need to copy mode and colors from segment 0 to make sure
// changes are propagated even when the config is changed during a wipe // changes are propagated even when the config is changed during a wipe
// segments->mode = mainsegment.mode; // segments->mode = mainsegment.mode;
// segments->colors[0] = mainsegment.colors[0]; // segments->colors[0] = mainsegment.colors[0];
} else { } else {
segments->setOption(SEG_OPTION_ON, 0, i); seg.setOption(SEG_OPTION_ON, false);
} }
// Always mark segments as "transitional", we are animating the staircase // Always mark segments as "transitional", we are animating the staircase
segments->setOption(SEG_OPTION_TRANSITIONAL, 1, i); seg.setOption(SEG_OPTION_TRANSITIONAL, true);
} }
colorUpdated(CALL_MODE_DIRECT_CHANGE); colorUpdated(CALL_MODE_DIRECT_CHANGE);
} }
@ -290,13 +289,13 @@ class Animated_Staircase : public Usermod {
} }
} else { } else {
// Restore segment options // Restore segment options
Segment* segments = strip.getSegments(); for (int i = 0; i < strip.getActiveSegmentsNum(); i++) {
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) { Segment &seg = strip.getSegment(i);
if (!segments->isActive()) { if (!seg.isActive()) {
maxSegmentId = i - 1; maxSegmentId = i - 1;
break; break;
} }
segments->setOption(SEG_OPTION_ON, 1, i); seg.setOption(SEG_OPTION_ON, true);
} }
colorUpdated(CALL_MODE_DIRECT_CHANGE); colorUpdated(CALL_MODE_DIRECT_CHANGE);
DEBUG_PRINTLN(F("Animated Staircase disabled.")); DEBUG_PRINTLN(F("Animated Staircase disabled."));

View File

@ -528,7 +528,7 @@ public:
effectCurrent = modes_alpha_indexes[effectCurrentIndex]; effectCurrent = modes_alpha_indexes[effectCurrentIndex];
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
strip.setMode(i, effectCurrent); strip.setMode(i, effectCurrent);
@ -556,7 +556,7 @@ public:
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0); effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.speed = effectSpeed; seg.speed = effectSpeed;
@ -584,7 +584,7 @@ public:
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0); effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.intensity = effectIntensity; seg.intensity = effectIntensity;
@ -613,22 +613,23 @@ public:
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
uint8_t id = strip.getFirstSelectedSegId(); uint8_t id = strip.getFirstSelectedSegId();
Segment& sid = strip.getSegment(id);
switch (par) { switch (par) {
case 3: val = strip.getSegment(id).custom3 = max(min((increase ? strip.getSegment(id).custom3+fadeAmount : strip.getSegment(id).custom3-fadeAmount), 255), 0); break; case 3: val = sid.custom3 = max(min((increase ? sid.custom3+fadeAmount : sid.custom3-fadeAmount), 255), 0); break;
case 2: val = strip.getSegment(id).custom2 = max(min((increase ? strip.getSegment(id).custom2+fadeAmount : strip.getSegment(id).custom2-fadeAmount), 255), 0); break; case 2: val = sid.custom2 = max(min((increase ? sid.custom2+fadeAmount : sid.custom2-fadeAmount), 255), 0); break;
default: val = strip.getSegment(id).custom1 = max(min((increase ? strip.getSegment(id).custom1+fadeAmount : strip.getSegment(id).custom1-fadeAmount), 255), 0); break; default: val = sid.custom1 = max(min((increase ? sid.custom1+fadeAmount : sid.custom1-fadeAmount), 255), 0); break;
} }
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || i == id) continue; if (!seg.isActive() || i == id) continue;
switch (par) { switch (par) {
case 3: strip.getSegment(i).custom3 = strip.getSegment(id).custom3; break; case 3: seg.custom3 = sid.custom3; break;
case 2: strip.getSegment(i).custom2 = strip.getSegment(id).custom2; break; case 2: seg.custom2 = sid.custom2; break;
default: strip.getSegment(i).custom1 = strip.getSegment(id).custom1; break; default: seg.custom1 = sid.custom1; break;
} }
} }
} else { } else {
Segment& seg = strip.getSegment(strip.getMainSegmentId()); Segment& seg = strip.getMainSegment();
switch (par) { switch (par) {
case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break; case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break;
case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break; case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break;
@ -657,7 +658,7 @@ public:
effectPalette = palettes_alpha_indexes[effectPaletteIndex]; effectPalette = palettes_alpha_indexes[effectPaletteIndex];
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.palette = effectPalette; seg.palette = effectPalette;
@ -686,7 +687,7 @@ public:
colorHStoRGB(currentHue1*256, currentSat1, col); colorHStoRGB(currentHue1*256, currentSat1, col);
stateChanged = true; stateChanged = true;
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]); seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
@ -715,7 +716,7 @@ public:
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0); currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
colorHStoRGB(currentHue1*256, currentSat1, col); colorHStoRGB(currentHue1*256, currentSat1, col);
if (applyToAll) { if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]); seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
@ -775,7 +776,7 @@ public:
#endif #endif
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0); currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
// if (applyToAll) { // if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) { for (byte i=0; i<strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
seg.setCCT(currentCCT); seg.setCCT(currentCCT);

View File

@ -3134,8 +3134,8 @@ typedef struct particle {
uint16_t mode_starburst(void) { uint16_t mode_starburst(void) {
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640 uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
uint8_t segs = strip.getActiveSegmentsNum(); uint8_t segs = strip.getActiveSegmentsNum();
if (segs <= (MAX_NUM_SEGMENTS /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
if (segs <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs if (segs <= (strip.getMaxSegments() /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
uint16_t maxStars = maxData / sizeof(star); //ESP8266: max. 4/9/19 stars/seg, ESP32: max. 10/21/42 stars/seg uint16_t maxStars = maxData / sizeof(star); //ESP8266: max. 4/9/19 stars/seg, ESP32: max. 10/21/42 stars/seg
uint8_t numStars = 1 + (SEGLEN >> 3); uint8_t numStars = 1 + (SEGLEN >> 3);
@ -3257,8 +3257,8 @@ uint16_t mode_exploding_fireworks(void)
//allocate segment data //allocate segment data
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640 uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
uint8_t segs = strip.getActiveSegmentsNum(); uint8_t segs = strip.getActiveSegmentsNum();
if (segs <= (MAX_NUM_SEGMENTS /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
if (segs <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs if (segs <= (strip.getMaxSegments() /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg
uint16_t numSparks = min(2 + ((rows*cols) >> 1), maxSparks); uint16_t numSparks = min(2 + ((rows*cols) >> 1), maxSparks);
@ -7667,12 +7667,21 @@ static const char *_data_FX_MODE_2DAKEMI PROGMEM = "2D Akemi@Color speed,Dance;H
static const char *_data_RESERVED PROGMEM = "Reserved"; static const char *_data_RESERVED PROGMEM = "Reserved";
void WS2812FX::addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name) { void WS2812FX::addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name) {
/*
if (id == 255) { for (int i=1; i<_modeCount; i++) if (_mode[i] == &mode_static) { id = i; break; } } // find empty slot if (id == 255) { for (int i=1; i<_modeCount; i++) if (_mode[i] == &mode_static) { id = i; break; } } // find empty slot
if (id < _modeCount) { if (id < _modeCount) {
if (_mode[id] != &mode_static) return; // do not overwrite alerady added effect if (_mode[id] != &mode_static) return; // do not overwrite alerady added effect
_mode[id] = mode_fn; _mode[id] = mode_fn;
_modeData[id] = mode_name; _modeData[id] = mode_name;
} }
*/
if (id >= _mode.size()) {
_mode.push_back(mode_fn);
_modeData.push_back(mode_name);
} else {
_mode.insert(_mode.begin()+id, mode_fn);
_modeData.insert(_modeData.begin()+id, mode_name);
}
} }
void WS2812FX::setupEffectData() { void WS2812FX::setupEffectData() {

View File

@ -27,6 +27,8 @@
#ifndef WS2812FX_h #ifndef WS2812FX_h
#define WS2812FX_h #define WS2812FX_h
#include <vector>
#include "const.h" #include "const.h"
#define FASTLED_INTERNAL //remove annoying pragma messages #define FASTLED_INTERNAL //remove annoying pragma messages
@ -68,30 +70,28 @@ uint32_t color_add(uint32_t,uint32_t);
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#ifdef ESP8266 #ifdef ESP8266
#define MAX_NUM_SEGMENTS 16 #define MAX_NUM_SEGMENTS 16
/* How many color transitions can run at once */
#define MAX_NUM_TRANSITIONS 8
/* How much data bytes all segments combined may allocate */ /* How much data bytes all segments combined may allocate */
#define MAX_SEGMENT_DATA 4096 #define MAX_SEGMENT_DATA 4096
#else #else
#ifndef MAX_NUM_SEGMENTS #ifndef MAX_NUM_SEGMENTS
#define MAX_NUM_SEGMENTS 32 #define MAX_NUM_SEGMENTS 32
#endif #endif
#define MAX_NUM_TRANSITIONS 24
#define MAX_SEGMENT_DATA 20480 #define MAX_SEGMENT_DATA 20480
#endif #endif
/* How much data bytes each segment should max allocate to leave enough space for other segments, /* How much data bytes each segment should max allocate to leave enough space for other segments,
assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */ assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */
#define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / MAX_NUM_SEGMENTS) #define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / strip.getMaxSegments())
#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15) #define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15)
#define NUM_COLORS 3 /* number of colors per segment */ #define NUM_COLORS 3 /* number of colors per segment */
#define SEGMENT strip._segments[strip.getCurrSegmentId()] #define SEGMENT strip._segments[strip.getCurrSegmentId()]
#define SEGENV strip._segments[strip.getCurrSegmentId()].runtime #define SEGENV strip._segments[strip.getCurrSegmentId()]
#define SEGCOLOR(x) strip.segColor(x) //#define SEGCOLOR(x) strip._segments[s//trip.getCurrSegmentId()].currentColor(x, strip._segments[strip.getCurrSegmentId()].colors[x])
//#define SEGLEN strip._segments[strip.getCurrSegmentId()].virtualLength() //#define SEGLEN strip._segments[strip.getCurrSegmentId()].virtualLength()
#define SEGLEN strip._virtualSegmentLength /* saves us a few kbytes of code */ #define SEGCOLOR(x) strip.segColor(x) /* saves us a few kbytes of code */
#define SEGLEN strip._virtualSegmentLength /* saves us a few kbytes of code */
#define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed))/SEGLEN) #define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed))/SEGLEN)
// some common colors // some common colors
@ -362,148 +362,220 @@ uint32_t color_add(uint32_t,uint32_t);
#define MODE_COUNT 185 #define MODE_COUNT 185
#endif #endif
struct Segment; // segment, 68 (92 in memory) bytes
typedef struct Segment {
public:
uint16_t start; // start index / start X coordinate 2D (left)
uint16_t stop; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0
uint16_t offset;
uint8_t speed;
uint8_t intensity;
uint8_t palette;
uint8_t mode;
union {
uint16_t options; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
struct {
uint16_t selected:1; // 0 : selected
uint16_t reverse:1; // 1 : reversed
uint16_t on:1; // 2 : is On
uint16_t mirror:1; // 3 : mirrored
uint16_t pxs:1; // 4 : indicates that the effect does not use FRAMETIME or needs getPixelColor (?)
uint16_t freeze:1; // 5 : paused/frozen
uint16_t reset:1; // 6 : indicates that Segment runtime requires reset
uint16_t transitional:1; // 7 : transitional (there is transition occuring)
uint16_t reverse_y:1; // 8 : reversed Y (2D)
uint16_t mirror_y:1; // 9 : mirrored Y (2D)
uint16_t transpose:1; // 10 : transposed (2D, swapped X & Y)
uint16_t map1D2D:3; // 11-13 : mapping for 1D effect on 2D (0-strip, 1-expand vertically, 2-circular, 3-rectangular, 4-7 reserved)
uint16_t reserved:2; // 14-15 : reserved
};
};
uint8_t grouping, spacing;
uint8_t opacity;
uint32_t colors[NUM_COLORS];
uint8_t cct; //0==1900K, 255==10091K
uint8_t custom1, custom2, custom3; // custom FX parameters
uint16_t startY; // start Y coodrinate 2D (top)
uint16_t stopY; // stop Y coordinate 2D (bottom)
char *name;
// color transitions // runtime data
typedef struct ColorTransition { // 20 bytes unsigned long next_time; // millis() of next update
uint32_t colorOld[NUM_COLORS]; uint32_t step; // custom "step" var
uint8_t briOld; uint32_t call; // call counter
uint8_t cctOld; uint16_t aux0; // custom var
uint32_t transitionStart; uint16_t aux1; // custom var
uint16_t transitionDur; byte* data;
void startTransition(Segment *seg, uint16_t dur); // transition has to start before actual segment values change
void handleTransition(Segment *seg, uint8_t &newBri, uint8_t &newCct, uint32_t *newCol);
uint16_t progress(); //transition progression between 0-65535
uint8_t currentBri(uint8_t briNew, bool useCct = false);
uint32_t currentColor(uint8_t slot, uint32_t colorNew) {
return color_blend(colorOld[slot], colorNew, progress(), true);
}
} color_transition;
// segment runtime parameters
typedef struct Segmentruntime { // 23 (24 in memory) bytes
unsigned long next_time; // millis() of next update
uint32_t step; // custom "step" var
uint32_t call; // call counter
uint16_t aux0; // custom var
uint16_t aux1; // custom var
byte* data = nullptr;
bool allocateData(uint16_t len);
void deallocateData();
void resetIfRequired();
/**
* Flags that before the next effect is calculated,
* the internal segment state should be reset.
* Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests.
*/
inline void markForReset() { _requiresReset = true; }
private: private:
uint16_t _dataLen = 0; uint8_t _capabilities;
bool _requiresReset = false; uint16_t _dataLen;
} segmentruntime;
// transition data, valid only if getOption(SEG_OPTION_TRANSITIONAL)==true
//struct Transition {
uint32_t _colorT[NUM_COLORS];
uint8_t _briT;
uint8_t _cctT;
uint32_t _start;
uint16_t _dur;
// Transition(uint16_t dur=10) : _briT(255), _cctT(127), _start(millis()), _dur(dur) {}
// Transition(uint16_t d, uint8_t b, uint8_t c, const uint32_t *o) : _briT(b), _cctT(c), _start(millis()), _dur(d) {
// for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = o[i];
// }
//} *_t; // this struct will bootloop ESP
// segment parameters public:
typedef struct Segment { // 40 (44 in memory) bytes
uint16_t start; // start index / start X coordinate 2D (left)
uint16_t stop; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0
uint16_t offset;
uint8_t speed;
uint8_t intensity;
uint8_t palette;
uint8_t mode;
uint16_t options; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
uint8_t grouping, spacing;
uint8_t opacity;
uint32_t colors[NUM_COLORS];
uint8_t cct; //0==1900K, 255==10091K
uint8_t _capabilities;
uint8_t custom1, custom2, custom3; // custom FX parameters
uint16_t startY; // start Y coodrinate 2D (top)
uint16_t stopY; // stop Y coordinate 2D (bottom)
char *name;
segmentruntime runtime;
color_transition transition;
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); } Segment(uint16_t sStart=0, uint16_t sStop=30) : start(sStart), stop(sStop) {
inline bool isSelected() { return getOption(0); } mode = DEFAULT_MODE;
inline bool isActive() { return stop > start; } colors[0] = DEFAULT_COLOR;
inline uint16_t width() { return stop - start; } colors[1] = BLACK;
inline uint16_t height() { return stopY - startY; } colors[2] = BLACK;
inline uint16_t length() { return width(); } startY = 0;
inline uint16_t groupLength() { return grouping + spacing; } stopY = 1;
inline uint8_t getLightCapabilities() { return _capabilities; } speed = DEFAULT_SPEED;
intensity = DEFAULT_INTENSITY;
custom1 = DEFAULT_C1;
custom2 = DEFAULT_C2;
custom3 = DEFAULT_C3;
grouping = 1;
spacing = 0;
offset = 0;
opacity = 255;
cct = 127;
name = nullptr;
options = NO_OPTIONS;
setOption(SEG_OPTION_SELECTED, 1);
setOption(SEG_OPTION_ON, 1);
call = 0;
step = 0;
next_time = 0;
aux0 = 0;
aux1 = 0;
data = nullptr;
_dataLen = 0;
//_t = nullptr;
}
bool setColor(uint8_t slot, uint32_t c); //returns true if changed Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) {
void setCCT(uint16_t k); Segment(sStartX, sStopX);
void setOpacity(uint8_t o); startY = sStartY;
void setOption(uint8_t n, bool val); stopY = sStopY;
uint8_t differs(Segment& b); }
void refreshLightCapabilities();
// 1D strip Segment(const Segment &orig); // copy constructor
uint16_t virtualLength(); Segment(Segment &&orig) noexcept; // move constructor
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline
void setPixelColor(int n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); } // automatically inline
void setPixelColor(float i, uint32_t c, bool aa = true);
void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, c.red, c.green, c.blue, 0, aa); }
uint32_t getPixelColor(uint16_t i);
// 1D support functions (some implement 2D as well)
void blur(uint8_t);
void fill(uint32_t c);
void fade_out(uint8_t r);
void fadeToBlackBy(uint8_t fadeBy);
void blendPixelColor(uint16_t n, uint32_t color, uint8_t blend);
void addPixelColor(uint16_t n, uint32_t color);
uint8_t get_random_wheel_index(uint8_t pos);
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
uint32_t color_wheel(uint8_t pos);
// 2D matrix ~Segment() {
uint16_t virtualWidth(); Serial.print(F("Destroying segment: "));
uint16_t virtualHeight(); if (name) Serial.println(name); else Serial.println();
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[]) if (name) delete[] name;
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color //if (_t) delete _t;
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline deallocateData();
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, c.red, c.green, c.blue); } // automatically inline }
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true);
void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); } Segment& operator= (const Segment &orig); // copy assignment
void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, c.red, c.green, c.blue, 0, aa); } Segment& operator= (Segment &&orig) noexcept; // move assignment
uint32_t getPixelColorXY(uint16_t x, uint16_t y);
// 2D support functions inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend); inline bool isSelected() { return getOption(0); }
void addPixelColorXY(uint16_t x, uint16_t y, uint32_t color); inline bool isActive() { return stop > start; }
void blur1d(CRGB* leds, fract8 blur_amount); inline uint16_t width() { return stop - start; }
void blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds=nullptr); // 1D box blur (with weight) inline uint16_t height() { return stopY - startY; }
void blur2d(CRGB* leds, fract8 blur_amount); inline uint16_t length() { return width(); }
void blurRow(uint16_t row, fract8 blur_amount, CRGB* leds=nullptr); inline uint16_t groupLength() { return grouping + spacing; }
void blurCol(uint16_t col, fract8 blur_amount, CRGB* leds=nullptr); inline uint8_t getLightCapabilities() { return _capabilities; }
void moveX(CRGB *leds, int8_t delta);
void moveY(CRGB *leds, int8_t delta); bool setColor(uint8_t slot, uint32_t c); //returns true if changed
void move(uint8_t dir, uint8_t delta, CRGB *leds=nullptr); void setCCT(uint16_t k);
void fill_solid(CRGB* leds, CRGB c); void setOpacity(uint8_t o);
void fill_circle(CRGB* leds, uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); void setOption(uint8_t n, bool val);
void fadeToBlackBy(CRGB* leds, uint8_t fadeBy); uint8_t differs(Segment& b);
void nscale8(CRGB* leds, uint8_t scale); void refreshLightCapabilities();
void setPixels(CRGB* leds);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, CRGB *leds = nullptr); // runtime data functions
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color, CRGB *leds = nullptr); bool allocateData(uint16_t len);
void wu_pixel(CRGB *leds, uint32_t x, uint32_t y, CRGB c); void deallocateData();
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { drawLine(x0, y0, x1, y1, CRGB(byte(c>>16), byte(c>>8), byte(c))); } void resetIfRequired();
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t c) { drawCharacter(chr, x, y, w, h, CRGB(byte(c>>16), byte(c>>8), byte(c))); } /**
* Flags that before the next effect is calculated,
* the internal segment state should be reset.
* Call resetIfRequired before calling the next effect function.
* Safe to call from interrupts and network requests.
*/
inline void markForReset() { reset = true; } // setOption(SEG_OPTION_RESET, true)
// transition functions
void startTransition(uint16_t dur); // transition has to start before actual segment values change
void handleTransition(void);
uint16_t progress(); //transition progression between 0-65535
uint8_t currentBri(uint8_t briNew, bool useCct = false);
uint32_t currentColor(uint8_t slot, uint32_t colorNew) { return getOption(SEG_OPTION_TRANSITIONAL) /*&& !_t*/ ? color_blend(/*_t->*/_colorT[slot], colorNew, progress(), true) : colorNew; }
// 1D strip
uint16_t virtualLength();
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline
void setPixelColor(int n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); } // automatically inline
void setPixelColor(float i, uint32_t c, bool aa = true);
void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, c.red, c.green, c.blue, 0, aa); }
uint32_t getPixelColor(uint16_t i);
// 1D support functions (some implement 2D as well)
void blur(uint8_t);
void fill(uint32_t c);
void fade_out(uint8_t r);
void fadeToBlackBy(uint8_t fadeBy);
void blendPixelColor(uint16_t n, uint32_t color, uint8_t blend);
void addPixelColor(uint16_t n, uint32_t color);
uint8_t get_random_wheel_index(uint8_t pos);
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
uint32_t color_wheel(uint8_t pos);
// 2D matrix
uint16_t virtualWidth();
uint16_t virtualHeight();
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment (for leds[])
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, c.red, c.green, c.blue); } // automatically inline
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true);
void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, c.red, c.green, c.blue, 0, aa); }
uint32_t getPixelColorXY(uint16_t x, uint16_t y);
// 2D support functions
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
void addPixelColorXY(uint16_t x, uint16_t y, uint32_t color);
void blur1d(CRGB* leds, fract8 blur_amount);
void blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds=nullptr); // 1D box blur (with weight)
void blur2d(CRGB* leds, fract8 blur_amount);
void blurRow(uint16_t row, fract8 blur_amount, CRGB* leds=nullptr);
void blurCol(uint16_t col, fract8 blur_amount, CRGB* leds=nullptr);
void moveX(CRGB *leds, int8_t delta);
void moveY(CRGB *leds, int8_t delta);
void move(uint8_t dir, uint8_t delta, CRGB *leds=nullptr);
void fill_solid(CRGB* leds, CRGB c);
void fill_circle(CRGB* leds, uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
void fadeToBlackBy(CRGB* leds, uint8_t fadeBy);
void nscale8(CRGB* leds, uint8_t scale);
void setPixels(CRGB* leds);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, CRGB *leds = nullptr);
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color, CRGB *leds = nullptr);
void wu_pixel(CRGB *leds, uint32_t x, uint32_t y, CRGB c);
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { drawLine(x0, y0, x1, y1, CRGB(byte(c>>16), byte(c>>8), byte(c))); }
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t c) { drawCharacter(chr, x, y, w, h, CRGB(byte(c>>16), byte(c>>8), byte(c))); }
} segment; } segment;
//static int i = sizeof(Segment);
// main "strip" class // main "strip" class
class WS2812FX { // 96 bytes class WS2812FX { // 96 bytes
typedef uint16_t (*mode_ptr)(void); // pointer to mode function typedef uint16_t (*mode_ptr)(void); // pointer to mode function
typedef void (*show_callback)(void); // pre show callback typedef void (*show_callback)(void); // pre show callback
typedef struct ModeData {
mode_ptr _fcn; // mode (effect) function
const char *_data; // mode (effect) name and its slider control data array
ModeData(uint16_t (*fcn)(void), const char *data) : _fcn(fcn), _data(data) {}
} mode_data_t;
static WS2812FX* instance; static WS2812FX* instance;
@ -511,22 +583,31 @@ class WS2812FX { // 96 bytes
WS2812FX() { WS2812FX() {
WS2812FX::instance = this; WS2812FX::instance = this;
_mode.reserve(_modeCount);
_modeData.reserve(_modeCount);
if (_mode.capacity() <= 1 || _modeData.capacity() <= 1) _modeCount = 1;
else setupEffectData();
/*
_mode = new mode_ptr[_modeCount]; _mode = new mode_ptr[_modeCount];
_modeData = new const char*[_modeCount]; _modeData = new const char*[_modeCount];
if (_mode && _modeData) setupEffectData(); if (_mode && _modeData) setupEffectData();
else _modeCount = 1; // only Solid will work else _modeCount = 1; // only Solid will work
*/
_brightness = DEFAULT_BRIGHTNESS; _brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black); currentPalette = CRGBPalette16(CRGB::Black);
targetPalette = CloudColors_p; targetPalette = CloudColors_p;
ablMilliampsMax = ABL_MILLIAMPS_DEFAULT; ablMilliampsMax = ABL_MILLIAMPS_DEFAULT;
currentMilliamps = 0; currentMilliamps = 0;
timebase = 0; timebase = 0;
resetSegments(); _usedSegmentData = 0;
//resetSegments(); // no need here
} }
~WS2812FX() { ~WS2812FX() {
delete[] _mode; //delete[] _mode;
delete[] _modeData; //delete[] _modeData;
_mode.clear();
_modeData.clear();
} }
static WS2812FX* getInstance(void) { return instance; } static WS2812FX* getInstance(void) { return instance; }
@ -542,7 +623,8 @@ class WS2812FX { // 96 bytes
setRange(uint16_t i, uint16_t i2, uint32_t col), setRange(uint16_t i, uint16_t i2, uint32_t col),
setTransitionMode(bool t), setTransitionMode(bool t),
calcGammaTable(float), calcGammaTable(float),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX, uint16_t startY=0, uint16_t stopY=0), purgeSegments(void),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 1, uint8_t spacing = 0, uint16_t offset = UINT16_MAX, uint16_t startY=0, uint16_t stopY=1),
setMainSegmentId(uint8_t n), setMainSegmentId(uint8_t n),
restartRuntime(), restartRuntime(),
resetSegments(), resetSegments(),
@ -563,6 +645,7 @@ class WS2812FX { // 96 bytes
inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments. inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments.
inline void setShowCallback(show_callback cb) { _callback = cb; } inline void setShowCallback(show_callback cb) { _callback = cb; }
inline void setTransition(uint16_t t) { _transitionDur = t; } inline void setTransition(uint16_t t) { _transitionDur = t; }
inline void appendSegment(const Segment &seg = Segment()) { _segments.push_back(seg); }
inline void addUsedSegmentData(int16_t size) { _usedSegmentData += size; } inline void addUsedSegmentData(int16_t size) { _usedSegmentData += size; }
bool bool
@ -582,7 +665,7 @@ class WS2812FX { // 96 bytes
paletteBlend = 0, paletteBlend = 0,
milliampsPerLed = 55, milliampsPerLed = 55,
cctBlending = 0, cctBlending = 0,
getActiveSegmentsNum(void), //getActiveSegmentsNum(void),
getFirstSelectedSegId(void), getFirstSelectedSegId(void),
getLastActiveSegmentId(void), getLastActiveSegmentId(void),
setPixelSegment(uint8_t n), setPixelSegment(uint8_t n),
@ -590,7 +673,8 @@ class WS2812FX { // 96 bytes
gamma8_cal(uint8_t, float); gamma8_cal(uint8_t, float);
inline uint8_t getBrightness(void) { return _brightness; } inline uint8_t getBrightness(void) { return _brightness; }
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
inline uint8_t getActiveSegmentsNum(void) { return _segments.size(); } // returns currently active (present) segments
inline uint8_t getCurrSegmentId(void) { return _segment_index; } inline uint8_t getCurrSegmentId(void) { return _segment_index; }
inline uint8_t getMainSegmentId(void) { return _mainSegment; } inline uint8_t getMainSegmentId(void) { return _mainSegment; }
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; }
@ -623,12 +707,13 @@ class WS2812FX { // 96 bytes
getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); } getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
const char ** const char **
getModeDataSrc(void) { return _modeData; } getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
inline Segment& getSegment(uint8_t id) { return _segments[id >= MAX_NUM_SEGMENTS ? getMainSegmentId() : id]; } //inline Segment& getSegment(uint8_t id) { return _segments[id >= getMaxSegments() ? getMainSegmentId() : id]; }
inline Segment& getSegment(uint8_t id) { return _segments[id >= _segments.size() ? getMainSegmentId() : id]; } // vectors
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; } inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; } inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
inline Segment* getSegments(void) { return _segments; } inline Segment* getSegments(void) { return &(_segments[0]); }
// 2D support (panels) // 2D support (panels)
bool bool
@ -674,25 +759,23 @@ class WS2812FX { // 96 bytes
CRGBPalette16 currentPalette; CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette; CRGBPalette16 targetPalette;
// using public variables to reduce code size increase due to inline function getSegment() (with bounds checking)
// and color transitions
uint8_t _bri_t; // used for opacity transitions uint8_t _bri_t; // used for opacity transitions
uint32_t _colors_t[3]; // used for color transitions uint32_t _colors_t[3]; // used for color transitions
uint16_t _virtualSegmentLength; uint16_t _virtualSegmentLength;
// using public array to reduce code size increase due to inline function getSegment() (with bounds checking) //segment _segments[MAX_NUM_SEGMENTS]; // SRAM footprint: 88 bytes per element
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 27 bytes per element std::vector<segment> _segments; // deleting a segment while effects play crashes ESP
// start, stop, offset, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[], capabilities, custom 1, custom 2, custom 3
{0, 7, 0, DEFAULT_SPEED, DEFAULT_INTENSITY, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}, 0, DEFAULT_C1, DEFAULT_C2, DEFAULT_C3, 0, 1}
};
friend class Segment; friend class Segment;
//size_t segSize = sizeof(Segment);
//segmentruntime _segmentruntimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element //size_t segsSize = sizeof(_segments);
//friend class Segmentruntime;
private: private:
uint16_t _length; uint16_t _length;
uint16_t _rand16seed; uint16_t _rand16seed;
uint8_t _brightness; uint8_t _brightness;
uint16_t _usedSegmentData = 0; uint16_t _usedSegmentData;
uint16_t _transitionDur = 750; uint16_t _transitionDur = 750;
uint8_t _targetFps = 42; uint8_t _targetFps = 42;
@ -705,8 +788,12 @@ class WS2812FX { // 96 bytes
_triggered; _triggered;
uint8_t _modeCount = MODE_COUNT; uint8_t _modeCount = MODE_COUNT;
mode_ptr *_mode; // SRAM footprint: 4 bytes per element //mode_ptr *_mode; // SRAM footprint: 4 bytes per element
const char **_modeData; // mode (effect) name and its slider control data array //const char **_modeData; // mode (effect) name and its slider control data array
std::vector<mode_ptr> _mode; // SRAM footprint: 4 bytes per element
std::vector<const char*> _modeData; // mode (effect) name and its slider control data array
//std::vector<ModeData> _modes; // this will require substantial rewrite of code
show_callback _callback = nullptr; show_callback _callback = nullptr;
@ -726,9 +813,6 @@ class WS2812FX { // 96 bytes
estimateCurrentAndLimitBri(void), estimateCurrentAndLimitBri(void),
load_gradient_palette(uint8_t), load_gradient_palette(uint8_t),
handle_palette(void); handle_palette(void);
uint16_t
transitionProgress(uint8_t tNr);
}; };
extern const char JSON_mode_names[]; extern const char JSON_mode_names[];

View File

@ -153,6 +153,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
if (!strip.isMatrix) return; // not a matrix set-up if (!strip.isMatrix) return; // not a matrix set-up
uint8_t _bri_t = strip._bri_t; uint8_t _bri_t = strip._bri_t;
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
if (_bri_t < 255) { if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t); byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t); byte g = scale8(G(col), _bri_t);

View File

@ -70,57 +70,157 @@
#endif #endif
///////////////////////////////////////////////////////////////////////////////
// ColorTransition class implementation
///////////////////////////////////////////////////////////////////////////////
void ColorTransition::startTransition(Segment *seg, uint16_t dur) {
// starting a transition has to occur before change
if (!seg->isActive()) return;
briOld = currentBri(seg->getOption(SEG_OPTION_ON) ? seg->opacity : 0);
cctOld = currentBri(seg->cct, true);
for (size_t i=0; i<NUM_COLORS; i++) colorOld[i] = currentColor(i, seg->colors[i]);
transitionDur = dur;
transitionStart = millis();
seg->setOption(SEG_OPTION_TRANSITIONAL, true);
}
uint16_t ColorTransition::progress() { //transition progression between 0-65535
uint32_t timeNow = millis();
if (timeNow - transitionStart > transitionDur) return 0xFFFFU;
uint32_t elapsed = timeNow - transitionStart;
return min(0xFFFFU, elapsed * 0xFFFFU / transitionDur);
}
uint8_t ColorTransition::currentBri(uint8_t briNew, bool useCct) {
uint32_t prog = progress() + 1;
if (useCct) return ((briNew * prog) + cctOld * (0x10000 - prog)) >> 16;
else return ((briNew * prog) + briOld * (0x10000 - prog)) >> 16;
}
void ColorTransition::handleTransition(Segment *seg, uint8_t &newBri, uint8_t &newCct, uint32_t *newCol) {
newBri = currentBri(newBri);
newCct = currentBri(newCct, true);
for (size_t i=0; i<NUM_COLORS; i++) newCol[i] = currentColor(i, newCol[i]);
unsigned long maxWait = millis() + 22;
if (seg->mode == FX_MODE_STATIC && seg->runtime.next_time > maxWait) seg->runtime.next_time = maxWait;
if (progress() == 0xFFFFU && seg->getOption(SEG_OPTION_TRANSITIONAL)) {
// finish transition
briOld = newBri;
cctOld = newCct;
for (size_t i=0; i<NUM_COLORS; i++) colorOld[i] = newCol[i];
seg->setOption(SEG_OPTION_TRANSITIONAL, false);
}
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Segment class implementation // Segment class implementation
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Segment::Segment(const Segment &orig) {
DEBUG_PRINTLN(F("-- Segment duplicated --"));
memcpy(this, &orig, sizeof(Segment));
name = nullptr;
data = nullptr;
_dataLen = 0;
//_t = nullptr;
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
if (orig.data) { allocateData(orig._dataLen); memcpy(data, orig.data, orig._dataLen); }
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
DEBUG_PRINTF(" Original data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" Constructed data: %p (%d)\n", data, (int)_dataLen);
}
Segment::Segment(Segment &&orig) noexcept {
DEBUG_PRINTLN(F("-- Move constructor --"));
memcpy(this, &orig, sizeof(Segment));
orig.name = nullptr;
orig.data = nullptr;
//orig._t = nullptr;
}
Segment& Segment::operator= (const Segment &orig) {
DEBUG_PRINTLN(F("-- Segment copied --"));
if (this != &orig) {
if (name) delete[] name;
//if (_t) delete _t;
deallocateData();
memcpy(this, &orig, sizeof(Segment));
name = nullptr;
data = nullptr;
_dataLen = 0;
//_t = nullptr;
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
if (orig.data) { allocateData(orig._dataLen); memcpy(data, orig.data, orig._dataLen); }
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
DEBUG_PRINTF(" Copied data: %p (%d)\n", orig.data, (int)orig._dataLen);
DEBUG_PRINTF(" New data: %p (%d)\n", data, (int)_dataLen);
}
return *this;
}
Segment& Segment::operator= (Segment &&orig) noexcept {
DEBUG_PRINTLN(F("-- Moving segment --"));
if (this != &orig) {
if (name) delete[] name; // free old name
//if (_t) delete _t;
deallocateData(); // free old runtime data
memcpy(this, &orig, sizeof(Segment));
orig.name = nullptr;
orig.data = nullptr;
//orig._t = nullptr;
}
return *this;
}
bool Segment::allocateData(uint16_t len) {
if (data && _dataLen == len) return true; //already allocated
DEBUG_PRINTF("-- Allocating data (size:%d) --\n", len);
deallocateData();
if (strip.getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
// if possible use SPI RAM on ESP32
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
if (psramFound())
data = (byte*) ps_malloc(len);
else
#endif
data = (byte*) malloc(len);
if (!data) return false; //allocation failed
strip.addUsedSegmentData(len);
_dataLen = len;
memset(data, 0, len);
return true;
}
void Segment::deallocateData() {
if (!data) return;
DEBUG_PRINTF("-- Deallocating data: %p (%d) --\n", data, (int)_dataLen);
free(data);
data = nullptr;
strip.addUsedSegmentData(-(int16_t)_dataLen);
_dataLen = 0;
}
/**
* If reset of this segment was requested, clears runtime
* settings of this segment.
* Must not be called while an effect mode function is running
* because it could access the data buffer and this method
* may free that data buffer.
*/
void Segment::resetIfRequired() {
if (reset) { // (getOption(SEG_OPTION_RESET))
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
deallocateData();
reset = false; // setOption(SEG_OPTION_RESET, false);
}
}
void Segment::startTransition(uint16_t dur) {
// starting a transition has to occur before change so we get current values 1st
/*uint8_t*/ _briT = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0); // comment out uint8_t if not using Transition struct
/*uint8_t*/ _cctT = currentBri(cct, true); // comment out uint8_t if not using Transition struct
//uint32_t _colorT[NUM_COLORS]; // comment out if not using Transition struct
for (size_t i=0; i<NUM_COLORS; i++) _colorT[i] = currentColor(i, colors[i]);
// comment out if not using Transition struct
//if (!_t) _t = new Transition(dur); // no previous transition running
//if (!_t) return; // failed to allocat data
//_t->_briT = _briT;
//_t->_cctT = _cctT;
//for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = _colorT[i];
setOption(SEG_OPTION_TRANSITIONAL, true);
}
uint16_t Segment::progress() { //transition progression between 0-65535
//if (!_t) return 0xFFFFU;
uint32_t timeNow = millis();
if (timeNow - /*_t->*/_start > /*_t->*/_dur) return 0xFFFFU;
return (timeNow - /*_t->*/_start) * 0xFFFFU / /*_t->*/_dur;
}
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
//if (!_t) return (useCct) ? cct : opacity;
if (getOption(SEG_OPTION_TRANSITIONAL)) {
uint32_t prog = progress() + 1;
if (useCct) return ((briNew * prog) + /*_t->*/_cctT * (0x10000 - prog)) >> 16;
else return ((briNew * prog) + /*_t->*/_briT * (0x10000 - prog)) >> 16;
} else {
return (useCct) ? cct : (getOption(SEG_OPTION_ON) ? opacity : 0);
}
}
void Segment::handleTransition() {
if (!getOption(SEG_OPTION_TRANSITIONAL)) return;
unsigned long maxWait = millis() + 20;
if (mode == FX_MODE_STATIC && next_time > maxWait) next_time = maxWait;
if (progress() == 0xFFFFU) {
//if (_t) { delete _t; _t = nullptr; }
setOption(SEG_OPTION_TRANSITIONAL, false); // finish transitioning segment
}
}
bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed
if (slot >= NUM_COLORS || c == colors[slot]) return false; if (slot >= NUM_COLORS || c == colors[slot]) return false;
transition.startTransition(this, strip.getTransition()); // start transition prior to change startTransition(strip.getTransition()); // start transition prior to change
colors[slot] = c; colors[slot] = c;
return true; return true;
} }
@ -132,19 +232,19 @@ void Segment::setCCT(uint16_t k) {
k = (k - 1900) >> 5; k = (k - 1900) >> 5;
} }
if (cct == k) return; if (cct == k) return;
transition.startTransition(this, strip.getTransition()); // start transition prior to change startTransition(strip.getTransition()); // start transition prior to change
cct = k; cct = k;
} }
void Segment::setOpacity(uint8_t o) { void Segment::setOpacity(uint8_t o) {
if (opacity == o) return; if (opacity == o) return;
transition.startTransition(this, strip.getTransition()); // start transition prior to change startTransition(strip.getTransition()); // start transition prior to change
opacity = o; opacity = o;
} }
void Segment::setOption(uint8_t n, bool val) { void Segment::setOption(uint8_t n, bool val) {
bool prevOn = getOption(SEG_OPTION_ON); bool prevOn = getOption(SEG_OPTION_ON);
if (n == SEG_OPTION_ON && val != prevOn) transition.startTransition(this, strip.getTransition()); // start transition prior to change if (n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
if (val) options |= 0x01 << n; if (val) options |= 0x01 << n;
else options &= ~(0x01 << n); else options &= ~(0x01 << n);
} }
@ -185,6 +285,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t len = length(); uint16_t len = length();
uint8_t _bri_t = strip._bri_t; uint8_t _bri_t = strip._bri_t;
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
if (_bri_t < 255) { if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t); byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t); byte g = scale8(G(col), _bri_t);
@ -289,9 +390,6 @@ uint8_t Segment::differs(Segment& b) {
} }
void Segment::refreshLightCapabilities() { void Segment::refreshLightCapabilities() {
if (!isActive()) {
_capabilities = 0; return;
}
uint8_t capabilities = 0; uint8_t capabilities = 0;
for (uint8_t b = 0; b < busses.getNumBusses(); b++) { for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
@ -487,51 +585,6 @@ uint32_t IRAM_ATTR Segment::color_from_palette(uint16_t i, bool mapping, bool wr
} }
///////////////////////////////////////////////////////////////////////////////
// Segmentruntime class implementation
///////////////////////////////////////////////////////////////////////////////
bool Segmentruntime::allocateData(uint16_t len){
if (data && _dataLen == len) return true; //already allocated
deallocateData();
if (strip.getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
// if possible use SPI RAM on ESP32
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
if (psramFound())
data = (byte*) ps_malloc(len);
else
#endif
data = (byte*) malloc(len);
if (!data) return false; //allocation failed
strip.addUsedSegmentData(len);
_dataLen = len;
memset(data, 0, len);
return true;
}
void Segmentruntime::deallocateData() {
free(data);
data = nullptr;
strip.addUsedSegmentData(-(int16_t)_dataLen);
_dataLen = 0;
}
/**
* If reset of this segment was request, clears runtime
* settings of this segment.
* Must not be called while an effect mode function is running
* because it could access the data buffer and this method
* may free that data buffer.
*/
void Segmentruntime::resetIfRequired() {
if (_requiresReset) {
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
deallocateData();
_requiresReset = false;
}
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// WS2812FX class implementation // WS2812FX class implementation
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -540,10 +593,14 @@ void Segmentruntime::resetIfRequired() {
void WS2812FX::finalizeInit(void) void WS2812FX::finalizeInit(void)
{ {
//reset segment runtimes //reset segment runtimes
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { for (segment &seg : _segments) {
_segments[i].runtime.markForReset(); seg.markForReset();
_segments[i].runtime.resetIfRequired(); seg.resetIfRequired();
} }
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// _segments[i].markForReset();
// _segments[i].resetIfRequired();
// }
_hasWhiteChannel = _isOffRefreshRequired = false; _hasWhiteChannel = _isOffRefreshRequired = false;
@ -596,21 +653,18 @@ void WS2812FX::service() {
if (nowUp - _lastShow < MIN_SHOW_DELAY) return; if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
bool doShow = false; bool doShow = false;
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++) _segment_index = 0;
{ for (segment &seg : _segments) {
//if (realtimeMode && useMainSegmentOnly && i == getMainSegmentId()) continue; // for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
_segment_index = i;
Segment &seg = _segments[_segment_index];
// reset the segment runtime data if needed, called before isActive to ensure deleted // reset the segment runtime data if needed, called before isActive to ensure deleted
// segment's buffers are cleared // segment's buffers are cleared
seg.runtime.resetIfRequired(); seg.resetIfRequired();
if (!seg.isActive()) continue; if (!seg.isActive()) continue;
// last condition ensures all solid segments are updated at the same time // last condition ensures all solid segments are updated at the same time
if(nowUp > seg.runtime.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) if(nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
{ {
if (seg.grouping == 0) seg.grouping = 1; //sanity check if (seg.grouping == 0) seg.grouping = 1; //sanity check
doShow = true; doShow = true;
@ -618,12 +672,12 @@ void WS2812FX::service() {
if (!seg.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen if (!seg.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
_virtualSegmentLength = seg.virtualLength(); _virtualSegmentLength = seg.virtualLength();
_bri_t = seg.getOption(SEG_OPTION_ON) ? seg.opacity : 0; _bri_t = seg.currentBri(seg.getOption(SEG_OPTION_ON) ? seg.opacity : 0);
uint8_t _cct_t = seg.cct; uint8_t _cct_t = seg.currentBri(seg.cct, true);
_colors_t[0] = seg.colors[0]; _colors_t[0] = seg.currentColor(0, seg.colors[0]);
_colors_t[1] = seg.colors[1]; _colors_t[1] = seg.currentColor(1, seg.colors[1]);
_colors_t[2] = seg.colors[2]; _colors_t[2] = seg.currentColor(2, seg.colors[2]);
seg.transition.handleTransition(&seg, _bri_t, _cct_t, _colors_t); seg.handleTransition();
if (!cctFromRgb || correctWB) busses.setSegmentCCT(_cct_t, correctWB); if (!cctFromRgb || correctWB) busses.setSegmentCCT(_cct_t, correctWB);
for (uint8_t c = 0; c < NUM_COLORS; c++) { for (uint8_t c = 0; c < NUM_COLORS; c++) {
@ -632,11 +686,12 @@ void WS2812FX::service() {
handle_palette(); handle_palette();
delay = (*_mode[seg.mode])(); delay = (*_mode[seg.mode])();
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.runtime.call++; if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
} }
seg.runtime.next_time = nowUp + delay; seg.next_time = nowUp + delay;
} }
_segment_index++;
} }
_virtualSegmentLength = 0; _virtualSegmentLength = 0;
busses.setSegmentCCT(-1); busses.setSegmentCCT(-1);
@ -838,13 +893,14 @@ void WS2812FX::setTargetFps(uint8_t fps) {
} }
void WS2812FX::setMode(uint8_t segid, uint8_t m) { void WS2812FX::setMode(uint8_t segid, uint8_t m) {
if (segid >= MAX_NUM_SEGMENTS) return; if (segid >= _segments.size()) return;
// if (segid >= getMaxSegments()) return;
if (m >= getModeCount()) m = getModeCount() - 1; if (m >= getModeCount()) m = getModeCount() - 1;
if (_segments[segid].mode != m) if (_segments[segid].mode != m) {
{ //_segments[segid].startTransition(strip.getTransition()); // set effect transitions
_segments[segid].runtime.markForReset(); _segments[segid].markForReset();
_segments[segid].mode = m; _segments[segid].mode = m;
} }
} }
@ -853,19 +909,21 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) {
void WS2812FX::setColor(uint8_t slot, uint32_t c) { void WS2812FX::setColor(uint8_t slot, uint32_t c) {
if (slot >= NUM_COLORS) return; if (slot >= NUM_COLORS) return;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) for (segment &seg : _segments) {
{ // for (int i = 0; i < getMaxSegments(); i++) {
if (_segments[i].isActive() && _segments[i].isSelected()) { // Segment &seg = getSegment(i);
_segments[i].setColor(slot, c); if (seg.isSelected()) {
seg.setColor(slot, c);
} }
} }
} }
void WS2812FX::setCCT(uint16_t k) { void WS2812FX::setCCT(uint16_t k) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) for (segment &seg : _segments) {
{ // for (int i = 0; i < getMaxSegments(); i++) {
if (_segments[i].isActive() && _segments[i].isSelected()) { // Segment &seg = getSegment(i);
_segments[i].setCCT(k); if (seg.isActive() && seg.isSelected()) {
seg.setCCT(k);
} }
} }
} }
@ -875,9 +933,10 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
if (_brightness == b) return; if (_brightness == b) return;
_brightness = b; _brightness = b;
if (_brightness == 0) { //unfreeze all segments on power off if (_brightness == 0) { //unfreeze all segments on power off
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) for (segment &seg : _segments) {
{ // for (int i = 0; i < getMaxSegments(); i++) {
_segments[i].setOption(SEG_OPTION_FREEZE, false); // Segment &seg = getSegment(i);
seg.setOption(SEG_OPTION_FREEZE, false);
} }
} }
if (direct) { if (direct) {
@ -885,51 +944,56 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
busses.setBrightness(b); busses.setBrightness(b);
} else { } else {
unsigned long t = millis(); unsigned long t = millis();
if (_segments[0].runtime.next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon if (_segments[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon
} }
} }
uint8_t WS2812FX::getFirstSelectedSegId(void) uint8_t WS2812FX::getFirstSelectedSegId(void)
{ {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) size_t i = 0;
{ for (segment &seg : _segments) {
if (_segments[i].isActive() && _segments[i].isSelected()) return i; // for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
if (seg.isSelected()) return i;
i++;
} }
// if none selected, use the main segment // if none selected, use the main segment
return getMainSegmentId(); return getMainSegmentId();
} }
void WS2812FX::setMainSegmentId(uint8_t n) { void WS2812FX::setMainSegmentId(uint8_t n) {
if (n >= MAX_NUM_SEGMENTS) return; // if (n >= getMaxSegments()) return;
//use supplied n if active, or first active // //use supplied n if active, or first active
if (_segments[n].isActive()) { // if (_segments[n].isActive()) {
_mainSegment = n; return; // _mainSegment = n; return;
} // }
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) // for (uint8_t i = 0; i < getMaxSegments(); i++) {
{ // if (_segments[i].isActive()) {
if (_segments[i].isActive()) { // _mainSegment = i; return;
_mainSegment = i; return; // }
} // }
}
_mainSegment = 0; _mainSegment = 0;
if (n < _segments.size()) {
_mainSegment = n;
}
return; return;
} }
uint8_t WS2812FX::getLastActiveSegmentId(void) { uint8_t WS2812FX::getLastActiveSegmentId(void) {
for (uint8_t i = MAX_NUM_SEGMENTS -1; i > 0; i--) { // for (uint8_t i = getMaxSegments() -1; i > 0; i--) {
if (_segments[i].isActive()) return i; // if (_segments[i].isActive()) return i;
} // }
return 0; // return 0;
return _segments.size()-1;
} }
uint8_t WS2812FX::getActiveSegmentsNum(void) { //uint8_t WS2812FX::getActiveSegmentsNum(void) {
uint8_t c = 0; // uint8_t c = 0;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) // for (uint8_t i = 0; i < getMaxSegments(); i++) {
{ // if (_segments[i].isActive()) c++;
if (_segments[i].isActive()) c++; // }
} // return c;
return c; //}
}
uint16_t WS2812FX::getLengthPhysical(void) { uint16_t WS2812FX::getLengthPhysical(void) {
uint16_t len = 0; uint16_t len = 0;
@ -972,8 +1036,21 @@ bool WS2812FX::hasCCTBus(void) {
return false; return false;
} }
void WS2812FX::purgeSegments(void) {
// remove inactive segments at the back
//while (_segments.back().stop == 0 && _segments.size() > 1) _segments.pop_back();
// remove all inactive segments (from the back)
int deleted = 0;
for (int i = _segments.size()-1; i > 0; i--) if (_segments[i].stop == 0) { DEBUG_PRINT(F(" Removing segment: ")); DEBUG_PRINTLN(i); deleted++; _segments.erase(_segments.begin() + i); }
if (deleted) {
_segments.shrink_to_fit();
if (_mainSegment >= _segments.size()) setMainSegmentId(0);
}
}
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) { void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) {
if (n >= MAX_NUM_SEGMENTS) return; if (n >= _segments.size()) return;
// if (n >= getMaxSegments()) return;
Segment& seg = _segments[n]; Segment& seg = _segments[n];
//return if neither bounds nor grouping have changed //return if neither bounds nor grouping have changed
@ -985,9 +1062,12 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
&& (!grouping || (seg.grouping == grouping && seg.spacing == spacing)) && (!grouping || (seg.grouping == grouping && seg.spacing == spacing))
&& (offset == UINT16_MAX || offset == seg.offset)) return; && (offset == UINT16_MAX || offset == seg.offset)) return;
if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off //if (seg.stop) setRange(seg.start, seg.stop -1, BLACK); //turn old segment range off
if (seg.stop) seg.fill(BLACK); //turn old segment range off
if (i2 <= i1) //disable segment if (i2 <= i1) //disable segment
{ {
// disabled segments should get removed using purgeSegments()
DEBUG_PRINTLN(F(" Segment marked inactive."));
seg.stop = 0; seg.stop = 0;
if (seg.name) { if (seg.name) {
delete[] seg.name; delete[] seg.name;
@ -995,6 +1075,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
} }
// if main segment is deleted, set first active as main segment // if main segment is deleted, set first active as main segment
if (n == _mainSegment) setMainSegmentId(0); if (n == _mainSegment) setMainSegmentId(0);
seg.markForReset();
return; return;
} }
if (isMatrix) { if (isMatrix) {
@ -1015,18 +1096,25 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
seg.spacing = spacing; seg.spacing = spacing;
} }
if (offset < UINT16_MAX) seg.offset = offset; if (offset < UINT16_MAX) seg.offset = offset;
_segments[n].runtime.markForReset(); seg.markForReset();
if (!boundsUnchanged) seg.refreshLightCapabilities(); if (!boundsUnchanged) seg.refreshLightCapabilities();
} }
void WS2812FX::restartRuntime() { void WS2812FX::restartRuntime() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { for (segment &seg : _segments) seg.markForReset();
_segments[i].runtime.markForReset(); // for (uint8_t i = 0; i < getMaxSegments(); i++) {
} // Segment &seg = getSegment(i);
// seg.markForReset();
// }
} }
void WS2812FX::resetSegments() { void WS2812FX::resetSegments() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) if (_segments[i].name) delete[] _segments[i].name; _segments.clear(); // destructs all Segment as part of clearing
segment seg = isMatrix ? Segment(0, matrixWidth, 0, matrixHeight) : Segment(0, _length);
_segments.push_back(seg);
_mainSegment = 0;
/*
for (uint8_t i = 0; i < getMaxSegments(); i++) if (_segments[i].name) delete[] _segments[i].name;
_mainSegment = 0; _mainSegment = 0;
memset(_segments, 0, sizeof(_segments)); memset(_segments, 0, sizeof(_segments));
//memset(_segmentruntimes, 0, sizeof(_segmentruntimes)); //memset(_segmentruntimes, 0, sizeof(_segmentruntimes));
@ -1034,9 +1122,11 @@ void WS2812FX::resetSegments() {
_segments[0].mode = DEFAULT_MODE; _segments[0].mode = DEFAULT_MODE;
_segments[0].colors[0] = DEFAULT_COLOR; _segments[0].colors[0] = DEFAULT_COLOR;
_segments[0].start = 0; _segments[0].start = 0;
_segments[0].startY = 0;
_segments[0].speed = DEFAULT_SPEED; _segments[0].speed = DEFAULT_SPEED;
_segments[0].intensity = DEFAULT_INTENSITY; _segments[0].intensity = DEFAULT_INTENSITY;
_segments[0].stop = _length; _segments[0].stop = isMatrix ? matrixWidth : _length;
_segments[0].stopY = isMatrix ? matrixHeight : 1;
_segments[0].grouping = 1; _segments[0].grouping = 1;
_segments[0].setOption(SEG_OPTION_SELECTED, 1); _segments[0].setOption(SEG_OPTION_SELECTED, 1);
_segments[0].setOption(SEG_OPTION_ON, 1); _segments[0].setOption(SEG_OPTION_ON, 1);
@ -1046,7 +1136,7 @@ void WS2812FX::resetSegments() {
_segments[0].custom2 = DEFAULT_C2; _segments[0].custom2 = DEFAULT_C2;
_segments[0].custom3 = DEFAULT_C3; _segments[0].custom3 = DEFAULT_C3;
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) for (uint16_t i = 1; i < getMaxSegments(); i++)
{ {
_segments[i].colors[0] = _segments[i].color_wheel(i*51); _segments[i].colors[0] = _segments[i].color_wheel(i*51);
_segments[i].grouping = 1; _segments[i].grouping = 1;
@ -1058,23 +1148,25 @@ void WS2812FX::resetSegments() {
_segments[i].custom1 = DEFAULT_C1; _segments[i].custom1 = DEFAULT_C1;
_segments[i].custom2 = DEFAULT_C2; _segments[i].custom2 = DEFAULT_C2;
_segments[i].custom3 = DEFAULT_C3; _segments[i].custom3 = DEFAULT_C3;
_segments[i].runtime.markForReset(); _segments[i].markForReset();
} }
_segments[0].runtime.markForReset(); _segments[0].markForReset();
*/
} }
void WS2812FX::makeAutoSegments(bool forceReset) { void WS2812FX::makeAutoSegments(bool forceReset) {
if (isMatrix) { if (isMatrix) {
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
// only create 1 2D segment // only create 1 2D segment
uint8_t mainSeg = getMainSegmentId(); if (forceReset || getActiveSegmentsNum() == 0) resetSegments(); // initialises 1 segment
if (forceReset) { else if (getActiveSegmentsNum() == 1) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { _segments[0].start = 0;
setSegment(i, 0, 0); _segments[0].stop = matrixWidth;
} _segments[0].startY = 0;
} _segments[0].stopY = matrixHeight;
if (getActiveSegmentsNum() < 2) { _segments[0].grouping = 1;
setSegment(mainSeg, 0, matrixWidth, 1, 0, 0, 0, matrixHeight); _segments[0].spacing = 0;
_mainSegment = 0;
} }
#endif #endif
} else if (autoSegments) { //make one segment per bus } else if (autoSegments) { //make one segment per bus
@ -1085,7 +1177,7 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
Bus* b = busses.getBus(i); Bus* b = busses.getBus(i);
segStarts[s] = b->getStart(); segStarts[s] = b->getStart();
segStops[s] = segStarts[s] + b->getLength(); segStops[s] = segStarts[s] + b->getLength();
//check for overlap with previous segments //check for overlap with previous segments
for (uint8_t j = 0; j < s; j++) { for (uint8_t j = 0; j < s; j++) {
@ -1098,22 +1190,24 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
} }
s++; s++;
} }
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { _segments.clear();
_segments[i].setOption(SEG_OPTION_SELECTED, true); for (uint8_t i = 0; i < s; i++) {
setSegment(i, segStarts[i], segStops[i]); Segment seg = Segment(segStarts[i], segStops[i]);
seg.setOption(SEG_OPTION_SELECTED, true);
_segments.push_back(seg);
} }
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// _segments[i].setOption(SEG_OPTION_SELECTED, true);
// setSegment(i, segStarts[i], segStops[i]);
// }
_mainSegment = 0;
} else { } else {
if (forceReset || getActiveSegmentsNum() == 0) resetSegments();
//expand the main seg to the entire length, but only if there are no other segments, or reset is forced //expand the main seg to the entire length, but only if there are no other segments, or reset is forced
uint8_t mainSeg = getMainSegmentId(); else if (getActiveSegmentsNum() == 1) {
_segments[0].start = 0;
if (forceReset) { _segments[0].stop = _length;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { _mainSegment = 0;
setSegment(i, 0, 0);
}
}
if (getActiveSegmentsNum() < 2) {
setSegment(mainSeg, 0, _length);
} }
} }
@ -1122,26 +1216,32 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
void WS2812FX::fixInvalidSegments() { void WS2812FX::fixInvalidSegments() {
//make sure no segment is longer than total (sanity check) //make sure no segment is longer than total (sanity check)
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) size_t i = 0;
{ for (std::vector<Segment>::iterator it = _segments.begin(); it != _segments.end(); i++, it++) {
if (_segments[i].start >= _length) setSegment(i, 0, 0); if (_segments[i].start >= _length) { _segments.erase(it); i--; it--; continue; }
if (_segments[i].stop > _length) setSegment(i, _segments[i].start, _length); if (_segments[i].stop > _length) _segments[i].stop = _length;
// this is always called as the last step after finalizeInit(), update covered bus types // this is always called as the last step after finalizeInit(), update covered bus types
getSegment(i).refreshLightCapabilities(); _segments[i].refreshLightCapabilities();
} }
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// if (_segments[i].start >= _length) { _segments[i].start = _segments[i].stop = 0; _segments[i].markForReset(); }
// if (_segments[i].stop > _length) { _segments[i].stop = _length; _segments[i].markForReset(); }
// // this is always called as the last step after finalizeInit(), update covered bus types
// if (_segments[i].isActive()) _segments[i].refreshLightCapabilities();
// }
} }
//true if all segments align with a bus, or if a segment covers the total length //true if all segments align with a bus, or if a segment covers the total length
bool WS2812FX::checkSegmentAlignment() { bool WS2812FX::checkSegmentAlignment() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) bool aligned = false;
{ for (segment &seg : _segments) {
if (_segments[i].start >= _segments[i].stop) continue; //inactive segment // for (uint8_t i = 0; i < getMaxSegments(); i++) {
bool aligned = false; // Segment &seg = getSegment(i);
for (uint8_t b = 0; b<busses.getNumBusses(); b++) { for (uint8_t b = 0; b<busses.getNumBusses(); b++) {
Bus *bus = busses.getBus(b); Bus *bus = busses.getBus(b);
if (_segments[i].start == bus->getStart() && _segments[i].stop == bus->getStart() + bus->getLength()) aligned = true; if (seg.start == bus->getStart() && seg.stop == bus->getStart() + bus->getLength()) aligned = true;
} }
if (_segments[i].start == 0 && _segments[i].stop == _length) aligned = true; if (seg.start == 0 && seg.stop == _length) aligned = true;
if (!aligned) return false; if (!aligned) return false;
} }
return true; return true;
@ -1153,7 +1253,8 @@ bool WS2812FX::checkSegmentAlignment() {
uint8_t WS2812FX::setPixelSegment(uint8_t n) uint8_t WS2812FX::setPixelSegment(uint8_t n)
{ {
uint8_t prevSegId = _segment_index; uint8_t prevSegId = _segment_index;
if (n < MAX_NUM_SEGMENTS) { if (n < _segments.size()) {
// if (n < getMaxSegments()) {
_segment_index = n; _segment_index = n;
_virtualSegmentLength = _segments[_segment_index].virtualLength(); _virtualSegmentLength = _segments[_segment_index].virtualLength();
} }
@ -1173,20 +1274,11 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
void WS2812FX::setTransitionMode(bool t) void WS2812FX::setTransitionMode(bool t)
{ {
unsigned long waitMax = millis() + 22; //refresh after 20 ms if transition enabled for (segment &seg : _segments) seg.startTransition(t ? getTransition() : 0);
for (uint16_t i = 0; i < MAX_NUM_SEGMENTS; i++) // for (uint8_t i = 0; i < getMaxSegments(); i++) {
{ // Segment &seg = getSegment(i);
if (_segments[i].isActive() && !_segments[i].getOption(SEG_OPTION_TRANSITIONAL)) { // seg.startTransition(t ? getTransition() : 0);
if (t) { // }
_segments[i].transition.transitionStart = millis();
_segments[i].transition.transitionDur = strip.getTransition();
}
_segments[i].setOption(SEG_OPTION_TRANSITIONAL, t);
if (t && _segments[i].mode == FX_MODE_STATIC && _segments[i].runtime.next_time > waitMax) {
_segments[i].runtime.next_time = waitMax;
}
}
}
} }
void WS2812FX::load_gradient_palette(uint8_t index) void WS2812FX::load_gradient_palette(uint8_t index)
@ -1313,7 +1405,7 @@ void WS2812FX::handle_palette(void)
load_gradient_palette(paletteIndex -13); load_gradient_palette(paletteIndex -13);
} }
if (singleSegmentMode && paletteFade && _segments[_segment_index].runtime.call > 0) //only blend if just one segment uses FastLED mode if (singleSegmentMode && paletteFade && _segments[_segment_index].call > 0) //only blend if just one segment uses FastLED mode
{ {
nblendPaletteTowardPalette(currentPalette, targetPalette, 48); nblendPaletteTowardPalette(currentPalette, targetPalette, 48);
} else } else
@ -1428,180 +1520,7 @@ int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0; uint8_t Bus::_cctBlend = 0;
uint8_t Bus::_gAWM = 255; uint8_t Bus::_gAWM = 255;
// WLEDSR: extensions
// Technical notes
// ===============
// If an effect name is followed by an @, slider and color control is effective.
// See setSliderAndColorControl in index.js for implementation
// If not effective then:
// - For AC effects (id<128) 2 sliders and 3 colors and the palette will be shown
// - For SR effects (id>128) 5 sliders and 3 colors and the palette will be shown
// If effective (@)
// - a ; seperates slider controls (left) from color controls (middle) and palette control (right)
// - if left, middle or right is empty no controls are shown
// - a , seperates slider controls (max 5) or color controls (max 3). Palette has only one value
// - a ! means that the default is used.
// - For sliders: Effect speeds, Effect intensity, Custom 1, Custom 2, Custom 3
// - For colors: Fx color, Background color, Custom
// - For palette: prompt for color palette OR palette ID if numeric (will hide palette selection)
//
// Note: If palette is on and no colors are specified 1,2 and 3 is shown in each color circle.
// If a color is specified, the 1,2 or 3 is replaced by that specification.
// Note: Effects can override default pattern behaviour
// - FadeToBlack can override the background setting
// - Defining SEGCOL(<i>) can override a specific palette using these values (e.g. Color Gradient)
const char JSON_mode_names[] PROGMEM = R"=====(["Mode names have moved"])====="; const char JSON_mode_names[] PROGMEM = R"=====(["Mode names have moved"])=====";
/*
R"=====([
"Solid",
"Blink@!,;!,!,;!",
"Breathe@!,;!,!;!",
"Wipe@!,!;!,!,;!",
"Wipe Random@!,;1,2,3;!",
"Random Colors@!,Fade time;1,2,3;!",
"Sweep@!,!;!,!,;!",
"Dynamic@!,!;1,2,3;!",
"Colorloop@!,Saturation;1,2,3;!",
"Rainbow@!,Size;1,2,3;!",
"Scan@!,# of dots;!,!,;!",
"Scan Dual@!,# of dots;!,!,;!",
"Fade@!,;!,!,;!",
"Theater@!,Gap size;!,!,;!",
"Theater Rainbow@!,Gap size;1,2,3;!",
"Running@!,Wave width;!,!,;!",
"Saw@!,Width;!,!,;!",
"Twinkle@!,;!,!,;!",
"Dissolve@Repeat speed,Dissolve speed;!,!,;!",
"Dissolve Rnd@Repeat speed,Dissolve speed;,!,;!",
"Sparkle@!,;!,!,;!",
"Sparkle Dark@!,!;Bg,Fx,;!",
"Sparkle+@!,!;Bg,Fx,;!",
"Strobe@!,;!,!,;!",
"Strobe Rainbow@!,;,!,;!",
"Strobe Mega@!,!;!,!,;!",
"Blink Rainbow@Frequency,Blink duration;!,!,;!",
"Android@!,Width;!,!,;!",
"Chase@!,Width;!,!,!;!",
"Chase Random@!,Width;!,,!;!",
"Chase Rainbow@!,Width;!,!,;0",
"Chase Flash@!,;Bg,Fx,!;!",
"Chase Flash Rnd@!,;,Fx,;!",
"Rainbow Runner@!,Size;Bg,,;!",
"Colorful@!,Saturation;1,2,3;!",
"Traffic Light@!,;,!,;!",
"Sweep Random",
"Chase 2@!,Width;!,!,;!",
"Aurora@!=24,!;1,2,3;!=50",
"Stream",
"Scanner",
"Lighthouse",
"Fireworks@Sharpness=96,Frequency=192;!,2,;!=11",
"Rain@Fade rate=128,Frequency=128;!,2,;!",
"Tetrix@!=224,Width=0;!,!,;!=11",
"Fire Flicker@!,!;!,,;!",
"Gradient@!,Spread=16;!,!,;!",
"Loading@!,Fade=16;!,!,;!",
"Police@!,Width;,Bg,;0",
"Fairy",
"Two Dots@!,Dot size;1,2,Bg;!",
"Fairy Twinkle",
"Running Dual",
"Halloween",
"Chase 3@!,Size;1,2,3;0",
"Tri Wipe@!,Width;1,2,3;0",
"Tri Fade",
"Lightning",
"ICU",
"Multi Comet",
"Scanner Dual",
"Stream 2",
"Oscillate",
"Pride 2015@!,;;",
"Juggle@!=16,Trail=240;!,!,;!",
"Palette@!,;1,2,3;!",
"Fire 2012@Spark rate=120,Decay=64;1,2,3;!",
"Colorwaves",
"Bpm@!=64,;1,2,3;!",
"Fill Noise",
"Noise 1",
"Noise 2",
"Noise 3",
"Noise 4",
"Colortwinkles@Fade speed,Spawn speed;1,2,3;!",
"Lake@!,;1,2,3;!",
"Meteor@!,Trail length;!,!,;!",
"Meteor Smooth@!,Trail length;!,!,;!",
"Railway",
"Ripple",
"Twinklefox",
"Twinklecat",
"Halloween Eyes@Duration,Eye fade time;Fx,Bg,;!",
"Solid Pattern@Fg size,Bg size;Fg,Bg,;!=0",
"Solid Pattern Tri@,Size;1,2,3;!=0",
"Spots@Spread,Width;!,!,;!",
"Spots Fade@Spread,Width;!,!,;!",
"Glitter",
"Candle@Flicker rate=96,Flicker intensity=224;!,!,;0",
"Fireworks Starburst",
"Fireworks 1D@Gravity,Firing side;!,!,;!",
"Bouncing Balls@Gravity,# of balls;!,!,;!",
"Sinelon",
"Sinelon Dual",
"Sinelon Rainbow",
"Popcorn",
"Drip@Gravity,# of drips;!,!;!",
"Plasma@Phase,;1,2,3;!",
"Percent@,% of fill;!,!,;!",
"Ripple Rainbow",
"Heartbeat@!,!;!,!,;!",
"Pacifica",
"Candle Multi@Flicker rate=96,Flicker intensity=224;!,!,;0",
"Solid Glitter@,!;!,,;0",
"Sunrise@Time [min]=60,;;0",
"Phased",
"Twinkleup@!,Intensity;!,!,;!",
"Noise Pal",
"Sine",
"Phased Noise",
"Flow",
"Chunchun@!,Gap size;!,!,;!",
"Dancing Shadows@!,# of shadows;!,,;!",
"Washing Machine",
"Candy Cane@!,Width;;",
"Blends@Shift speed,Blend speed;1,2,3,!",
"TV Simulator",
"Dynamic Smooth",
"2D Black Hole@Fade rate,Outer Y freq.,Outer X freq.,Inner X freq.,Inner Y freq.;;",
"2D DNA@Scroll speed,Blur;;!",
"2D DNA Spiral@Scroll speed,Blur;;!",
"2D Drift@Rotation speed,Blur amount;;!",
"2D Firenoise@X scale,Y scale;;",
"2D Frizzles@X frequency,Y frequency;;!",
"2D Hipnotic@X scale,Y scale;;!",
"2D Lissajous@X frequency,Fadetime;!,!,!;!",
"2D Matrix@Falling speed,Spawning rate,Trail,Custom color;Spawn,Trail;",
"2D Akemi@Color speed,Dance;Head palette,Arms & Legs,Eyes & Mouth;Face palette",
"2D Colored Bursts@Speed,Number of lines;;!",
"2D Game Of Life@!,;!,!;!",
"2D Julia@,Max iterations per pixel,X center,Y center,Area size;;!",
"2D Metaballs@Speed;!,!,!;!",
"2D Noise@Speed,Scale;!,!,!;!",
"2D Plasma Ball@Speed;!,!,!;!",
"2D Polar Lights@Speed,X scale,Palette;!,!,!;!",
"2D Pulser@Speed,Blur;;!",
"2D Sindots@Speed,Dot distance;;!",
"2D Squared Swirl@,,,,Blur;,,;!",
"2D Sun Radiation@Variance,Brightness;;",
"2D Tartan@X scale,Y scale;;!",
"2D Waverly@Fade rate,Sensitivity;;!",
"2D Spaceships@Fade rate,Blur;!,!,!;!",
"2D Crazy Bees@Fade rate,Blur;;",
"2D Ghost Rider@Fade rate,Blur;!,!,!;!",
"2D Blobs@!,# blobs;!,!,!;!"
])=====";
*/
const char JSON_palette_names[] PROGMEM = R"=====([ const char JSON_palette_names[] PROGMEM = R"=====([
"Default","* Random Cycle","* Color 1","* Colors 1&2","* Color Gradient","* Colors Only","Party","Cloud","Lava","Ocean", "Default","* Random Cycle","* Color 1","* Colors 1&2","* Color Gradient","* Colors Only","Party","Cloud","Lava","Ocean",
"Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash", "Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash",

View File

@ -1,405 +1,406 @@
#ifndef WLED_CONST_H #ifndef WLED_CONST_H
#define WLED_CONST_H #define WLED_CONST_H
/* /*
* Readability defines and their associated numerical values + compile-time constants * Readability defines and their associated numerical values + compile-time constants
*/ */
#define GRADIENT_PALETTE_COUNT 58 #define GRADIENT_PALETTE_COUNT 58
//Defaults //Defaults
#define DEFAULT_CLIENT_SSID "Your_Network" #define DEFAULT_CLIENT_SSID "Your_Network"
#define DEFAULT_AP_PASS "wled1234" #define DEFAULT_AP_PASS "wled1234"
#define DEFAULT_OTA_PASS "wledota" #define DEFAULT_OTA_PASS "wledota"
//increase if you need more //increase if you need more
#ifndef WLED_MAX_USERMODS #ifndef WLED_MAX_USERMODS
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_USERMODS 4 #define WLED_MAX_USERMODS 4
#else #else
#define WLED_MAX_USERMODS 6 #define WLED_MAX_USERMODS 6
#endif #endif
#endif #endif
#ifndef WLED_MAX_BUSSES #ifndef WLED_MAX_BUSSES
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_BUSSES 3 #define WLED_MAX_BUSSES 3
#else #else
#ifdef CONFIG_IDF_TARGET_ESP32S2 #ifdef CONFIG_IDF_TARGET_ESP32S2
#define WLED_MAX_BUSSES 5 #define WLED_MAX_BUSSES 5
#else #else
#define WLED_MAX_BUSSES 10 #define WLED_MAX_BUSSES 10
#endif #endif
#endif #endif
#endif #endif
#ifndef WLED_MAX_BUTTONS #ifndef WLED_MAX_BUTTONS
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_BUTTONS 2 #define WLED_MAX_BUTTONS 2
#else #else
#define WLED_MAX_BUTTONS 4 #define WLED_MAX_BUTTONS 4
#endif #endif
#endif #endif
#ifdef ESP8266 #ifdef ESP8266
#define WLED_MAX_COLOR_ORDER_MAPPINGS 5 #define WLED_MAX_COLOR_ORDER_MAPPINGS 5
#else #else
#define WLED_MAX_COLOR_ORDER_MAPPINGS 10 #define WLED_MAX_COLOR_ORDER_MAPPINGS 10
#endif #endif
//Usermod IDs //Usermod IDs
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present #define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID #define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
#define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h" #define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h"
#define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h" #define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h"
#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h" #define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h"
#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h" #define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h"
#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h" #define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h"
#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h #define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h
#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h" #define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h"
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h" #define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h" #define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
#define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h" #define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h"
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h" #define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h" #define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h"
#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h" #define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h"
#define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h" #define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h"
#define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h" #define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h"
#define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h" #define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h"
#define USERMOD_ID_BATTERY_STATUS_BASIC 18 //Usermod "usermod_v2_battery_status_basic.h" #define USERMOD_ID_BATTERY_STATUS_BASIC 18 //Usermod "usermod_v2_battery_status_basic.h"
#define USERMOD_ID_PWM_FAN 19 //Usermod "usermod_PWM_fan.h" #define USERMOD_ID_PWM_FAN 19 //Usermod "usermod_PWM_fan.h"
#define USERMOD_ID_BH1750 20 //Usermod "usermod_bh1750.h" #define USERMOD_ID_BH1750 20 //Usermod "usermod_bh1750.h"
#define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 //Usermod "usermod_v2_seven_segment_display.h" #define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 //Usermod "usermod_v2_seven_segment_display.h"
#define USERMOD_RGB_ROTARY_ENCODER 22 //Usermod "rgb-rotary-encoder.h" #define USERMOD_RGB_ROTARY_ENCODER 22 //Usermod "rgb-rotary-encoder.h"
#define USERMOD_ID_QUINLED_AN_PENTA 23 //Usermod "quinled-an-penta.h" #define USERMOD_ID_QUINLED_AN_PENTA 23 //Usermod "quinled-an-penta.h"
#define USERMOD_ID_SSDR 24 //Usermod "usermod_v2_seven_segment_display_reloaded.h" #define USERMOD_ID_SSDR 24 //Usermod "usermod_v2_seven_segment_display_reloaded.h"
#define USERMOD_ID_CRONIXIE 25 //Usermod "usermod_cronixie.h" #define USERMOD_ID_CRONIXIE 25 //Usermod "usermod_cronixie.h"
#define USERMOD_ID_WIZLIGHTS 26 //Usermod "wizlights.h" #define USERMOD_ID_WIZLIGHTS 26 //Usermod "wizlights.h"
#define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h" #define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h"
#define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h" #define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h"
#define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h" #define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h"
#define USERMOD_ID_AUDIOREACTIVE 30 //Usermod "audioreactive.h" #define USERMOD_ID_AUDIOREACTIVE 30 //Usermod "audioreactive.h"
//Access point behavior //Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost) #define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
#define AP_BEHAVIOR_ALWAYS 2 //Always open #define AP_BEHAVIOR_ALWAYS 2 //Always open
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec #define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
//Notifier callMode //Notifier callMode
#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates #define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
#define CALL_MODE_DIRECT_CHANGE 1 #define CALL_MODE_DIRECT_CHANGE 1
#define CALL_MODE_BUTTON 2 //default button actions applied to selected segments #define CALL_MODE_BUTTON 2 //default button actions applied to selected segments
#define CALL_MODE_NOTIFICATION 3 #define CALL_MODE_NOTIFICATION 3
#define CALL_MODE_NIGHTLIGHT 4 #define CALL_MODE_NIGHTLIGHT 4
#define CALL_MODE_NO_NOTIFY 5 #define CALL_MODE_NO_NOTIFY 5
#define CALL_MODE_FX_CHANGED 6 //no longer used #define CALL_MODE_FX_CHANGED 6 //no longer used
#define CALL_MODE_HUE 7 #define CALL_MODE_HUE 7
#define CALL_MODE_PRESET_CYCLE 8 #define CALL_MODE_PRESET_CYCLE 8
#define CALL_MODE_BLYNK 9 #define CALL_MODE_BLYNK 9
#define CALL_MODE_ALEXA 10 #define CALL_MODE_ALEXA 10
#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only #define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
#define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro #define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro
//RGB to RGBW conversion mode //RGB to RGBW conversion mode
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider #define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel #define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel #define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0) #define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support #define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
//realtime modes //realtime modes
#define REALTIME_MODE_INACTIVE 0 #define REALTIME_MODE_INACTIVE 0
#define REALTIME_MODE_GENERIC 1 #define REALTIME_MODE_GENERIC 1
#define REALTIME_MODE_UDP 2 #define REALTIME_MODE_UDP 2
#define REALTIME_MODE_HYPERION 3 #define REALTIME_MODE_HYPERION 3
#define REALTIME_MODE_E131 4 #define REALTIME_MODE_E131 4
#define REALTIME_MODE_ADALIGHT 5 #define REALTIME_MODE_ADALIGHT 5
#define REALTIME_MODE_ARTNET 6 #define REALTIME_MODE_ARTNET 6
#define REALTIME_MODE_TPM2NET 7 #define REALTIME_MODE_TPM2NET 7
#define REALTIME_MODE_DDP 8 #define REALTIME_MODE_DDP 8
//realtime override modes //realtime override modes
#define REALTIME_OVERRIDE_NONE 0 #define REALTIME_OVERRIDE_NONE 0
#define REALTIME_OVERRIDE_ONCE 1 #define REALTIME_OVERRIDE_ONCE 1
#define REALTIME_OVERRIDE_ALWAYS 2 #define REALTIME_OVERRIDE_ALWAYS 2
//E1.31 DMX modes //E1.31 DMX modes
#define DMX_MODE_DISABLED 0 //not used #define DMX_MODE_DISABLED 0 //not used
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels) #define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels) #define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels) #define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels) #define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels) #define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
#define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels) #define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels)
//Light capability byte (unused) 0bRCCCTTTT //Light capability byte (unused) 0bRCCCTTTT
//bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior //bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior
//bits 4/5/6: specifies the class of LED driver - 0b000 (dec. 0-15) unconfigured/reserved //bits 4/5/6: specifies the class of LED driver - 0b000 (dec. 0-15) unconfigured/reserved
// - 0b001 (dec. 16-31) digital (data pin only) // - 0b001 (dec. 16-31) digital (data pin only)
// - 0b010 (dec. 32-47) analog (PWM) // - 0b010 (dec. 32-47) analog (PWM)
// - 0b011 (dec. 48-63) digital (data + clock / SPI) // - 0b011 (dec. 48-63) digital (data + clock / SPI)
// - 0b100 (dec. 64-79) unused/reserved // - 0b100 (dec. 64-79) unused/reserved
// - 0b101 (dec. 80-95) virtual network busses // - 0b101 (dec. 80-95) virtual network busses
// - 0b110 (dec. 96-111) unused/reserved // - 0b110 (dec. 96-111) unused/reserved
// - 0b111 (dec. 112-127) unused/reserved // - 0b111 (dec. 112-127) unused/reserved
//bit 7 is reserved and set to 0 //bit 7 is reserved and set to 0
#define TYPE_NONE 0 //light is not configured #define TYPE_NONE 0 //light is not configured
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light #define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
//Digital types (data pin only) (16-31) //Digital types (data pin only) (16-31)
#define TYPE_WS2812_1CH 20 //white-only chips #define TYPE_WS2812_1CH 20 //white-only chips
#define TYPE_WS2812_WWA 21 //amber + warm + cold white #define TYPE_WS2812_WWA 21 //amber + warm + cold white
#define TYPE_WS2812_RGB 22 #define TYPE_WS2812_RGB 22
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern) #define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units #define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units
#define TYPE_SK6812_RGBW 30 #define TYPE_SK6812_RGBW 30
#define TYPE_TM1814 31 #define TYPE_TM1814 31
//"Analog" types (PWM) (32-47) //"Analog" types (PWM) (32-47)
#define TYPE_ONOFF 40 //binary output (relays etc.) #define TYPE_ONOFF 40 //binary output (relays etc.)
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel #define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
#define TYPE_ANALOG_2CH 42 //analog WW + CW #define TYPE_ANALOG_2CH 42 //analog WW + CW
#define TYPE_ANALOG_3CH 43 //analog RGB #define TYPE_ANALOG_3CH 43 //analog RGB
#define TYPE_ANALOG_4CH 44 //analog RGBW #define TYPE_ANALOG_4CH 44 //analog RGBW
#define TYPE_ANALOG_5CH 45 //analog RGB + WW + CW #define TYPE_ANALOG_5CH 45 //analog RGB + WW + CW
//Digital types (data + clock / SPI) (48-63) //Digital types (data + clock / SPI) (48-63)
#define TYPE_WS2801 50 #define TYPE_WS2801 50
#define TYPE_APA102 51 #define TYPE_APA102 51
#define TYPE_LPD8806 52 #define TYPE_LPD8806 52
#define TYPE_P9813 53 #define TYPE_P9813 53
//Network types (master broadcast) (80-95) //Network types (master broadcast) (80-95)
#define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus) #define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus)
#define TYPE_NET_E131_RGB 81 //network E131 RGB bus (master broadcast bus) #define TYPE_NET_E131_RGB 81 //network E131 RGB bus (master broadcast bus)
#define TYPE_NET_ARTNET_RGB 82 //network ArtNet RGB bus (master broadcast bus) #define TYPE_NET_ARTNET_RGB 82 //network ArtNet RGB bus (master broadcast bus)
#define IS_DIGITAL(t) ((t) & 0x10) //digital are 16-31 and 48-63 #define IS_DIGITAL(t) ((t) & 0x10) //digital are 16-31 and 48-63
#define IS_PWM(t) ((t) > 40 && (t) < 46) #define IS_PWM(t) ((t) > 40 && (t) < 46)
#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only #define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only
#define IS_2PIN(t) ((t) > 47) #define IS_2PIN(t) ((t) > 47)
//Color orders //Color orders
#define COL_ORDER_GRB 0 //GRB(w),defaut #define COL_ORDER_GRB 0 //GRB(w),defaut
#define COL_ORDER_RGB 1 //common for WS2811 #define COL_ORDER_RGB 1 //common for WS2811
#define COL_ORDER_BRG 2 #define COL_ORDER_BRG 2
#define COL_ORDER_RBG 3 #define COL_ORDER_RBG 3
#define COL_ORDER_BGR 4 #define COL_ORDER_BGR 4
#define COL_ORDER_GBR 5 #define COL_ORDER_GBR 5
#define COL_ORDER_MAX 5 #define COL_ORDER_MAX 5
//Button type //Button type
#define BTN_TYPE_NONE 0 #define BTN_TYPE_NONE 0
#define BTN_TYPE_RESERVED 1 #define BTN_TYPE_RESERVED 1
#define BTN_TYPE_PUSH 2 #define BTN_TYPE_PUSH 2
#define BTN_TYPE_PUSH_ACT_HIGH 3 #define BTN_TYPE_PUSH_ACT_HIGH 3
#define BTN_TYPE_SWITCH 4 #define BTN_TYPE_SWITCH 4
#define BTN_TYPE_PIR_SENSOR 5 #define BTN_TYPE_PIR_SENSOR 5
#define BTN_TYPE_TOUCH 6 #define BTN_TYPE_TOUCH 6
#define BTN_TYPE_ANALOG 7 #define BTN_TYPE_ANALOG 7
#define BTN_TYPE_ANALOG_INVERTED 8 #define BTN_TYPE_ANALOG_INVERTED 8
//Ethernet board types //Ethernet board types
#define WLED_NUM_ETH_TYPES 8 #define WLED_NUM_ETH_TYPES 8
#define WLED_ETH_NONE 0 #define WLED_ETH_NONE 0
#define WLED_ETH_WT32_ETH01 1 #define WLED_ETH_WT32_ETH01 1
#define WLED_ETH_ESP32_POE 2 #define WLED_ETH_ESP32_POE 2
#define WLED_ETH_WESP32 3 #define WLED_ETH_WESP32 3
#define WLED_ETH_QUINLED 4 #define WLED_ETH_QUINLED 4
#define WLED_ETH_TWILIGHTLORD 5 #define WLED_ETH_TWILIGHTLORD 5
#define WLED_ETH_ESP32DEUX 6 #define WLED_ETH_ESP32DEUX 6
//Hue error codes //Hue error codes
#define HUE_ERROR_INACTIVE 0 #define HUE_ERROR_INACTIVE 0
#define HUE_ERROR_UNAUTHORIZED 1 #define HUE_ERROR_UNAUTHORIZED 1
#define HUE_ERROR_LIGHTID 3 #define HUE_ERROR_LIGHTID 3
#define HUE_ERROR_PUSHLINK 101 #define HUE_ERROR_PUSHLINK 101
#define HUE_ERROR_JSON_PARSING 250 #define HUE_ERROR_JSON_PARSING 250
#define HUE_ERROR_TIMEOUT 251 #define HUE_ERROR_TIMEOUT 251
#define HUE_ERROR_ACTIVE 255 #define HUE_ERROR_ACTIVE 255
//Segment option byte bits //Segment option byte bits
#define SEG_OPTION_SELECTED 0 #define SEG_OPTION_SELECTED 0
#define SEG_OPTION_REVERSED 1 #define SEG_OPTION_REVERSED 1
#define SEG_OPTION_ON 2 #define SEG_OPTION_ON 2
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment #define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor #define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed #define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
#define SEG_OPTION_TRANSITIONAL 7 #define SEG_OPTION_RESET 6 //Segment runtime requires reset
#define SEG_OPTION_REVERSED_Y 8 #define SEG_OPTION_TRANSITIONAL 7
#define SEG_OPTION_MIRROR_Y 9 #define SEG_OPTION_REVERSED_Y 8
#define SEG_OPTION_TRANSPOSED 10 #define SEG_OPTION_MIRROR_Y 9
#define SEG_OPTION_TRANSPOSED 10
//Segment differs return byte
#define SEG_DIFFERS_BRI 0x01 //Segment differs return byte
#define SEG_DIFFERS_OPT 0x02 #define SEG_DIFFERS_BRI 0x01
#define SEG_DIFFERS_COL 0x04 #define SEG_DIFFERS_OPT 0x02
#define SEG_DIFFERS_FX 0x08 #define SEG_DIFFERS_COL 0x04
#define SEG_DIFFERS_BOUNDS 0x10 #define SEG_DIFFERS_FX 0x08
#define SEG_DIFFERS_GSO 0x20 #define SEG_DIFFERS_BOUNDS 0x10
#define SEG_DIFFERS_SEL 0x80 #define SEG_DIFFERS_GSO 0x20
#define SEG_DIFFERS_SEL 0x80
//Playlist option byte
#define PL_OPTION_SHUFFLE 0x01 //Playlist option byte
#define PL_OPTION_SHUFFLE 0x01
// WLED Error modes
#define ERR_NONE 0 // All good :) // WLED Error modes
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?) #define ERR_NONE 0 // All good :)
#define ERR_JSON 9 // JSON parsing failed (input too large?) #define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) #define ERR_JSON 9 // JSON parsing failed (input too large?)
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached #define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist #define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist #define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured #define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented) #define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented) #define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented) #define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
//Timer mode types
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness //Timer mode types
#define NL_MODE_FADE 1 //Fade to target brightness gradually #define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
#define NL_MODE_COLORFADE 2 //Fade to target brightness and secondary color gradually #define NL_MODE_FADE 1 //Fade to target brightness gradually
#define NL_MODE_SUN 3 //Sunrise/sunset. Target brightness is set immediately, then Sunrise effect is started. Max 60 min. #define NL_MODE_COLORFADE 2 //Fade to target brightness and secondary color gradually
#define NL_MODE_SUN 3 //Sunrise/sunset. Target brightness is set immediately, then Sunrise effect is started. Max 60 min.
#define NTP_PACKET_SIZE 48
#define NTP_PACKET_SIZE 48
//maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses
#ifndef MAX_LEDS //maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses
#ifdef ESP8266 #ifndef MAX_LEDS
#define MAX_LEDS 1664 //can't rely on memory limit to limit this to 1600 LEDs #ifdef ESP8266
#else #define MAX_LEDS 1664 //can't rely on memory limit to limit this to 1600 LEDs
#define MAX_LEDS 8192 #else
#endif #define MAX_LEDS 8192
#endif #endif
#endif
#ifndef MAX_LED_MEMORY
#ifdef ESP8266 #ifndef MAX_LED_MEMORY
#define MAX_LED_MEMORY 4000 #ifdef ESP8266
#else #define MAX_LED_MEMORY 4000
#define MAX_LED_MEMORY 64000 #else
#endif #define MAX_LED_MEMORY 64000
#endif #endif
#endif
#ifndef MAX_LEDS_PER_BUS
#define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102) #ifndef MAX_LEDS_PER_BUS
#endif #define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102)
#endif
// string temp buffer (now stored in stack locally)
#ifdef ESP8266 // string temp buffer (now stored in stack locally)
#define SETTINGS_STACK_BUF_SIZE 2048 #ifdef ESP8266
#else #define SETTINGS_STACK_BUF_SIZE 2048
#define SETTINGS_STACK_BUF_SIZE 3096 #else
#endif #define SETTINGS_STACK_BUF_SIZE 3096
#endif
#ifdef WLED_USE_ETHERNET
#define E131_MAX_UNIVERSE_COUNT 20 #ifdef WLED_USE_ETHERNET
#else #define E131_MAX_UNIVERSE_COUNT 20
#ifdef ESP8266 #else
#define E131_MAX_UNIVERSE_COUNT 9 #ifdef ESP8266
#else #define E131_MAX_UNIVERSE_COUNT 9
#define E131_MAX_UNIVERSE_COUNT 12 #else
#endif #define E131_MAX_UNIVERSE_COUNT 12
#endif #endif
#endif
#ifndef ABL_MILLIAMPS_DEFAULT
#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit #ifndef ABL_MILLIAMPS_DEFAULT
#else #define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit
#if ABL_MILLIAMPS_DEFAULT < 250 // make sure value is at least 250 #else
#define ABL_MILLIAMPS_DEFAULT 250 #if ABL_MILLIAMPS_DEFAULT < 250 // make sure value is at least 250
#endif #define ABL_MILLIAMPS_DEFAULT 250
#endif #endif
#endif
// PWM settings
#ifndef WLED_PWM_FREQ // PWM settings
#ifdef ESP8266 #ifndef WLED_PWM_FREQ
#define WLED_PWM_FREQ 880 //PWM frequency proven as good for LEDs #ifdef ESP8266
#else #define WLED_PWM_FREQ 880 //PWM frequency proven as good for LEDs
#define WLED_PWM_FREQ 19531 #else
#endif #define WLED_PWM_FREQ 19531
#endif #endif
#endif
#define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive
#define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive
// Size of buffer for API JSON object (increase for more segments)
#ifdef ESP8266 // Size of buffer for API JSON object (increase for more segments)
#define JSON_BUFFER_SIZE 10240 #ifdef ESP8266
#else #define JSON_BUFFER_SIZE 10240
#define JSON_BUFFER_SIZE 24576 #else
#endif #define JSON_BUFFER_SIZE 24576
#endif
#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048)
#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048)
// Maximum size of node map (list of other WLED instances)
#ifdef ESP8266 // Maximum size of node map (list of other WLED instances)
#define WLED_MAX_NODES 24 #ifdef ESP8266
#else #define WLED_MAX_NODES 24
#define WLED_MAX_NODES 150 #else
#endif #define WLED_MAX_NODES 150
#endif
//this is merely a default now and can be changed at runtime
#ifndef LEDPIN //this is merely a default now and can be changed at runtime
#if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)) #ifndef LEDPIN
#define LEDPIN 2 // GPIO2 (D4) on Wemod D1 mini compatible boards #if defined(ESP8266) || (defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM))
#else #define LEDPIN 2 // GPIO2 (D4) on Wemod D1 mini compatible boards
#define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards #else
#endif #define LEDPIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards
#endif #endif
#endif
#ifdef WLED_ENABLE_DMX
#if (LEDPIN == 2) #ifdef WLED_ENABLE_DMX
#undef LEDPIN #if (LEDPIN == 2)
#define LEDPIN 1 #undef LEDPIN
#warning "Pin conflict compiling with DMX and LEDs on pin 2. The default LED pin has been changed to pin 1." #define LEDPIN 1
#endif #warning "Pin conflict compiling with DMX and LEDs on pin 2. The default LED pin has been changed to pin 1."
#endif #endif
#endif
#ifndef DEFAULT_LED_COUNT
#define DEFAULT_LED_COUNT 30 #ifndef DEFAULT_LED_COUNT
#endif #define DEFAULT_LED_COUNT 30
#endif
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
#if defined(ESP8266) && defined(HW_PIN_SCL)
#undef HW_PIN_SCL #if defined(ESP8266) && defined(HW_PIN_SCL)
#endif #undef HW_PIN_SCL
#if defined(ESP8266) && defined(HW_PIN_SDA) #endif
#undef HW_PIN_SDA #if defined(ESP8266) && defined(HW_PIN_SDA)
#endif #undef HW_PIN_SDA
#ifndef HW_PIN_SCL #endif
#ifdef ESP8266 #ifndef HW_PIN_SCL
#define HW_PIN_SCL 5 #ifdef ESP8266
#else #define HW_PIN_SCL 5
#define HW_PIN_SCL 22 #else
#endif #define HW_PIN_SCL 22
#endif #endif
#ifndef HW_PIN_SDA #endif
#ifdef ESP8266 #ifndef HW_PIN_SDA
#define HW_PIN_SDA 4 #ifdef ESP8266
#else #define HW_PIN_SDA 4
#define HW_PIN_SDA 21 #else
#endif #define HW_PIN_SDA 21
#endif #endif
#endif
#if defined(ESP8266) && defined(HW_PIN_CLOCKSPI)
#undef HW_PIN_CLOCKSPI #if defined(ESP8266) && defined(HW_PIN_CLOCKSPI)
#endif #undef HW_PIN_CLOCKSPI
#if defined(ESP8266) && defined(HW_PIN_DATASPI) #endif
#undef HW_PIN_DATASPI #if defined(ESP8266) && defined(HW_PIN_DATASPI)
#endif #undef HW_PIN_DATASPI
#ifndef HW_PIN_CLOCKSPI #endif
#ifdef ESP8266 #ifndef HW_PIN_CLOCKSPI
#define HW_PIN_CLOCKSPI 14 #ifdef ESP8266
#else #define HW_PIN_CLOCKSPI 14
#define HW_PIN_CLOCKSPI 18 #else
#endif #define HW_PIN_CLOCKSPI 18
#endif #endif
#ifndef HW_PIN_DATASPI #endif
#ifdef ESP8266 #ifndef HW_PIN_DATASPI
#define HW_PIN_DATASPI 13 #ifdef ESP8266
#else #define HW_PIN_DATASPI 13
#define HW_PIN_DATASPI 23 #else
#endif #define HW_PIN_DATASPI 23
#endif #endif
#endif
#endif
#endif

View File

@ -2363,6 +2363,11 @@ function rSegs()
bt.style.color = "var(--c-f)"; bt.style.color = "var(--c-f)";
bt.innerHTML = "Reset segments"; bt.innerHTML = "Reset segments";
var obj = {"seg":[{"start":0,"stop":ledCount,"sel":true}]}; var obj = {"seg":[{"start":0,"stop":ledCount,"sel":true}]};
if (isM) {
obj.seg[0].stop = mw;
obj.seg[0].startX = 0;
obj.seg[0].stopY = mh;
}
for (let i=1; i<=lSeg; i++) obj.seg.push({"stop":0}); for (let i=1; i<=lSeg; i++) obj.seg.push({"stop":0});
requestJson(obj); requestJson(obj);
} }

View File

@ -6,9 +6,38 @@
<title>WLED Settings</title> <title>WLED Settings</title>
<script> <script>
var d=document; var d=document;
var loc = false, locip;
function gId(n){return d.getElementById(n);} function gId(n){return d.getElementById(n);}
function S(){GetV();} // https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function GetV(){} function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S(){
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=0';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script> </script>
<style> <style>
body { body {

View File

@ -41,8 +41,6 @@
} }
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10'; var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
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
//if (loc) loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
//else { GetV(); UI(); }
} }
var maxPanels=64; var maxPanels=64;
@ -104,9 +102,6 @@ Serpentine: <input type="checkbox" name="P${i}S"></div>`;
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";
} }
//values injected by server while sending HTML
//fun-ction GetV() {}
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>

View File

@ -6,35 +6,65 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>DMX Settings</title> <title>DMX Settings</title>
<script> <script>
function GCH(num) { var d=document;
d=document; var loc = false, locip;
d.getElementById('dmxchannels').innerHTML += ""; function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
for (i=0;i<num;i++) { function B(){window.history.back();}
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n"; function GCH(num) {
} d.getElementById('dmxchannels').innerHTML += "";
} for (i=0;i<num;i++) {
function mMap(){ d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
d=document;
numCh=document.Sf.CN.value;
numGap=document.Sf.CG.value;
if (parseInt(numCh)>parseInt(numGap)) {
d.getElementById("gapwarning").style.display="block";
} else {
d.getElementById("gapwarning").style.display="none";
}
for (i=0;i<15;i++) {
if (i>=numCh) {
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
d.getElementById("CH"+(i+1)).disabled = true;
} else {
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
d.getElementById("CH"+(i+1)).disabled = false;
} }
} }
} function mMap(){
function S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();} numCh=document.Sf.CN.value;
function GetV(){} numGap=document.Sf.CG.value;
if (parseInt(numCh)>parseInt(numGap)) {
d.getElementById("gapwarning").style.display="block";
} else {
d.getElementById("gapwarning").style.display="none";
}
for (i=0;i<15;i++) {
if (i>=numCh) {
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
d.getElementById("CH"+(i+1)).disabled = true;
} else {
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
d.getElementById("CH"+(i+1)).disabled = false;
}
}
}
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GCH(15);GetV();mMap();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S(){
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>

View File

@ -8,10 +8,29 @@
<script> <script>
var d=document,laprev=55,maxB=1,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32 var d=document,laprev=55,maxB=1,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
var customStarts=false,startsDirty=[],maxCOOverrides=5; var customStarts=false,startsDirty=[],maxCOOverrides=5;
var loc = false, locip;
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");} function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
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);}
function off(n){d.getElementsByName(n)[0].value = -1;} function off(n){d.getElementsByName(n)[0].value = -1;}
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();checkSi();setABL();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
var timeout; var timeout;
function showToast(text, error = false) function showToast(text, error = false)
{ {
@ -506,12 +525,17 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
} }
} }
} }
function S(){GetV();checkSi();setABL();} function S(){
function GetV() if (window.location.protocol == "file:") {
{ loc = true;
//values injected by server while sending HTML locip = localStorage.getItem('locIp');
//d.um_p=[6,7,8,9,10,11,1];bLimits(3,4096,4000,1664);d.Sf.MS.checked=1;addLEDs(1);d.Sf.L00.value=2;d.Sf.LC0.value=30;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=15;d.Sf.CV0.checked=1;d.Sf.SL0.checked=0;addLEDs(1);d.Sf.L01.value=10;d.Sf.L11.value=10;d.Sf.L21.value=1;d.Sf.L31.value=10;d.Sf.LC1.value=60;d.Sf.LT1.value=80;d.Sf.CO1.value=1;d.Sf.LS1.value=0;d.Sf.CV1.checked=0;d.Sf.SL1.checked=0;d.Sf.MA.value=850;d.Sf.LA.value=0;d.Sf.CA.value=56;d.Sf.AW.value=3;d.Sf.BO.checked=1;d.Sf.BP.value=80;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=100;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=0;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=12;d.Sf.RM.checked=1;addBtn(0,0,0);addBtn(1,-1,0);d.Sf.TT.value=32;d.Sf.IR.value=-1;d.Sf.IT.value=0; if (!locip) {
//d.um_p=[6,7,8,9,10,11,14,15,13,1,21,19,22,25,26,27,5,23,18,17];bLimits(10,2048,64000,8192);d.Sf.MS.checked=1;d.Sf.CCT.checked=0;addLEDs(1);d.Sf.L00.value=192;d.Sf.L10.value=168;d.Sf.L20.value=0;d.Sf.L30.value=61;d.Sf.LC0.value=421;d.Sf.LT0.value=80;d.Sf.CO0.value=1;d.Sf.LS0.value=0;d.Sf.CV0.checked=0;d.Sf.SL0.checked=0;d.Sf.RF0.checked=0;d.Sf.MA.value=850;d.Sf.LA.value=0;d.Sf.CA.value=127;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=0;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=1;d.Sf.BF.value=100;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=-1;d.Sf.RM.checked=1;addBtn(0,-1,0);addBtn(1,-1,0);addBtn(2,-1,0);addBtn(3,-1,0);d.Sf.TT.value=32;d.Sf.IR.value=-1;d.Sf.IT.value=8; locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=2';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
} }
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>

View File

@ -7,11 +7,30 @@
<title>Misc Settings</title> <title>Misc Settings</title>
<script> <script>
var d = document; var d = document;
var loc = false, locip;
function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); } function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); }
function B() { window.open("/settings","_self"); } function B() { window.open("/settings","_self"); }
function U() { window.open("/update","_self"); } function U() { window.open("/update","_self"); }
function gId(s) { return d.getElementById(s); } function gId(s) { return d.getElementById(s); }
function isObj(o) { return (o && typeof o === 'object' && !Array.isArray(o)); } function isObj(o) { return (o && typeof o === 'object' && !Array.isArray(o)); }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
var timeout; var timeout;
function showToast(text, error = false) function showToast(text, error = false)
{ {
@ -40,16 +59,24 @@
event.preventDefault(); event.preventDefault();
return false; return false;
} }
function GetV() function S() {
{ if (window.location.protocol == "file:") {
//values injected by server while sending HTML loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=6';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
} }
</script> </script>
<style> <style>
@import url("style.css"); @import url("style.css");
</style> </style>
</head> </head>
<body onload="GetV()"> <body onload="S()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="toprow"> <div class="toprow">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>

View File

@ -5,42 +5,71 @@
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Sync Settings</title> <title>Sync Settings</title>
<script>var d=document; <script>var d=document;
function gId(s) var loc = false, locip;
{ function gId(s)
return d.getElementById(s);
}
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
function B(){window.open("/settings","_self");}
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
function FC()
{
for(j=0;j<8;j++)
{ {
gId("G"+(j+1)).checked=gId("GS").value>>j&1; return d.getElementById(s);
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
} }
} function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
function GC() function B(){window.open("/settings","_self");}
{ function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
var a=0, b=0; else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();SetVal();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function FC()
{
for(j=0;j<8;j++)
{
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
}
}
function GC()
{
var a=0, b=0;
var m=1; var m=1;
for(j=0;j<8;j++) for(j=0;j<8;j++)
{ {
a+=gId("G"+(j+1)).checked*m; a+=gId("G"+(j+1)).checked*m;
b+=gId("R"+(j+1)).checked*m; b+=gId("R"+(j+1)).checked*m;
m*=2; m*=2;
}
gId("GS").value=a;
gId("GR").value=b;
} }
gId("GS").value=a; function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
gId("GR").value=b; function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
} function S(){
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;} if (window.location.protocol == "file:") {
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();} loc = true;
function S(){GetV();SetVal();} locip = localStorage.getItem('locIp');
function GetV(){var d=document;} if (!locip) {
</script> locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>
<body onload="S()"> <body onload="S()">

View File

@ -7,26 +7,42 @@
<title>Time Settings</title> <title>Time Settings</title>
<script> <script>
var d=document; var d=document;
var loc = false, locip;
var el=false; var el=false;
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
function H() function H() { window.open("https://kno.wled.ge/features/settings/#time-settings"); }
{ function B() { window.open("/settings","_self"); }
window.open("https://kno.wled.ge/features/settings/#time-settings"); function gId(s) { return d.getElementById(s); }
function gN(s) { return d.getElementsByName(s)[0]; }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
BTa();GetV();updLoc();Cs();FC();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
} }
function B() function S() {
{ if (window.location.protocol == "file:") {
window.open("/settings","_self"); loc = true;
} locip = localStorage.getItem('locIp');
function S() if (!locip) {
{ locip = prompt("File Mode. Please enter WLED IP!");
BTa();GetV();updLoc();Cs();FC(); localStorage.setItem('locIp', locip);
} }
function gId(s) }
{ var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=5';
return d.getElementById(s); loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
function gN(s) {
return d.getElementsByName(s)[0];
} }
function expand(o,i) function expand(o,i)
{ {
@ -34,10 +50,7 @@
t.style.display = t.style.display!=="none" ? "none" : ""; t.style.display = t.style.display!=="none" ? "none" : "";
o.innerHTML = t.style.display==="none" ? "&#128197;" : "&#x2715;"; o.innerHTML = t.style.display==="none" ? "&#128197;" : "&#x2715;";
} }
function Cs() function Cs() { gId("cac").style.display=(gN("OL").checked)?"block":"none"; }
{
gId("cac").style.display=(gN("OL").checked)?"block":"none";
}
function BTa() function BTa()
{ {
var ih="<thead><tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr></thead>"; var ih="<thead><tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr></thead>";
@ -132,10 +145,6 @@
if (parseFloat(d.Sf.LT.value)<0) { d.Sf.LTR.value = "S"; d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } else d.Sf.LTR.value = "N"; if (parseFloat(d.Sf.LT.value)<0) { d.Sf.LTR.value = "S"; d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } else d.Sf.LTR.value = "N";
if (parseFloat(d.Sf.LN.value)<0) { d.Sf.LNR.value = "W"; d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } else d.Sf.LNR.value = "E"; if (parseFloat(d.Sf.LN.value)<0) { d.Sf.LNR.value = "W"; d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } else d.Sf.LNR.value = "E";
} }
function GetV()
{
//values injected by server while sending HTML
}
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>

View File

@ -7,6 +7,7 @@
<title>UI Settings</title> <title>UI Settings</title>
<script> <script>
var d = document; var d = document;
var loc = false, locip;
var initial_ds, initial_st, initial_su; var initial_ds, initial_st, initial_su;
var sett = null; var sett = null;
var l = { var l = {
@ -41,10 +42,7 @@
} }
} }
}; };
function gId(s) function gId(s) { return d.getElementById(s); }
{
return d.getElementById(s);
}
function isObject(item) { function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item)); return (item && typeof item === 'object' && !Array.isArray(item));
} }
@ -164,22 +162,43 @@
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit(); if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
} }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
initial_ds = d.Sf.DS.value;
initial_st = d.Sf.ST.checked;
initial_su = d.Sf.SU.checked;
GetLS();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S() function S()
{ {
GetV(); if (window.location.protocol == "file:") {
initial_ds = d.Sf.DS.value; loc = true;
initial_st = d.Sf.ST.checked; locip = localStorage.getItem('locIp');
initial_su = d.Sf.SU.checked; if (!locip) {
GetLS(); locip = prompt("File Mode. Please enter WLED IP!");
} localStorage.setItem('locIp', locip);
function H() }
{ }
window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
} loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
function B()
{
window.open("/settings","_self");
} }
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
function B() { window.open("/settings","_self"); }
function UI() function UI()
{ {
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none'; gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
@ -214,7 +233,6 @@
fO.value = ''; fO.value = '';
return false; return false;
} }
function GetV(){var d=document;}
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>

View File

@ -192,7 +192,6 @@
e.preventDefault(); e.preventDefault();
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914 if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
} }
//fun-ction GetV() {} // replaced during 'npm run build'
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>

View File

@ -6,16 +6,44 @@
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>WiFi Settings</title> <title>WiFi Settings</title>
<script> <script>
var d=document;
var loc = false, locip;
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");} function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
function B(){window.open("/settings","_self");} function B(){window.open("/settings","_self");}
function GetV() // https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
{ function loadJS(FILE_URL, async = true) {
//values injected by server while sending HTML let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S() {
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=1';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
} }
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>
<body onload="GetV()"> <body onload="S()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">
<div class="toprow"> <div class="toprow">
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -89,7 +89,7 @@ byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte highe
void changeEffect(uint8_t fx) void changeEffect(uint8_t fx)
{ {
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
strip.setMode(i, fx); strip.setMode(i, fx);
@ -105,7 +105,7 @@ void changeEffect(uint8_t fx)
void changePalette(uint8_t pal) void changePalette(uint8_t pal)
{ {
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.palette = pal; seg.palette = pal;
@ -124,7 +124,7 @@ void changeEffectSpeed(int8_t amount)
int16_t new_val = (int16_t) effectSpeed + amount; int16_t new_val = (int16_t) effectSpeed + amount;
effectSpeed = (byte)constrain(new_val,0,255); effectSpeed = (byte)constrain(new_val,0,255);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.speed = effectSpeed; seg.speed = effectSpeed;
@ -147,7 +147,7 @@ void changeEffectSpeed(int8_t amount)
prim_hsv.h = (byte)new_val; prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col); hsv2rgb_rainbow(prim_hsv, fastled_col);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0])); seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
@ -171,7 +171,7 @@ void changeEffectIntensity(int8_t amount)
int16_t new_val = (int16_t) effectIntensity + amount; int16_t new_val = (int16_t) effectIntensity + amount;
effectIntensity = (byte)constrain(new_val,0,255); effectIntensity = (byte)constrain(new_val,0,255);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.intensity = effectIntensity; seg.intensity = effectIntensity;
@ -192,7 +192,7 @@ void changeEffectIntensity(int8_t amount)
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255 prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
hsv2rgb_rainbow(prim_hsv, fastled_col); hsv2rgb_rainbow(prim_hsv, fastled_col);
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0])); seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
@ -214,7 +214,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
{ {
if (irApplyToAllSelected) { if (irApplyToAllSelected) {
// main segment may not be selected! // main segment may not be selected!
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
byte capabilities = seg.getLightCapabilities(); byte capabilities = seg.getLightCapabilities();

View File

@ -11,11 +11,20 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
byte id = elem["id"] | it; byte id = elem["id"] | it;
if (id >= strip.getMaxSegments()) return; if (id >= strip.getMaxSegments()) return;
int stop = elem["stop"] | -1;
// if using vectors use this code to append segment
if (id >= strip.getActiveSegmentsNum()) {
if (stop <= 0) return; // ignore empty/inactive segments
DEBUG_PRINT(F("Adding segment: ")); DEBUG_PRINTLN(id);
strip.appendSegment(Segment(0, strip.getLengthTotal()));
id = strip.getActiveSegmentsNum()-1; // segments are added at the end of list
}
Segment& seg = strip.getSegment(id); Segment& seg = strip.getSegment(id);
Segment prev = seg; //make a backup so we can tell if something changed Segment prev = seg; //make a backup so we can tell if something changed
uint16_t start = elem["start"] | seg.start; uint16_t start = elem["start"] | seg.start;
int stop = elem["stop"] | -1;
if (stop < 0) { if (stop < 0) {
uint16_t len = elem["len"]; uint16_t len = elem["len"];
stop = (len > 0) ? start + len : seg.stop; stop = (len > 0) ? start + len : seg.stop;
@ -232,7 +241,6 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
// send UDP if not in preset and something changed that is not just selection // send UDP if not in preset and something changed that is not just selection
// send UDP if something changed that is not just selection or segment power/opacity // send UDP if something changed that is not just selection or segment power/opacity
if ((seg.differs(prev) & 0x7E) && seg.getOption(SEG_OPTION_ON)==prev.getOption(SEG_OPTION_ON)) stateChanged = true; if ((seg.differs(prev) & 0x7E) && seg.getOption(SEG_OPTION_ON)==prev.getOption(SEG_OPTION_ON)) stateChanged = true;
return;
} }
// deserializes WLED state (fileDoc points to doc object if called from web server) // deserializes WLED state (fileDoc points to doc object if called from web server)
@ -250,7 +258,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff(); if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
if (bri && !onBefore) { // unfreeze all segments when turning on if (bri && !onBefore) { // unfreeze all segments when turning on
for (uint8_t s=0; s < strip.getMaxSegments(); s++) { for (uint8_t s=0; s < strip.getActiveSegmentsNum(); s++) {
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false); strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false);
} }
if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live
@ -328,13 +336,11 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (id < 0) { if (id < 0) {
//apply all selected segments //apply all selected segments
//bool didSet = false; //bool didSet = false;
for (byte s = 0; s < strip.getMaxSegments(); s++) { for (byte s = 0; s < strip.getActiveSegmentsNum(); s++) {
Segment &sg = strip.getSegment(s); Segment &sg = strip.getSegment(s);
if (sg.isActive()) { if (sg.isSelected()) {
if (sg.isSelected()) { deserializeSegment(segVar, s, presetId);
deserializeSegment(segVar, s, presetId); //didSet = true;
//didSet = true;
}
} }
} }
//TODO: not sure if it is good idea to change first active but unselected segment //TODO: not sure if it is good idea to change first active but unselected segment
@ -346,9 +352,12 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
JsonArray segs = segVar.as<JsonArray>(); JsonArray segs = segVar.as<JsonArray>();
for (JsonObject elem : segs) for (JsonObject elem : segs)
{ {
DEBUG_PRINT(F(" Deserializing segment: ")); DEBUG_PRINTLN(it);
deserializeSegment(elem, it, presetId); deserializeSegment(elem, it, presetId);
it++; it++;
} }
// DEBUG_PRINTLN(F(" Purging segments."));
// strip.purgeSegments(); // prune inactive segments (resets ESP if effect running)
} }
usermods.readFromJsonState(root); usermods.readFromJsonState(root);
@ -496,8 +505,16 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
bool selectedSegmentsOnly = root[F("sc")] | false; bool selectedSegmentsOnly = root[F("sc")] | false;
JsonArray seg = root.createNestedArray("seg"); JsonArray seg = root.createNestedArray("seg");
for (byte s = 0; s < strip.getMaxSegments(); s++) { for (byte s = 0; s < strip.getMaxSegments(); s++) {
if (s >= strip.getActiveSegmentsNum()) {
if (forPreset && segmentBounds) { //disable segments not part of preset
JsonObject seg0 = seg.createNestedObject();
seg0["stop"] = 0;
continue;
} else
break;
}
Segment &sg = strip.getSegment(s); Segment &sg = strip.getSegment(s);
if (selectedSegmentsOnly && !sg.isSelected()) continue; if (!forPreset && selectedSegmentsOnly && !sg.isSelected()) continue;
if (sg.isActive()) { if (sg.isActive()) {
JsonObject seg0 = seg.createNestedObject(); JsonObject seg0 = seg.createNestedObject();
serializeSegment(seg0, sg, s, forPreset, segmentBounds); serializeSegment(seg0, sg, s, forPreset, segmentBounds);
@ -520,6 +537,7 @@ void serializeInfo(JsonObject root)
leds["fps"] = strip.getFps(); leds["fps"] = strip.getFps();
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
leds[F("maxseg")] = strip.getMaxSegments(); leds[F("maxseg")] = strip.getMaxSegments();
leds[F("actseg")] = strip.getActiveSegmentsNum();
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config //leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D

View File

@ -31,7 +31,7 @@ void applyValuesToSelectedSegs()
// copy of first selected segment to tell if value was updated // copy of first selected segment to tell if value was updated
uint8_t firstSel = strip.getFirstSelectedSegId(); uint8_t firstSel = strip.getFirstSelectedSegId();
Segment selsegPrev = strip.getSegment(firstSel); Segment selsegPrev = strip.getSegment(firstSel);
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue; if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;

View File

@ -84,7 +84,7 @@ void handlePresets(bool force)
presetToApply = 0; //clear request for preset presetToApply = 0; //clear request for preset
callModeToApply = 0; callModeToApply = 0;
DEBUG_PRINTLN(F("Applying preset: ")); DEBUG_PRINT(F("Applying preset: "));
DEBUG_PRINTLN(tmpPreset); DEBUG_PRINTLN(tmpPreset);
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32

View File

@ -608,7 +608,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SS=")); pos = req.indexOf(F("SS="));
if (pos > 0) { if (pos > 0) {
byte t = getNumVal(&req, pos); byte t = getNumVal(&req, pos);
if (t < strip.getMaxSegments()) { if (t < strip.getActiveSegmentsNum()) {
selectedSeg = t; selectedSeg = t;
singleSegment = true; singleSegment = true;
} }
@ -618,7 +618,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SV=")); //segment selected pos = req.indexOf(F("SV=")); //segment selected
if (pos > 0) { if (pos > 0) {
byte t = getNumVal(&req, pos); byte t = getNumVal(&req, pos);
if (t == 2) for (uint8_t i = 0; i < strip.getMaxSegments(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments if (t == 2) for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments
selseg.setOption(SEG_OPTION_SELECTED, t); selseg.setOption(SEG_OPTION_SELECTED, t);
} }
@ -824,7 +824,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged); stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
// apply to main and all selected segments to prevent #1618. // apply to main and all selected segments to prevent #1618.
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
if (fxModeChanged) strip.setMode(i, effectIn); if (fxModeChanged) strip.setMode(i, effectIn);

View File

@ -89,9 +89,9 @@ void notify(byte callMode, bool followUp)
udpOut[37] = strip.hasCCTBus() ? 0 : 255; //check this is 0 for the next value to be significant udpOut[37] = strip.hasCCTBus() ? 0 : 255; //check this is 0 for the next value to be significant
udpOut[38] = mainseg.cct; udpOut[38] = mainseg.cct;
udpOut[39] = strip.getMaxSegments(); udpOut[39] = strip.getActiveSegmentsNum();
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment) udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment &selseg = strip.getSegment(i); Segment &selseg = strip.getSegment(i);
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte
udpOut[0 +ofs] = i; udpOut[0 +ofs] = i;
@ -155,7 +155,7 @@ void realtimeLock(uint32_t timeoutMs, byte md)
for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0); for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0);
// if WLED was off and using main segment only, freeze non-main segments so they stay off // if WLED was off and using main segment only, freeze non-main segments so they stay off
if (useMainSegmentOnly && bri == 0) { if (useMainSegmentOnly && bri == 0) {
for (uint8_t s=0; s < strip.getMaxSegments(); s++) { for (uint8_t s=0; s < strip.getActiveSegmentsNum(); s++) {
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true); strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true);
} }
} }
@ -342,7 +342,7 @@ void handleNotifications()
for (uint8_t i = 0; i < numSrcSegs; i++) { for (uint8_t i = 0; i < numSrcSegs; i++) {
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
uint8_t id = udpIn[0 +ofs]; uint8_t id = udpIn[0 +ofs];
if (id > strip.getMaxSegments()) break; if (id > strip.getActiveSegmentsNum()) break;
Segment& selseg = strip.getSegment(id); Segment& selseg = strip.getSegment(id);
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]); uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]); uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
@ -377,7 +377,7 @@ void handleNotifications()
// simple effect sync, applies to all selected segments // simple effect sync, applies to all selected segments
if (applyEffects && (version < 11 || !receiveSegmentOptions)) { if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) { for (uint8_t i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i); Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue; if (!seg.isActive() || !seg.isSelected()) continue;
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]); if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);

View File

@ -118,6 +118,8 @@ void WLED::loop()
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis; if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
#endif #endif
} }
if (offMode) strip.purgeSegments(); // remove inactive segments from memory (no effects running)
yield(); yield();
#ifdef ESP8266 #ifdef ESP8266
MDNS.update(); MDNS.update();

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2207081 #define VERSION 2207171
//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

View File

@ -154,7 +154,6 @@ void initServer()
}); });
server.on("/json", HTTP_GET, [](AsyncWebServerRequest *request){ server.on("/json", HTTP_GET, [](AsyncWebServerRequest *request){
while (strip.isUpdating()) delay(1);
serveJson(request); serveJson(request);
}); });
@ -162,8 +161,6 @@ void initServer()
bool verboseResponse = false; bool verboseResponse = false;
bool isConfig = false; bool isConfig = false;
while (strip.isUpdating()) delay(1);
if (!requestJSONBufferLock(14)) return; if (!requestJSONBufferLock(14)) return;
DeserializationError error = deserializeJson(doc, (uint8_t*)(request->_tempObject)); DeserializationError error = deserializeJson(doc, (uint8_t*)(request->_tempObject));

View File

@ -96,8 +96,6 @@ void sendDataWs(AsyncWebSocketClient * client)
if (!ws.count()) return; if (!ws.count()) return;
AsyncWebSocketMessageBuffer * buffer; AsyncWebSocketMessageBuffer * buffer;
while (strip.isUpdating()) delay(1);
if (!requestJSONBufferLock(12)) return; if (!requestJSONBufferLock(12)) return;
JsonObject state = doc.createNestedObject("state"); JsonObject state = doc.createNestedObject("state");