Bugfix for saving usermod settings.

Modification of global interface pin allocation.
Code relocation in 4LD.
This commit is contained in:
Blaz Kristan 2022-08-15 20:23:47 +02:00
parent e6f74751d4
commit 7125d19af1
7 changed files with 345 additions and 312 deletions

View File

@ -185,6 +185,123 @@ class FourLineDisplayUsermod : public Usermod {
u8x8_cad_EndTransfer(u8x8_struct); u8x8_cad_EndTransfer(u8x8_struct);
} }
/**
* Wrappers for screen drawing
*/
void setFlipMode(uint8_t mode) {
if (type == NONE || !enabled) return;
u8x8->setFlipMode(mode);
}
void setContrast(uint8_t contrast) {
if (type == NONE || !enabled) return;
u8x8->setContrast(contrast);
}
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) {
if (type == NONE || !enabled) return;
u8x8->setFont(u8x8_font_chroma48medium8_r);
if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string);
else u8x8->drawString(col, row, string);
}
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
if (type == NONE || !enabled) return;
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->draw2x2String(col, row, string);
}
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) {
if (type == NONE || !enabled) return;
u8x8->setFont(font);
if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph);
else u8x8->drawGlyph(col, row, glyph);
}
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
if (type == NONE || !enabled) return;
u8x8->setFont(font);
u8x8->draw2x2Glyph(col, row, glyph);
}
uint8_t getCols() {
if (type==NONE || !enabled) return 0;
return u8x8->getCols();
}
void clear() {
if (type == NONE || !enabled) return;
u8x8->clear();
}
void setPowerSave(uint8_t save) {
if (type == NONE || !enabled) return;
u8x8->setPowerSave(save);
}
void center(String &line, uint8_t width) {
int len = line.length();
if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line;
for (byte i=line.length(); i<width; i++) line += ' ';
}
void draw2x2GlyphIcons() {
if (lineHeight == 2) {
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x2, true); //brightness icon
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x2, true); //speed icon
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x2, true); //intensity icon
drawGlyph(14, 2*lineHeight, 4, u8x8_4LineDisplay_WLED_icons_2x2, true); //palette icon
drawGlyph(14, 3*lineHeight, 5, u8x8_4LineDisplay_WLED_icons_2x2, true); //effect icon
} else {
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x1); //brightness icon
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x1); //speed icon
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x1); //intensity icon
drawGlyph(15, 2, 4, u8x8_4LineDisplay_WLED_icons_1x1); //palette icon
drawGlyph(15, 3, 5, u8x8_4LineDisplay_WLED_icons_1x1); //effect icon
}
}
/**
* Display the current date and time in large characters
* on the middle rows. Based 24 or 12 hour depending on
* the useAMPM configuration.
*/
void showTime() {
if (type == NONE || !enabled || !displayTurnedOff) return;
unsigned long now = millis();
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
drawing = true;
char lineBuffer[LINE_BUFFER_SIZE];
static byte lastSecond;
byte secondCurrent = second(localTime);
byte minuteCurrent = minute(localTime);
byte hourCurrent = hour(localTime);
if (knownMinute != minuteCurrent) { //only redraw clock if it has changed
//updateLocalTime();
byte AmPmHour = hourCurrent;
boolean isitAM = true;
if (useAMPM) {
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
if (AmPmHour == 0) { AmPmHour = 12; }
}
if (knownHour != hourCurrent) {
// only update date when hour changes
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
}
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
draw2x2String(2, lineHeight*2, lineBuffer); //draw hour, min. blink ":" depending on odd/even seconds
if (useAMPM) drawString(12, lineHeight*2, (isitAM ? "AM" : "PM"), true); //draw am/pm if using 12 time
drawStatusIcons(); //icons power, wifi, timer, etc
knownMinute = minuteCurrent;
knownHour = hourCurrent;
}
if (showSeconds && secondCurrent != lastSecond) {
lastSecond = secondCurrent;
draw2x2String(6, lineHeight*2, secondCurrent%2 ? " " : ":");
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line
}
drawing = false;
}
public: public:
// gets called once at boot. Do all initialization that doesn't depend on // gets called once at boot. Do all initialization that doesn't depend on
@ -195,14 +312,21 @@ class FourLineDisplayUsermod : public Usermod {
bool isHW, isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64); bool isHW, isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64);
PinOwner po = PinOwner::UM_FourLineDisplay; PinOwner po = PinOwner::UM_FourLineDisplay;
if (isSPI) { if (isSPI) {
PinManagerPinType cspins[2] = { { ioPin[3], true }, { ioPin[4], true } };
if (!pinManager.allocateMultiplePins(cspins, 2, PinOwner::UM_FourLineDisplay)) { type=NONE; return; }
isHW = (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi && ioPin[2]==spi_cs); isHW = (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi && ioPin[2]==spi_cs);
if (isHW) po = PinOwner::HW_SPI; // allow multiple allocations of HW I2C bus pins if (isHW) po = PinOwner::HW_SPI; // allow multiple allocations of HW I2C bus pins
PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true }}; PinManagerPinType pins[3] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true } };
if (!pinManager.allocateMultiplePins(pins, 5, po)) { type=NONE; return; } if (!pinManager.allocateMultiplePins(pins, 5, po)) {
pinManager.deallocatePin(ioPin[3], PinOwner::UM_FourLineDisplay);
pinManager.deallocatePin(ioPin[4], PinOwner::UM_FourLineDisplay);
type = NONE;
return;
}
} else { } else {
isHW = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda); isHW = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda);
if (isHW) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins if (isHW) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } }; PinManagerPinType pins[2] = { {ioPin[0], true }, { ioPin[1], true } };
if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; } if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; }
} }
@ -320,58 +444,6 @@ class FourLineDisplayUsermod : public Usermod {
#endif #endif
} }
/**
* Wrappers for screen drawing
*/
void setFlipMode(uint8_t mode) {
if (type == NONE || !enabled) return;
u8x8->setFlipMode(mode);
}
void setContrast(uint8_t contrast) {
if (type == NONE || !enabled) return;
u8x8->setContrast(contrast);
}
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) {
if (type == NONE || !enabled) return;
u8x8->setFont(u8x8_font_chroma48medium8_r);
if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string);
else u8x8->drawString(col, row, string);
}
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
if (type == NONE || !enabled) return;
u8x8->setFont(u8x8_font_chroma48medium8_r);
u8x8->draw2x2String(col, row, string);
}
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) {
if (type == NONE || !enabled) return;
u8x8->setFont(font);
if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph);
else u8x8->drawGlyph(col, row, glyph);
}
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
if (type == NONE || !enabled) return;
u8x8->setFont(font);
u8x8->draw2x2Glyph(col, row, glyph);
}
uint8_t getCols() {
if (type==NONE || !enabled) return 0;
return u8x8->getCols();
}
void clear() {
if (type == NONE || !enabled) return;
u8x8->clear();
}
void setPowerSave(uint8_t save) {
if (type == NONE || !enabled) return;
u8x8->setPowerSave(save);
}
void center(String &line, uint8_t width) {
int len = line.length();
if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line;
for (byte i=line.length(); i<width; i++) line += ' ';
}
//function to update lastredraw //function to update lastredraw
void updateRedrawTime() { void updateRedrawTime() {
lastRedraw = millis(); lastRedraw = millis();
@ -525,22 +597,6 @@ class FourLineDisplayUsermod : public Usermod {
} }
} }
void draw2x2GlyphIcons() {
if (lineHeight == 2) {
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x2, true); //brightness icon
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x2, true); //speed icon
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x2, true); //intensity icon
drawGlyph(14, 2*lineHeight, 4, u8x8_4LineDisplay_WLED_icons_2x2, true); //palette icon
drawGlyph(14, 3*lineHeight, 5, u8x8_4LineDisplay_WLED_icons_2x2, true); //effect icon
} else {
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x1); //brightness icon
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x1); //speed icon
drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x1); //intensity icon
drawGlyph(15, 2, 4, u8x8_4LineDisplay_WLED_icons_1x1); //palette icon
drawGlyph(15, 3, 5, u8x8_4LineDisplay_WLED_icons_1x1); //effect icon
}
}
void drawStatusIcons() { void drawStatusIcons() {
uint8_t col = 15; uint8_t col = 15;
uint8_t row = 0; uint8_t row = 0;
@ -566,8 +622,8 @@ class FourLineDisplayUsermod : public Usermod {
if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1); if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1);
} }
//Display the current effect or palette (desiredEntry) //Display the current effect or palette (desiredEntry)
// on the appropriate line (row). // on the appropriate line (row).
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) { void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
char lineBuffer[MAX_JSON_CHARS]; char lineBuffer[MAX_JSON_CHARS];
if (overlayUntil == 0) { if (overlayUntil == 0) {
@ -815,55 +871,6 @@ class FourLineDisplayUsermod : public Usermod {
} }
} }
/**
* Display the current date and time in large characters
* on the middle rows. Based 24 or 12 hour depending on
* the useAMPM configuration.
*/
void showTime() {
if (type == NONE || !enabled || !displayTurnedOff) return;
unsigned long now = millis();
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
drawing = true;
char lineBuffer[LINE_BUFFER_SIZE];
static byte lastSecond;
byte secondCurrent = second(localTime);
byte minuteCurrent = minute(localTime);
byte hourCurrent = hour(localTime);
if (knownMinute != minuteCurrent) { //only redraw clock if it has changed
//updateLocalTime();
byte AmPmHour = hourCurrent;
boolean isitAM = true;
if (useAMPM) {
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
if (AmPmHour == 0) { AmPmHour = 12; }
}
if (knownHour != hourCurrent) {
// only update date when hour changes
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
draw2x2String(2, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays, draw month and day
}
sprintf_P(lineBuffer,PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent);
draw2x2String(2, lineHeight*2, lineBuffer); //draw hour, min. blink ":" depending on odd/even seconds
if (useAMPM) drawString(12, lineHeight*2, (isitAM ? "AM" : "PM"), true); //draw am/pm if using 12 time
drawStatusIcons(); //icons power, wifi, timer, etc
knownMinute = minuteCurrent;
knownHour = hourCurrent;
}
if (showSeconds && secondCurrent != lastSecond) {
lastSecond = secondCurrent;
draw2x2String(6, lineHeight*2, secondCurrent%2 ? " " : ":");
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line
}
drawing = false;
}
/** /**
* handleButton() can be used to override default button behaviour. Returning true * handleButton() can be used to override default button behaviour. Returning true
* will prevent button working in a default way. * will prevent button working in a default way.

View File

@ -271,12 +271,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(i2c_sda, hw_if_i2c[0]); CJSON(i2c_sda, hw_if_i2c[0]);
CJSON(i2c_scl, hw_if_i2c[1]); CJSON(i2c_scl, hw_if_i2c[1]);
PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } }; PinManagerPinType i2c[2] = { { i2c_sda, true }, { i2c_scl, true } };
if (pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) { if (i2c_scl >= 0 && i2c_sda >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
#ifdef ESP32 #ifdef ESP32
Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called prior) Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called prior)
#endif #endif
Wire.begin(); Wire.begin();
pinManager.deallocateMultiplePins(i2c, 2, PinOwner::HW_I2C);
} else { } else {
i2c_sda = -1; i2c_sda = -1;
i2c_scl = -1; i2c_scl = -1;
@ -286,13 +285,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(spi_sclk, hw_if_spi[1]); CJSON(spi_sclk, hw_if_spi[1]);
CJSON(spi_cs, hw_if_spi[2]); CJSON(spi_cs, hw_if_spi[2]);
PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_sclk, true }, { spi_cs, true } }; PinManagerPinType spi[3] = { { spi_mosi, true }, { spi_sclk, true }, { spi_cs, true } };
if (pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) { if (spi_mosi >= 0 && spi_sclk >= 0 && spi_cs >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
#ifdef ESP8266 #ifdef ESP8266
SPI.begin(); SPI.begin();
#else #else
SPI.begin(spi_sclk, (int8_t)-1, spi_mosi, spi_cs); SPI.begin(spi_sclk, (int8_t)-1, spi_mosi, spi_cs);
#endif #endif
pinManager.deallocateMultiplePins(spi, 3, PinOwner::HW_SPI);
} else { } else {
spi_mosi = -1; spi_mosi = -1;
spi_sclk = -1; spi_sclk = -1;

View File

@ -58,6 +58,20 @@
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; } if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff"; if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
} }
} else {
switch (o.name) {
case "SDA": break;
case "SCL": break;
case "MOSI": break;
case "SCLK": break;
case "CS": break;
default: return;
}
for (var i=0; i<pins.length; i++) {
if (k==pinO[i]) continue;
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
}
} }
} }
function getPins(o) { function getPins(o) {
@ -80,7 +94,6 @@
} }
} }
} }
function updPins() {}
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
if (isO(o)) { if (isO(o)) {
urows += '<hr style="width:260px">'; urows += '<hr style="width:260px">';
@ -158,7 +171,9 @@
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript // https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
function addInfo(name,el,txt) { function addInfo(name,el,txt) {
let obj = d.getElementsByName(name); let obj = d.getElementsByName(name);
if (obj[el]) obj[el].insertAdjacentHTML('afterend', '&nbsp;'+txt); if (!obj.length) return;
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
else if (obj[el]) obj[el].insertAdjacentHTML('afterend', '&nbsp;'+txt);
} }
// load settings and insert values into DOM // load settings and insert values into DOM
function ldS() { function ldS() {
@ -209,14 +224,14 @@
<h2>Usermod Setup</h2> <h2>Usermod Setup</h2>
Global I<sup>2</sup>C GPIOs (HW)<br> Global I<sup>2</sup>C GPIOs (HW)<br>
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br> <i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
SDA:<input type="number" min="-1" max="33" name="SDA" onchange="updPins()" class="s" placeholder="SDA"> SDA:<input type="number" min="-1" max="33" name="SDA" onchange="check(this,'if')" class="s" placeholder="SDA">
SCL:<input type="number" min="-1" max="33" name="SCL" onchange="updPins()" class="s" placeholder="SCL"> SCL:<input type="number" min="-1" max="33" name="SCL" onchange="check(this,'if')" class="s" placeholder="SCL">
<hr style="width:260px"> <hr style="width:260px">
Global SPI GPIOs (HW)<br> Global SPI GPIOs (HW)<br>
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br> <i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
MOSI:<input type="number" min="-1" max="33" name="MOSI" onchange="updPins()" class="s" placeholder="MOSI"> MOSI:<input type="number" min="-1" max="33" name="MOSI" onchange="check(this,'if')" class="s" placeholder="MOSI">
SCLK:<input type="number" min="-1" max="33" name="SCLK" onchange="updPins()" class="s" placeholder="SCLK"> SCLK:<input type="number" min="-1" max="33" name="SCLK" onchange="check(this,'if')" class="s" placeholder="SCLK">
CS:<input type="number" min="-1" max="33" name="CS" onchange="updPins()" class="s" placeholder="CS"> CS:<input type="number" min="-1" max="33" name="CS" onchange="check(this,'if')" class="s" placeholder="CS">
<div id="um">Loading settings...</div> <div id="um">Loading settings...</div>
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button> <hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form> </form>

View File

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

View File

@ -478,49 +478,53 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (!requestJSONBufferLock(5)) return; if (!requestJSONBufferLock(5)) return;
// global I2C & SPI pins // global I2C & SPI pins
uint8_t oldpins[3]; int8_t hw_sda_pin = !request->arg(F("SDA")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SDA")).toInt()));
int8_t hw_sda_pin = max(-1,min(33,(int)request->arg(F("SDA")).toInt())); int8_t hw_scl_pin = !request->arg(F("SCL")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCL")).toInt()));
int8_t hw_scl_pin = max(-1,min(33,(int)request->arg(F("SCL")).toInt()));
oldpins[0] = i2c_sda;
oldpins[1] = i2c_scl;
pinManager.deallocateMultiplePins(oldpins, 2, PinOwner::HW_I2C);
#ifdef ESP8266 #ifdef ESP8266
// cannot change pins on ESP8266 // cannot change pins on ESP8266
if (hw_sda_pin != HW_PIN_SDA) hw_sda_pin = HW_PIN_SDA; if (hw_sda_pin >= 0 && hw_sda_pin != HW_PIN_SDA) hw_sda_pin = HW_PIN_SDA;
if (hw_scl_pin != HW_PIN_SCL) hw_scl_pin = HW_PIN_SCL; if (hw_scl_pin >= 0 && hw_scl_pin != HW_PIN_SCL) hw_scl_pin = HW_PIN_SCL;
#endif #endif
PinManagerPinType i2c[2] = { { hw_sda_pin, true }, { hw_scl_pin, true } }; PinManagerPinType i2c[2] = { { hw_sda_pin, true }, { hw_scl_pin, true } };
if (pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) { if (hw_sda_pin >= 0 && hw_scl_pin >= 0 && pinManager.allocateMultiplePins(i2c, 2, PinOwner::HW_I2C)) {
i2c_sda = hw_sda_pin; i2c_sda = hw_sda_pin;
i2c_scl = hw_scl_pin; i2c_scl = hw_scl_pin;
#ifdef ESP32 #ifdef ESP32
Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called) Wire.setPins(i2c_sda, i2c_scl); // this will fail if Wire is initilised (Wire.begin() called)
pinManager.deallocateMultiplePins(i2c, 2, PinOwner::HW_I2C);
#endif #endif
Wire.begin();
} else { } else {
// there is no Wire.end()
DEBUG_PRINTLN(F("Could not allocate I2C pins."));
uint8_t i2c[2] = { i2c_scl, i2c_sda };
pinManager.deallocateMultiplePins(i2c, 2, PinOwner::HW_I2C); // just in case deallocation of old pins
i2c_sda = -1; i2c_sda = -1;
i2c_scl = -1; i2c_scl = -1;
} }
int8_t hw_mosi_pin = max(-1,min(33,(int)request->arg(F("MOSI")).toInt())); int8_t hw_mosi_pin = !request->arg(F("MOSI")).length() ? -1 : max(-1,min(33,(int)request->arg(F("MOSI")).toInt()));
int8_t hw_sclk_pin = max(-1,min(33,(int)request->arg(F("SCLK")).toInt())); int8_t hw_sclk_pin = !request->arg(F("SCLK")).length() ? -1 : max(-1,min(33,(int)request->arg(F("SCLK")).toInt()));
int8_t hw_cs_pin = max(-1,min(33,(int)request->arg(F("CS")).toInt())); int8_t hw_cs_pin = !request->arg(F("CS")).length() ? -1 : max(-1,min(33,(int)request->arg(F("CS")).toInt()));
oldpins[0] = spi_mosi;
oldpins[1] = spi_sclk;
oldpins[2] = spi_cs;
pinManager.deallocateMultiplePins(oldpins, 3, PinOwner::HW_SPI);
#ifdef ESP8266 #ifdef ESP8266
// cannot change pins on ESP8266 // cannot change pins on ESP8266
if (hw_mosi_pin != HW_PIN_DATASPI) hw_mosi_pin = HW_PIN_DATASPI; if (hw_mosi_pin >= 0 && hw_mosi_pin != HW_PIN_DATASPI) hw_mosi_pin = HW_PIN_DATASPI;
if (hw_sclk_pin != HW_PIN_CLOCKSPI) hw_sclk_pin = HW_PIN_CLOCKSPI; if (hw_sclk_pin >= 0 && hw_sclk_pin != HW_PIN_CLOCKSPI) hw_sclk_pin = HW_PIN_CLOCKSPI;
if (hw_cs_pin != HW_PIN_CSSPI) hw_cs_pin = HW_PIN_CSSPI; if (hw_cs_pin >= 0 && hw_cs_pin != HW_PIN_CSSPI) hw_cs_pin = HW_PIN_CSSPI;
#endif #endif
PinManagerPinType spi[3] = { { hw_mosi_pin, true }, { hw_sclk_pin, true }, { hw_cs_pin, true } }; PinManagerPinType spi[3] = { { hw_mosi_pin, true }, { hw_sclk_pin, true }, { hw_cs_pin, true } };
if (pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) { if (hw_mosi_pin >= 0 && hw_sclk_pin >= 0 && hw_cs_pin >= 0 && pinManager.allocateMultiplePins(spi, 3, PinOwner::HW_SPI)) {
spi_mosi = hw_mosi_pin; spi_mosi = hw_mosi_pin;
spi_sclk = hw_sclk_pin; spi_sclk = hw_sclk_pin;
spi_cs = hw_cs_pin; spi_cs = hw_cs_pin;
pinManager.deallocateMultiplePins(spi, 3, PinOwner::HW_SPI); #ifdef ESP8266
SPI.begin();
#else
SPI.begin(spi_sclk, (int8_t)-1, spi_mosi, spi_cs);
#endif
} else { } else {
//SPI.end();
DEBUG_PRINTLN(F("Could not allocate SPI pins."));
uint8_t spi[3] = { spi_mosi, spi_sclk, spi_cs };
pinManager.deallocateMultiplePins(spi, 3, PinOwner::HW_SPI); // just in case deallocation of old pins
spi_mosi = -1; spi_mosi = -1;
spi_sclk = -1; spi_sclk = -1;
spi_cs = -1; spi_cs = -1;
@ -536,7 +540,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
// POST request parameters are combined as <usermodname>_<usermodparameter> // POST request parameters are combined as <usermodname>_<usermodparameter>
int umNameEnd = name.indexOf(":"); int umNameEnd = name.indexOf(":");
if (umNameEnd<1) break; // parameter does not contain ":" or on 1st place -> wrong if (umNameEnd<1) continue; // parameter does not contain ":" or on 1st place -> wrong
JsonObject mod = um[name.substring(0,umNameEnd)]; // get a usermod JSON object JsonObject mod = um[name.substring(0,umNameEnd)]; // get a usermod JSON object
if (mod.isNull()) { if (mod.isNull()) {

View File

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

View File

@ -639,6 +639,11 @@ void getSettingsJS(byte subPage, char* dest)
sappend('v',SET_F("MOSI"),spi_mosi); sappend('v',SET_F("MOSI"),spi_mosi);
sappend('v',SET_F("SCLK"),spi_sclk); sappend('v',SET_F("SCLK"),spi_sclk);
sappend('v',SET_F("CS"),spi_cs); sappend('v',SET_F("CS"),spi_cs);
oappend(SET_F("addInfo('SDA','")); oappendi(HW_PIN_SDA); oappend(SET_F("');"));
oappend(SET_F("addInfo('SCL','")); oappendi(HW_PIN_SCL); oappend(SET_F("');"));
oappend(SET_F("addInfo('MOSI','")); oappendi(HW_PIN_DATASPI); oappend(SET_F("');"));
oappend(SET_F("addInfo('SCLK','")); oappendi(HW_PIN_CLOCKSPI); oappend(SET_F("');"));
oappend(SET_F("addInfo('CS','")); oappendi(HW_PIN_CSSPI); oappend(SET_F("');"));
usermods.appendConfigData(); usermods.appendConfigData();
} }