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

View File

@ -103,25 +103,24 @@ class Animated_Staircase : public Usermod {
void updateSegments() {
mainSegmentId = strip.getMainSegmentId();
Segment* segments = strip.getSegments();
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
if (!segments->isActive()) {
for (int i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment &seg = strip.getSegment(i);
if (!seg.isActive()) {
maxSegmentId = i - 1;
break;
}
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
// changes are propagated even when the config is changed during a wipe
// segments->mode = mainsegment.mode;
// segments->colors[0] = mainsegment.colors[0];
} else {
segments->setOption(SEG_OPTION_ON, 0, i);
seg.setOption(SEG_OPTION_ON, false);
}
// 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);
}
@ -290,13 +289,13 @@ class Animated_Staircase : public Usermod {
}
} else {
// Restore segment options
Segment* segments = strip.getSegments();
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
if (!segments->isActive()) {
for (int i = 0; i < strip.getActiveSegmentsNum(); i++) {
Segment &seg = strip.getSegment(i);
if (!seg.isActive()) {
maxSegmentId = i - 1;
break;
}
segments->setOption(SEG_OPTION_ON, 1, i);
seg.setOption(SEG_OPTION_ON, true);
}
colorUpdated(CALL_MODE_DIRECT_CHANGE);
DEBUG_PRINTLN(F("Animated Staircase disabled."));

View File

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

View File

@ -3134,8 +3134,8 @@ typedef struct particle {
uint16_t mode_starburst(void) {
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
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 <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 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
uint8_t numStars = 1 + (SEGLEN >> 3);
@ -3257,8 +3257,8 @@ uint16_t mode_exploding_fireworks(void)
//allocate segment data
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
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 <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 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
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";
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 < _modeCount) {
if (_mode[id] != &mode_static) return; // do not overwrite alerady added effect
_mode[id] = mode_fn;
_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() {

View File

@ -27,6 +27,8 @@
#ifndef WS2812FX_h
#define WS2812FX_h
#include <vector>
#include "const.h"
#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 */
#ifdef ESP8266
#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 */
#define MAX_SEGMENT_DATA 4096
#else
#ifndef MAX_NUM_SEGMENTS
#define MAX_NUM_SEGMENTS 32
#endif
#define MAX_NUM_TRANSITIONS 24
#define MAX_SEGMENT_DATA 20480
#endif
/* 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. */
#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 NUM_COLORS 3 /* number of colors per segment */
#define SEGMENT strip._segments[strip.getCurrSegmentId()]
#define SEGENV strip._segments[strip.getCurrSegmentId()].runtime
#define SEGCOLOR(x) strip.segColor(x)
#define SEGENV strip._segments[strip.getCurrSegmentId()]
//#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._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)
// some common colors
@ -362,148 +362,220 @@ uint32_t color_add(uint32_t,uint32_t);
#define MODE_COUNT 185
#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
typedef struct ColorTransition { // 20 bytes
uint32_t colorOld[NUM_COLORS];
uint8_t briOld;
uint8_t cctOld;
uint32_t transitionStart;
uint16_t transitionDur;
// runtime data
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;
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:
uint16_t _dataLen = 0;
bool _requiresReset = false;
} segmentruntime;
uint8_t _capabilities;
uint16_t _dataLen;
// 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
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;
public:
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
inline bool isSelected() { return getOption(0); }
inline bool isActive() { return stop > start; }
inline uint16_t width() { return stop - start; }
inline uint16_t height() { return stopY - startY; }
inline uint16_t length() { return width(); }
inline uint16_t groupLength() { return grouping + spacing; }
inline uint8_t getLightCapabilities() { return _capabilities; }
Segment(uint16_t sStart=0, uint16_t sStop=30) : start(sStart), stop(sStop) {
mode = DEFAULT_MODE;
colors[0] = DEFAULT_COLOR;
colors[1] = BLACK;
colors[2] = BLACK;
startY = 0;
stopY = 1;
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
void setCCT(uint16_t k);
void setOpacity(uint8_t o);
void setOption(uint8_t n, bool val);
uint8_t differs(Segment& b);
void refreshLightCapabilities();
Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) {
Segment(sStartX, sStopX);
startY = sStartY;
stopY = sStopY;
}
// 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);
Segment(const Segment &orig); // copy constructor
Segment(Segment &&orig) noexcept; // move constructor
// 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() {
Serial.print(F("Destroying segment: "));
if (name) Serial.println(name); else Serial.println();
if (name) delete[] name;
//if (_t) delete _t;
deallocateData();
}
Segment& operator= (const Segment &orig); // copy assignment
Segment& operator= (Segment &&orig) noexcept; // move assignment
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
inline bool isSelected() { return getOption(0); }
inline bool isActive() { return stop > start; }
inline uint16_t width() { return stop - start; }
inline uint16_t height() { return stopY - startY; }
inline uint16_t length() { return width(); }
inline uint16_t groupLength() { return grouping + spacing; }
inline uint8_t getLightCapabilities() { return _capabilities; }
bool setColor(uint8_t slot, uint32_t c); //returns true if changed
void setCCT(uint16_t k);
void setOpacity(uint8_t o);
void setOption(uint8_t n, bool val);
uint8_t differs(Segment& b);
void refreshLightCapabilities();
// runtime data functions
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() { 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;
//static int i = sizeof(Segment);
// main "strip" class
class WS2812FX { // 96 bytes
typedef uint16_t (*mode_ptr)(void); // pointer to mode function
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;
@ -511,22 +583,31 @@ class WS2812FX { // 96 bytes
WS2812FX() {
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];
_modeData = new const char*[_modeCount];
if (_mode && _modeData) setupEffectData();
else _modeCount = 1; // only Solid will work
*/
_brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black);
targetPalette = CloudColors_p;
ablMilliampsMax = ABL_MILLIAMPS_DEFAULT;
currentMilliamps = 0;
timebase = 0;
resetSegments();
_usedSegmentData = 0;
//resetSegments(); // no need here
}
~WS2812FX() {
delete[] _mode;
delete[] _modeData;
//delete[] _mode;
//delete[] _modeData;
_mode.clear();
_modeData.clear();
}
static WS2812FX* getInstance(void) { return instance; }
@ -542,7 +623,8 @@ class WS2812FX { // 96 bytes
setRange(uint16_t i, uint16_t i2, uint32_t col),
setTransitionMode(bool t),
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),
restartRuntime(),
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 setShowCallback(show_callback cb) { _callback = cb; }
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; }
bool
@ -582,7 +665,7 @@ class WS2812FX { // 96 bytes
paletteBlend = 0,
milliampsPerLed = 55,
cctBlending = 0,
getActiveSegmentsNum(void),
//getActiveSegmentsNum(void),
getFirstSelectedSegId(void),
getLastActiveSegmentId(void),
setPixelSegment(uint8_t n),
@ -590,7 +673,8 @@ class WS2812FX { // 96 bytes
gamma8_cal(uint8_t, float);
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 getMainSegmentId(void) { return _mainSegment; }
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"); }
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& getMainSegment(void) { return _segments[getMainSegmentId()]; }
inline Segment* getSegments(void) { return _segments; }
inline Segment* getSegments(void) { return &(_segments[0]); }
// 2D support (panels)
bool
@ -674,25 +759,23 @@ class WS2812FX { // 96 bytes
CRGBPalette16 currentPalette;
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
uint32_t _colors_t[3]; // used for color transitions
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: 27 bytes per element
// 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}
};
//segment _segments[MAX_NUM_SEGMENTS]; // SRAM footprint: 88 bytes per element
std::vector<segment> _segments; // deleting a segment while effects play crashes ESP
friend class Segment;
//segmentruntime _segmentruntimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
//friend class Segmentruntime;
//size_t segSize = sizeof(Segment);
//size_t segsSize = sizeof(_segments);
private:
uint16_t _length;
uint16_t _rand16seed;
uint8_t _brightness;
uint16_t _usedSegmentData = 0;
uint16_t _usedSegmentData;
uint16_t _transitionDur = 750;
uint8_t _targetFps = 42;
@ -705,8 +788,12 @@ class WS2812FX { // 96 bytes
_triggered;
uint8_t _modeCount = MODE_COUNT;
mode_ptr *_mode; // SRAM footprint: 4 bytes per element
const char **_modeData; // mode (effect) name and its slider control data array
//mode_ptr *_mode; // SRAM footprint: 4 bytes per element
//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;
@ -726,9 +813,6 @@ class WS2812FX { // 96 bytes
estimateCurrentAndLimitBri(void),
load_gradient_palette(uint8_t),
handle_palette(void);
uint16_t
transitionProgress(uint8_t tNr);
};
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
uint8_t _bri_t = strip._bri_t;
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t);

View File

@ -70,57 +70,157 @@
#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::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
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;
return true;
}
@ -132,19 +232,19 @@ void Segment::setCCT(uint16_t k) {
k = (k - 1900) >> 5;
}
if (cct == k) return;
transition.startTransition(this, strip.getTransition()); // start transition prior to change
startTransition(strip.getTransition()); // start transition prior to change
cct = k;
}
void Segment::setOpacity(uint8_t o) {
if (opacity == o) return;
transition.startTransition(this, strip.getTransition()); // start transition prior to change
startTransition(strip.getTransition()); // start transition prior to change
opacity = o;
}
void Segment::setOption(uint8_t n, bool val) {
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;
else options &= ~(0x01 << n);
}
@ -185,6 +285,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
uint16_t len = length();
uint8_t _bri_t = strip._bri_t;
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
if (_bri_t < 255) {
byte r = scale8(R(col), _bri_t);
byte g = scale8(G(col), _bri_t);
@ -289,9 +390,6 @@ uint8_t Segment::differs(Segment& b) {
}
void Segment::refreshLightCapabilities() {
if (!isActive()) {
_capabilities = 0; return;
}
uint8_t capabilities = 0;
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
///////////////////////////////////////////////////////////////////////////////
@ -540,10 +593,14 @@ void Segmentruntime::resetIfRequired() {
void WS2812FX::finalizeInit(void)
{
//reset segment runtimes
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
_segments[i].runtime.markForReset();
_segments[i].runtime.resetIfRequired();
for (segment &seg : _segments) {
seg.markForReset();
seg.resetIfRequired();
}
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// _segments[i].markForReset();
// _segments[i].resetIfRequired();
// }
_hasWhiteChannel = _isOffRefreshRequired = false;
@ -596,21 +653,18 @@ void WS2812FX::service() {
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
bool doShow = false;
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
{
//if (realtimeMode && useMainSegmentOnly && i == getMainSegmentId()) continue;
_segment_index = i;
Segment &seg = _segments[_segment_index];
_segment_index = 0;
for (segment &seg : _segments) {
// for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
// reset the segment runtime data if needed, called before isActive to ensure deleted
// segment's buffers are cleared
seg.runtime.resetIfRequired();
seg.resetIfRequired();
if (!seg.isActive()) continue;
// 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
doShow = true;
@ -618,12 +672,12 @@ void WS2812FX::service() {
if (!seg.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
_virtualSegmentLength = seg.virtualLength();
_bri_t = seg.getOption(SEG_OPTION_ON) ? seg.opacity : 0;
uint8_t _cct_t = seg.cct;
_colors_t[0] = seg.colors[0];
_colors_t[1] = seg.colors[1];
_colors_t[2] = seg.colors[2];
seg.transition.handleTransition(&seg, _bri_t, _cct_t, _colors_t);
_bri_t = seg.currentBri(seg.getOption(SEG_OPTION_ON) ? seg.opacity : 0);
uint8_t _cct_t = seg.currentBri(seg.cct, true);
_colors_t[0] = seg.currentColor(0, seg.colors[0]);
_colors_t[1] = seg.currentColor(1, seg.colors[1]);
_colors_t[2] = seg.currentColor(2, seg.colors[2]);
seg.handleTransition();
if (!cctFromRgb || correctWB) busses.setSegmentCCT(_cct_t, correctWB);
for (uint8_t c = 0; c < NUM_COLORS; c++) {
@ -632,11 +686,12 @@ void WS2812FX::service() {
handle_palette();
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;
busses.setSegmentCCT(-1);
@ -838,13 +893,14 @@ void WS2812FX::setTargetFps(uint8_t fps) {
}
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 (_segments[segid].mode != m)
{
_segments[segid].runtime.markForReset();
if (_segments[segid].mode != m) {
//_segments[segid].startTransition(strip.getTransition()); // set effect transitions
_segments[segid].markForReset();
_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) {
if (slot >= NUM_COLORS) return;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && _segments[i].isSelected()) {
_segments[i].setColor(slot, c);
for (segment &seg : _segments) {
// for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
if (seg.isSelected()) {
seg.setColor(slot, c);
}
}
}
void WS2812FX::setCCT(uint16_t k) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && _segments[i].isSelected()) {
_segments[i].setCCT(k);
for (segment &seg : _segments) {
// for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
if (seg.isActive() && seg.isSelected()) {
seg.setCCT(k);
}
}
}
@ -875,9 +933,10 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
if (_brightness == b) return;
_brightness = b;
if (_brightness == 0) { //unfreeze all segments on power off
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
_segments[i].setOption(SEG_OPTION_FREEZE, false);
for (segment &seg : _segments) {
// for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
seg.setOption(SEG_OPTION_FREEZE, false);
}
}
if (direct) {
@ -885,51 +944,56 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
busses.setBrightness(b);
} else {
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)
{
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && _segments[i].isSelected()) return i;
size_t i = 0;
for (segment &seg : _segments) {
// for (int i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
if (seg.isSelected()) return i;
i++;
}
// if none selected, use the main segment
return getMainSegmentId();
}
void WS2812FX::setMainSegmentId(uint8_t n) {
if (n >= MAX_NUM_SEGMENTS) return;
//use supplied n if active, or first active
if (_segments[n].isActive()) {
_mainSegment = n; return;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive()) {
_mainSegment = i; return;
}
}
// if (n >= getMaxSegments()) return;
// //use supplied n if active, or first active
// if (_segments[n].isActive()) {
// _mainSegment = n; return;
// }
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// if (_segments[i].isActive()) {
// _mainSegment = i; return;
// }
// }
_mainSegment = 0;
if (n < _segments.size()) {
_mainSegment = n;
}
return;
}
uint8_t WS2812FX::getLastActiveSegmentId(void) {
for (uint8_t i = MAX_NUM_SEGMENTS -1; i > 0; i--) {
if (_segments[i].isActive()) return i;
}
return 0;
// for (uint8_t i = getMaxSegments() -1; i > 0; i--) {
// if (_segments[i].isActive()) return i;
// }
// return 0;
return _segments.size()-1;
}
uint8_t WS2812FX::getActiveSegmentsNum(void) {
uint8_t c = 0;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive()) c++;
}
return c;
}
//uint8_t WS2812FX::getActiveSegmentsNum(void) {
// uint8_t c = 0;
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// if (_segments[i].isActive()) c++;
// }
// return c;
//}
uint16_t WS2812FX::getLengthPhysical(void) {
uint16_t len = 0;
@ -972,8 +1036,21 @@ bool WS2812FX::hasCCTBus(void) {
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) {
if (n >= MAX_NUM_SEGMENTS) return;
if (n >= _segments.size()) return;
// if (n >= getMaxSegments()) return;
Segment& seg = _segments[n];
//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))
&& (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
{
// disabled segments should get removed using purgeSegments()
DEBUG_PRINTLN(F(" Segment marked inactive."));
seg.stop = 0;
if (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 (n == _mainSegment) setMainSegmentId(0);
seg.markForReset();
return;
}
if (isMatrix) {
@ -1015,18 +1096,25 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
seg.spacing = spacing;
}
if (offset < UINT16_MAX) seg.offset = offset;
_segments[n].runtime.markForReset();
seg.markForReset();
if (!boundsUnchanged) seg.refreshLightCapabilities();
}
void WS2812FX::restartRuntime() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
_segments[i].runtime.markForReset();
}
for (segment &seg : _segments) seg.markForReset();
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
// seg.markForReset();
// }
}
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;
memset(_segments, 0, sizeof(_segments));
//memset(_segmentruntimes, 0, sizeof(_segmentruntimes));
@ -1034,9 +1122,11 @@ void WS2812FX::resetSegments() {
_segments[0].mode = DEFAULT_MODE;
_segments[0].colors[0] = DEFAULT_COLOR;
_segments[0].start = 0;
_segments[0].startY = 0;
_segments[0].speed = DEFAULT_SPEED;
_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].setOption(SEG_OPTION_SELECTED, 1);
_segments[0].setOption(SEG_OPTION_ON, 1);
@ -1046,7 +1136,7 @@ void WS2812FX::resetSegments() {
_segments[0].custom2 = DEFAULT_C2;
_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].grouping = 1;
@ -1058,23 +1148,25 @@ void WS2812FX::resetSegments() {
_segments[i].custom1 = DEFAULT_C1;
_segments[i].custom2 = DEFAULT_C2;
_segments[i].custom3 = DEFAULT_C3;
_segments[i].runtime.markForReset();
_segments[i].markForReset();
}
_segments[0].runtime.markForReset();
_segments[0].markForReset();
*/
}
void WS2812FX::makeAutoSegments(bool forceReset) {
if (isMatrix) {
#ifndef WLED_DISABLE_2D
// only create 1 2D segment
uint8_t mainSeg = getMainSegmentId();
if (forceReset) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
setSegment(i, 0, 0);
}
}
if (getActiveSegmentsNum() < 2) {
setSegment(mainSeg, 0, matrixWidth, 1, 0, 0, 0, matrixHeight);
if (forceReset || getActiveSegmentsNum() == 0) resetSegments(); // initialises 1 segment
else if (getActiveSegmentsNum() == 1) {
_segments[0].start = 0;
_segments[0].stop = matrixWidth;
_segments[0].startY = 0;
_segments[0].stopY = matrixHeight;
_segments[0].grouping = 1;
_segments[0].spacing = 0;
_mainSegment = 0;
}
#endif
} else if (autoSegments) { //make one segment per bus
@ -1085,7 +1177,7 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
Bus* b = busses.getBus(i);
segStarts[s] = b->getStart();
segStops[s] = segStarts[s] + b->getLength();
segStops[s] = segStarts[s] + b->getLength();
//check for overlap with previous segments
for (uint8_t j = 0; j < s; j++) {
@ -1098,22 +1190,24 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
}
s++;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
_segments[i].setOption(SEG_OPTION_SELECTED, true);
setSegment(i, segStarts[i], segStops[i]);
_segments.clear();
for (uint8_t i = 0; i < s; 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 {
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
uint8_t mainSeg = getMainSegmentId();
if (forceReset) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
setSegment(i, 0, 0);
}
}
if (getActiveSegmentsNum() < 2) {
setSegment(mainSeg, 0, _length);
else if (getActiveSegmentsNum() == 1) {
_segments[0].start = 0;
_segments[0].stop = _length;
_mainSegment = 0;
}
}
@ -1122,26 +1216,32 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
void WS2812FX::fixInvalidSegments() {
//make sure no segment is longer than total (sanity check)
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].start >= _length) setSegment(i, 0, 0);
if (_segments[i].stop > _length) setSegment(i, _segments[i].start, _length);
size_t i = 0;
for (std::vector<Segment>::iterator it = _segments.begin(); it != _segments.end(); i++, it++) {
if (_segments[i].start >= _length) { _segments.erase(it); i--; it--; continue; }
if (_segments[i].stop > _length) _segments[i].stop = _length;
// 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
bool WS2812FX::checkSegmentAlignment() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].start >= _segments[i].stop) continue; //inactive segment
bool aligned = false;
bool aligned = false;
for (segment &seg : _segments) {
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
for (uint8_t b = 0; b<busses.getNumBusses(); 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;
}
return true;
@ -1153,7 +1253,8 @@ bool WS2812FX::checkSegmentAlignment() {
uint8_t WS2812FX::setPixelSegment(uint8_t n)
{
uint8_t prevSegId = _segment_index;
if (n < MAX_NUM_SEGMENTS) {
if (n < _segments.size()) {
// if (n < getMaxSegments()) {
_segment_index = n;
_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)
{
unsigned long waitMax = millis() + 22; //refresh after 20 ms if transition enabled
for (uint16_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && !_segments[i].getOption(SEG_OPTION_TRANSITIONAL)) {
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;
}
}
}
for (segment &seg : _segments) seg.startTransition(t ? getTransition() : 0);
// for (uint8_t i = 0; i < getMaxSegments(); i++) {
// Segment &seg = getSegment(i);
// seg.startTransition(t ? getTransition() : 0);
// }
}
void WS2812FX::load_gradient_palette(uint8_t index)
@ -1313,7 +1405,7 @@ void WS2812FX::handle_palette(void)
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);
} else
@ -1428,180 +1520,7 @@ int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0;
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"])=====";
/*
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"=====([
"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",

View File

@ -225,6 +225,7 @@
#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_FREEZE 5 //Segment contents will not be refreshed
#define SEG_OPTION_RESET 6 //Segment runtime requires reset
#define SEG_OPTION_TRANSITIONAL 7
#define SEG_OPTION_REVERSED_Y 8
#define SEG_OPTION_MIRROR_Y 9

View File

@ -2363,6 +2363,11 @@ function rSegs()
bt.style.color = "var(--c-f)";
bt.innerHTML = "Reset segments";
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});
requestJson(obj);
}

View File

@ -6,9 +6,38 @@
<title>WLED Settings</title>
<script>
var d=document;
var loc = false, locip;
function gId(n){return d.getElementById(n);}
function S(){GetV();}
function GetV(){}
// 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!");
});
}
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>
<style>
body {

View File

@ -41,8 +41,6 @@
}
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
//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;
@ -104,9 +102,6 @@ Serpentine: <input type="checkbox" name="P${i}S"></div>`;
gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none";
gId("pnl_rem").style.display = (i>1) ? "inline":"none";
}
//values injected by server while sending HTML
//fun-ction GetV() {}
</script>
<style>@import url("style.css");</style>
</head>

View File

@ -6,35 +6,65 @@
<meta charset="utf-8">
<title>DMX Settings</title>
<script>
function GCH(num) {
d=document;
d.getElementById('dmxchannels').innerHTML += "";
for (i=0;i<num;i++) {
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 mMap(){
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;
var d=document;
var loc = false, locip;
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
function B(){window.history.back();}
function GCH(num) {
d.getElementById('dmxchannels').innerHTML += "";
for (i=0;i<num;i++) {
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 S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();}
function GetV(){}
function mMap(){
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;
}
}
}
// 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>
<style>@import url("style.css");</style>
</head>

View File

@ -8,10 +8,29 @@
<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 customStarts=false,startsDirty=[],maxCOOverrides=5;
var loc = false, locip;
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
function B(){window.open("/settings","_self");}
function gId(n){return d.getElementById(n);}
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;
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 GetV()
{
//values injected by server while sending HTML
//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;
//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;
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=2';
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>

View File

@ -7,11 +7,30 @@
<title>Misc Settings</title>
<script>
var d = document;
var loc = false, locip;
function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); }
function B() { window.open("/settings","_self"); }
function U() { window.open("/update","_self"); }
function gId(s) { return d.getElementById(s); }
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;
function showToast(text, error = false)
{
@ -40,16 +59,24 @@
event.preventDefault();
return false;
}
function GetV()
{
//values injected by server while sending HTML
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=6';
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>
</head>
<body onload="GetV()">
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<div class="toprow">
<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 charset="utf-8">
<title>Sync Settings</title>
<script>var d=document;
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++)
<script>var d=document;
var loc = false, locip;
function gId(s)
{
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
return d.getElementById(s);
}
}
function GC()
{
var a=0, b=0;
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;} }
// 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;
for(j=0;j<8;j++)
{
a+=gId("G"+(j+1)).checked*m;
b+=gId("R"+(j+1)).checked*m;
m*=2;
var m=1;
for(j=0;j<8;j++)
{
a+=gId("G"+(j+1)).checked*m;
b+=gId("R"+(j+1)).checked*m;
m*=2;
}
gId("GS").value=a;
gId("GR").value=b;
}
gId("GS").value=a;
gId("GR").value=b;
}
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
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(){GetV();SetVal();}
function GetV(){var d=document;}
</script>
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
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(){
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=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>
</head>
<body onload="S()">

View File

@ -7,26 +7,42 @@
<title>Time Settings</title>
<script>
var d=document;
var loc = false, locip;
var el=false;
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
function H()
{
window.open("https://kno.wled.ge/features/settings/#time-settings");
function H() { window.open("https://kno.wled.ge/features/settings/#time-settings"); }
function B() { window.open("/settings","_self"); }
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()
{
window.open("/settings","_self");
}
function S()
{
BTa();GetV();updLoc();Cs();FC();
}
function gId(s)
{
return d.getElementById(s);
}
function gN(s) {
return d.getElementsByName(s)[0];
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=5';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
function expand(o,i)
{
@ -34,10 +50,7 @@
t.style.display = t.style.display!=="none" ? "none" : "";
o.innerHTML = t.style.display==="none" ? "&#128197;" : "&#x2715;";
}
function Cs()
{
gId("cac").style.display=(gN("OL").checked)?"block":"none";
}
function Cs() { gId("cac").style.display=(gN("OL").checked)?"block":"none"; }
function BTa()
{
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.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>
<style>@import url("style.css");</style>
</head>

View File

@ -7,6 +7,7 @@
<title>UI Settings</title>
<script>
var d = document;
var loc = false, locip;
var initial_ds, initial_st, initial_su;
var sett = null;
var l = {
@ -41,10 +42,7 @@
}
}
};
function gId(s)
{
return d.getElementById(s);
}
function gId(s) { return d.getElementById(s); }
function isObject(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();
}
// 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()
{
GetV();
initial_ds = d.Sf.DS.value;
initial_st = d.Sf.ST.checked;
initial_su = d.Sf.SU.checked;
GetLS();
}
function H()
{
window.open("https://kno.wled.ge/features/settings/#user-interface-settings");
}
function B()
{
window.open("/settings","_self");
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=3';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
function B() { window.open("/settings","_self"); }
function UI()
{
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
@ -214,7 +233,6 @@
fO.value = '';
return false;
}
function GetV(){var d=document;}
</script>
<style>@import url("style.css");</style>
</head>

View File

@ -192,7 +192,6 @@
e.preventDefault();
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
}
//fun-ction GetV() {} // replaced during 'npm run build'
</script>
<style>@import url("style.css");</style>
</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"/>
<title>WiFi Settings</title>
<script>
var d=document;
var loc = false, locip;
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
function B(){window.open("/settings","_self");}
function GetV()
{
//values injected by server while sending HTML
// 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!");
});
}
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>
<style>@import url("style.css");</style>
</head>
<body onload="GetV()">
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<div class="toprow">
<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!!
const uint16_t PAGE_index_L = 28426;
const uint16_t PAGE_index_L = 28450;
const uint8_t PAGE_index[] PROGMEM = {
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,
@ -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,
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,
0x99, 0x30, 0x07, 0x29, 0x1a, 0xa1, 0x30, 0xce, 0xe3, 0x52, 0x33, 0xfe, 0xbf, 0xe2, 0xae, 0xff,
0xa9, 0x71, 0x23, 0xd9, 0xff, 0xfe, 0xfe, 0x0a, 0xa3, 0x24, 0x20, 0x1d, 0x02, 0x64, 0xb3, 0x9b,
0xec, 0xda, 0xc8, 0xae, 0x3d, 0x36, 0xf7, 0x8e, 0xba, 0x64, 0x1f, 0x15, 0xf6, 0xb2, 0x97, 0xa2,
0xa8, 0xc3, 0x36, 0x63, 0xac, 0x5a, 0x21, 0x29, 0x96, 0x58, 0xe0, 0x19, 0xff, 0xef, 0xaf, 0xbb,
0xe7, 0xfb, 0x48, 0xb2, 0xcd, 0x26, 0x75, 0xaf, 0x2a, 0x1b, 0x60, 0x34, 0x1a, 0xf5, 0xcc, 0xf4,
0xf4, 0xf4, 0xf4, 0x74, 0x7f, 0xba, 0x91, 0x4c, 0x7d, 0x19, 0xec, 0x37, 0x92, 0x8f, 0xb7, 0xd1,
0xcd, 0xa4, 0xdb, 0x4f, 0x1a, 0xe8, 0xc4, 0x0a, 0x16, 0x35, 0x26, 0xe4, 0x76, 0xca, 0xce, 0x4b,
0x1e, 0xb3, 0x6b, 0x13, 0x84, 0x58, 0x00, 0x6a, 0xbc, 0xcb, 0x5a, 0xa8, 0x14, 0xbc, 0xf7, 0xfe,
0x7e, 0x21, 0x5f, 0x2c, 0x6b, 0x96, 0x4b, 0xdf, 0x1d, 0x4b, 0xd3, 0x16, 0xda, 0x8d, 0xfe, 0x52,
0xaa, 0x19, 0x34, 0x9b, 0xfc, 0xb8, 0x5d, 0x8b, 0xd6, 0x48, 0x6f, 0xd3, 0xf0, 0x2f, 0x46, 0x3e,
0x3c, 0xd9, 0xca, 0x00, 0x3d, 0x67, 0x78, 0x38, 0x4a, 0x8a, 0x7a, 0xe8, 0xa2, 0xba, 0x35, 0x50,
0x41, 0x42, 0xf3, 0x49, 0x61, 0x3d, 0x1a, 0xf9, 0x68, 0x50, 0x47, 0x99, 0x0a, 0xa7, 0x36, 0x95,
0xa0, 0x0b, 0xbd, 0xb8, 0x8c, 0x77, 0xf2, 0xee, 0x75, 0x0b, 0x3e, 0x48, 0x5f, 0xbf, 0x6e, 0x9f,
0xcf, 0xe4, 0xc7, 0x74, 0xb8, 0x12, 0xb5, 0xda, 0x58, 0x0b, 0x16, 0xdf, 0x8f, 0xd9, 0x8d, 0xae,
0xb9, 0xe1, 0xcb, 0xdc, 0xaa, 0xe1, 0x38, 0x68, 0x9e, 0xdb, 0xb1, 0xb8, 0x42, 0xe2, 0x89, 0xcc,
0xc8, 0x6a, 0xac, 0x39, 0xa9, 0x23, 0xb7, 0x00, 0xb6, 0xdc, 0xd2, 0x00, 0x12, 0x86, 0xb9, 0xe3,
0xba, 0xbc, 0xd8, 0xab, 0x8d, 0x94, 0x59, 0xdd, 0x08, 0x33, 0x66, 0x09, 0x51, 0xb6, 0x16, 0x09,
0xe9, 0x62, 0x7e, 0x3f, 0x9b, 0xa5, 0x8c, 0x60, 0x21, 0x5b, 0x37, 0x6c, 0x3d, 0x59, 0xe6, 0xa6,
0x8d, 0x53, 0xcc, 0x53, 0x3c, 0x60, 0x72, 0x39, 0x4d, 0xeb, 0xf3, 0x73, 0x86, 0x8e, 0xc9, 0x2e,
0x78, 0xd1, 0x76, 0xd0, 0x45, 0x3a, 0xc2, 0x7a, 0x03, 0x84, 0x2c, 0xa1, 0x11, 0xa1, 0x8c, 0x9a,
0x25, 0x59, 0x52, 0xb1, 0xf4, 0x69, 0xab, 0x2e, 0x14, 0xeb, 0xfa, 0x90, 0xa1, 0xf9, 0x10, 0xe8,
0x95, 0x94, 0x7f, 0x1d, 0xd9, 0x7a, 0x7a, 0x38, 0x67, 0xa8, 0xf9, 0x91, 0x48, 0x0e, 0xe2, 0x43,
0xb6, 0xe3, 0xb3, 0x27, 0x5f, 0xd5, 0xfa, 0xa3, 0xe8, 0x63, 0xa3, 0x12, 0xed, 0xea, 0xcb, 0x66,
0x17, 0x0d, 0xcd, 0xd8, 0xe8, 0x1e, 0x6a, 0xd2, 0xdd, 0xde, 0x0f, 0xa4, 0x59, 0x47, 0x62, 0xff,
0xe6, 0x94, 0x64, 0xfd, 0xee, 0x6a, 0xd8, 0xc1, 0xbb, 0x13, 0xa5, 0xcb, 0xda, 0x2a, 0x15, 0x8c,
0x37, 0x30, 0xbe, 0xf0, 0x86, 0xea, 0xf3, 0xbc, 0x5f, 0x27, 0xfc, 0x8a, 0xce, 0xa8, 0x44, 0x37,
0x88, 0xb8, 0x93, 0x1b, 0xc4, 0xf0, 0x25, 0xd3, 0x32, 0xe0, 0xe4, 0xc1, 0x0f, 0x84, 0xc4, 0x26,
0xf7, 0x60, 0x8c, 0x97, 0xf5, 0x17, 0x28, 0x4e, 0xf8, 0x39, 0x5b, 0xef, 0x88, 0xbc, 0xe1, 0x07,
0x18, 0x36, 0xa5, 0x6e, 0xd4, 0x2a, 0x20, 0x3c, 0x1a, 0x0c, 0x60, 0x59, 0xe5, 0x0b, 0xe9, 0xc6,
0x65, 0x54, 0xfe, 0x76, 0xa9, 0x15, 0x30, 0x34, 0x9c, 0xe3, 0xfc, 0xf1, 0xfe, 0x38, 0x99, 0x37,
0x6a, 0x73, 0xb2, 0x85, 0x4e, 0x5f, 0xc1, 0x57, 0xcf, 0x53, 0xea, 0x64, 0xd8, 0x91, 0xea, 0xec,
0x56, 0x19, 0x4f, 0x3e, 0xc2, 0x9b, 0x8e, 0xfa, 0x7f, 0xbd, 0x92, 0xd8, 0x19, 0xe5, 0x06, 0xac,
0x62, 0x97, 0x55, 0x2d, 0x5c, 0x83, 0x33, 0x9e, 0x96, 0xa0, 0x33, 0x21, 0x70, 0x89, 0x8c, 0x95,
0x25, 0x9d, 0x2b, 0x14, 0xca, 0xee, 0x9a, 0x75, 0x43, 0x29, 0x2d, 0x27, 0xb4, 0x6c, 0xc4, 0xba,
0xf8, 0xd3, 0x17, 0xf3, 0x5a, 0xd2, 0x2f, 0xd0, 0x11, 0x4f, 0x1a, 0x81, 0x26, 0x78, 0x2d, 0xf4,
0x32, 0xda, 0xcb, 0xff, 0x47, 0xda, 0x4f, 0xf9, 0x47, 0x35, 0x78, 0x57, 0x9e, 0x71, 0x39, 0xf5,
0x02, 0xea, 0x89, 0xaa, 0x17, 0x53, 0x7d, 0xed, 0x00, 0xc2, 0xa8, 0x5b, 0x99, 0xbb, 0x71, 0x41,
0xa6, 0x59, 0xf3, 0x6f, 0x23, 0x4d, 0x55, 0x59, 0x43, 0x9a, 0x86, 0x3e, 0xfe, 0xc4, 0x6e, 0xa0,
0x5a, 0x7f, 0x37, 0x9b, 0x94, 0xc5, 0xa0, 0x6d, 0xe1, 0x1b, 0x44, 0xa7, 0x77, 0x05, 0x90, 0x64,
0x2f, 0x48, 0x67, 0xc1, 0x5e, 0x0f, 0x54, 0xde, 0x0e, 0x1e, 0x1a, 0x6b, 0x11, 0x44, 0x37, 0xf4,
0x65, 0xd3, 0x71, 0xa3, 0x5a, 0xa1, 0xfd, 0x0a, 0x5d, 0x09, 0x54, 0x3e, 0xcd, 0x94, 0xa8, 0x13,
0xa0, 0x26, 0x26, 0xfe, 0x35, 0x25, 0x87, 0x35, 0xbe, 0x58, 0x52, 0x7a, 0x41, 0x6b, 0x9d, 0x4b,
0xb8, 0x8d, 0xeb, 0xed, 0x30, 0x88, 0x3b, 0x84, 0x15, 0xc1, 0x46, 0x3c, 0x51, 0xb0, 0xc6, 0x55,
0xa5, 0x5e, 0x57, 0x8f, 0x2f, 0x41, 0x25, 0x86, 0x3e, 0x8c, 0x64, 0x6a, 0xa3, 0xad, 0xa0, 0x89,
0x1d, 0x41, 0xa4, 0xd3, 0x81, 0x75, 0x68, 0xc6, 0xfb, 0x6b, 0x6c, 0xb2, 0xa5, 0x05, 0xa3, 0xac,
0xe9, 0x31, 0xc8, 0x51, 0xb9, 0x4c, 0xcd, 0x1e, 0xfd, 0x9e, 0x36, 0x75, 0xe8, 0x68, 0xd8, 0x24,
0x1b, 0xe7, 0xde, 0xd0, 0x4f, 0x19, 0xae, 0x55, 0x46, 0xb7, 0x96, 0x30, 0xbd, 0x78, 0x05, 0x65,
0x90, 0xc9, 0xe5, 0x5a, 0x60, 0xbd, 0xfc, 0x2d, 0xa6, 0xd0, 0x16, 0x43, 0x4a, 0x9b, 0xe4, 0x9e,
0xdc, 0x24, 0x71, 0x57, 0xdc, 0x93, 0xba, 0xc3, 0xd7, 0xaf, 0x40, 0xf8, 0xc0, 0xc8, 0xbb, 0x80,
0xd9, 0xea, 0x14, 0xea, 0xd4, 0x08, 0x0a, 0x2e, 0xa6, 0xd2, 0xc6, 0x19, 0xf0, 0xfe, 0x47, 0xa5,
0xcb, 0x7c, 0x48, 0xaa, 0x39, 0xcf, 0x7e, 0x09, 0x5f, 0xfd, 0x27, 0xc8, 0x5c, 0x11, 0x09, 0x20,
0xca, 0x56, 0xd6, 0xb2, 0x5d, 0x0f, 0x0b, 0x49, 0x83, 0x37, 0x2d, 0x1d, 0x55, 0x03, 0xfe, 0x3c,
0x2d, 0xb5, 0xb2, 0x81, 0xbd, 0x7e, 0x7e, 0xae, 0x9a, 0x40, 0x1e, 0xbf, 0x02, 0xe5, 0xb1, 0x69,
0x4a, 0x8a, 0xbc, 0x67, 0x66, 0xfd, 0xea, 0x49, 0x84, 0x9b, 0x77, 0xe7, 0x67, 0x9d, 0x29, 0xcf,
0x16, 0xab, 0x72, 0x78, 0x76, 0x74, 0xae, 0x4f, 0xf1, 0xf6, 0xb8, 0x48, 0x88, 0xa3, 0x55, 0x03,
0x50, 0x60, 0xe5, 0xff, 0x6c, 0xfb, 0x68, 0xd7, 0xfc, 0x68, 0x57, 0xcc, 0x42, 0xb9, 0x6a, 0xdd,
0x52, 0x49, 0xc0, 0x57, 0x39, 0x26, 0x3b, 0x6e, 0x51, 0x75, 0xf4, 0x3e, 0x74, 0xe3, 0xea, 0x3d,
0x4a, 0xd3, 0xd1, 0x29, 0x99, 0x0d, 0x7d, 0x07, 0x93, 0x26, 0xa3, 0xbe, 0xd3, 0x55, 0xfa, 0x0e,
0x4e, 0x3a, 0xeb, 0xd7, 0x13, 0x43, 0xaf, 0x86, 0x2d, 0xd4, 0xe1, 0xb4, 0x6f, 0xde, 0xf3, 0xd1,
0x5b, 0xfc, 0x9c, 0x6f, 0xf9, 0xd2, 0x1c, 0xbd, 0xd6, 0xd6, 0x24, 0x4d, 0xc6, 0xd8, 0x77, 0x13,
0x86, 0x92, 0x13, 0xb8, 0xd7, 0xfe, 0x45, 0x1a, 0x8a, 0xbd, 0x7d, 0xb6, 0xbf, 0x77, 0xc3, 0x52,
0x1b, 0xff, 0xf2, 0xdc, 0xa7, 0xf2, 0xad, 0xe1, 0x2f, 0x39, 0x86, 0xe6, 0x5e, 0x7f, 0x6f, 0x5b,
0x3b, 0xe5, 0xb9, 0x6d, 0xa8, 0xdc, 0x5b, 0x19, 0x94, 0x37, 0xb2, 0x02, 0x26, 0xa6, 0x16, 0x5d,
0xf2, 0x26, 0x05, 0xcf, 0x49, 0x30, 0x35, 0xa6, 0x13, 0x9f, 0x6b, 0x04, 0x57, 0xd9, 0x77, 0x5b,
0xa8, 0x00, 0x57, 0x60, 0xb7, 0x64, 0x5e, 0x58, 0x6c, 0xe3, 0xda, 0x39, 0x52, 0x09, 0x33, 0x27,
0xf7, 0x32, 0xe5, 0xf6, 0x24, 0x6e, 0xea, 0x1c, 0x34, 0xb9, 0x63, 0xc1, 0x72, 0x7e, 0x9a, 0xe4,
0x15, 0xcf, 0xc6, 0x64, 0x3b, 0x71, 0x71, 0xc0, 0x87, 0x90, 0x99, 0x51, 0x8f, 0x0d, 0xa9, 0xdb,
0xf4, 0x05, 0x99, 0xd0, 0x23, 0xfd, 0x28, 0x90, 0x79, 0xf2, 0xd0, 0x17, 0x62, 0xdb, 0x7b, 0xbb,
0x29, 0xcb, 0xc8, 0x1b, 0x41, 0x5c, 0x8e, 0x16, 0xe5, 0xdf, 0xb8, 0x1b, 0x4c, 0x33, 0xcd, 0x70,
0xac, 0xab, 0x1d, 0x26, 0x95, 0x2d, 0xab, 0x6a, 0xc4, 0xfb, 0x02, 0xa1, 0x8d, 0xcf, 0xbd, 0x7a,
0x06, 0x15, 0xc3, 0xd0, 0x85, 0x0c, 0xae, 0xac, 0xdf, 0x27, 0x0a, 0x51, 0x59, 0xdd, 0x83, 0xbd,
0x89, 0xbe, 0x83, 0x8d, 0x24, 0x4f, 0x51, 0xe8, 0xc4, 0x3d, 0x09, 0xa0, 0xd5, 0xa2, 0xfc, 0xdb,
0x9a, 0x3e, 0x5a, 0x39, 0xd4, 0x9a, 0x08, 0x45, 0xfe, 0x17, 0xa5, 0xf5, 0x7b, 0xdf, 0xba, 0xb6,
0x0f, 0x05, 0x44, 0x86, 0x96, 0x27, 0xb1, 0xdb, 0xcb, 0xdb, 0x13, 0xad, 0xb0, 0x07, 0x0a, 0x9e,
0x8b, 0xef, 0xe4, 0xc2, 0x80, 0x7f, 0xa3, 0x08, 0xdf, 0xac, 0xad, 0xa7, 0x07, 0x30, 0xdf, 0x06,
0x7b, 0x73, 0x33, 0xd6, 0xf6, 0xcb, 0x57, 0x9a, 0x8a, 0x6b, 0x37, 0x3e, 0xf2, 0xbe, 0xc7, 0x1c,
0x47, 0x4d, 0xce, 0xfb, 0xfb, 0x05, 0xf9, 0x67, 0xb5, 0x50, 0xfb, 0x51, 0x59, 0x58, 0x5a, 0x2a,
0x7c, 0x03, 0xc4, 0xed, 0x77, 0x57, 0x5b, 0x7d, 0x4c, 0x4e, 0xdf, 0x2b, 0x98, 0xbe, 0xb5, 0xf7,
0x30, 0xb6, 0x3c, 0xb5, 0x94, 0x10, 0x49, 0x2f, 0x17, 0xa6, 0xdf, 0xbf, 0x7e, 0x7d, 0x7c, 0xc8,
0xe5, 0x69, 0x74, 0xd8, 0x83, 0x6d, 0x91, 0x15, 0xf0, 0x4b, 0xd7, 0x3c, 0x6c, 0x92, 0x79, 0xaa,
0x36, 0xe3, 0x4a, 0xc9, 0x70, 0xcd, 0x53, 0x47, 0x5d, 0xcc, 0x75, 0x58, 0x36, 0xf7, 0xf6, 0xcf,
0xe8, 0x80, 0x1e, 0x51, 0xd9, 0x05, 0xd5, 0x81, 0xa8, 0xb9, 0x03, 0x1f, 0xb7, 0xa3, 0xdf, 0x32,
0x86, 0xad, 0xed, 0xc6, 0x1a, 0x1e, 0xac, 0x4b, 0xf0, 0x97, 0xf0, 0x60, 0x0d, 0xc5, 0x58, 0x5e,
0x58, 0x38, 0xcc, 0xa1, 0xae, 0xb6, 0x6a, 0x50, 0x75, 0x7c, 0x49, 0x09, 0xe9, 0x89, 0x19, 0x24,
0xd1, 0x5c, 0x6d, 0xb8, 0x9f, 0x61, 0x96, 0xf4, 0x8c, 0xc1, 0xf1, 0x65, 0x5c, 0x75, 0x40, 0xb5,
0x03, 0xd5, 0xa9, 0xa7, 0xb2, 0xa5, 0xc3, 0x7e, 0x8d, 0xaf, 0x63, 0x2a, 0x72, 0xa1, 0x57, 0xed,
0x78, 0xca, 0x22, 0x1a, 0x59, 0x03, 0x14, 0x5d, 0x9d, 0x44, 0xda, 0x92, 0xe8, 0x3e, 0x8b, 0xab,
0x45, 0x30, 0xf8, 0x0a, 0xd1, 0xbd, 0x46, 0x44, 0x7b, 0xc3, 0x9a, 0xd7, 0x82, 0x96, 0xd9, 0xf2,
0x42, 0xaf, 0x1b, 0x45, 0x86, 0xfc, 0x26, 0xf7, 0x39, 0xf3, 0xc6, 0xe7, 0xda, 0x34, 0xde, 0x12,
0x92, 0xd9, 0x7f, 0x46, 0xac, 0x9b, 0x1b, 0xed, 0xb2, 0xed, 0x7d, 0x8e, 0x67, 0x20, 0x5f, 0xde,
0x34, 0x7a, 0xaa, 0x76, 0x7d, 0xd7, 0x93, 0x84, 0x34, 0x6c, 0x7c, 0x6d, 0x5a, 0x41, 0xe9, 0x5c,
0xad, 0x49, 0xa5, 0x40, 0x1a, 0xb9, 0x66, 0xa0, 0xeb, 0x57, 0xfd, 0x94, 0xcd, 0xaa, 0xc1, 0xb6,
0x52, 0x54, 0x9a, 0x67, 0x24, 0x1f, 0x6f, 0xf9, 0xe1, 0xb4, 0xf1, 0xcb, 0x64, 0xe0, 0xd8, 0xfe,
0xd3, 0x82, 0x79, 0x75, 0x16, 0x7a, 0xc3, 0xe9, 0x89, 0xf4, 0x75, 0xe6, 0x02, 0x30, 0x09, 0xcd,
0x5e, 0x9b, 0xa6, 0x07, 0xfa, 0x49, 0x83, 0x19, 0xb8, 0x6a, 0xc2, 0x4f, 0x11, 0xb5, 0x7b, 0x4d,
0xb5, 0x79, 0xf0, 0x87, 0x78, 0xc9, 0xa2, 0x86, 0x72, 0xfb, 0x30, 0x99, 0xb3, 0x0f, 0xdb, 0x61,
0x27, 0xc0, 0xc6, 0x23, 0x89, 0x72, 0x55, 0x5d, 0xf7, 0xa9, 0xe1, 0x03, 0xcc, 0x21, 0x0b, 0xba,
0x7b, 0x1d, 0x1b, 0x4a, 0x01, 0xa2, 0x11, 0x08, 0x5a, 0xd8, 0x0c, 0xcd, 0x29, 0x8a, 0x31, 0xa7,
0x04, 0x02, 0xda, 0x8d, 0x6f, 0x69, 0x0f, 0xb0, 0xc3, 0x02, 0xe5, 0x6d, 0xad, 0x1a, 0x1d, 0x0a,
0x82, 0xbb, 0xbc, 0x5a, 0x39, 0xd0, 0xc2, 0x1c, 0x59, 0x9c, 0x70, 0x85, 0xb9, 0x0f, 0x3f, 0x62,
0xa4, 0xa2, 0x97, 0x68, 0x89, 0xf1, 0x88, 0xe8, 0x2e, 0xcf, 0xc7, 0x90, 0xfc, 0x2f, 0xb4, 0xbb,
0x5b, 0x55, 0xfb, 0xd8, 0x8f, 0x8f, 0xf8, 0xad, 0x36, 0xcc, 0xf0, 0xc1, 0x1f, 0x21, 0xa2, 0x84,
0x83, 0x18, 0x7c, 0xbf, 0x92, 0xe1, 0xd3, 0x31, 0x0b, 0xd7, 0xd3, 0xb2, 0x8e, 0x12, 0xdb, 0x61,
0x94, 0x22, 0x03, 0x11, 0xdb, 0x99, 0x3e, 0x64, 0xa1, 0x9f, 0x99, 0x68, 0xe8, 0x96, 0x37, 0xa9,
0x00, 0xd3, 0xb7, 0xf9, 0x4e, 0xcd, 0xb0, 0x74, 0x22, 0x2b, 0x37, 0x22, 0xd2, 0x65, 0x9b, 0x10,
0xe9, 0xf0, 0xee, 0x21, 0xda, 0x89, 0x33, 0x79, 0x61, 0x6c, 0xd6, 0x02, 0x96, 0x30, 0xae, 0x65,
0xc6, 0xd6, 0xb3, 0xbb, 0xc4, 0x78, 0x94, 0xc7, 0xad, 0xbd, 0x0a, 0x13, 0xeb, 0x59, 0xf1, 0xb0,
0xb0, 0x00, 0x6b, 0x74, 0x02, 0x45, 0xcc, 0x69, 0xa8, 0x03, 0x29, 0x69, 0xb8, 0xb2, 0x7e, 0x15,
0xf2, 0xd4, 0x3a, 0x30, 0x47, 0x78, 0xa1, 0x51, 0xf3, 0x8e, 0x29, 0x11, 0xac, 0x3d, 0x83, 0xe1,
0xfe, 0xd2, 0x4f, 0xc3, 0xbb, 0xa4, 0x3f, 0x0e, 0xd1, 0xb9, 0x39, 0x9c, 0x2c, 0x92, 0x7e, 0x63,
0xbf, 0x09, 0xb4, 0x5e, 0xa1, 0xf5, 0xc1, 0x6c, 0xe4, 0xab, 0xd5, 0xc0, 0xc1, 0xfb, 0x33, 0x80,
0xed, 0xa6, 0x5b, 0x00, 0xdb, 0xdd, 0x6c, 0x06, 0xb6, 0x0b, 0x8b, 0xe6, 0x3a, 0xf9, 0x4c, 0x4f,
0x03, 0x8f, 0x6e, 0x81, 0x96, 0xe3, 0xa9, 0x0c, 0x81, 0x2c, 0xa6, 0xf1, 0x8d, 0xf8, 0x3d, 0x9f,
0xc5, 0xc5, 0x8a, 0xff, 0x0a, 0x9c, 0x41, 0x61, 0x0e, 0x3c, 0x17, 0x17, 0xb3, 0xfd, 0x71, 0x17,
0xe6, 0xb5, 0xac, 0x70, 0x6c, 0xfa, 0xcf, 0xf0, 0x90, 0x33, 0x33, 0x64, 0xcf, 0xc9, 0x9e, 0x9f,
0x77, 0x6a, 0xe5, 0xd9, 0x49, 0x5c, 0x06, 0x37, 0x72, 0x09, 0x71, 0x24, 0x67, 0xce, 0x7a, 0x5f,
0x31, 0xf3, 0x7c, 0xf6, 0x92, 0xf2, 0xe7, 0xb5, 0x40, 0x84, 0x26, 0x7a, 0x62, 0xbe, 0x11, 0x39,
0x71, 0x90, 0xf2, 0xe1, 0xa7, 0xa4, 0x39, 0xf1, 0x38, 0x94, 0x7f, 0xe6, 0xc5, 0x6f, 0x71, 0x8d,
0x8c, 0x31, 0x92, 0x91, 0xaf, 0xda, 0x59, 0x28, 0xd9, 0x82, 0x85, 0x16, 0x5b, 0xb0, 0xd0, 0x74,
0x33, 0x0b, 0xa5, 0x8a, 0x85, 0x12, 0x49, 0x34, 0xb0, 0xd0, 0x42, 0xfc, 0x0e, 0x2c, 0x34, 0x5d,
0x99, 0xbc, 0x92, 0x9a, 0xbc, 0xa2, 0x26, 0x64, 0xa9, 0xf3, 0x2e, 0x8c, 0x9a, 0xb4, 0x40, 0x50,
0xf9, 0xe6, 0x68, 0xaa, 0xb9, 0x83, 0x5d, 0x22, 0x01, 0x55, 0x59, 0x5b, 0xb5, 0xe1, 0x89, 0xb8,
0x92, 0x85, 0xbd, 0x6b, 0x07, 0x6f, 0x5b, 0x65, 0x53, 0x07, 0x07, 0xad, 0x02, 0x11, 0xe7, 0x36,
0x02, 0xc9, 0x67, 0x87, 0x9b, 0x63, 0xfe, 0x4c, 0x02, 0x3a, 0x6e, 0x7c, 0x09, 0x57, 0x7b, 0xab,
0x98, 0xb2, 0xa4, 0xa8, 0xcc, 0x15, 0xb9, 0xa6, 0xad, 0xdf, 0xec, 0xa6, 0x7e, 0x6b, 0x6f, 0xe9,
0xe7, 0x64, 0x4d, 0x3b, 0x20, 0x7b, 0xda, 0xa4, 0x63, 0xbd, 0x9d, 0x75, 0x04, 0xdd, 0xd9, 0x04,
0xdd, 0xad, 0x21, 0xe8, 0x63, 0xb1, 0xa6, 0x9d, 0xaa, 0xb0, 0xda, 0xa9, 0x8a, 0xf6, 0x76, 0x44,
0x9e, 0xd8, 0xf6, 0xb6, 0x40, 0xa6, 0xee, 0xbc, 0x40, 0x88, 0x37, 0xb4, 0x8f, 0x59, 0x61, 0xdb,
0xdb, 0xdf, 0x4a, 0x5c, 0xdb, 0xc1, 0x16, 0x2a, 0x73, 0xa3, 0x8c, 0x83, 0x33, 0xf6, 0xfe, 0x25,
0xc6, 0x9a, 0x78, 0x95, 0x07, 0xc2, 0x81, 0x83, 0x62, 0xc4, 0x94, 0xf2, 0x9d, 0x47, 0x88, 0xdf,
0xc0, 0xc6, 0xae, 0x63, 0x5d, 0x58, 0x1c, 0xbb, 0x91, 0x2a, 0xb5, 0x00, 0x18, 0x1f, 0x9a, 0x4d,
0x41, 0xc3, 0xef, 0xae, 0x82, 0x60, 0x8d, 0x4e, 0x50, 0xfd, 0x4b, 0xd1, 0xc2, 0x63, 0xc7, 0x62,
0x36, 0x62, 0x7a, 0xd1, 0xba, 0x11, 0xa7, 0x7b, 0x32, 0xb4, 0xda, 0xc5, 0x57, 0xeb, 0x8b, 0x59,
0xda, 0x53, 0xf9, 0x48, 0xea, 0xc1, 0xaa, 0x2d, 0xaf, 0x5e, 0x9a, 0xbe, 0xbd, 0x57, 0xd7, 0x86,
0x46, 0x12, 0x09, 0xdd, 0x68, 0xab, 0x00, 0x6f, 0x81, 0xe3, 0xb6, 0x0e, 0xd8, 0xae, 0xb2, 0xe3,
0xbf, 0xa9, 0xdb, 0x61, 0x2b, 0x9d, 0x35, 0xa8, 0x36, 0xb6, 0x01, 0xb7, 0xae, 0x41, 0x5c, 0xcc,
0x1e, 0x35, 0x8b, 0xb0, 0x1a, 0x8b, 0x49, 0x84, 0xc0, 0x97, 0xcd, 0xc0, 0xda, 0x98, 0xdf, 0x6d,
0xe6, 0x61, 0xcb, 0xa0, 0xe1, 0xed, 0x67, 0x43, 0x65, 0xa9, 0xb0, 0xa7, 0x63, 0xc3, 0x6c, 0xb4,
0x13, 0xf6, 0x67, 0x8c, 0x3c, 0xb4, 0xd5, 0x67, 0xee, 0x80, 0xe3, 0x82, 0x76, 0xd6, 0x73, 0x6d,
0x15, 0xd7, 0x31, 0x9c, 0x02, 0x57, 0x32, 0x20, 0x32, 0x82, 0xdf, 0x24, 0x17, 0xca, 0xc7, 0xc6,
0xb6, 0x2c, 0xb4, 0x88, 0x1a, 0x17, 0x28, 0x64, 0x88, 0xc6, 0x26, 0x93, 0xe6, 0x26, 0x6b, 0x70,
0x12, 0xb5, 0x66, 0x39, 0x3e, 0x03, 0xf0, 0x96, 0x84, 0x3a, 0x81, 0x03, 0xd7, 0xf3, 0x33, 0x1b,
0x1e, 0x07, 0xb6, 0xd8, 0x59, 0xad, 0x5c, 0x65, 0x4a, 0x03, 0x50, 0x30, 0xb5, 0x4b, 0x1f, 0x13,
0x5f, 0x72, 0x69, 0x34, 0x3d, 0x8e, 0xcb, 0x7e, 0xcf, 0x2c, 0xe8, 0x41, 0x81, 0xf8, 0xb5, 0x1b,
0x97, 0xae, 0xb8, 0xb1, 0xc8, 0xfa, 0x29, 0xaf, 0xcb, 0x6c, 0x94, 0x53, 0xcc, 0x5d, 0x1b, 0x74,
0xb0, 0x36, 0x0e, 0x69, 0x88, 0x62, 0xb5, 0x1a, 0x88, 0xe0, 0x46, 0x79, 0x81, 0x0a, 0x6b, 0x7e,
0x47, 0x5d, 0xa6, 0x3e, 0x24, 0xa0, 0xba, 0x99, 0x7f, 0xe9, 0xe0, 0xe7, 0x73, 0xb4, 0x01, 0x31,
0x2f, 0x38, 0x89, 0x09, 0x75, 0x59, 0xf8, 0xa3, 0x0a, 0x18, 0xfe, 0x2a, 0x94, 0x2f, 0x05, 0xda,
0x3d, 0xeb, 0xf7, 0x54, 0xff, 0x9e, 0x61, 0x44, 0xa6, 0xf4, 0xdc, 0x04, 0x92, 0x48, 0xd2, 0xe4,
0x19, 0x86, 0x3c, 0x86, 0x86, 0xb6, 0xf1, 0x53, 0x3e, 0x46, 0xe7, 0x62, 0x61, 0x67, 0xea, 0x78,
0xfb, 0xf2, 0x8e, 0x74, 0xdf, 0xeb, 0xf8, 0x1e, 0x5e, 0x04, 0x04, 0xde, 0x1a, 0x59, 0x4c, 0xd7,
0x30, 0x12, 0x35, 0x10, 0xe6, 0xab, 0x38, 0x73, 0x3d, 0xb9, 0xf8, 0x35, 0x92, 0x06, 0xcb, 0x86,
0xde, 0x9e, 0x9d, 0x74, 0x91, 0x1c, 0xa8, 0xdb, 0x76, 0x3b, 0x04, 0x7a, 0xfc, 0xd9, 0xb0, 0xf7,
0x3a, 0x0a, 0x60, 0x85, 0x2f, 0x80, 0x4a, 0xe1, 0x46, 0x7b, 0xf6, 0x1e, 0x94, 0x21, 0x58, 0x6b,
0x13, 0xd6, 0xc1, 0x9b, 0xa6, 0x1c, 0x54, 0x59, 0x56, 0x96, 0x18, 0x6a, 0x47, 0xba, 0x2d, 0xc2,
0xc6, 0xf8, 0xc5, 0x07, 0xc3, 0x72, 0x40, 0x87, 0x72, 0xf1, 0x65, 0xfc, 0xe2, 0x87, 0xd8, 0x87,
0x13, 0xbf, 0xf2, 0x67, 0xf5, 0xb4, 0x83, 0x6e, 0xb0, 0x5f, 0x9c, 0x49, 0xcc, 0xb0, 0xa5, 0x3e,
0xa8, 0x34, 0xd9, 0x1f, 0x82, 0x6a, 0xe4, 0x97, 0xca, 0x55, 0x57, 0x7b, 0x91, 0x85, 0x25, 0x1f,
0x5f, 0xfc, 0x49, 0x91, 0xa5, 0x50, 0x2b, 0x99, 0x18, 0xd4, 0x90, 0x57, 0x87, 0x71, 0x5e, 0x2b,
0x0f, 0x4b, 0xf3, 0x71, 0x59, 0x7f, 0x3c, 0xb5, 0x1e, 0x4f, 0xe7, 0x9f, 0x8d, 0xc7, 0x1e, 0x01,
0xe3, 0xab, 0xc7, 0xe9, 0x9d, 0x52, 0x73, 0x11, 0x72, 0x4c, 0xde, 0xd2, 0x37, 0xcc, 0x86, 0x51,
0x13, 0x61, 0x1a, 0xd4, 0xb1, 0x20, 0x33, 0x5a, 0x1b, 0x17, 0x4a, 0x1d, 0x18, 0x54, 0x8b, 0xa7,
0x65, 0x69, 0xc2, 0x00, 0x66, 0xc1, 0x8a, 0xc7, 0xc4, 0xf2, 0x69, 0x2f, 0x91, 0x6d, 0xe3, 0x2c,
0xcc, 0x94, 0x7b, 0xa7, 0x84, 0x09, 0x43, 0x24, 0x30, 0xe3, 0xc3, 0x78, 0xfd, 0x64, 0xc1, 0x82,
0x7b, 0xbb, 0xdf, 0xbc, 0x7d, 0xf3, 0xe6, 0xcd, 0xa0, 0xc3, 0x59, 0xbd, 0x43, 0x86, 0xbc, 0xce,
0x13, 0xc6, 0x9b, 0x1a, 0x77, 0xa6, 0x1d, 0x72, 0x44, 0xe6, 0xd1, 0xe3, 0xc6, 0xf2, 0x58, 0x7a,
0xc1, 0xf0, 0xa0, 0xfb, 0xe2, 0x4f, 0x5d, 0x3c, 0x81, 0x06, 0xf5, 0x28, 0xb0, 0x9f, 0x92, 0xac,
0x33, 0x25, 0x91, 0xd3, 0xc1, 0xee, 0x99, 0x1f, 0xe5, 0x9f, 0xc3, 0x93, 0x55, 0x7d, 0x41, 0x7e,
0x6d, 0xf7, 0x84, 0x85, 0x93, 0x42, 0x47, 0x8b, 0xf1, 0x2d, 0x03, 0x3e, 0x9e, 0xa1, 0xbb, 0xd4,
0x5d, 0x7e, 0x93, 0xcc, 0x9e, 0x70, 0x15, 0x52, 0xfc, 0x29, 0x5f, 0x8a, 0xa0, 0xdc, 0x71, 0x3e,
0x82, 0x1f, 0x05, 0xae, 0xb3, 0xb8, 0x38, 0x03, 0x96, 0x80, 0x13, 0xe2, 0x87, 0x81, 0x61, 0x3f,
0x10, 0x7e, 0x03, 0x6a, 0xb2, 0x52, 0x03, 0xfc, 0x01, 0x66, 0xe6, 0xf7, 0x34, 0x4e, 0xad, 0xf5,
0x7e, 0x31, 0x26, 0x24, 0x51, 0x5c, 0xe7, 0x7c, 0x85, 0x17, 0x67, 0xf5, 0x25, 0x8e, 0xb0, 0x89,
0x87, 0xf9, 0x88, 0xfb, 0xbc, 0x5f, 0x16, 0x67, 0x57, 0x20, 0x1f, 0x2d, 0x47, 0x79, 0x28, 0xe2,
0x44, 0xd5, 0x8b, 0xf3, 0x7a, 0xd1, 0x97, 0x7a, 0x11, 0x3a, 0xbf, 0xc1, 0x02, 0xd1, 0x1f, 0x58,
0x66, 0xfd, 0xe2, 0x43, 0x08, 0x8c, 0xd4, 0xf7, 0xda, 0x46, 0x0b, 0x41, 0xc2, 0x18, 0xe3, 0x63,
0x94, 0xb1, 0x87, 0xf4, 0x89, 0xc4, 0xcf, 0x8d, 0x9c, 0xb1, 0x43, 0x0f, 0x36, 0x05, 0x64, 0x45,
0x5c, 0xe8, 0xea, 0x43, 0xc8, 0x9a, 0x54, 0x8a, 0x5d, 0xfa, 0x3d, 0xb5, 0x9e, 0xc1, 0xe0, 0x60,
0x59, 0xa0, 0xd3, 0x61, 0xc8, 0xd0, 0x72, 0x1c, 0x0e, 0x6d, 0x17, 0x0e, 0xdd, 0x28, 0xf4, 0xe2,
0xae, 0xfa, 0x09, 0x46, 0x33, 0x8e, 0x42, 0x33, 0x1e, 0x3d, 0x58, 0x85, 0x08, 0xd7, 0x68, 0xc6,
0x84, 0x73, 0xcf, 0x34, 0x29, 0x1f, 0x29, 0x95, 0x94, 0xf4, 0xf6, 0xc6, 0x67, 0x92, 0x91, 0xec,
0x52, 0x0c, 0x93, 0x34, 0xb9, 0x68, 0x7b, 0x5f, 0x36, 0x8f, 0x63, 0xef, 0x91, 0x25, 0x11, 0xc3,
0xaa, 0x9c, 0x76, 0xbb, 0x2f, 0x69, 0xf7, 0xf8, 0xcd, 0x8c, 0xdf, 0x98, 0xa3, 0xcd, 0x5b, 0x0b,
0xc6, 0xb5, 0x82, 0xcf, 0xe6, 0x21, 0x63, 0x9b, 0x10, 0x04, 0xd9, 0x3b, 0xa8, 0x6c, 0x08, 0xb7,
0x73, 0xc7, 0x77, 0xbc, 0xc9, 0x0a, 0x7c, 0x83, 0xb6, 0xae, 0x81, 0x35, 0x86, 0xd3, 0x6c, 0x36,
0xf2, 0xed, 0x36, 0x6f, 0xd0, 0xca, 0xb9, 0x0a, 0x6c, 0x8e, 0x03, 0x12, 0x6b, 0x33, 0x4c, 0x2e,
0xca, 0x5c, 0xb5, 0x9e, 0xd6, 0xa1, 0x38, 0x5f, 0x30, 0x50, 0xf6, 0xf5, 0xfe, 0x0e, 0xbe, 0x6b,
0xd0, 0x07, 0x9a, 0x8c, 0x65, 0xce, 0xd4, 0x30, 0x41, 0x4b, 0x84, 0x6b, 0x8a, 0xd9, 0xc0, 0x08,
0xcb, 0x68, 0x83, 0x47, 0x44, 0x7f, 0xad, 0x2a, 0x68, 0xba, 0x48, 0x78, 0x7c, 0x24, 0x5c, 0xf0,
0x01, 0x26, 0x0f, 0x73, 0x55, 0x4d, 0xf1, 0x0c, 0xb9, 0xf7, 0x9c, 0xe0, 0xcf, 0xfd, 0xc5, 0xed,
0xe4, 0xa2, 0x5a, 0xf8, 0x95, 0x01, 0x7e, 0x08, 0xcc, 0x0f, 0x42, 0x6e, 0x8a, 0xf8, 0xe8, 0x7c,
0x1c, 0xe4, 0x16, 0xe2, 0x22, 0x86, 0x87, 0x36, 0x30, 0xbd, 0x08, 0x6c, 0x50, 0xdb, 0x4b, 0x65,
0x01, 0x2a, 0xb6, 0x22, 0xdf, 0x13, 0xa4, 0xbd, 0x83, 0x84, 0x47, 0xb1, 0x3e, 0x78, 0x12, 0x9c,
0xc7, 0x91, 0x8e, 0xd8, 0x29, 0x4e, 0x45, 0x82, 0x10, 0x6f, 0x01, 0xd2, 0x18, 0x13, 0xcb, 0x2c,
0x41, 0x2f, 0x5c, 0xce, 0xfb, 0xb0, 0xbf, 0xc2, 0xbf, 0x2f, 0x7d, 0x34, 0xba, 0x07, 0x87, 0xa5,
0xe9, 0x19, 0xff, 0x3a, 0xb2, 0x93, 0x97, 0xed, 0x83, 0x06, 0x31, 0xb8, 0xc9, 0x97, 0xec, 0x70,
0x6e, 0x56, 0x3b, 0xfe, 0xde, 0xa9, 0x17, 0xac, 0x1e, 0x60, 0xcc, 0x99, 0x4f, 0x85, 0xe3, 0x49,
0xe9, 0xc3, 0x0b, 0x07, 0x44, 0x51, 0x70, 0x82, 0x4d, 0x70, 0xe2, 0xa0, 0x70, 0xa5, 0xc7, 0x92,
0x71, 0xa0, 0x48, 0x1c, 0x32, 0x74, 0x47, 0x70, 0xd3, 0x5b, 0xa8, 0x71, 0x13, 0xa1, 0xcf, 0xe6,
0x08, 0xc3, 0x34, 0x0c, 0xec, 0x2c, 0x02, 0x0a, 0x77, 0x75, 0x11, 0xda, 0x29, 0x04, 0xd4, 0x83,
0xdb, 0xd0, 0xce, 0x1f, 0xa0, 0x91, 0x5a, 0x39, 0x03, 0x81, 0x3e, 0x6c, 0x7e, 0x62, 0xce, 0x1e,
0x2f, 0x08, 0x07, 0xc5, 0x00, 0x45, 0xea, 0xd6, 0xec, 0x8b, 0x0e, 0xc3, 0x5d, 0x22, 0x47, 0x9a,
0xb3, 0x38, 0xc8, 0xf8, 0x36, 0xb2, 0x0f, 0xbb, 0x60, 0x95, 0x5f, 0x88, 0x66, 0xbe, 0x97, 0x59,
0x09, 0xe0, 0x23, 0x53, 0x45, 0x49, 0xa9, 0xcb, 0xb2, 0xd9, 0x66, 0x6c, 0x91, 0xe3, 0xc0, 0xa3,
0x7b, 0xb4, 0xd4, 0x26, 0xfb, 0x9e, 0x85, 0x63, 0xab, 0xa4, 0x1c, 0x57, 0xe2, 0x52, 0x3c, 0xcc,
0xeb, 0x6c, 0x6a, 0x0e, 0xe3, 0xdf, 0x15, 0x29, 0xa9, 0x85, 0xb6, 0xa9, 0x81, 0x2e, 0xcd, 0xe2,
0x5f, 0x55, 0x71, 0x1e, 0x56, 0x71, 0xb2, 0xc8, 0x0f, 0x4f, 0x39, 0x05, 0xe5, 0x97, 0x8f, 0xf9,
0x2f, 0xb7, 0x13, 0x1f, 0x38, 0x2d, 0x05, 0x4e, 0xc3, 0x14, 0x7b, 0x82, 0xd7, 0xdc, 0x56, 0x33,
0xf6, 0x28, 0x83, 0x86, 0x2e, 0x92, 0x49, 0x4a, 0x83, 0xdd, 0x98, 0xd5, 0xc7, 0x6b, 0xc9, 0x14,
0xf4, 0xcd, 0x78, 0x3c, 0xee, 0x1c, 0x74, 0x5f, 0x7f, 0x17, 0x76, 0x30, 0x8b, 0x9d, 0xb7, 0x0f,
0xeb, 0x7a, 0xdf, 0x0b, 0xf1, 0xe7, 0xad, 0xf8, 0x39, 0x81, 0xcd, 0x19, 0xc5, 0xd1, 0x1a, 0x0a,
0xc7, 0x4d, 0xf4, 0xfd, 0xfa, 0xa7, 0xd0, 0x17, 0x45, 0xd1, 0x76, 0xf4, 0x19, 0x5f, 0xfe, 0x87,
0x1a, 0x58, 0x73, 0xb6, 0x3e, 0xb3, 0x14, 0xf4, 0x0e, 0xbd, 0x4a, 0x80, 0x4d, 0x78, 0x90, 0x68,
0xb0, 0xec, 0xc2, 0x31, 0x8d, 0xdf, 0x80, 0x7d, 0x66, 0x4f, 0x88, 0x1a, 0xbe, 0xbb, 0x8b, 0xc0,
0xe8, 0x04, 0x84, 0x65, 0x8a, 0x4e, 0x11, 0x55, 0xca, 0x1a, 0xdf, 0x50, 0x06, 0x78, 0xfd, 0x86,
0x6a, 0xc4, 0x84, 0xdf, 0x37, 0x59, 0x56, 0xa4, 0xa8, 0xd2, 0xb6, 0x0e, 0x63, 0xad, 0x7c, 0x1f,
0x84, 0xc0, 0xe7, 0x5c, 0xf5, 0x55, 0x4b, 0xde, 0xfb, 0x06, 0xc1, 0x40, 0x4d, 0x94, 0x31, 0x58,
0x0a, 0x42, 0x15, 0x26, 0x73, 0xae, 0xae, 0x38, 0x9b, 0x8d, 0xc7, 0x51, 0xe4, 0x69, 0x18, 0xb8,
0x35, 0xcb, 0x2c, 0xe6, 0xc8, 0x5c, 0x55, 0x80, 0x69, 0x83, 0xb4, 0x50, 0xe9, 0x39, 0x67, 0x4b,
0x29, 0x76, 0xc4, 0xc6, 0x88, 0x40, 0x3f, 0x8a, 0x29, 0xd0, 0xbc, 0x5f, 0xf1, 0x5e, 0xc1, 0x89,
0xca, 0x5a, 0x3f, 0x70, 0x1e, 0xad, 0x82, 0xbe, 0x53, 0x74, 0x3a, 0x1f, 0xc3, 0xf6, 0x96, 0xc2,
0x78, 0x94, 0x5f, 0x60, 0x22, 0xe1, 0x5f, 0xd4, 0x2a, 0xb2, 0xff, 0x48, 0x92, 0x13, 0x67, 0x36,
0x60, 0x2e, 0xd6, 0x13, 0x32, 0xb7, 0x58, 0xe9, 0xef, 0xda, 0x4e, 0x60, 0xb5, 0x73, 0xb1, 0xb1,
0x9d, 0xd2, 0x6b, 0x14, 0x01, 0x4e, 0x3b, 0xbf, 0x6e, 0x6c, 0xe7, 0x8b, 0xd7, 0x28, 0x33, 0x9c,
0x76, 0xfe, 0x51, 0x6f, 0xc7, 0x5f, 0x72, 0x8e, 0xef, 0x37, 0xad, 0x8c, 0x95, 0xf3, 0x3e, 0x2e,
0x66, 0x8b, 0x4b, 0x9d, 0x7d, 0x21, 0xac, 0xe2, 0xa6, 0x5d, 0x01, 0x44, 0x7e, 0xd3, 0x9e, 0x30,
0xd0, 0xcc, 0x22, 0x92, 0x63, 0x4a, 0xf7, 0x1a, 0xf4, 0x0a, 0x0d, 0xae, 0xb9, 0xff, 0x42, 0x73,
0x02, 0x4f, 0x97, 0x37, 0x17, 0x31, 0x0b, 0xdd, 0xb2, 0x5b, 0x84, 0xba, 0x76, 0xca, 0x26, 0x71,
0x29, 0x61, 0x93, 0xc5, 0x23, 0xa7, 0x8b, 0x9f, 0x6c, 0x7f, 0x41, 0xa5, 0x0c, 0x84, 0xcd, 0x9a,
0x4f, 0x55, 0x5b, 0x23, 0x4c, 0xf6, 0x99, 0x7f, 0x45, 0x54, 0xb0, 0x99, 0x8f, 0x39, 0xc6, 0x24,
0xb1, 0x32, 0x96, 0xed, 0x1a, 0x16, 0xdd, 0x59, 0x63, 0x1a, 0x4f, 0xd8, 0x75, 0x9c, 0x6f, 0xc2,
0x76, 0x13, 0xa1, 0xb6, 0xc9, 0x10, 0x71, 0x11, 0x66, 0xe8, 0xaf, 0x29, 0x48, 0x4d, 0x1f, 0x71,
0x76, 0x37, 0xb2, 0x0c, 0x65, 0xd8, 0xeb, 0xed, 0xe0, 0xab, 0x26, 0xe4, 0x74, 0xa3, 0xc1, 0x4a,
0xa9, 0x52, 0x81, 0x4c, 0xc4, 0xe5, 0x6a, 0x0a, 0x63, 0x98, 0x85, 0x52, 0xa2, 0x3a, 0x26, 0x87,
0x8b, 0x7e, 0x1e, 0x8e, 0x61, 0x12, 0x32, 0x5d, 0x74, 0x4b, 0x45, 0x93, 0x38, 0xd5, 0x45, 0x13,
0x2a, 0x7a, 0x80, 0xcd, 0xcd, 0x19, 0x30, 0xfa, 0x88, 0xbc, 0xfa, 0x85, 0x8f, 0xf4, 0x2f, 0x2f,
0xaf, 0x42, 0xfa, 0xef, 0x6a, 0xb5, 0x12, 0x57, 0xa3, 0x88, 0x85, 0x4d, 0xb5, 0xe3, 0x4b, 0x3e,
0x38, 0xf9, 0x95, 0x7b, 0xf5, 0x69, 0x19, 0x28, 0xc7, 0x29, 0xfa, 0xa7, 0x36, 0xdf, 0x3a, 0x4c,
0xa7, 0x95, 0x6b, 0x4d, 0x46, 0x0a, 0xe6, 0x53, 0x53, 0xd7, 0x43, 0x48, 0xfb, 0xff, 0x46, 0xe9,
0x20, 0x52, 0x1c, 0xe0, 0xdf, 0x32, 0x5d, 0xc2, 0xd1, 0xd1, 0x6d, 0x52, 0xcd, 0xef, 0x27, 0x78,
0x17, 0x78, 0xf4, 0x2e, 0x59, 0x4c, 0xf3, 0x3c, 0xff, 0x9c, 0xb0, 0x23, 0xcc, 0x8e, 0x71, 0xf4,
0x90, 0x7c, 0x4e, 0xf0, 0xa0, 0xcc, 0x0d, 0x92, 0x0b, 0x18, 0x48, 0x7e, 0x40, 0x93, 0x88, 0x39,
0xbe, 0x3f, 0x9f, 0xee, 0xc7, 0xdd, 0x37, 0xc1, 0xf0, 0x38, 0x42, 0x4d, 0x06, 0x3f, 0x1b, 0x84,
0xf3, 0xe9, 0xb0, 0x27, 0xff, 0x3c, 0x8e, 0x50, 0xd4, 0xbf, 0x7a, 0x15, 0xc7, 0xf3, 0x29, 0x95,
0xec, 0xc7, 0xc7, 0x58, 0x12, 0xbd, 0x31, 0x4a, 0xa0, 0x01, 0xa9, 0xdd, 0x20, 0xf2, 0x4b, 0x60,
0x9d, 0x1b, 0xae, 0xe7, 0x25, 0xba, 0x91, 0xcd, 0xa7, 0xab, 0xb0, 0x83, 0x88, 0x39, 0x61, 0xe7,
0x75, 0xf4, 0x1d, 0x26, 0x44, 0x0b, 0xdf, 0x76, 0x45, 0x62, 0x16, 0xd0, 0x88, 0x16, 0x16, 0xbc,
0x20, 0x14, 0xfc, 0x42, 0xa6, 0x42, 0x6e, 0xe6, 0xc4, 0xe7, 0x96, 0x00, 0xa0, 0x43, 0x0a, 0xe6,
0xe5, 0x0c, 0x06, 0x32, 0x05, 0x47, 0xfb, 0x59, 0xc5, 0xf4, 0x22, 0x42, 0x90, 0xba, 0x59, 0xb2,
0xb8, 0xeb, 0xfc, 0xc2, 0x26, 0x79, 0x2e, 0x0e, 0x84, 0x3e, 0xff, 0x3e, 0x68, 0xa9, 0xb5, 0x14,
0x12, 0x70, 0xc8, 0x8e, 0xbd, 0x23, 0x6e, 0x70, 0x58, 0x49, 0x52, 0x2f, 0x6c, 0x28, 0x44, 0x4c,
0xef, 0x6e, 0xcb, 0xa7, 0x45, 0xc9, 0x69, 0x93, 0xb4, 0x5f, 0x04, 0x5f, 0x49, 0x25, 0xff, 0xb0,
0x26, 0xf2, 0x82, 0x72, 0xd9, 0x48, 0x1a, 0xc2, 0x96, 0xe6, 0x66, 0x6e, 0x73, 0x34, 0x96, 0xea,
0x7a, 0xd4, 0xb3, 0xbc, 0x53, 0x96, 0xfc, 0x72, 0x3b, 0xe2, 0x17, 0xa0, 0x12, 0x4b, 0x82, 0x3c,
0x12, 0x76, 0xa2, 0x95, 0xe1, 0xbb, 0xc2, 0xe2, 0xee, 0x80, 0x09, 0xdf, 0x15, 0xe6, 0xf8, 0xae,
0x88, 0xcb, 0xd3, 0x76, 0xa7, 0x19, 0xb2, 0x03, 0x18, 0x59, 0xa5, 0x4d, 0xd0, 0x48, 0x2b, 0x03,
0xb5, 0x81, 0xc9, 0x8d, 0x58, 0x48, 0xd3, 0x71, 0x0a, 0x07, 0xec, 0x05, 0x68, 0x61, 0x18, 0x82,
0x8e, 0xe9, 0x85, 0x7d, 0xef, 0x21, 0x25, 0x1c, 0xce, 0x47, 0x4f, 0xc4, 0xe7, 0xa3, 0x12, 0xc2,
0xcf, 0xdf, 0x86, 0x0d, 0xae, 0xe2, 0xd0, 0xf4, 0x98, 0xd2, 0xe7, 0x0b, 0x26, 0x23, 0xa0, 0x1f,
0x72, 0x1a, 0xcc, 0x2f, 0xc2, 0x93, 0x82, 0x0f, 0x30, 0x08, 0x21, 0xe6, 0x9b, 0x0a, 0xcb, 0xca,
0xaa, 0xb7, 0x5c, 0x85, 0xb7, 0xea, 0x7a, 0x87, 0x77, 0x22, 0x0a, 0x05, 0xe8, 0x9e, 0x41, 0x66,
0x59, 0x23, 0x33, 0x74, 0x60, 0x17, 0x97, 0x45, 0xdf, 0x6c, 0x38, 0xfc, 0x62, 0x82, 0xd4, 0x61,
0xa6, 0xd7, 0xfa, 0x11, 0x30, 0xe4, 0x2a, 0x9c, 0x34, 0xb2, 0xb0, 0xf0, 0xed, 0x5b, 0xeb, 0x02,
0xc3, 0x25, 0x8c, 0x2c, 0x2a, 0xdb, 0xa5, 0x58, 0x05, 0x52, 0x1e, 0x47, 0x05, 0xa9, 0xb9, 0xfb,
0xcc, 0xce, 0xb4, 0xfa, 0x07, 0xb0, 0x1d, 0x9b, 0x93, 0xb4, 0xae, 0x45, 0x6a, 0x2c, 0xd1, 0x70,
0x64, 0x0e, 0xb8, 0x6d, 0xd0, 0x87, 0xe1, 0xb7, 0x46, 0x0d, 0xa6, 0x0d, 0xda, 0x38, 0x29, 0x0f,
0xef, 0x46, 0xae, 0xf9, 0xa9, 0x36, 0x1a, 0xfb, 0x5d, 0x18, 0x0f, 0xb4, 0x3e, 0x05, 0x7d, 0x84,
0x04, 0xdd, 0x32, 0x85, 0x2b, 0xe2, 0xa4, 0xfe, 0xcc, 0xd3, 0x15, 0x73, 0x0c, 0x08, 0x95, 0x36,
0xd1, 0xca, 0x54, 0xb5, 0x01, 0xd7, 0xb5, 0x7a, 0x19, 0xa4, 0x2b, 0x0b, 0x08, 0xd5, 0xb0, 0x6a,
0x81, 0xd6, 0x36, 0xf6, 0x95, 0xf1, 0x02, 0xbb, 0x10, 0x56, 0x7a, 0x21, 0xb1, 0xf6, 0x23, 0x8d,
0x0a, 0x02, 0x47, 0xa3, 0xb8, 0xd0, 0x15, 0x5c, 0x47, 0x40, 0x15, 0x06, 0x8e, 0xdd, 0xab, 0xd6,
0xf4, 0x8b, 0x44, 0x42, 0x12, 0x7b, 0x05, 0xde, 0xb6, 0x7b, 0x31, 0x46, 0xba, 0x45, 0xfd, 0xee,
0x20, 0xd1, 0xb0, 0x1f, 0x89, 0x84, 0xfd, 0xc8, 0xe2, 0xf2, 0x32, 0xb9, 0x0a, 0x53, 0x38, 0x20,
0x6f, 0x35, 0x0c, 0x55, 0xfe, 0xcf, 0xa2, 0x60, 0x8b, 0xd3, 0x31, 0x82, 0xba, 0x0e, 0x32, 0x87,
0xfa, 0x54, 0x0f, 0x13, 0xef, 0x82, 0x5d, 0x3f, 0xc0, 0xcc, 0x42, 0x3b, 0x94, 0xbd, 0x54, 0xce,
0x0e, 0x12, 0xb7, 0xbb, 0xab, 0xdf, 0xf3, 0x7a, 0xef, 0x39, 0x60, 0xae, 0x74, 0x6b, 0x04, 0x56,
0x35, 0x72, 0x3c, 0xa5, 0x6c, 0x9c, 0x71, 0x00, 0xd7, 0xa6, 0xa8, 0x7d, 0x21, 0x95, 0x18, 0x79,
0x28, 0x26, 0xf9, 0x7d, 0x69, 0x0f, 0xb5, 0x3c, 0x61, 0x20, 0xe0, 0x78, 0x75, 0x38, 0xcb, 0xa7,
0xf7, 0x68, 0x16, 0xaa, 0xa8, 0x11, 0xe4, 0xb7, 0x1f, 0xf1, 0x48, 0xe6, 0xe3, 0xb9, 0x84, 0xff,
0xe6, 0xd1, 0x5d, 0xad, 0x7d, 0x0a, 0xc8, 0x17, 0x77, 0xe3, 0xea, 0xdd, 0x42, 0xab, 0x65, 0x21,
0xa6, 0xc9, 0xd2, 0xc0, 0x21, 0xb8, 0xa3, 0xd8, 0x81, 0x94, 0x0c, 0x7d, 0xd7, 0x03, 0x39, 0xda,
0xf4, 0xd7, 0x80, 0x1f, 0x98, 0xb2, 0x80, 0x10, 0x5d, 0x49, 0xdb, 0xa2, 0xf2, 0xf8, 0x32, 0xbb,
0x42, 0xff, 0x20, 0xbf, 0xe2, 0xf5, 0x24, 0xe0, 0xff, 0x49, 0x19, 0x48, 0x04, 0x0f, 0xcc, 0xc2,
0x9d, 0x9e, 0x94, 0x07, 0xd5, 0x20, 0x85, 0x29, 0xe4, 0xb5, 0x48, 0xc4, 0x33, 0xee, 0x22, 0x7f,
0xd0, 0xe5, 0x39, 0x3f, 0x6a, 0x44, 0x18, 0xe0, 0xb4, 0xc1, 0x32, 0xb3, 0xd0, 0x6a, 0x6d, 0x72,
0xaa, 0x05, 0x52, 0x63, 0x40, 0xd3, 0x9a, 0x44, 0x19, 0xb8, 0x15, 0x36, 0x6d, 0x2e, 0x5d, 0x46,
0x45, 0x41, 0x9e, 0xe9, 0x01, 0x8f, 0x54, 0xea, 0x41, 0x55, 0xfe, 0x69, 0x86, 0xa2, 0xcb, 0x1d,
0x55, 0x39, 0xc8, 0x09, 0x33, 0xbc, 0x54, 0x73, 0xa1, 0xfe, 0x8b, 0xa3, 0x03, 0xe7, 0x70, 0x43,
0x21, 0xc6, 0x55, 0x36, 0xc4, 0x11, 0xb5, 0x6c, 0x8f, 0x65, 0xa3, 0xed, 0xd1, 0xcc, 0xbe, 0xb7,
0x43, 0x7c, 0xd8, 0x54, 0x4b, 0x39, 0x82, 0xf3, 0xdd, 0xac, 0xc1, 0x39, 0x56, 0xd7, 0x08, 0xd9,
0x90, 0xa6, 0x53, 0x4e, 0x36, 0x92, 0xec, 0xbe, 0xa5, 0x3d, 0x60, 0xf4, 0x7b, 0x08, 0x91, 0xa8,
0xae, 0x3a, 0xb3, 0x60, 0x24, 0x7d, 0xdf, 0xb3, 0xab, 0xb8, 0x10, 0xbf, 0x28, 0xb3, 0x75, 0xa8,
0x79, 0x50, 0xd5, 0xc2, 0xab, 0x52, 0x9c, 0x42, 0x55, 0x20, 0xf0, 0x1f, 0x02, 0xed, 0x46, 0xaf,
0xca, 0x62, 0x8d, 0xae, 0x92, 0x11, 0xf6, 0x82, 0x59, 0x03, 0xb1, 0x85, 0x6a, 0x6d, 0x21, 0x94,
0xa7, 0xd5, 0x10, 0xe2, 0x5d, 0x44, 0xd2, 0x5c, 0x43, 0x33, 0x64, 0xc1, 0xc3, 0x93, 0x87, 0x7c,
0x46, 0xa9, 0x74, 0x0c, 0x9f, 0x78, 0xe0, 0xbb, 0xfe, 0xfa, 0x37, 0x64, 0xc2, 0xe1, 0x62, 0x5c,
0x24, 0xbf, 0x82, 0x26, 0x0c, 0x05, 0xd2, 0x7a, 0x9e, 0x99, 0x17, 0x7a, 0x71, 0x1a, 0x52, 0x06,
0x8f, 0xda, 0xbd, 0x96, 0xc8, 0xe5, 0xc0, 0x5f, 0x70, 0x2e, 0x3d, 0xa9, 0x67, 0xdc, 0x43, 0x3b,
0x93, 0x8e, 0xf6, 0x02, 0xdf, 0x6a, 0x4d, 0xdc, 0x00, 0x0f, 0xa6, 0x37, 0xf2, 0x50, 0xb6, 0xf4,
0x40, 0x26, 0xa3, 0xad, 0x37, 0x69, 0x3b, 0xd3, 0xaf, 0xaa, 0xaf, 0x08, 0x0b, 0x30, 0x6c, 0xb3,
0x19, 0x49, 0x2d, 0x6d, 0x9b, 0xad, 0xf9, 0x4e, 0x4c, 0xd2, 0xfb, 0x85, 0xdf, 0x98, 0xad, 0xa7,
0xfe, 0xc4, 0x74, 0x67, 0xe0, 0x4f, 0x57, 0x3c, 0xbe, 0xfa, 0xdf, 0xa7, 0x75, 0x7f, 0x13, 0xc9,
0xb7, 0x98, 0x71, 0x30, 0xfc, 0x10, 0xbf, 0xa2, 0x55, 0x98, 0x10, 0x25, 0x71, 0x14, 0x3e, 0x46,
0x02, 0xba, 0x9b, 0x3a, 0x77, 0x41, 0x17, 0x4b, 0xd2, 0xd5, 0xda, 0xa0, 0x9e, 0x83, 0x5a, 0x2f,
0x95, 0xb2, 0xcd, 0x23, 0xbf, 0x6e, 0x3e, 0xe6, 0xf7, 0x30, 0x4b, 0xe5, 0xc8, 0x2d, 0x40, 0x74,
0x7b, 0x66, 0xec, 0xf7, 0xe3, 0xf2, 0x6c, 0x91, 0x13, 0xb8, 0x91, 0xdc, 0xf1, 0xb9, 0xc0, 0xc0,
0xcc, 0x57, 0xcc, 0xcc, 0x77, 0x45, 0x9b, 0x2d, 0x25, 0xb1, 0x42, 0xdd, 0xb9, 0xfc, 0x04, 0x07,
0x30, 0xdf, 0x83, 0x77, 0xd5, 0xd5, 0x27, 0x68, 0xce, 0x32, 0x9b, 0x98, 0xa9, 0x03, 0xc3, 0x01,
0x99, 0xdb, 0xec, 0x77, 0x8a, 0x29, 0x6a, 0x16, 0x52, 0x22, 0xa9, 0x14, 0xe3, 0x6a, 0x5e, 0x49,
0xec, 0x5b, 0x79, 0xc7, 0xc5, 0x5e, 0xa3, 0xab, 0x0c, 0xcc, 0xb5, 0x2e, 0x43, 0x53, 0x41, 0xe7,
0x30, 0xbb, 0x51, 0x39, 0x7f, 0x97, 0xf0, 0xb7, 0x0f, 0x83, 0x29, 0x87, 0x0a, 0x5a, 0x43, 0x83,
0xe6, 0xbf, 0xd4, 0xc0, 0x8a, 0x5c, 0xd1, 0xd5, 0x78, 0x32, 0xe5, 0x1a, 0x9f, 0x17, 0x5c, 0xf2,
0x59, 0xb8, 0x12, 0x9c, 0xf5, 0x31, 0x2f, 0xc2, 0x7f, 0x9f, 0x36, 0xf9, 0xf0, 0x0b, 0xf6, 0xda,
0xf1, 0xe5, 0xdc, 0x44, 0x81, 0x85, 0xcd, 0x44, 0xbc, 0xcf, 0xfb, 0xcf, 0x6b, 0xec, 0xee, 0x3a,
0xe3, 0x50, 0x27, 0x2b, 0xae, 0x0e, 0x1e, 0x23, 0x99, 0x79, 0x9e, 0xf4, 0xc0, 0x12, 0x81, 0x42,
0xf7, 0xfd, 0xec, 0x2f, 0xe5, 0xd1, 0xc3, 0x27, 0x50, 0x1d, 0xf3, 0xbf, 0x25, 0x8f, 0xec, 0xc6,
0xef, 0x05, 0x83, 0x68, 0x07, 0x65, 0xac, 0xcf, 0xc9, 0x1d, 0x46, 0x84, 0xfa, 0x12, 0xa8, 0x82,
0x13, 0xca, 0x86, 0x88, 0x05, 0xe9, 0xf0, 0xb0, 0xdb, 0xdb, 0xdd, 0xdd, 0xaa, 0xab, 0x70, 0x70,
0xe0, 0x23, 0x03, 0xed, 0x40, 0xaf, 0xb9, 0x56, 0x40, 0x9e, 0x2c, 0x70, 0x06, 0x5f, 0x54, 0x4f,
0xbe, 0x77, 0x70, 0x90, 0x78, 0x21, 0x7f, 0xef, 0x20, 0xce, 0x90, 0xb8, 0xee, 0x41, 0x2a, 0xcd,
0x2e, 0x63, 0x54, 0x0c, 0x3e, 0x97, 0x82, 0x04, 0xd0, 0xeb, 0xdb, 0xda, 0x98, 0x79, 0x61, 0x1a,
0x6c, 0x3b, 0xae, 0x5d, 0x68, 0x48, 0xac, 0x08, 0xd3, 0x0f, 0x47, 0x27, 0xf2, 0x5b, 0x36, 0x40,
0xd2, 0x3a, 0x9a, 0x94, 0x3c, 0x6f, 0x64, 0x37, 0x53, 0xba, 0xc3, 0x78, 0xf8, 0x34, 0xfc, 0xe1,
0xed, 0x0f, 0xcf, 0xcf, 0xf0, 0xf3, 0xf5, 0xf1, 0xdb, 0xdd, 0xdd, 0x87, 0x4f, 0x27, 0x3f, 0xf4,
0xa2, 0xa0, 0x35, 0x1d, 0x26, 0x87, 0x14, 0x5e, 0x3e, 0x7c, 0x92, 0xc9, 0x1a, 0x49, 0x58, 0x11,
0x0e, 0xa9, 0x99, 0x52, 0x70, 0x60, 0x9c, 0x8a, 0x29, 0x38, 0x48, 0x4c, 0x2d, 0x87, 0x92, 0x1c,
0x94, 0xa7, 0x79, 0x8a, 0xdd, 0xc7, 0xfe, 0x31, 0x9e, 0xb9, 0x25, 0x94, 0x65, 0x13, 0x69, 0xec,
0x24, 0xc9, 0x66, 0xbd, 0x27, 0x6a, 0x72, 0x60, 0x64, 0x1f, 0xc6, 0xfd, 0x95, 0x7e, 0xad, 0x2a,
0x74, 0x53, 0x02, 0x73, 0x9c, 0x78, 0xac, 0x8e, 0x7f, 0x2c, 0xca, 0x39, 0xe0, 0x1d, 0x5a, 0xa0,
0x38, 0x33, 0xbe, 0x8b, 0x05, 0x57, 0xbe, 0x0b, 0x9b, 0x0f, 0x76, 0xc5, 0xf4, 0xce, 0x0b, 0x45,
0x95, 0x40, 0xfc, 0x12, 0xab, 0xbf, 0x61, 0xe0, 0xba, 0xbd, 0xd7, 0x91, 0xe2, 0x6d, 0xd0, 0x48,
0x19, 0x8d, 0xaf, 0x28, 0xc6, 0x91, 0x7f, 0xa0, 0xdf, 0x69, 0xb0, 0x63, 0xa3, 0x94, 0xff, 0x81,
0x4b, 0x14, 0x0d, 0x3c, 0xc0, 0x3c, 0x3c, 0x0e, 0x4c, 0x36, 0x39, 0x12, 0x9f, 0xda, 0xe9, 0xf6,
0xc5, 0xd7, 0x30, 0x75, 0xb3, 0xa2, 0x5b, 0x93, 0xe0, 0x30, 0x9f, 0xdc, 0x4a, 0x45, 0x86, 0x74,
0xa0, 0xde, 0x04, 0x28, 0xe6, 0x6f, 0x35, 0xe4, 0x3d, 0xcf, 0xb5, 0x21, 0x87, 0x27, 0xe8, 0x11,
0x55, 0xe1, 0xa3, 0xca, 0xf5, 0x1c, 0x86, 0x02, 0xea, 0x8d, 0xbc, 0x08, 0xcf, 0x84, 0xf7, 0x55,
0xee, 0xbd, 0x60, 0xf6, 0xd4, 0x52, 0xe0, 0x71, 0x95, 0x92, 0x0e, 0x34, 0x11, 0x41, 0x6b, 0xaf,
0xf0, 0x07, 0xb9, 0xc7, 0x3e, 0xc4, 0xb0, 0xce, 0x0d, 0x29, 0xc2, 0x40, 0x28, 0xbe, 0x67, 0xac,
0x80, 0xb3, 0xcf, 0xe1, 0xe1, 0xa1, 0xc8, 0xc7, 0x5a, 0x49, 0x7d, 0x51, 0xca, 0x7e, 0x95, 0x89,
0x15, 0x76, 0xc4, 0x79, 0x32, 0x83, 0x63, 0x1f, 0x77, 0xcf, 0x87, 0x43, 0x25, 0x39, 0x7b, 0xf1,
0xdf, 0xca, 0x20, 0x30, 0x61, 0x3f, 0x12, 0xe0, 0xeb, 0x40, 0x3c, 0x41, 0xf8, 0xb6, 0x11, 0x49,
0xf9, 0xe7, 0x67, 0xfb, 0x24, 0x0a, 0xa7, 0x64, 0x28, 0xa5, 0x5b, 0xf9, 0xd0, 0xa0, 0x06, 0xca,
0x42, 0x7a, 0x2b, 0xe8, 0x37, 0xd6, 0xa7, 0x80, 0x62, 0x65, 0xaf, 0xaa, 0x75, 0x63, 0xc5, 0x57,
0x54, 0xab, 0x84, 0xc8, 0xbc, 0x10, 0xb8, 0x5c, 0x2c, 0x36, 0xd8, 0xf5, 0xe9, 0x0c, 0x81, 0x82,
0x82, 0x65, 0x78, 0xa3, 0x82, 0x91, 0xe0, 0xff, 0x0b, 0x87, 0x38, 0xfc, 0x7f, 0x88, 0xba, 0x08,
0xb4, 0x53, 0xaf, 0x75, 0x97, 0xa3, 0x03, 0x59, 0xfe, 0x00, 0x8d, 0xe1, 0xb2, 0x6e, 0xaf, 0x58,
0xe1, 0x0e, 0xc9, 0x71, 0x9c, 0x37, 0xd4, 0xa4, 0x26, 0xe1, 0xe8, 0xed, 0x85, 0x28, 0xdf, 0x37,
0xd4, 0xbb, 0x2f, 0x36, 0x55, 0xa3, 0x0f, 0x83, 0x02, 0xa8, 0xeb, 0xfd, 0xd7, 0xc9, 0x11, 0xc8,
0xe0, 0xa4, 0xa8, 0x86, 0x9d, 0x93, 0x23, 0x4c, 0x19, 0x81, 0x3f, 0xe7, 0xd5, 0x5d, 0x3a, 0xec,
0xfc, 0x1f, 0x60, 0xcb, 0x0a, 0xef, 0x66, 0x5c, 0x01, 0x00
0x99, 0x30, 0x07, 0x29, 0x1a, 0xa1, 0x30, 0xce, 0xe3, 0x52, 0x33, 0xfe, 0xbf, 0xe2, 0xae, 0xb6,
0xb9, 0x6d, 0xe3, 0x08, 0x7f, 0xef, 0xaf, 0xa0, 0x90, 0x44, 0x02, 0x2a, 0x48, 0x02, 0x25, 0x3b,
0xb1, 0x49, 0x81, 0x1c, 0x57, 0x4e, 0x5b, 0x4d, 0x13, 0xd7, 0x13, 0xb9, 0x71, 0x32, 0x1a, 0x4d,
0x45, 0x52, 0x47, 0x11, 0x63, 0x10, 0x40, 0x08, 0xc8, 0x92, 0x4a, 0xf1, 0xbf, 0x77, 0x77, 0xef,
0xfd, 0x00, 0x90, 0x94, 0x93, 0x69, 0x67, 0xe2, 0x48, 0x3a, 0x1c, 0x0e, 0x7b, 0x77, 0x7b, 0x7b,
0x7b, 0x7b, 0xbb, 0xcf, 0x36, 0x92, 0xa9, 0x2f, 0x83, 0xfd, 0x46, 0xf2, 0xf1, 0x36, 0xba, 0x99,
0x74, 0xfb, 0x49, 0x03, 0x9d, 0x58, 0xc1, 0xa2, 0xc6, 0x84, 0xdc, 0x4e, 0xd9, 0xfb, 0x92, 0xc7,
0xec, 0xda, 0x04, 0x21, 0x16, 0x80, 0x1a, 0xef, 0xb2, 0x16, 0x2a, 0x05, 0xef, 0xbd, 0xbd, 0x5b,
0xc8, 0x17, 0xcb, 0x9a, 0xe5, 0xd2, 0x77, 0xc7, 0xd2, 0xb4, 0x85, 0x76, 0xa3, 0x3f, 0x97, 0x6a,
0x06, 0xcd, 0x26, 0x3f, 0x6c, 0xd7, 0xa2, 0x35, 0xd2, 0xdb, 0x34, 0xfc, 0x93, 0x91, 0x0f, 0x4f,
0xb6, 0xd2, 0x47, 0xcf, 0x19, 0x1e, 0x8e, 0x92, 0xa2, 0x1e, 0xba, 0xa8, 0x6e, 0x0d, 0x54, 0x90,
0xd0, 0x7c, 0x52, 0x58, 0x8f, 0x86, 0x3e, 0x1a, 0xd4, 0x51, 0xa6, 0xc2, 0xa9, 0x4d, 0x25, 0xe8,
0x42, 0x2f, 0x2e, 0xe3, 0x9d, 0xbc, 0x7b, 0xdd, 0x82, 0x0f, 0xd2, 0xd3, 0xaf, 0xdb, 0xe7, 0x33,
0xf9, 0x31, 0x1d, 0xae, 0x44, 0xad, 0x36, 0xd6, 0x82, 0xc5, 0xf7, 0x7d, 0x76, 0xa3, 0x6b, 0x6e,
0xf8, 0x32, 0xb7, 0x6a, 0x38, 0x0e, 0x9a, 0xef, 0xed, 0x58, 0x5c, 0x21, 0xf1, 0x44, 0x66, 0x64,
0x35, 0xd6, 0x9c, 0xd4, 0xa1, 0x5b, 0x00, 0x5b, 0x6e, 0x69, 0x00, 0x09, 0xc3, 0xdc, 0x71, 0x5d,
0x5e, 0xec, 0xd5, 0x46, 0xca, 0xac, 0x6e, 0x84, 0x19, 0xb3, 0x84, 0x28, 0x5b, 0x8b, 0x84, 0x74,
0x31, 0xbb, 0x9b, 0x4e, 0x53, 0x46, 0xb0, 0x90, 0xad, 0x1b, 0xb6, 0x9e, 0x2c, 0x73, 0xd3, 0xc6,
0x29, 0xe6, 0x29, 0x1e, 0x30, 0xb9, 0x9c, 0xa6, 0xf5, 0xe9, 0x29, 0x43, 0xc7, 0x64, 0x17, 0xbc,
0x68, 0x3b, 0xe8, 0x22, 0x1d, 0x61, 0xbd, 0x01, 0x42, 0x96, 0xd0, 0x88, 0x50, 0x46, 0x4d, 0x93,
0x2c, 0xa9, 0x58, 0xfa, 0xb8, 0x55, 0x17, 0x8a, 0x75, 0x7d, 0xc8, 0xd0, 0x7c, 0x08, 0xf4, 0x4a,
0xca, 0xbf, 0x8c, 0x6c, 0x3d, 0x3d, 0x9c, 0x33, 0xd4, 0xfc, 0x48, 0x24, 0x07, 0xf1, 0x21, 0xdb,
0xf1, 0xd9, 0x93, 0xaf, 0x6a, 0xfd, 0x51, 0xf4, 0xb1, 0x51, 0x89, 0x76, 0xf5, 0x65, 0xb3, 0x8b,
0x86, 0x66, 0x6c, 0x74, 0x0f, 0x35, 0xe9, 0xee, 0xf1, 0x77, 0xa4, 0x59, 0x47, 0x62, 0xff, 0xe6,
0x94, 0x64, 0xbd, 0xee, 0x6a, 0xd0, 0xc1, 0xbb, 0x13, 0xa5, 0xcb, 0xda, 0x2a, 0x15, 0x8c, 0x37,
0x30, 0xbe, 0xf0, 0x86, 0xea, 0xf1, 0xbc, 0x5f, 0xa7, 0xfc, 0x8a, 0xce, 0xa8, 0x44, 0x37, 0x88,
0xb8, 0x93, 0x1b, 0xc4, 0xf0, 0x25, 0xd3, 0x32, 0xe0, 0xe4, 0xc1, 0x0f, 0x84, 0xc4, 0x26, 0xf7,
0x60, 0x8c, 0x97, 0xf5, 0x17, 0x28, 0x4e, 0xf8, 0x39, 0x5b, 0xef, 0x88, 0xbc, 0xc1, 0x3b, 0x18,
0x36, 0xa5, 0x6e, 0xd4, 0x2a, 0x20, 0x3c, 0x1a, 0x0c, 0x60, 0x59, 0xe5, 0x0b, 0xe9, 0xc6, 0x65,
0x54, 0xfe, 0x7a, 0xa9, 0x15, 0x30, 0x34, 0x9c, 0xe3, 0xfc, 0xf1, 0xfe, 0x38, 0x99, 0x37, 0x6a,
0x73, 0xb2, 0x85, 0x4e, 0x5f, 0xc1, 0x57, 0xdf, 0xa7, 0xd4, 0xc9, 0xb0, 0x23, 0xd5, 0xd9, 0xad,
0x32, 0x9e, 0x7c, 0x80, 0x37, 0x1d, 0xf5, 0xff, 0x7a, 0x25, 0xb1, 0x33, 0xca, 0x0d, 0x58, 0xc5,
0x2e, 0xab, 0x5a, 0xb8, 0x06, 0xe7, 0x3c, 0x2d, 0x41, 0x67, 0x4c, 0xe0, 0x12, 0x19, 0x2b, 0x4b,
0x3a, 0x57, 0x28, 0x94, 0xdd, 0x35, 0xeb, 0x86, 0x52, 0x5a, 0x8e, 0x69, 0xd9, 0x88, 0x75, 0xf1,
0x87, 0x2f, 0xe6, 0xb5, 0xa4, 0x5f, 0xa0, 0x23, 0x9e, 0x34, 0x02, 0x8d, 0xf1, 0x5a, 0xe8, 0x79,
0xb4, 0x97, 0xff, 0x47, 0xda, 0xcf, 0xf8, 0x47, 0x35, 0x78, 0x57, 0x9e, 0x71, 0x39, 0xf5, 0x0c,
0xea, 0x89, 0xaa, 0x67, 0x53, 0x7d, 0xed, 0x00, 0xc2, 0xa8, 0x5b, 0x99, 0xf9, 0xa8, 0x20, 0xd3,
0xac, 0xf9, 0xb7, 0x91, 0xa6, 0xaa, 0xac, 0x21, 0x4d, 0x43, 0x1f, 0x7f, 0x60, 0x37, 0x50, 0xad,
0xb7, 0x9b, 0x8d, 0xcb, 0xa2, 0xdf, 0xb6, 0xf0, 0x0d, 0xa2, 0xd3, 0x79, 0x01, 0x24, 0xd9, 0x0b,
0xd2, 0x59, 0xb0, 0xd7, 0x7d, 0x95, 0xb7, 0x83, 0x87, 0xc6, 0x5a, 0x04, 0xd1, 0x0d, 0x7d, 0xd9,
0x74, 0xdc, 0xa8, 0x56, 0x68, 0xbf, 0x42, 0x57, 0x02, 0x95, 0x4f, 0x33, 0x25, 0xea, 0x04, 0xa8,
0x89, 0x89, 0x7f, 0x4d, 0xc9, 0x61, 0x8d, 0x2f, 0x96, 0x94, 0x5e, 0xd0, 0x5a, 0xe7, 0x12, 0x6e,
0xe3, 0x7a, 0x3b, 0x0c, 0xe2, 0x0e, 0x61, 0x45, 0xb0, 0x21, 0x4f, 0x14, 0xac, 0x71, 0x55, 0xa9,
0xd7, 0xd5, 0xc3, 0x73, 0x50, 0x89, 0xa1, 0x0f, 0x43, 0x99, 0xda, 0x68, 0x2b, 0x68, 0x62, 0x47,
0x10, 0xe9, 0x74, 0x60, 0x1d, 0x9a, 0xf1, 0xde, 0x1a, 0x9b, 0x6c, 0x69, 0xc1, 0x28, 0x6b, 0x7a,
0x0c, 0x72, 0x54, 0x2e, 0x53, 0xb3, 0x47, 0xbf, 0xa5, 0x4d, 0x1d, 0x3a, 0x1a, 0x34, 0xc9, 0xc6,
0x99, 0x37, 0xf0, 0x53, 0x86, 0x6b, 0x95, 0xd1, 0xad, 0x25, 0x4c, 0x2f, 0x5e, 0x41, 0x19, 0x64,
0x72, 0xb9, 0x16, 0x58, 0x2f, 0x7f, 0x8d, 0x29, 0xb4, 0xc5, 0x90, 0xd2, 0x26, 0xb9, 0x27, 0x37,
0x49, 0xdc, 0x15, 0xf7, 0xa4, 0xee, 0xf0, 0xe5, 0x2b, 0x10, 0x3e, 0x30, 0xf4, 0x2e, 0x60, 0xb6,
0x3a, 0x85, 0x3a, 0x35, 0x82, 0x82, 0x8b, 0xa9, 0xb4, 0x71, 0x06, 0xbc, 0x7f, 0xaa, 0x74, 0x99,
0xf7, 0x49, 0x35, 0xe3, 0xd9, 0x2f, 0xe1, 0xab, 0xff, 0x02, 0x99, 0x2b, 0x22, 0x01, 0x44, 0xd9,
0xca, 0x5a, 0xb6, 0xeb, 0x61, 0x21, 0x69, 0xf0, 0x26, 0xa5, 0xa3, 0x6a, 0xc0, 0x9f, 0x67, 0xa5,
0x56, 0x36, 0xb0, 0xd7, 0x4f, 0x4f, 0x55, 0x13, 0xc8, 0xe3, 0x17, 0xa0, 0x3c, 0x36, 0x4d, 0x49,
0x91, 0x1f, 0x9b, 0x59, 0xbf, 0x8e, 0x25, 0xc2, 0xcd, 0x9b, 0xf7, 0xe7, 0x9d, 0x09, 0xcf, 0x16,
0xab, 0x72, 0x78, 0x76, 0x74, 0xae, 0x4f, 0xf1, 0xf6, 0xa8, 0x48, 0x88, 0xa3, 0x55, 0x03, 0x50,
0x60, 0xe5, 0xff, 0x6c, 0xfb, 0x68, 0xd7, 0xfc, 0x68, 0x57, 0xcc, 0x42, 0xb9, 0x6a, 0xdd, 0x52,
0x49, 0xc0, 0x57, 0x39, 0x26, 0x3b, 0x6e, 0x51, 0x75, 0xf4, 0x3e, 0x74, 0xe3, 0xea, 0x3d, 0x4a,
0xd3, 0xd1, 0x29, 0x99, 0x0d, 0x7d, 0x07, 0x93, 0x26, 0xa3, 0xbe, 0xd3, 0x55, 0xfa, 0x0e, 0x4e,
0x3a, 0xeb, 0xd5, 0x13, 0x43, 0xaf, 0x06, 0x2d, 0xd4, 0xe1, 0xb4, 0x6f, 0xde, 0xf3, 0xd1, 0x5b,
0xfc, 0x3d, 0xdf, 0xf2, 0xa5, 0x39, 0x7a, 0xad, 0xad, 0x49, 0x9a, 0x8c, 0xb1, 0xef, 0x26, 0x0c,
0x25, 0x27, 0x70, 0xaf, 0xfd, 0x8b, 0x34, 0x14, 0x7b, 0xfb, 0x6c, 0x7f, 0xef, 0x86, 0xa5, 0x36,
0xfe, 0xe5, 0x7b, 0x9f, 0xca, 0xb7, 0x86, 0xbf, 0xe4, 0x18, 0x9a, 0x7b, 0xbd, 0xbd, 0x6d, 0xed,
0x94, 0xef, 0x6d, 0x43, 0xe5, 0xde, 0xca, 0xa0, 0xbc, 0x91, 0x15, 0x30, 0x31, 0xb5, 0xe8, 0x92,
0x37, 0x2e, 0x78, 0x4e, 0x82, 0x89, 0x31, 0x9d, 0xf8, 0x5c, 0x23, 0xb8, 0xca, 0xbe, 0xdb, 0x42,
0x05, 0xb8, 0x02, 0xbb, 0x25, 0xf3, 0xc2, 0x62, 0x1b, 0xd7, 0xce, 0x91, 0x4a, 0x98, 0x39, 0xb9,
0x97, 0x29, 0xb7, 0x27, 0x71, 0x53, 0x67, 0xbf, 0xc9, 0x1d, 0x0b, 0x96, 0xf3, 0xe3, 0x38, 0xaf,
0x78, 0x36, 0x26, 0xdb, 0x89, 0x8b, 0x03, 0x3e, 0x84, 0xcc, 0x8c, 0x7a, 0x6c, 0x48, 0xdd, 0xa6,
0x2f, 0xc8, 0x84, 0x1e, 0xe9, 0x47, 0x81, 0xcc, 0x93, 0x87, 0xbe, 0x10, 0xdb, 0xde, 0xdb, 0x4d,
0x58, 0x46, 0xde, 0x08, 0xe2, 0x72, 0xb4, 0x28, 0xff, 0xca, 0xdd, 0x60, 0x9a, 0x69, 0x86, 0x63,
0x5d, 0xed, 0x30, 0xa9, 0x6c, 0x59, 0x55, 0x23, 0xde, 0x17, 0x08, 0x6d, 0x7c, 0xee, 0xd5, 0x33,
0xa8, 0x18, 0x86, 0x2e, 0x64, 0x70, 0x65, 0xfd, 0x3e, 0x55, 0x88, 0xca, 0xea, 0x1e, 0xec, 0x55,
0xf4, 0x0d, 0x6c, 0x24, 0x79, 0x8a, 0x42, 0x27, 0x3e, 0x96, 0x00, 0x5a, 0x2d, 0xca, 0xbf, 0xad,
0xe9, 0xa3, 0x95, 0x43, 0xad, 0x89, 0x50, 0xe4, 0x7f, 0x51, 0x5a, 0xbf, 0xf7, 0xb5, 0x6b, 0xfb,
0x50, 0x40, 0x64, 0x68, 0x79, 0x12, 0xbb, 0xbd, 0xbc, 0x3d, 0xd1, 0x0a, 0x7b, 0xa0, 0xe0, 0xb9,
0xf8, 0x4e, 0x2e, 0x0c, 0xf8, 0x37, 0x8a, 0xf0, 0xcd, 0xda, 0x7a, 0x7a, 0x00, 0xf3, 0x6d, 0xb0,
0x37, 0x37, 0x63, 0x6d, 0xbf, 0x7c, 0xa5, 0xa9, 0xb8, 0x76, 0xe3, 0x23, 0xef, 0x7b, 0xcc, 0x71,
0xd4, 0xe4, 0xbc, 0xbd, 0x5b, 0x90, 0x7f, 0x56, 0x0b, 0xb5, 0x1f, 0x94, 0x85, 0xa5, 0xa5, 0xc2,
0x57, 0x40, 0xdc, 0x7e, 0x77, 0xb5, 0xd5, 0xc7, 0xe4, 0xf4, 0xbd, 0x80, 0xe9, 0x5b, 0x7b, 0x0f,
0x63, 0xcb, 0x53, 0x4b, 0x09, 0x91, 0xf4, 0x72, 0x61, 0xfa, 0xed, 0xcb, 0x97, 0x27, 0x87, 0x5c,
0x9e, 0x46, 0x87, 0xc7, 0xb0, 0x2d, 0xb2, 0x02, 0x7e, 0xe9, 0x9a, 0x87, 0x4d, 0x32, 0x4f, 0xd5,
0x66, 0x5c, 0x29, 0x19, 0xae, 0x79, 0xea, 0xa8, 0x8b, 0xb9, 0x0e, 0xcb, 0xe6, 0xde, 0xfe, 0x11,
0x1d, 0xd0, 0x23, 0x2a, 0xbb, 0xa0, 0x3a, 0x10, 0x35, 0x77, 0xe0, 0xc3, 0x76, 0xf4, 0x5b, 0xc6,
0xb0, 0xb5, 0xdd, 0x58, 0xc3, 0x83, 0x75, 0x09, 0xfe, 0x1c, 0x1e, 0xac, 0xa1, 0x18, 0xcb, 0x0b,
0x0b, 0x87, 0x39, 0xd4, 0xd5, 0x56, 0x0d, 0xaa, 0x8e, 0x2f, 0x29, 0x21, 0x3d, 0x31, 0x83, 0x24,
0x9a, 0xab, 0x0d, 0xf7, 0x33, 0xcc, 0x92, 0x9e, 0x31, 0x38, 0xbe, 0x8c, 0xaa, 0x0e, 0xa8, 0x76,
0xa0, 0x3a, 0x1d, 0xab, 0x6c, 0xe9, 0xb0, 0x5f, 0xe3, 0xeb, 0x98, 0x8a, 0x5c, 0xe8, 0x55, 0x3b,
0x9e, 0xb2, 0x88, 0x46, 0xd6, 0x00, 0x45, 0x57, 0xa7, 0x91, 0xb6, 0x24, 0xba, 0xcf, 0xe2, 0x6a,
0x11, 0xf4, 0xbf, 0x40, 0x74, 0xaf, 0x11, 0xd1, 0xde, 0xa0, 0xe6, 0xb5, 0xa0, 0x65, 0xb6, 0xbc,
0xd0, 0xeb, 0x46, 0x91, 0x21, 0xbf, 0xc9, 0x7d, 0xce, 0xbc, 0xf1, 0xb9, 0x36, 0x8d, 0xb7, 0x84,
0x64, 0xf6, 0xbf, 0x11, 0xeb, 0xe6, 0x46, 0xbb, 0x6c, 0x7b, 0x9f, 0xe3, 0x19, 0xc8, 0x97, 0x37,
0x8d, 0x9e, 0xaa, 0x5d, 0xdf, 0xf5, 0x24, 0x21, 0x0d, 0x1b, 0x5f, 0x9b, 0x56, 0x50, 0x3a, 0x57,
0x6b, 0x52, 0x29, 0x90, 0x46, 0xae, 0x29, 0xe8, 0xfa, 0x55, 0x2f, 0x65, 0xd3, 0xaa, 0xbf, 0xad,
0x14, 0x95, 0xe6, 0x19, 0xc9, 0xc7, 0x5b, 0x7e, 0x38, 0x6d, 0xfc, 0x32, 0x19, 0x38, 0xb6, 0xff,
0xb4, 0x60, 0x5e, 0x9d, 0x85, 0xde, 0x70, 0x7a, 0x22, 0x7d, 0x9d, 0xb9, 0x00, 0x4c, 0x42, 0xb3,
0xd7, 0xa6, 0xe9, 0xbe, 0x7e, 0xd2, 0x60, 0x06, 0xae, 0x9a, 0xf0, 0x53, 0x44, 0xed, 0xe3, 0xa6,
0xda, 0x3c, 0xf8, 0x43, 0xbc, 0x64, 0x51, 0x43, 0xb9, 0x7d, 0x98, 0xcc, 0xd9, 0x87, 0xed, 0xb0,
0x53, 0x60, 0xe3, 0xa1, 0x44, 0xb9, 0xaa, 0xae, 0x7b, 0xd4, 0xf0, 0x01, 0xe6, 0x90, 0x05, 0xdd,
0xbd, 0x8e, 0x0d, 0xa5, 0x00, 0xd1, 0x08, 0x04, 0x2d, 0x6c, 0x86, 0xe6, 0x14, 0xc5, 0x98, 0x53,
0x02, 0x01, 0xed, 0x46, 0xb7, 0xb4, 0x07, 0xd8, 0x61, 0x81, 0xf2, 0xb6, 0x56, 0x8d, 0x0e, 0x05,
0xc1, 0x5d, 0x5e, 0xad, 0x1c, 0x68, 0x61, 0x8e, 0x2c, 0x4e, 0xb8, 0xc2, 0xdc, 0x87, 0x1f, 0x31,
0x52, 0xd1, 0x4b, 0xb4, 0xc4, 0x78, 0x44, 0x74, 0x97, 0xe7, 0x63, 0x48, 0xfe, 0x17, 0xda, 0xdd,
0xad, 0xaa, 0x7d, 0xec, 0xfb, 0x07, 0xfc, 0x56, 0x1b, 0x66, 0x78, 0xff, 0xf7, 0x10, 0x51, 0xc2,
0x41, 0x0c, 0xbe, 0x5f, 0xc9, 0xf0, 0xe9, 0x98, 0x85, 0xeb, 0x69, 0x59, 0x47, 0x89, 0xed, 0x30,
0x4a, 0x91, 0x81, 0x88, 0xed, 0x4c, 0x1f, 0xb2, 0xd0, 0xcf, 0x4c, 0x34, 0x74, 0xcb, 0x9b, 0x54,
0x80, 0xe9, 0xdb, 0x7c, 0xa7, 0x66, 0x58, 0x3a, 0x91, 0x95, 0x1b, 0x11, 0xe9, 0xb2, 0x4d, 0x88,
0x74, 0x78, 0xf7, 0x10, 0xed, 0xc4, 0x99, 0xbc, 0x30, 0x36, 0x6b, 0x01, 0x4b, 0x18, 0xd7, 0x32,
0x23, 0xeb, 0xd9, 0x3c, 0x31, 0x1e, 0xe5, 0x71, 0x6b, 0xaf, 0xc2, 0xc4, 0x7a, 0x56, 0xdc, 0x2f,
0x2c, 0xc0, 0x1a, 0x9d, 0x40, 0x11, 0x73, 0x1a, 0xea, 0x40, 0x4a, 0x1a, 0xae, 0xac, 0x57, 0x85,
0x3c, 0xb5, 0x0e, 0xcc, 0x11, 0x5e, 0x68, 0xd4, 0xbc, 0x63, 0x4a, 0x04, 0x6b, 0xcf, 0x60, 0xb8,
0x3f, 0xf7, 0xd2, 0x70, 0x9e, 0xf4, 0x46, 0x21, 0x3a, 0x37, 0x87, 0xe3, 0x45, 0xd2, 0x6b, 0xec,
0x37, 0x81, 0xd6, 0x2b, 0xb4, 0x3e, 0x98, 0x8d, 0x7c, 0xb5, 0xea, 0x3b, 0x78, 0x7f, 0x06, 0xb0,
0xdd, 0x64, 0x0b, 0x60, 0xbb, 0x9b, 0xcd, 0xc0, 0x76, 0x61, 0xd1, 0x5c, 0x27, 0x9f, 0xea, 0x69,
0xe0, 0xd1, 0x2d, 0xd0, 0x72, 0x3c, 0x91, 0x21, 0x90, 0xc5, 0x24, 0xbe, 0x11, 0xbf, 0xe7, 0xd3,
0xb8, 0x58, 0xf1, 0x5f, 0x81, 0x33, 0x28, 0xcc, 0x81, 0xe7, 0xe2, 0x62, 0xb6, 0x3f, 0xee, 0xc2,
0xbc, 0x96, 0x15, 0x8e, 0x4d, 0xff, 0x1b, 0x1e, 0x72, 0x66, 0x86, 0xec, 0x39, 0xd9, 0xd3, 0xd3,
0x4e, 0xad, 0x3c, 0x3b, 0x8d, 0xcb, 0xe0, 0x46, 0x2e, 0x21, 0x8e, 0xe4, 0xcc, 0x59, 0xef, 0x0b,
0x66, 0x9e, 0xcf, 0x5e, 0x52, 0xfe, 0xb8, 0x16, 0x88, 0xd0, 0x44, 0x4f, 0xcc, 0x37, 0x22, 0x27,
0xf6, 0x53, 0x3e, 0xfc, 0x94, 0x34, 0x27, 0x1e, 0x85, 0xf2, 0xcf, 0xbc, 0xf8, 0x35, 0xae, 0x91,
0x31, 0x42, 0x32, 0xf2, 0x55, 0x3b, 0x0b, 0x25, 0x5b, 0xb0, 0xd0, 0x62, 0x0b, 0x16, 0x9a, 0x6c,
0x66, 0xa1, 0x54, 0xb1, 0x50, 0x22, 0x89, 0x06, 0x16, 0x5a, 0x88, 0xdf, 0x81, 0x85, 0x26, 0x2b,
0x93, 0x57, 0x52, 0x93, 0x57, 0xd4, 0x84, 0x2c, 0x75, 0xde, 0x85, 0x61, 0x93, 0x16, 0x08, 0x2a,
0xdf, 0x0c, 0x4d, 0x35, 0x73, 0xd8, 0x25, 0x12, 0x50, 0x95, 0xb5, 0x55, 0x1b, 0x9e, 0x88, 0x2b,
0x59, 0xd8, 0xbb, 0x76, 0xf0, 0xb6, 0x55, 0x36, 0x75, 0x70, 0xd0, 0x2a, 0x10, 0x71, 0x6e, 0x23,
0x90, 0x7c, 0x76, 0xb8, 0x39, 0xe6, 0xcf, 0x24, 0xa0, 0xe3, 0xc6, 0x97, 0x70, 0xb5, 0xb7, 0x8a,
0x29, 0x4b, 0x8a, 0xca, 0x5c, 0x91, 0x6b, 0xda, 0xfa, 0xd5, 0x6e, 0xea, 0xd7, 0xf6, 0x96, 0x7e,
0x4c, 0xd6, 0xb4, 0x03, 0xb2, 0xa7, 0x4d, 0x3a, 0xd6, 0xdb, 0x59, 0x47, 0xd0, 0xdc, 0x26, 0x68,
0xbe, 0x86, 0xa0, 0x0f, 0xc5, 0x9a, 0x76, 0xaa, 0xc2, 0x6a, 0xa7, 0x2a, 0xda, 0xdb, 0x11, 0x79,
0x62, 0xdb, 0xdb, 0x02, 0x99, 0xba, 0xf3, 0x0c, 0x21, 0xde, 0xd0, 0x3e, 0x66, 0x85, 0x6d, 0x6f,
0x7f, 0x2b, 0x71, 0x6d, 0x07, 0x5b, 0xa8, 0xcc, 0x8d, 0x32, 0x0e, 0xce, 0xd8, 0xfb, 0x97, 0x18,
0x6b, 0xe2, 0x55, 0x1e, 0x08, 0x07, 0x0e, 0x8a, 0x11, 0x53, 0xca, 0x77, 0x1e, 0x21, 0x7e, 0x03,
0x1b, 0xbb, 0x8e, 0x75, 0x61, 0x71, 0xec, 0x46, 0xaa, 0xd4, 0x02, 0x60, 0x7c, 0x68, 0x36, 0x05,
0x0d, 0xbf, 0xbb, 0x0a, 0x82, 0x35, 0x3a, 0x41, 0xf5, 0x8b, 0xa2, 0x85, 0xc7, 0x8e, 0xc5, 0x6c,
0xc8, 0xf4, 0xa2, 0x75, 0x23, 0x4e, 0xf7, 0x64, 0x68, 0xb5, 0x8b, 0xaf, 0xd6, 0x13, 0xb3, 0xb4,
0xa7, 0xf2, 0x91, 0xd4, 0x83, 0x55, 0x5b, 0x5e, 0xbd, 0x34, 0x7d, 0x7b, 0xaf, 0xae, 0x0d, 0x8d,
0x24, 0x12, 0xba, 0xd1, 0x56, 0x01, 0xde, 0x02, 0xc7, 0x6d, 0x1d, 0xb0, 0x5d, 0x65, 0xc7, 0x7f,
0x53, 0xb7, 0xc3, 0x56, 0x3a, 0x6b, 0x50, 0x6d, 0x6c, 0x03, 0x6e, 0x5d, 0x83, 0xb8, 0x98, 0x3e,
0x68, 0x16, 0x61, 0x35, 0x16, 0x93, 0x08, 0x81, 0xcf, 0x9b, 0x81, 0xb5, 0x31, 0xbf, 0xdb, 0xcc,
0xc3, 0x96, 0x41, 0xc3, 0xdb, 0xcf, 0x86, 0xca, 0x52, 0x61, 0x4f, 0xc7, 0x86, 0xd9, 0x68, 0x27,
0xec, 0x8f, 0x18, 0x79, 0x68, 0xab, 0xc7, 0xdc, 0x01, 0xc7, 0x05, 0xed, 0xac, 0xe7, 0xda, 0x2a,
0xae, 0x63, 0x38, 0x05, 0xae, 0x64, 0x40, 0x64, 0x04, 0xbf, 0x49, 0x2e, 0x94, 0x0f, 0x8d, 0x6d,
0x59, 0x68, 0x11, 0x35, 0x2e, 0x50, 0xc8, 0x10, 0x8d, 0x4d, 0x26, 0xcd, 0x4d, 0xd6, 0xe0, 0x24,
0x6a, 0xcd, 0x72, 0x7c, 0x06, 0xe0, 0x2d, 0x09, 0x75, 0x02, 0x07, 0xae, 0xa7, 0x27, 0x36, 0x38,
0x09, 0x6c, 0xb1, 0xb3, 0x5a, 0xb9, 0xca, 0x94, 0x06, 0xa0, 0x60, 0x6a, 0x97, 0x3e, 0x21, 0xbe,
0xe4, 0xd2, 0x68, 0x72, 0x12, 0x97, 0xbd, 0x63, 0xb3, 0xe0, 0x18, 0x0a, 0xc4, 0xaf, 0xdd, 0xb8,
0x74, 0xc5, 0x8d, 0x45, 0xd6, 0x0f, 0x79, 0x5d, 0x66, 0xa3, 0x9c, 0x62, 0xee, 0xda, 0xa0, 0x83,
0xb5, 0x71, 0x48, 0x43, 0x14, 0xab, 0x55, 0x5f, 0x04, 0x37, 0xca, 0x0b, 0x54, 0x58, 0xf3, 0x3b,
0xea, 0x32, 0xf5, 0x3e, 0x01, 0xd5, 0xcd, 0xfc, 0x4b, 0x07, 0x3f, 0xbf, 0x47, 0x1b, 0x10, 0xf3,
0x82, 0xd3, 0x98, 0x50, 0x97, 0x85, 0x3f, 0xaa, 0x80, 0xe1, 0xaf, 0x42, 0xf9, 0x52, 0xa0, 0xdd,
0xb3, 0x7e, 0x4b, 0xf5, 0xef, 0x19, 0x46, 0x64, 0x4a, 0xcf, 0x4d, 0x20, 0x89, 0x24, 0x4d, 0x9e,
0x61, 0xc8, 0x63, 0x68, 0x68, 0x1b, 0x3f, 0xe4, 0x23, 0x74, 0x2e, 0x16, 0x76, 0xa6, 0x8e, 0xb7,
0x2f, 0xef, 0x48, 0xf7, 0xbd, 0x8e, 0xef, 0xe1, 0x45, 0x40, 0xe0, 0xad, 0x91, 0xc5, 0x74, 0x0d,
0x23, 0x51, 0x03, 0x61, 0xbe, 0x8a, 0x73, 0xd7, 0x93, 0x8b, 0x5f, 0x23, 0x69, 0xb0, 0x6c, 0xe8,
0xed, 0xf9, 0x69, 0x17, 0xc9, 0x81, 0xba, 0x6d, 0xb7, 0x43, 0xa0, 0xc7, 0x9f, 0x0f, 0x8e, 0x5f,
0x46, 0x01, 0xac, 0xf0, 0x05, 0x50, 0x29, 0xdc, 0x68, 0xcf, 0xdf, 0x82, 0x32, 0x04, 0x6b, 0x6d,
0xcc, 0x3a, 0x78, 0xd3, 0x94, 0x83, 0x2a, 0xcb, 0xca, 0x12, 0x43, 0xed, 0x48, 0xb7, 0x45, 0xd8,
0x18, 0xbf, 0x78, 0x67, 0x58, 0x0e, 0xe8, 0x50, 0x2e, 0xbe, 0x8c, 0x5f, 0x7c, 0x17, 0xfb, 0x70,
0xe2, 0x57, 0xfe, 0xac, 0x9e, 0x76, 0xd0, 0x0d, 0xf6, 0x8b, 0x73, 0x89, 0x19, 0xb6, 0xd4, 0x07,
0x95, 0x26, 0xfb, 0x43, 0x50, 0x0d, 0xfd, 0x52, 0xb9, 0xea, 0x6a, 0x2f, 0xb2, 0xb0, 0xe4, 0xe3,
0x8b, 0x3f, 0x29, 0xb2, 0x14, 0x6a, 0x25, 0x63, 0x83, 0x1a, 0xf2, 0xea, 0x30, 0xce, 0x6b, 0xe5,
0x61, 0x69, 0x3e, 0x2e, 0xeb, 0x8f, 0x27, 0xd6, 0xe3, 0xc9, 0xec, 0x93, 0xf1, 0xd8, 0x23, 0x60,
0x7c, 0xf5, 0x38, 0x9d, 0x2b, 0x35, 0x17, 0x21, 0xc7, 0xe4, 0x2d, 0x7d, 0xc3, 0x6c, 0x18, 0x35,
0x11, 0xa6, 0x41, 0x1d, 0x0b, 0x32, 0xa3, 0xb5, 0x51, 0xa1, 0xd4, 0x81, 0x7e, 0xb5, 0x78, 0x5c,
0x96, 0x26, 0x0c, 0x60, 0x16, 0xac, 0x78, 0x4c, 0x2c, 0x9f, 0xf6, 0x12, 0xd9, 0x36, 0xce, 0xc2,
0x4c, 0xb9, 0x77, 0x4a, 0x98, 0x30, 0x44, 0x02, 0x33, 0x3e, 0x8c, 0xd7, 0x4f, 0x16, 0x2c, 0xb8,
0xb7, 0xfb, 0xd5, 0xeb, 0x57, 0xaf, 0x5e, 0xf5, 0x3b, 0x9c, 0xd5, 0x3b, 0x64, 0xc8, 0xeb, 0x3c,
0x62, 0xbc, 0xa9, 0x71, 0x67, 0xda, 0x21, 0x47, 0x64, 0x1e, 0x3d, 0x6e, 0x2c, 0x8f, 0xa5, 0x17,
0x0c, 0x0e, 0xba, 0xcf, 0xfe, 0xd4, 0xc5, 0x23, 0x68, 0x50, 0x0f, 0x02, 0xfb, 0x29, 0xc9, 0x3a,
0x13, 0x12, 0x39, 0x1d, 0xec, 0x9e, 0xf9, 0x51, 0xfe, 0x39, 0x3c, 0x59, 0xd5, 0x17, 0xe4, 0x97,
0x76, 0x4f, 0x58, 0x38, 0x29, 0x74, 0xb4, 0x18, 0xdd, 0x32, 0xe0, 0xe3, 0x29, 0xba, 0x4b, 0xcd,
0xf3, 0x9b, 0x64, 0xfa, 0x88, 0xab, 0x90, 0xe2, 0x4f, 0xf9, 0x52, 0x04, 0xe5, 0x8e, 0xf3, 0x11,
0xfc, 0x28, 0x70, 0x9d, 0xc5, 0xc5, 0x39, 0xb0, 0x04, 0x9c, 0x10, 0xdf, 0xf5, 0x0d, 0xfb, 0x81,
0xf0, 0x1b, 0x50, 0x93, 0x95, 0x1a, 0xe0, 0x0f, 0x30, 0x33, 0xbf, 0xa5, 0x71, 0x6a, 0xad, 0xf7,
0x8b, 0x11, 0x21, 0x89, 0xe2, 0x3a, 0xe7, 0x2b, 0xbc, 0x38, 0xaf, 0x2f, 0x71, 0x84, 0x4d, 0x3c,
0xcc, 0x87, 0xdc, 0xe7, 0xfd, 0xb2, 0x38, 0xbf, 0x02, 0xf9, 0x68, 0x39, 0xca, 0x43, 0x11, 0x27,
0xaa, 0x5e, 0x9c, 0xd7, 0x8b, 0x3e, 0xd7, 0x8b, 0xd0, 0xf9, 0x0d, 0x16, 0x88, 0xfe, 0xc0, 0x32,
0xeb, 0x15, 0xef, 0x42, 0x60, 0xa4, 0x9e, 0xd7, 0x36, 0x5a, 0x08, 0x12, 0xc6, 0x18, 0x1f, 0xa3,
0x8c, 0xdd, 0xa7, 0x8f, 0x24, 0x7e, 0x6e, 0xe4, 0x8c, 0x1d, 0x7a, 0xb0, 0x29, 0x20, 0x2b, 0xe2,
0x42, 0x57, 0x1f, 0x42, 0xd6, 0xa4, 0x52, 0xec, 0xd2, 0x6f, 0xa9, 0xf5, 0x0c, 0x06, 0x07, 0xcb,
0x02, 0x9d, 0x0e, 0x43, 0x86, 0x96, 0xe3, 0x70, 0x68, 0xbb, 0x70, 0xe8, 0x46, 0xa1, 0x17, 0xf3,
0xea, 0x07, 0x18, 0xcd, 0x38, 0x0a, 0xcd, 0x78, 0xf4, 0x60, 0x15, 0x22, 0x5c, 0xa3, 0x19, 0x13,
0xce, 0x3d, 0xd3, 0xa4, 0x7c, 0xa4, 0x54, 0x52, 0xd2, 0xdb, 0x1b, 0x9f, 0x49, 0x46, 0xb2, 0x4b,
0x31, 0x4c, 0xd2, 0xe4, 0xa2, 0xed, 0x7d, 0xd9, 0x3c, 0x8e, 0xbd, 0x47, 0x96, 0x44, 0x0c, 0xab,
0x72, 0xda, 0xed, 0x3e, 0xa7, 0xdd, 0x93, 0x57, 0x53, 0x7e, 0x63, 0x8e, 0x36, 0x6f, 0x2d, 0x18,
0xd7, 0x0a, 0x3e, 0x9b, 0x87, 0x8c, 0x6d, 0x42, 0x10, 0x64, 0xef, 0xa0, 0xb2, 0x21, 0xdc, 0xce,
0x1d, 0xdf, 0xf1, 0x26, 0x2b, 0xf0, 0x0d, 0xda, 0xba, 0xfa, 0xd6, 0x18, 0x4e, 0xb2, 0xe9, 0xd0,
0xb7, 0xdb, 0xbc, 0x41, 0x2b, 0xe7, 0x2a, 0xb0, 0x39, 0x0e, 0x48, 0xac, 0xcd, 0x30, 0xb9, 0x28,
0x73, 0xd5, 0x7a, 0x52, 0x87, 0xe2, 0x7c, 0xc6, 0x40, 0xd9, 0xd7, 0xfb, 0x3b, 0xf8, 0xae, 0x41,
0x1f, 0x68, 0x32, 0x96, 0x39, 0x53, 0xc3, 0x04, 0x2d, 0x11, 0xae, 0x29, 0x66, 0x7d, 0x23, 0x2c,
0xa3, 0x0d, 0x1e, 0x11, 0xfd, 0xb5, 0xaa, 0xa0, 0xe9, 0x22, 0xe1, 0xe1, 0x81, 0x70, 0xc1, 0xfb,
0x98, 0x3c, 0xcc, 0x55, 0x35, 0xc5, 0x33, 0xe4, 0xde, 0xf7, 0x04, 0x7f, 0xee, 0x2f, 0x6e, 0xc7,
0x17, 0xd5, 0xc2, 0xaf, 0x0c, 0xf0, 0x43, 0x60, 0x7e, 0x10, 0x72, 0x13, 0xc4, 0x47, 0xe7, 0xe3,
0x20, 0xb7, 0x10, 0x17, 0x31, 0x3c, 0xb4, 0x81, 0xe9, 0x45, 0x60, 0x83, 0xda, 0x5e, 0x2a, 0x0b,
0x50, 0xb1, 0x15, 0xf9, 0x9e, 0x20, 0xed, 0x1d, 0x24, 0x3c, 0x8a, 0xf5, 0xc1, 0x93, 0xe0, 0x2c,
0x8e, 0x74, 0xc4, 0x4e, 0x71, 0x26, 0x12, 0x84, 0x78, 0x0b, 0x90, 0xc6, 0x98, 0x58, 0x66, 0x09,
0x7a, 0xe1, 0x72, 0xd6, 0x83, 0xfd, 0x15, 0xfe, 0x7d, 0xee, 0xa1, 0xd1, 0x3d, 0x38, 0x2c, 0x4d,
0xcf, 0xf8, 0x97, 0x91, 0x9d, 0xbc, 0x6c, 0x1f, 0x34, 0x88, 0xfe, 0x4d, 0xbe, 0x64, 0x87, 0x33,
0xb3, 0xda, 0xc9, 0xb7, 0x4e, 0xbd, 0x60, 0x75, 0x0f, 0x63, 0xce, 0x7c, 0x2a, 0x1c, 0x8d, 0x4b,
0x1f, 0x5e, 0x38, 0x20, 0x8a, 0x82, 0x53, 0x6c, 0x82, 0x13, 0x07, 0x85, 0x2b, 0x3d, 0x96, 0x8c,
0x03, 0x45, 0xe2, 0x90, 0xa1, 0x3b, 0x82, 0x9b, 0xde, 0x42, 0x8d, 0x9b, 0x08, 0x7d, 0x36, 0x47,
0x18, 0xa6, 0xa1, 0x6f, 0x67, 0x11, 0x50, 0xb8, 0xab, 0x8b, 0xd0, 0x4e, 0x21, 0xa0, 0x1e, 0xdc,
0x86, 0x76, 0xfe, 0x00, 0x8d, 0xd4, 0xca, 0x19, 0x08, 0xf4, 0x61, 0xf3, 0x13, 0x33, 0xf6, 0x70,
0x41, 0x38, 0x28, 0x06, 0x28, 0x52, 0xb7, 0x66, 0x5f, 0x74, 0x18, 0xee, 0x12, 0x39, 0xd2, 0x9c,
0xc5, 0x7e, 0xc6, 0xb7, 0x91, 0x7d, 0xd8, 0x05, 0xab, 0xfc, 0x42, 0x34, 0xf3, 0xad, 0xcc, 0x4a,
0x00, 0x1f, 0x99, 0x28, 0x4a, 0x4a, 0x5d, 0x96, 0x4d, 0x37, 0x63, 0x8b, 0x9c, 0x04, 0x1e, 0xdd,
0xa3, 0xa5, 0x36, 0xd9, 0x77, 0x2c, 0x1c, 0x59, 0x25, 0xe5, 0xa8, 0x12, 0x97, 0xe2, 0x61, 0x5e,
0x67, 0x53, 0x73, 0x18, 0xff, 0xae, 0x48, 0x49, 0x2d, 0xb4, 0x4d, 0x0d, 0x74, 0x69, 0x16, 0xff,
0xac, 0x8a, 0xf3, 0xb0, 0x8a, 0x93, 0x45, 0x7e, 0x78, 0xc6, 0x29, 0x28, 0x3f, 0x7f, 0xc8, 0x7f,
0xba, 0x1d, 0xfb, 0xc0, 0x69, 0x29, 0x70, 0x1a, 0xa6, 0xd8, 0x13, 0xbc, 0xe6, 0xb6, 0x9a, 0xb1,
0x07, 0x19, 0x34, 0x74, 0x91, 0x8c, 0x53, 0x1a, 0xec, 0xc6, 0xac, 0x3e, 0x5e, 0x4b, 0xa6, 0xa0,
0xaf, 0x46, 0xa3, 0x51, 0xe7, 0xa0, 0xfb, 0xf2, 0x9b, 0xb0, 0x83, 0x59, 0xec, 0xbc, 0x7d, 0x58,
0xd7, 0xfb, 0x5e, 0x88, 0x3f, 0x6f, 0xc5, 0xcf, 0x31, 0x6c, 0xce, 0x28, 0x8e, 0xd6, 0x50, 0x38,
0x6a, 0xa2, 0xef, 0xe7, 0x3f, 0x84, 0xbe, 0x28, 0x8a, 0xb6, 0xa3, 0xcf, 0xf8, 0xf2, 0x3f, 0xd4,
0xc0, 0x9a, 0xb3, 0xf5, 0x89, 0xa5, 0xa0, 0x77, 0xe8, 0x55, 0x02, 0x6c, 0xc2, 0x83, 0x44, 0x83,
0x65, 0x17, 0x8e, 0x69, 0xfc, 0x06, 0xec, 0x13, 0x7b, 0x44, 0xd4, 0xf0, 0xdd, 0x5d, 0x04, 0x46,
0x27, 0x20, 0x2c, 0x53, 0x74, 0x8a, 0xa8, 0x52, 0xd6, 0xf8, 0x86, 0x32, 0xc0, 0xeb, 0x37, 0x54,
0x23, 0x26, 0xfc, 0xbe, 0xc9, 0xb2, 0x22, 0x45, 0x95, 0xb6, 0x75, 0x18, 0x6b, 0xe5, 0xdb, 0x20,
0x04, 0x3e, 0xe7, 0xaa, 0xaf, 0x5a, 0xf2, 0xde, 0x57, 0x08, 0x06, 0x6a, 0xa2, 0x8c, 0xc1, 0x52,
0x10, 0xaa, 0x30, 0x99, 0x73, 0x75, 0xc5, 0xe9, 0x74, 0x34, 0x8a, 0x22, 0x4f, 0xc3, 0xc0, 0xad,
0x59, 0x66, 0x31, 0x47, 0xe6, 0xaa, 0x02, 0x4c, 0x1b, 0xa4, 0x85, 0xca, 0xb1, 0x73, 0xb6, 0x94,
0x62, 0x47, 0x6c, 0x8c, 0x08, 0xf4, 0xa3, 0x98, 0x02, 0xcd, 0xfb, 0x15, 0xef, 0x15, 0x9c, 0xa8,
0xac, 0xf5, 0x03, 0xe7, 0xd1, 0x2a, 0xe8, 0x39, 0x45, 0x67, 0xb3, 0x11, 0x6c, 0x6f, 0x29, 0x8c,
0x47, 0xf9, 0x19, 0x26, 0x12, 0xfe, 0x45, 0xad, 0x22, 0xfb, 0xf7, 0x24, 0x39, 0x71, 0x66, 0x03,
0xe6, 0x62, 0x3d, 0x21, 0x33, 0x8b, 0x95, 0xfe, 0xae, 0xed, 0x04, 0x56, 0x3b, 0x17, 0x1b, 0xdb,
0x29, 0xbd, 0x46, 0x11, 0xe0, 0xb4, 0xf3, 0xf3, 0xc6, 0x76, 0x3e, 0x7b, 0x8d, 0x32, 0xc3, 0x69,
0xe7, 0x1f, 0xf5, 0x76, 0xfc, 0x25, 0xe7, 0xf8, 0x5e, 0xd3, 0xca, 0x58, 0x39, 0xef, 0xe3, 0x62,
0xb6, 0xb8, 0xd4, 0xd9, 0x17, 0xc2, 0x2a, 0x6e, 0xda, 0x15, 0x40, 0xe4, 0x37, 0xed, 0x09, 0x7d,
0xcd, 0x2c, 0x22, 0x39, 0xa6, 0x74, 0xaf, 0x41, 0xaf, 0xd0, 0xe0, 0x9a, 0xfb, 0x2f, 0x34, 0x27,
0xf0, 0x74, 0x79, 0x73, 0x11, 0xb3, 0xd0, 0x2d, 0xbb, 0x45, 0xa8, 0x6b, 0xa7, 0x6c, 0x1c, 0x97,
0x12, 0x36, 0x59, 0x3c, 0x72, 0xba, 0xf8, 0xd1, 0xf6, 0x17, 0x54, 0xca, 0x40, 0xd8, 0xac, 0xf9,
0x54, 0xb5, 0x35, 0xc2, 0x64, 0x9f, 0xf9, 0x57, 0x44, 0x05, 0x9b, 0xf9, 0x98, 0x63, 0x4c, 0x12,
0x2b, 0x63, 0xd9, 0xae, 0x61, 0xd1, 0x9d, 0x35, 0xa6, 0xf1, 0x84, 0x5d, 0xc7, 0xf9, 0x26, 0x6c,
0x37, 0x11, 0x6a, 0x9b, 0x0c, 0x11, 0x17, 0x61, 0x86, 0xfe, 0x92, 0x82, 0xd4, 0xf4, 0x11, 0x67,
0x77, 0x23, 0xcb, 0x50, 0x86, 0xbd, 0xe3, 0x1d, 0x7c, 0xd5, 0x84, 0x9c, 0x6e, 0x34, 0x58, 0x29,
0x55, 0x2a, 0x90, 0x89, 0xb8, 0x5c, 0x4d, 0x61, 0x04, 0xb3, 0x50, 0x4a, 0x54, 0xc7, 0xe4, 0x70,
0xd1, 0xcb, 0xc3, 0x11, 0x4c, 0x42, 0xa6, 0x8b, 0x6e, 0xa9, 0x68, 0x1c, 0xa7, 0xba, 0x68, 0x4c,
0x45, 0xf7, 0xb0, 0xb9, 0x39, 0x03, 0x46, 0x1f, 0x91, 0x57, 0xbf, 0xf0, 0x91, 0xde, 0xe5, 0xe5,
0x55, 0x48, 0xff, 0x5d, 0xad, 0x56, 0xe2, 0x6a, 0x14, 0xb1, 0xb0, 0xa9, 0x76, 0x7c, 0xc9, 0x07,
0x27, 0xbf, 0x72, 0xaf, 0x3e, 0x2d, 0x03, 0xe5, 0x28, 0x45, 0xff, 0xd4, 0xe6, 0x5b, 0x87, 0xc9,
0xa4, 0x72, 0xad, 0xc9, 0x48, 0xc1, 0x6c, 0x62, 0xea, 0x7a, 0x08, 0x69, 0xff, 0x37, 0x94, 0x0e,
0x22, 0xc5, 0x01, 0xfe, 0x2d, 0xd3, 0x25, 0x1c, 0x1d, 0xdd, 0x26, 0xd5, 0xec, 0x6e, 0x8c, 0x77,
0x81, 0x47, 0x6f, 0x92, 0xc5, 0x24, 0xcf, 0xf3, 0x4f, 0x09, 0x3b, 0xc2, 0xec, 0x18, 0x47, 0xf7,
0xc9, 0xa7, 0x04, 0x0f, 0xca, 0xdc, 0x20, 0xb9, 0x80, 0x81, 0xe4, 0x07, 0x34, 0x89, 0x98, 0xe3,
0xfb, 0xb3, 0xc9, 0x7e, 0xdc, 0x7d, 0x15, 0x0c, 0x4e, 0x22, 0xd4, 0x64, 0xf0, 0xb3, 0x41, 0x38,
0x9b, 0x0c, 0x8e, 0xe5, 0x9f, 0x27, 0x11, 0x8a, 0xfa, 0x17, 0x2f, 0xe2, 0x78, 0x36, 0xa1, 0x92,
0xfd, 0xf8, 0x04, 0x4b, 0xa2, 0x57, 0x46, 0x09, 0x34, 0x20, 0xb5, 0x1b, 0x44, 0x7e, 0x09, 0xac,
0x73, 0xc3, 0xf5, 0xac, 0x44, 0x37, 0xb2, 0xd9, 0x64, 0x15, 0x76, 0x10, 0x31, 0x27, 0xec, 0xbc,
0x8c, 0xbe, 0xc1, 0x84, 0x68, 0xe1, 0xeb, 0xae, 0x48, 0xcc, 0x02, 0x1a, 0xd1, 0xc2, 0x82, 0x17,
0x84, 0x82, 0x9f, 0xc8, 0x54, 0xc8, 0xcd, 0x9c, 0xf8, 0xdc, 0x12, 0x00, 0x74, 0x48, 0xc1, 0xbc,
0x9c, 0x41, 0x5f, 0xa6, 0xe0, 0x68, 0x3f, 0xab, 0x98, 0x5e, 0x44, 0x08, 0x52, 0x37, 0x4d, 0x16,
0xf3, 0xce, 0x4f, 0x6c, 0x9c, 0xe7, 0xe2, 0x40, 0xe8, 0xf3, 0xef, 0x83, 0x96, 0x5a, 0x4b, 0x21,
0x01, 0x87, 0xec, 0xd8, 0x3b, 0xe2, 0x06, 0x87, 0x95, 0x24, 0xf5, 0xc2, 0x86, 0x42, 0xc4, 0xf4,
0xee, 0xb6, 0x7c, 0x5a, 0x94, 0x9c, 0x36, 0x49, 0xfb, 0x45, 0xf0, 0x85, 0x54, 0xf2, 0x0f, 0x6b,
0x22, 0x2f, 0x28, 0x97, 0x8d, 0xa4, 0x21, 0x6c, 0x69, 0x6e, 0xea, 0x36, 0x47, 0x63, 0xa9, 0xae,
0x47, 0x3d, 0xcb, 0x3b, 0x65, 0xc9, 0x2f, 0xb7, 0x23, 0x7e, 0x01, 0x2a, 0xb1, 0x24, 0xc8, 0x23,
0x61, 0x27, 0x5a, 0x5d, 0xad, 0x64, 0x36, 0x40, 0x01, 0xa9, 0x46, 0xb7, 0xcf, 0xf1, 0xfc, 0x3e,
0x34, 0x0a, 0xe0, 0xfd, 0x5f, 0xe8, 0x50, 0x6e, 0x54, 0xf9, 0x35, 0x9e, 0xcf, 0x0c, 0x38, 0xcc,
0xb8, 0xdb, 0x67, 0xc2, 0xef, 0x85, 0x39, 0x7e, 0x2f, 0xe2, 0xe2, 0xb5, 0xdd, 0xe1, 0x86, 0x6c,
0x08, 0x46, 0x46, 0x6a, 0x13, 0x70, 0xd2, 0xca, 0x5e, 0x6d, 0xe0, 0x79, 0x23, 0x8e, 0xd2, 0x64,
0x94, 0xc2, 0xe1, 0x7c, 0x01, 0x1a, 0x1c, 0x86, 0xaf, 0x63, 0x6a, 0x62, 0xdf, 0xbb, 0x4f, 0x09,
0xc3, 0xf3, 0xc1, 0x13, 0xb1, 0xfd, 0xa8, 0xc0, 0xf0, 0xb3, 0xbb, 0x61, 0xbf, 0xab, 0x38, 0xac,
0x3d, 0xa6, 0x03, 0xfa, 0x8c, 0x89, 0x0c, 0xe8, 0x87, 0x9c, 0x42, 0xf3, 0x8b, 0xf0, 0xa4, 0xe0,
0x93, 0x03, 0x02, 0x8c, 0xf9, 0xa6, 0xb2, 0xb3, 0xb2, 0xea, 0x2d, 0x57, 0xe1, 0xad, 0xba, 0x1a,
0xe2, 0x9d, 0x88, 0x42, 0x01, 0xd8, 0x67, 0x90, 0x59, 0xd6, 0xc8, 0x0c, 0x1d, 0xc8, 0xc6, 0x65,
0xd1, 0x33, 0x1b, 0x0e, 0x3f, 0x9b, 0x00, 0x77, 0x98, 0x25, 0xb6, 0x7e, 0x7c, 0x0c, 0xb9, 0xfa,
0x27, 0x0d, 0x34, 0x2c, 0x7c, 0xfd, 0xda, 0xba, 0xfc, 0x70, 0x09, 0x23, 0x6b, 0xcc, 0x76, 0xe9,
0x59, 0x81, 0x94, 0x87, 0x61, 0x41, 0x2a, 0xf2, 0x3e, 0xb3, 0xb3, 0xb4, 0xfe, 0x0e, 0x5c, 0xc8,
0xe6, 0x04, 0xaf, 0x6b, 0x51, 0x1e, 0x4b, 0x34, 0x3a, 0x99, 0x03, 0x6e, 0x5f, 0x06, 0xc0, 0xf0,
0x5b, 0xa3, 0x06, 0xd3, 0x06, 0x6d, 0x9c, 0x96, 0x87, 0xf3, 0xa1, 0x6b, 0xba, 0xaa, 0x8d, 0xc6,
0x7e, 0x17, 0xc6, 0x03, 0x2d, 0x57, 0x41, 0x0f, 0xe1, 0x44, 0xb7, 0x4c, 0xff, 0x8a, 0x18, 0xab,
0x3f, 0xf2, 0x54, 0xc7, 0x1c, 0x3f, 0x42, 0xa5, 0x5c, 0xb4, 0xb2, 0x5c, 0x6d, 0xc0, 0x84, 0xad,
0x9e, 0x07, 0x07, 0xcb, 0x02, 0x42, 0x44, 0xac, 0x5a, 0x60, 0xb9, 0x8d, 0x3d, 0x69, 0xb4, 0xc0,
0x2e, 0x84, 0x95, 0x5e, 0x48, 0xac, 0xfd, 0x38, 0xa4, 0x02, 0xc8, 0xd1, 0xa0, 0x2e, 0xf4, 0x0c,
0xd7, 0x89, 0x50, 0x85, 0x90, 0x63, 0xf7, 0xaa, 0x35, 0xfd, 0x22, 0x91, 0x90, 0xc4, 0x5e, 0x81,
0x37, 0xf5, 0x5e, 0x8c, 0x51, 0x72, 0x51, 0xaf, 0xdb, 0x4f, 0x34, 0x64, 0x48, 0x22, 0x21, 0x43,
0xb2, 0xb8, 0xbc, 0x4c, 0xae, 0xc2, 0x14, 0x0e, 0xd7, 0x5b, 0x0d, 0x43, 0x95, 0xff, 0xab, 0x28,
0xd8, 0xe2, 0x6c, 0x84, 0x80, 0xb0, 0xfd, 0xcc, 0xa1, 0x3e, 0xd5, 0xc3, 0xc4, 0xbb, 0x60, 0xd7,
0x0f, 0x30, 0x2b, 0xd1, 0x0e, 0xc9, 0x3a, 0x39, 0x3b, 0x48, 0xdc, 0xee, 0xae, 0x7e, 0xcf, 0x3b,
0x7e, 0xcb, 0xc1, 0x76, 0xa5, 0x4b, 0x24, 0xb0, 0xaa, 0x91, 0x1f, 0x2a, 0x65, 0xa3, 0x8c, 0x83,
0xbf, 0x36, 0x45, 0xfc, 0x0b, 0xa9, 0xc4, 0xc8, 0xbb, 0x31, 0xc9, 0xef, 0x4a, 0x7b, 0xa8, 0xe5,
0xe9, 0x04, 0xc1, 0xca, 0xab, 0xc3, 0x69, 0x3e, 0xb9, 0x43, 0x93, 0x52, 0x45, 0x8d, 0x20, 0xbf,
0x7d, 0x8f, 0xc7, 0x39, 0x1f, 0xcf, 0x34, 0xfc, 0x37, 0x8f, 0xee, 0x79, 0xed, 0x13, 0x44, 0xbe,
0x98, 0x8f, 0xaa, 0x37, 0x0b, 0xad, 0xd2, 0x85, 0x98, 0x62, 0x4b, 0x83, 0x8e, 0xe0, 0x6e, 0x64,
0x07, 0x61, 0x32, 0xf4, 0x7b, 0x0f, 0xe4, 0x68, 0xd3, 0x5f, 0x7d, 0x7e, 0xd8, 0xca, 0x02, 0x42,
0x83, 0x25, 0x4d, 0x8d, 0xca, 0xe3, 0xcb, 0xec, 0x0a, 0x7d, 0x8b, 0xfc, 0x8a, 0xd7, 0x93, 0xc9,
0x02, 0x4e, 0xcb, 0x40, 0xa2, 0x7f, 0x60, 0x06, 0xef, 0xf4, 0xb4, 0x3c, 0xa8, 0xfa, 0x29, 0x4c,
0x21, 0xaf, 0x45, 0x22, 0x9e, 0x71, 0xf7, 0xfa, 0x83, 0x2e, 0xcf, 0x17, 0x52, 0x23, 0xc2, 0x00,
0xb6, 0x0d, 0x96, 0x99, 0x85, 0x74, 0x6b, 0x93, 0x53, 0x2d, 0x90, 0x1a, 0x03, 0xd6, 0xd6, 0x24,
0xca, 0xc0, 0xbc, 0xb0, 0x69, 0x73, 0xe9, 0x32, 0x2a, 0x0a, 0xf2, 0x4c, 0xef, 0x79, 0xa4, 0x52,
0x0f, 0xaa, 0xf2, 0x6d, 0x33, 0x94, 0x64, 0xee, 0xe4, 0xca, 0x01, 0x52, 0x98, 0xe1, 0xe1, 0x9a,
0x8b, 0xa3, 0x83, 0x38, 0x76, 0x70, 0x0e, 0x37, 0x94, 0x69, 0x5c, 0x65, 0x03, 0x1c, 0x51, 0xcb,
0x6e, 0x59, 0x36, 0xda, 0x2d, 0xcd, 0xcc, 0x7d, 0x3b, 0xc4, 0x87, 0x4d, 0xb5, 0x94, 0x13, 0x39,
0xdf, 0xcd, 0x1a, 0x1c, 0x6b, 0x75, 0x8d, 0x90, 0x0d, 0x68, 0x3a, 0xe5, 0x64, 0x23, 0xc9, 0xee,
0x5b, 0xda, 0x7b, 0x46, 0xbf, 0x87, 0xf0, 0x8a, 0xea, 0x9a, 0x34, 0x0b, 0x86, 0xd2, 0x6f, 0x3e,
0xbb, 0x8a, 0x0b, 0xf1, 0x8b, 0x32, 0x79, 0x87, 0x9a, 0x07, 0x55, 0x2d, 0xbc, 0x66, 0xc5, 0x29,
0x54, 0x05, 0x02, 0x3b, 0x22, 0xd0, 0x2e, 0xf8, 0xaa, 0x2c, 0xd6, 0xc8, 0x2c, 0x19, 0xe1, 0x36,
0x98, 0x35, 0x10, 0x97, 0xa8, 0xd6, 0x16, 0xc2, 0x80, 0x5a, 0x0d, 0x21, 0x56, 0x46, 0x24, 0x4d,
0x3d, 0x34, 0x43, 0x16, 0xb4, 0x3c, 0x79, 0xd7, 0x67, 0x94, 0x86, 0xc7, 0xf0, 0xa7, 0x07, 0xbe,
0xeb, 0xad, 0x7f, 0x43, 0x26, 0x2b, 0x2e, 0x46, 0x45, 0xf2, 0x33, 0x68, 0xd1, 0x50, 0x20, 0x2d,
0xef, 0x99, 0x79, 0x19, 0x18, 0xa7, 0x21, 0x65, 0xff, 0xa8, 0xdd, 0x89, 0x89, 0x3c, 0x10, 0xfc,
0x05, 0xe7, 0xc2, 0x94, 0x7a, 0xc6, 0xbd, 0xbb, 0x33, 0xe9, 0xa4, 0x2f, 0xb0, 0xb1, 0xd6, 0xc4,
0x1c, 0xf0, 0x40, 0x7c, 0x23, 0x87, 0x65, 0x4b, 0x0f, 0x64, 0x22, 0xdb, 0x7a, 0x93, 0xb6, 0x23,
0xfe, 0xaa, 0xfa, 0x82, 0x90, 0x02, 0xc3, 0xae, 0x9b, 0x91, 0xd4, 0xd2, 0x76, 0xdd, 0x9a, 0xdf,
0xc5, 0x38, 0xbd, 0x5b, 0xf8, 0x8d, 0x99, 0x7e, 0xea, 0x4f, 0x4c, 0x57, 0x08, 0xfe, 0x74, 0xc5,
0x63, 0xb3, 0xff, 0x7d, 0x56, 0xf7, 0x55, 0x91, 0x7c, 0x8b, 0xd9, 0x0a, 0xc3, 0x77, 0xf1, 0x0b,
0x5a, 0x85, 0x09, 0x51, 0x02, 0x6a, 0xe9, 0x43, 0x24, 0x60, 0xbf, 0xa9, 0x73, 0x17, 0x74, 0x29,
0x25, 0xdd, 0xb4, 0x0d, 0xea, 0x39, 0x20, 0xf6, 0x52, 0x29, 0xea, 0x3c, 0x6a, 0xec, 0xe6, 0x43,
0x7e, 0x07, 0xb3, 0x54, 0x0e, 0xdd, 0x02, 0x44, 0xc6, 0x67, 0xc6, 0x7e, 0x3f, 0x2a, 0xcf, 0x17,
0x39, 0x01, 0x23, 0xc9, 0x1d, 0x9f, 0x0b, 0x0c, 0xcc, 0x9a, 0xc5, 0xcc, 0x5c, 0x59, 0xb4, 0xd9,
0x52, 0x02, 0x2c, 0xd4, 0x9b, 0xcb, 0x8f, 0x70, 0x78, 0xf3, 0x3d, 0x78, 0x57, 0x5d, 0x9b, 0x82,
0xd6, 0x2d, 0x33, 0x91, 0x99, 0x3a, 0x30, 0x1c, 0xae, 0xb9, 0xbd, 0x7f, 0xa7, 0x98, 0xa0, 0x66,
0x21, 0x25, 0x92, 0x4a, 0x4f, 0xae, 0xe6, 0x95, 0xc4, 0xbe, 0x95, 0xb3, 0x5c, 0xec, 0x35, 0xba,
0x4a, 0xdf, 0x5c, 0xeb, 0x32, 0xac, 0x15, 0x74, 0x0e, 0xb3, 0x1b, 0x95, 0xf3, 0x77, 0x09, 0x7f,
0xfb, 0x30, 0x98, 0x72, 0xa8, 0xa0, 0x35, 0x34, 0x86, 0xfe, 0xa2, 0x06, 0x56, 0xe4, 0x99, 0xae,
0x46, 0xe3, 0x09, 0xd7, 0xf8, 0xbc, 0xe0, 0x92, 0xcf, 0xc2, 0x95, 0xe0, 0xac, 0x0f, 0x79, 0x11,
0xfe, 0xfb, 0xac, 0xc9, 0xff, 0x5f, 0xb0, 0xd7, 0x8e, 0x2f, 0xe7, 0x26, 0x0a, 0x2c, 0x5c, 0x27,
0xe2, 0x7d, 0xde, 0x7f, 0x5e, 0x63, 0x77, 0xd7, 0x19, 0x87, 0x3a, 0x59, 0x71, 0x75, 0xf0, 0x10,
0xc9, 0xac, 0xf5, 0xa4, 0x07, 0x96, 0x08, 0x32, 0xba, 0xef, 0x67, 0x7f, 0x2e, 0x8f, 0xee, 0x3f,
0x82, 0xea, 0x98, 0xff, 0x35, 0x79, 0x60, 0x37, 0xfe, 0x71, 0xd0, 0x8f, 0x76, 0x50, 0xc6, 0xfa,
0x9c, 0xdc, 0x41, 0x44, 0x88, 0x31, 0x81, 0x2a, 0x38, 0xa5, 0x4c, 0x8a, 0x58, 0x90, 0x0e, 0x0e,
0xbb, 0xc7, 0xbb, 0xbb, 0x5b, 0x75, 0x15, 0x0e, 0x0e, 0x7c, 0x64, 0xa0, 0x1d, 0xe8, 0x35, 0xd7,
0x0a, 0xc8, 0x0b, 0x06, 0xce, 0xef, 0x8b, 0xea, 0xd1, 0xf7, 0x0e, 0x0e, 0x12, 0x2f, 0xe4, 0xef,
0x1d, 0xc4, 0x19, 0x12, 0xd7, 0x3d, 0x48, 0xa5, 0xc9, 0x66, 0x84, 0x8a, 0xc1, 0xa7, 0x52, 0x90,
0x00, 0x7a, 0x7d, 0x5b, 0x1b, 0x53, 0x2f, 0x4c, 0x83, 0x6d, 0xc7, 0xb5, 0x0b, 0x0d, 0x89, 0x15,
0x61, 0xfa, 0xf0, 0xe8, 0x24, 0x80, 0xcb, 0x06, 0x38, 0x5b, 0x47, 0x93, 0x92, 0xe7, 0x8d, 0xec,
0x66, 0x42, 0xf7, 0x1f, 0xf7, 0x1f, 0x07, 0xdf, 0xbd, 0xfe, 0xee, 0xe9, 0x09, 0x7e, 0xbe, 0x3c,
0x79, 0xbd, 0xbb, 0x7b, 0xff, 0xf1, 0xf4, 0xbb, 0xe3, 0x28, 0x68, 0x4d, 0xa5, 0xc9, 0xe1, 0x88,
0x97, 0xf7, 0x1f, 0x65, 0xa2, 0x47, 0x12, 0x56, 0x84, 0x61, 0x6a, 0xa6, 0x23, 0xec, 0x1b, 0x27,
0x6a, 0x0a, 0x2c, 0x12, 0x53, 0xcb, 0x61, 0x28, 0xfb, 0xe5, 0x59, 0x9e, 0x62, 0xf7, 0xb1, 0x7f,
0x8c, 0x67, 0x7d, 0x09, 0x65, 0xd9, 0x58, 0x1a, 0x4a, 0x49, 0xb2, 0x59, 0xef, 0x89, 0x9a, 0x1c,
0x54, 0xd9, 0x87, 0x71, 0x7f, 0xa1, 0x5f, 0xab, 0x0a, 0xdd, 0x94, 0xc0, 0x2b, 0x27, 0x1e, 0xab,
0x63, 0x27, 0x8b, 0x72, 0x0e, 0x96, 0x87, 0xd6, 0x2b, 0xce, 0x8c, 0x6f, 0x62, 0xc1, 0x95, 0x6f,
0xc2, 0xe6, 0x83, 0x5d, 0x31, 0x99, 0x7b, 0xa1, 0xa8, 0x12, 0x88, 0x5f, 0x62, 0xf5, 0x37, 0x0c,
0x5c, 0xf7, 0xf8, 0x65, 0xa4, 0x78, 0x1b, 0x34, 0x52, 0x46, 0xe3, 0x2b, 0x8a, 0x71, 0xe4, 0xef,
0xe9, 0x77, 0x1a, 0xec, 0xd8, 0x28, 0xe5, 0x7f, 0xe0, 0x12, 0x45, 0xe3, 0x10, 0x30, 0x0f, 0x8f,
0x21, 0x93, 0x4d, 0x0e, 0xc5, 0xa7, 0x76, 0xba, 0x3d, 0xf1, 0x35, 0x4c, 0xfb, 0xac, 0xe8, 0xd6,
0x24, 0x38, 0xcc, 0x27, 0xb7, 0x52, 0x91, 0x5d, 0x1d, 0xa8, 0x37, 0xc1, 0x8d, 0xf9, 0x5b, 0x0d,
0x39, 0xd3, 0x73, 0x6d, 0x04, 0xe2, 0xc9, 0x7d, 0x44, 0x55, 0xf8, 0xa8, 0x72, 0x5b, 0x87, 0xa1,
0x80, 0x7a, 0x43, 0x2f, 0xc2, 0x33, 0xe1, 0x5d, 0x95, 0x7b, 0xcf, 0x98, 0x3d, 0xb5, 0x14, 0x78,
0x4c, 0xa6, 0xa4, 0x03, 0xcd, 0x4b, 0xd0, 0xda, 0x0b, 0xfc, 0x41, 0xae, 0xb5, 0xf7, 0x31, 0xac,
0x73, 0x43, 0x8a, 0x30, 0x10, 0x8a, 0x6f, 0x19, 0x2b, 0xe0, 0xec, 0x73, 0x78, 0x78, 0x28, 0x72,
0xb9, 0x56, 0x52, 0x5f, 0x94, 0xb2, 0x5f, 0x65, 0x71, 0x85, 0x1d, 0x71, 0x96, 0x4c, 0xe1, 0xd8,
0xc7, 0x5d, 0xfb, 0xe1, 0x50, 0x49, 0x8e, 0x62, 0xfc, 0xb7, 0x32, 0x08, 0x4c, 0xc8, 0x90, 0x04,
0xf8, 0x3a, 0x10, 0x4f, 0x10, 0xfa, 0x6d, 0x48, 0x52, 0xfe, 0xe9, 0xc9, 0x3e, 0x89, 0xc2, 0x29,
0x19, 0x4a, 0xe9, 0x46, 0x3f, 0x34, 0xa8, 0x81, 0xb2, 0x90, 0xde, 0x0a, 0x7a, 0x8d, 0xf5, 0x29,
0x18, 0x59, 0xd9, 0xba, 0x6a, 0xdd, 0x58, 0xf1, 0x15, 0xd5, 0x2a, 0x21, 0x32, 0x2f, 0x04, 0x2e,
0x17, 0x8b, 0x0d, 0x76, 0x7d, 0x3a, 0x43, 0xa0, 0xa0, 0x60, 0x19, 0xde, 0xc6, 0x60, 0x14, 0xf9,
0x7f, 0xe0, 0x10, 0x87, 0xff, 0x0f, 0x51, 0x17, 0x81, 0x76, 0xea, 0xb5, 0xe6, 0x39, 0x3a, 0x9f,
0xe5, 0xf7, 0xd0, 0x18, 0x2e, 0xeb, 0xf6, 0x8a, 0x15, 0xee, 0x90, 0x1c, 0x03, 0x7a, 0x43, 0x4d,
0x6a, 0x12, 0x8e, 0xde, 0x5e, 0x88, 0xf2, 0x7d, 0x43, 0xbd, 0xbb, 0x62, 0x53, 0x35, 0xfa, 0x30,
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)
{
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);
if (!seg.isActive() || !seg.isSelected()) continue;
strip.setMode(i, fx);
@ -105,7 +105,7 @@ void changeEffect(uint8_t fx)
void changePalette(uint8_t pal)
{
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);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.palette = pal;
@ -124,7 +124,7 @@ void changeEffectSpeed(int8_t amount)
int16_t new_val = (int16_t) effectSpeed + amount;
effectSpeed = (byte)constrain(new_val,0,255);
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);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.speed = effectSpeed;
@ -147,7 +147,7 @@ void changeEffectSpeed(int8_t amount)
prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col);
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);
if (!seg.isActive() || !seg.isSelected()) continue;
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;
effectIntensity = (byte)constrain(new_val,0,255);
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);
if (!seg.isActive() || !seg.isSelected()) continue;
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
hsv2rgb_rainbow(prim_hsv, fastled_col);
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);
if (!seg.isActive() || !seg.isSelected()) continue;
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) {
// 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);
if (!seg.isActive() || !seg.isSelected()) continue;
byte capabilities = seg.getLightCapabilities();

View File

@ -11,11 +11,20 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
byte id = elem["id"] | it;
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 prev = seg; //make a backup so we can tell if something changed
uint16_t start = elem["start"] | seg.start;
int stop = elem["stop"] | -1;
if (stop < 0) {
uint16_t len = elem["len"];
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 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;
return;
}
// 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 (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);
}
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) {
//apply all selected segments
//bool didSet = false;
for (byte s = 0; s < strip.getMaxSegments(); s++) {
for (byte s = 0; s < strip.getActiveSegmentsNum(); s++) {
Segment &sg = strip.getSegment(s);
if (sg.isActive()) {
if (sg.isSelected()) {
deserializeSegment(segVar, s, presetId);
//didSet = true;
}
if (sg.isSelected()) {
deserializeSegment(segVar, s, presetId);
//didSet = true;
}
}
//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>();
for (JsonObject elem : segs)
{
DEBUG_PRINT(F(" Deserializing segment: ")); DEBUG_PRINTLN(it);
deserializeSegment(elem, it, presetId);
it++;
}
// DEBUG_PRINTLN(F(" Purging segments."));
// strip.purgeSegments(); // prune inactive segments (resets ESP if effect running)
}
usermods.readFromJsonState(root);
@ -496,8 +505,16 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
bool selectedSegmentsOnly = root[F("sc")] | false;
JsonArray seg = root.createNestedArray("seg");
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);
if (selectedSegmentsOnly && !sg.isSelected()) continue;
if (!forPreset && selectedSegmentsOnly && !sg.isSelected()) continue;
if (sg.isActive()) {
JsonObject seg0 = seg.createNestedObject();
serializeSegment(seg0, sg, s, forPreset, segmentBounds);
@ -520,6 +537,7 @@ void serializeInfo(JsonObject root)
leds["fps"] = strip.getFps();
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
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
#ifndef WLED_DISABLE_2D

View File

@ -31,7 +31,7 @@ void applyValuesToSelectedSegs()
// copy of first selected segment to tell if value was updated
uint8_t firstSel = strip.getFirstSelectedSegId();
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);
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;

View File

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

View File

@ -608,7 +608,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SS="));
if (pos > 0) {
byte t = getNumVal(&req, pos);
if (t < strip.getMaxSegments()) {
if (t < strip.getActiveSegmentsNum()) {
selectedSeg = t;
singleSegment = true;
}
@ -618,7 +618,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("SV=")); //segment selected
if (pos > 0) {
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);
}
@ -824,7 +824,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
// 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);
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
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[38] = mainseg.cct;
udpOut[39] = strip.getMaxSegments();
udpOut[39] = strip.getActiveSegmentsNum();
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);
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte
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);
// if WLED was off and using main segment only, freeze non-main segments so they stay off
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);
}
}
@ -342,7 +342,7 @@ void handleNotifications()
for (uint8_t i = 0; i < numSrcSegs; i++) {
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
uint8_t id = udpIn[0 +ofs];
if (id > strip.getMaxSegments()) break;
if (id > strip.getActiveSegmentsNum()) break;
Segment& selseg = strip.getSegment(id);
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+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
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);
if (!seg.isActive() || !seg.isSelected()) continue;
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);

View File

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

View File

@ -8,7 +8,7 @@
*/
// 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
//#define WLED_USE_MY_CONFIG

View File

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

View File

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