diff --git a/TouchController.cpp b/TouchController.cpp new file mode 100644 index 0000000..ebd5537 --- /dev/null +++ b/TouchController.cpp @@ -0,0 +1,106 @@ +#include "TouchController.h" + +TouchController::TouchController(XPT2046_Touchscreen *touchScreen) { + this->touchScreen = touchScreen; +} + +bool TouchController::loadCalibration() { + // always use this to "mount" the filesystem + bool result = SPIFFS.begin(); + Serial.println("SPIFFS opened: " + result); + + // this opens the file "f.txt" in read-mode + File f = SPIFFS.open("/calibration.txt", "r"); + + if (!f) { + return false; + } else { + + //Lets read line by line from the file + String dxStr = f.readStringUntil('\n'); + String dyStr = f.readStringUntil('\n'); + String axStr = f.readStringUntil('\n'); + String ayStr = f.readStringUntil('\n'); + + dx = dxStr.toFloat(); + dy = dyStr.toFloat(); + ax = axStr.toInt(); + ay = ayStr.toInt(); + + } + f.close(); + +} + +bool TouchController::saveCalibration() { + bool result = SPIFFS.begin(); + + // open the file in write mode + File f = SPIFFS.open("/calibration.txt", "w"); + if (!f) { + Serial.println("file creation failed"); + } + // now write two lines in key/value style with end-of-line characters + f.println(dx); + f.println(dy); + f.println(ax); + f.println(ay); + + f.close(); +} + +void TouchController::startCalibration(CalibrationCallback *calibrationCallback) { + state = 0; + this->calibrationCallback = calibrationCallback; +} + +void TouchController::continueCalibration() { + TS_Point p = touchScreen->getPoint(); + + if (state == 0) { + (*calibrationCallback)(10, 10); + if (touchScreen->touched()) { + p1 = p; + state++; + lastStateChange = millis(); + } + + } else if (state == 1) { + (*calibrationCallback)(230, 310); + if (touchScreen->touched() && (millis() - lastStateChange > 1000)) { + + p2 = p; + state++; + lastStateChange = millis(); + dx = 240.0 / abs(p1.y - p2.y); + dy = 320.0 / abs(p1.x - p2.x); + ax = p1.y < p2.y ? p1.y : p2.y; + ay = p1.x < p2.x ? p1.x : p2.x; + } + + } +} +bool TouchController::isCalibrationFinished() { + return state == 2; +} + +bool TouchController::isTouched() { + touchScreen->touched(); +} + +bool TouchController::isTouched(int16_t debounceMillis) { + if (touchScreen->touched() && millis() - lastTouched > debounceMillis) { + lastTouched = millis(); + return true; + } + return false; +} +TS_Point TouchController::getPoint() { + TS_Point p = touchScreen->getPoint(); + int x = (p.y - ax) * dx; + int y = 320 - (p.x - ay) * dy; + p.x = x; + p.y = y; + return p; +} + diff --git a/TouchController.h b/TouchController.h new file mode 100644 index 0000000..c3763ae --- /dev/null +++ b/TouchController.h @@ -0,0 +1,36 @@ +#include +#include + +#ifndef _TOUCH_CONTROLLERH_ +#define _TOUCH_CONTROLLERH_ + +typedef void (*CalibrationCallback)(int16_t x, int16_t y); + +class TouchController { + public: + TouchController(XPT2046_Touchscreen *touchScreen); + bool loadCalibration(); + bool saveCalibration(); + void startCalibration(CalibrationCallback *callback); + void continueCalibration(); + bool isCalibrationFinished(); + bool isTouched(); + bool isTouched(int16_t debounceMillis); + TS_Point getPoint(); + + private: + XPT2046_Touchscreen *touchScreen; + float dx = 0.0; + float dy = 0.0; + int ax = 0; + int ay = 0; + int state = 0; + long lastStateChange = 0; + long lastTouched = 0; + CalibrationCallback *calibrationCallback; + TS_Point p1, p2; + +}; + +#endif + diff --git a/esp8266-weather-station-color.ino b/esp8266-weather-station-color.ino index 9f63c05..63194bb 100644 --- a/esp8266-weather-station-color.ino +++ b/esp8266-weather-station-color.ino @@ -21,6 +21,8 @@ See more at https://blog.squix.org #include #include #include +#include +#include "TouchController.h" /*** * Install the following libraries through Arduino Library Manager @@ -34,6 +36,7 @@ See more at https://blog.squix.org #include #include #include +#include #include #include #include @@ -54,6 +57,7 @@ See more at https://blog.squix.org #define MINI_BLUE 3 #define MAX_FORECASTS 12 +#define MAX_ALERTS 1 // defines the colors usable in the paletted 16 color frame buffer uint16_t palette[] = {ILI9341_BLACK, // 0 @@ -66,6 +70,8 @@ int SCREEN_HEIGHT = 320; // Limited to 4 colors due to memory constraints int BITS_PER_PIXEL = 2; // 2^2 = 4 colors +ADC_MODE(ADC_VCC); + // HOSTNAME for OTA update #define HOSTNAME "ESP8266-OTA-" @@ -74,9 +80,13 @@ ILI9341_SPI tft = ILI9341_SPI(TFT_CS, TFT_DC); MiniGrafx gfx = MiniGrafx(&tft, BITS_PER_PIXEL, palette); Carousel carousel(&gfx, 0, 0, 240, 100); +XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ); +TouchController touchController(&ts); + WGConditions conditions; WGForecast forecasts[MAX_FORECASTS]; WGAstronomy astronomy; +WGAlert alerts[MAX_ALERTS]; // Setup simpleDSTadjust Library rules simpleDSTadjust dstAdjusted(StartRule, EndRule); @@ -88,18 +98,27 @@ void drawCurrentWeather(); void drawForecast(); void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex); void drawAstronomy(); +void drawAlert(); +void drawCurrentWeatherDetail(); +void drawLabelValue(uint8_t line, String label, String value); +void drawForecastTable(uint8_t start); +void drawAbout(); void drawSeparator(uint16_t y); const char* getMeteoconIconFromProgmem(String iconText); const char* getMiniMeteoconIconFromProgmem(String iconText); void drawForecast1(MiniGrafx *display, CarouselState* state, int16_t x, int16_t y); void drawForecast2(MiniGrafx *display, CarouselState* state, int16_t x, int16_t y); FrameCallback frames[] = { drawForecast1, drawForecast2 }; +void calibrationCallback(int16_t x, int16_t y); +CalibrationCallback calibration = &calibrationCallback; int frameCount = 2; + +// how many different screens do we have? +int screenCount = 5; long lastDownloadUpdate = millis(); -void updateCalendar(); - String moonAgeImage = ""; +uint16_t screen = 0; void setup() { Serial.begin(115200); @@ -111,6 +130,29 @@ void setup() { digitalWrite(TFT_LED, HIGH); gfx.init(); + gfx.fillBuffer(MINI_BLACK); + gfx.commit(); + + ts.begin(); + + SPIFFS.begin(); + //SPIFFS.remove("/calibration.txt"); + boolean isCalibrationAvailable = touchController.loadCalibration(); + if (!isCalibrationAvailable) { + Serial.println("Calibration not available"); + touchController.startCalibration(&calibration); + while (!touchController.isCalibrationFinished()) { + gfx.fillBuffer(0); + gfx.setColor(MINI_YELLOW); + gfx.setTextAlignment(TEXT_ALIGN_CENTER); + gfx.drawString(120, 160, "Please calibrate\ntouch screen by\ntouch point"); + touchController.continueCalibration(); + gfx.commit(); + yield(); + } + touchController.saveCalibration(); + } + gfx.fillBuffer(MINI_BLACK); gfx.setFont(ArialRoundedMTBold_14); gfx.setColor(MINI_YELLOW); @@ -135,21 +177,41 @@ void setup() { long lastDrew = 0; void loop() { - gfx.fillBuffer(MINI_BLACK); - drawTime(); - drawCurrentWeather(); - int remainingTimeBudget = carousel.update(); - - if (remainingTimeBudget > 0) { - // You can do some work here - // Don't do stuff if you are below your - // time budget. - delay(remainingTimeBudget); + if (touchController.isTouched(500)) { + TS_Point p = touchController.getPoint(); + if (p.y < 80) { + IS_STYLE_12HR = !IS_STYLE_12HR; + } else { + screen = (screen + 1) % screenCount; + } + } + + gfx.fillBuffer(MINI_BLACK); + if (screen == 0) { + drawTime(); + int remainingTimeBudget = carousel.update(); + if (remainingTimeBudget > 0) { + // You can do some work here + // Don't do stuff if you are below your + // time budget. + delay(remainingTimeBudget); + } + drawCurrentWeather(); + drawAstronomy(); + } else if (screen == 1) { + drawCurrentWeatherDetail(); + } else if (screen == 2) { + drawForecastTable(0); + } else if (screen == 3) { + drawForecastTable(6); + } else if (screen == 4) { + drawAbout(); } - drawAstronomy(); gfx.commit(); + + // Check if we should update weather information if (millis() - lastDownloadUpdate > 1000 * UPDATE_INTERVAL_SECS) { updateData(); @@ -177,22 +239,33 @@ void updateData() { forecastClient->updateForecast(forecasts, MAX_FORECASTS, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); delete forecastClient; forecastClient = nullptr; + drawProgress(80, "Updating astronomy..."); - - WundergroundAstronomy *astronomyClient = new WundergroundAstronomy(STYLE_12HR); + WundergroundAstronomy *astronomyClient = new WundergroundAstronomy(IS_STYLE_12HR); astronomyClient->updateAstronomy(&astronomy, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); delete astronomyClient; astronomyClient = nullptr; moonAgeImage = String((char) (65 + 26 * (((15 + astronomy.moonAge.toInt()) % 30) / 30.0))); + drawProgress(90, "Updating alerts..."); + WundergroundAlerts *alertClient = new WundergroundAlerts(); + alertClient->updateAlerts(alerts, MAX_ALERTS, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); + delete alertClient; + alertClient = nullptr; + + delay(1000); } + // Progress bar helper void drawProgress(uint8_t percentage, String text) { gfx.fillBuffer(MINI_BLACK); + gfx.drawPalettedBitmapFromPgm(23, 30, SquixLogo); gfx.setFont(ArialRoundedMTBold_14); gfx.setTextAlignment(TEXT_ALIGN_CENTER); + gfx.setColor(MINI_WHITE); + gfx.drawString(120, 80, "https://blog.squix.org"); gfx.setColor(MINI_YELLOW); gfx.drawString(120, 146, text); @@ -207,15 +280,6 @@ void drawProgress(uint8_t percentage, String text) { // draws the clock void drawTime() { - /*gfx.setTextAlignment(TEXT_ALIGN_CENTER); - gfx.setColor(MINI_WHITE); - gfx.setFont(ArialRoundedMTBold_14); - String date = conditions.date; - gfx.drawString(120, 6, date); - - gfx.setFont(ArialRoundedMTBold_36); - String time = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); - gfx.drawString(120, 20, time);*/ char *dstAbbrev; char time_str[11]; time_t now = dstAdjusted.time(&dstAbbrev); @@ -223,13 +287,14 @@ void drawTime() { gfx.setTextAlignment(TEXT_ALIGN_CENTER); gfx.setFont(ArialRoundedMTBold_14); + gfx.setColor(MINI_WHITE); String date = ctime(&now); date = date.substring(0,11) + String(1900 + timeinfo->tm_year); gfx.drawString(120, 6, date); gfx.setFont(ArialRoundedMTBold_36); - if (STYLE_12HR) { + if (IS_STYLE_12HR) { int hour = (timeinfo->tm_hour+11)%12+1; // take care of noon and midnight sprintf(time_str, "%2d:%02d:%02d\n",hour, timeinfo->tm_min, timeinfo->tm_sec); gfx.drawString(120, 20, time_str); @@ -241,7 +306,7 @@ void drawTime() { gfx.setTextAlignment(TEXT_ALIGN_LEFT); gfx.setFont(ArialMT_Plain_10); gfx.setColor(MINI_BLUE); - if (STYLE_12HR) { + if (IS_STYLE_12HR) { sprintf(time_str, "%s\n%s", dstAbbrev, timeinfo->tm_hour>=12?"PM":"AM"); gfx.drawString(195, 27, time_str); } else { @@ -255,10 +320,11 @@ void drawCurrentWeather() { gfx.setTransparentColor(MINI_BLACK); gfx.drawPalettedBitmapFromPgm(0, 55, getMeteoconIconFromProgmem(conditions.weatherIcon)); // Weather Text + gfx.setFont(ArialRoundedMTBold_14); - gfx.setColor(MINI_YELLOW); + gfx.setColor(MINI_BLUE); gfx.setTextAlignment(TEXT_ALIGN_RIGHT); - gfx.drawString(220, 76, conditions.weatherText); + gfx.drawString(220, 65, DISPLAYED_CITY_NAME); gfx.setFont(ArialRoundedMTBold_36); gfx.setColor(MINI_WHITE); @@ -268,7 +334,12 @@ void drawCurrentWeather() { degreeSign = "°C"; } String temp = conditions.currentTemp + degreeSign; - gfx.drawString(220, 89, temp); + gfx.drawString(220, 78, temp); + + gfx.setFont(ArialRoundedMTBold_14); + gfx.setColor(MINI_YELLOW); + gfx.setTextAlignment(TEXT_ALIGN_RIGHT); + gfx.drawString(220, 118, conditions.weatherText); } @@ -331,6 +402,121 @@ void drawAstronomy() { } +void drawAlert() { + +} + +void drawCurrentWeatherDetail() { + gfx.setFont(ArialRoundedMTBold_14); + gfx.setTextAlignment(TEXT_ALIGN_CENTER); + gfx.setColor(MINI_WHITE); + gfx.drawString(120, 2, "Current Conditions"); + + //gfx.setTransparentColor(MINI_BLACK); + //gfx.drawPalettedBitmapFromPgm(0, 20, getMeteoconIconFromProgmem(conditions.weatherIcon)); + + String degreeSign = "°F"; + if (IS_METRIC) { + degreeSign = "°C"; + } + // String weatherIcon; + // String weatherText; + drawLabelValue(0, "Temperature:", conditions.currentTemp + degreeSign); + drawLabelValue(1, "Feels Like:", conditions.feelslike + degreeSign); + drawLabelValue(2, "Dew Point:", conditions.dewPoint + degreeSign); + drawLabelValue(3, "Wind Speed:", conditions.windSpeed); + drawLabelValue(4, "Wind Dir:", conditions.windDir); + drawLabelValue(5, "Humidity:", conditions.humidity); + drawLabelValue(6, "Pressure:", conditions.pressure); + drawLabelValue(7, "Precipitation:", conditions.precipitationToday); + drawLabelValue(8, "UV:", conditions.UV); + gfx.setTextAlignment(TEXT_ALIGN_LEFT); + gfx.setColor(MINI_YELLOW); + gfx.drawString(15, 185, "Description: "); + gfx.setColor(MINI_WHITE); + gfx.drawStringMaxWidth(15, 200, 240 - 2 * 15, forecasts[0].forecastText); +} + +void drawLabelValue(uint8_t line, String label, String value) { + const uint8_t labelX = 15; + const uint8_t valueX = 150; + gfx.setTextAlignment(TEXT_ALIGN_LEFT); + gfx.setColor(MINI_YELLOW); + gfx.drawString(labelX, 30 + line * 15, label); + gfx.setColor(MINI_WHITE); + gfx.drawString(valueX, 30 + line * 15, value); +} +void drawForecastTable(uint8_t start) { + gfx.setFont(ArialRoundedMTBold_14); + gfx.setTextAlignment(TEXT_ALIGN_CENTER); + gfx.setColor(MINI_WHITE); + gfx.drawString(120, 2, "Forecasts"); + uint16_t y = 0; + + String degreeSign = "°F"; + if (IS_METRIC) { + degreeSign = "°C"; + } + for (uint8_t i = start; i < start + 6; i++) { + gfx.setTextAlignment(TEXT_ALIGN_LEFT); + y = 30 + (i - start) * 45; + if (y > 320) { + break; + } + gfx.drawPalettedBitmapFromPgm(0, y, getMiniMeteoconIconFromProgmem(forecasts[i].forecastIcon)); + + gfx.setColor(MINI_YELLOW); + gfx.setFont(ArialRoundedMTBold_14); + + gfx.drawString(50, y, forecasts[i].forecastTitle); + gfx.setColor(MINI_WHITE); + gfx.drawString(50, y + 15, getShortText(forecasts[i].forecastIcon)); + gfx.setColor(MINI_WHITE); + gfx.setTextAlignment(TEXT_ALIGN_RIGHT); + + String temp = ""; + if (i % 2 == 0) { + temp = forecasts[i].forecastHighTemp; + } else { + temp = forecasts[i - 1].forecastLowTemp; + } + gfx.drawString(235, y, temp + degreeSign); + /*gfx.setColor(MINI_WHITE); + gfx.drawString(x + 25, y, forecasts[dayIndex].forecastLowTemp + "|" + forecasts[dayIndex].forecastHighTemp); + + gfx.drawPalettedBitmapFromPgm(x, y + 15, getMiniMeteoconIconFromProgmem(forecasts[dayIndex].forecastIcon));*/ + gfx.setColor(MINI_BLUE); + gfx.drawString(235, y + 15, forecasts[i].PoP + "%"); + + } +} + +void drawAbout() { + gfx.fillBuffer(MINI_BLACK); + gfx.drawPalettedBitmapFromPgm(23, 30, SquixLogo); + + gfx.setFont(ArialRoundedMTBold_14); + gfx.setTextAlignment(TEXT_ALIGN_CENTER); + gfx.setColor(MINI_WHITE); + gfx.drawString(120, 80, "https://blog.squix.org"); + + gfx.setFont(ArialRoundedMTBold_14); + gfx.setTextAlignment(TEXT_ALIGN_CENTER); + gfx.setColor(MINI_WHITE); + gfx.drawString(120, 115, "About"); + drawLabelValue(8, "Heap Mem:", String(ESP.getFreeHeap() / 1024)+"kb"); + drawLabelValue(9, "Flash Mem:", String(ESP.getFlashChipRealSize() / 1024 / 1024) + "MB"); + drawLabelValue(10, "WiFi Strength:", String(WiFi.RSSI()) + "dB"); + drawLabelValue(11, "Chip ID:", String(ESP.getChipId())); + drawLabelValue(12, "VCC: ", String(ESP.getVcc() / 1024.0) +"V"); + drawLabelValue(13, "CPU Freq.: ", String(ESP.getCpuFreqMHz()) + "MHz"); +} + +void calibrationCallback(int16_t x, int16_t y) { + gfx.setColor(1); + gfx.fillCircle(x, y, 10); +} + // Helper function, should be part of the weather station library and should disappear soon const char* getMeteoconIconFromProgmem(String iconText) { @@ -339,7 +525,7 @@ const char* getMeteoconIconFromProgmem(String iconText) { if (iconText == "chancesleet") return chancesleet; if (iconText == "chancesnow") return chancesnow; if (iconText == "chancetstorms") return chancestorms; - if (iconText == "cloudy") return clear; + if (iconText == "clear") return clear; if (iconText == "cloudy") return cloudy; if (iconText == "flurries") return flurries; if (iconText == "fog") return fog; @@ -381,5 +567,31 @@ const char* getMiniMeteoconIconFromProgmem(String iconText) { return miniunknown; } +// Helper function, should be part of the weather station library and should disappear soon +const String getShortText(String iconText) { + + if (iconText == "chanceflurries") return "Chance of Flurries"; + if (iconText == "chancerain") return "Chance of Rain"; + if (iconText == "chancesleet") return "Chance of Sleet"; + if (iconText == "chancesnow") return "Chance of Snow"; + if (iconText == "chancetstorms") return "Chance of Storms"; + if (iconText == "clear") return "Clear"; + if (iconText == "cloudy") return "Cloudy"; + if (iconText == "flurries") return "Flurries"; + if (iconText == "fog") return "Fog"; + if (iconText == "hazy") return "Hazy"; + if (iconText == "mostlycloudy") return "Mostly Cloudy"; + if (iconText == "mostlysunny") return "Mostly Sunny"; + if (iconText == "partlycloudy") return "Partly Couldy"; + if (iconText == "partlysunny") return "Partly Sunny"; + if (iconText == "sleet") return "Sleet"; + if (iconText == "rain") return "Rain"; + if (iconText == "snow") return "Snow"; + if (iconText == "sunny") return "Sunny"; + if (iconText == "tstorms") return "Storms"; + + + return "-"; +} diff --git a/settings.h b/settings.h index 6106837..c1f0a32 100644 --- a/settings.h +++ b/settings.h @@ -28,7 +28,9 @@ const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes #define TFT_CS D1 #define TFT_LED D8 - +// touch screen pins +#define TOUCH_CS D3 +#define TOUCH_IRQ D4 // Wunderground Settings @@ -37,7 +39,8 @@ const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes // e.g. http://api.wunderground.com/api/808ba87ed77c4511/conditions/q/CH/Zurich.json // e.g. http://api.wunderground.com/api/808ba87ed77c4511/conditions/q/CA/SAN_FRANCISCO.json <- note that in the US you use the state instead of country code -const String WUNDERGRROUND_API_KEY = "WUNDERGROUND_API_KEY"; +const String DISPLAYED_CITY_NAME = "Zürich"; +const String WUNDERGRROUND_API_KEY = "808ba87ed77c4501"; const String WUNDERGRROUND_LANGUAGE = "EN"; const String WUNDERGROUND_COUNTRY = "CH"; const String WUNDERGROUND_CITY = "Zurich"; @@ -52,10 +55,10 @@ struct dstRule EndRule = {"CET", Last, Sun, Oct, 2, 0}; // Central Europea // struct dstRule EndRule = {"EST", First, Sun, Nov, 1, 0}; // Eastern Standard time = UTC/GMT -5 hour // values in metric or imperial system? -const boolean IS_METRIC = true; +bool IS_METRIC = true; // Change for 12 Hour/ 24 hour style clock -#define STYLE_12HR false +bool IS_STYLE_12HR = false; // change for different ntp (time servers) #define NTP_SERVERS "0.ch.pool.ntp.org", "1.ch.pool.ntp.org", "2.ch.pool.ntp.org" diff --git a/weathericons.h b/weathericons.h index e118c4f..cd2f4b3 100644 --- a/weathericons.h +++ b/weathericons.h @@ -1,3 +1,150 @@ +const char SquixLogo[] PROGMEM = { + 0x01, // Version: 1 + 0x02, // BitDepth: 2 + 0x00, 0xC1, // Width: 193 + 0x00, 0x38, // Height: 56 + // Round width to next byte: 200 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x54, 0x00, 0x00, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, + 0x15, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x15, 0x55, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x05, 0x55, 0x55, 0x40, 0x00, 0x00, 0x01, 0x55, 0x55, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x54, 0x00, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x01, 0x55, + 0x55, 0x50, 0x00, 0x00, 0x05, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x55, 0x55, 0x50, 0x00, 0x00, 0x15, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x00, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x15, 0x55, 0x54, + 0x00, 0x00, 0x15, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, + 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x05, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, + 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x05, 0x55, 0x55, 0x40, 0x01, + 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x15, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, + 0x05, 0x55, 0x50, 0x00, 0x01, 0x55, 0x55, 0x50, 0x05, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x50, 0x15, 0x55, + 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x55, 0x55, 0x54, 0x15, 0x55, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, + 0x50, 0x00, 0x00, 0x15, 0x55, 0x54, 0x15, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, + 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x15, 0x55, 0x55, 0x55, 0x00, 0x01, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x00, 0x00, 0x55, 0x55, 0x00, 0x15, 0x55, 0x55, 0x55, 0x40, + 0x01, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, + 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, + 0x00, 0x55, 0x55, 0x00, 0x15, 0x05, 0x55, 0x55, 0x50, 0x01, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x00, 0x55, 0x55, 0x00, 0x14, 0x01, 0x55, 0x55, 0x54, 0x01, 0x55, + 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, 0x05, 0x55, + 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x00, 0x55, + 0x55, 0x00, 0x14, 0x01, 0x55, 0x55, 0x55, 0x01, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, + 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x55, 0x55, 0x00, 0x15, 0x05, 0x55, 0x55, 0x55, 0x41, 0x55, 0x50, 0x15, + 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x55, 0x55, 0x00, + 0x15, 0x55, 0x55, 0x55, 0x55, 0x50, 0x55, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, + 0x55, 0x50, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x55, 0x55, 0x00, 0x15, 0x54, 0x15, 0x55, 0x55, 0x54, 0x15, 0x50, 0x15, 0x55, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x55, 0x55, 0x00, 0x15, 0x51, + 0x40, 0x00, 0x00, 0x00, 0x05, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, + 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x15, 0x55, 0x40, 0x55, 0x55, 0x00, 0x15, 0x51, 0x45, 0x55, 0x55, 0x55, 0x41, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x55, 0x55, 0x00, 0x15, 0x54, 0x14, 0x15, + 0x55, 0x55, 0x50, 0x50, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, + 0x05, 0x55, 0x55, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, + 0x55, 0x40, 0x55, 0x55, 0x00, 0x15, 0x55, 0x51, 0x40, 0x00, 0x00, 0x00, 0x10, 0x15, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x40, 0x55, 0x55, 0x40, 0x15, 0x55, 0x51, 0x45, 0x55, 0x55, + 0x55, 0x00, 0x05, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x00, 0x55, 0x55, + 0x54, 0x15, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x40, + 0x15, 0x55, 0x50, 0x15, 0x55, 0x54, 0x15, 0x55, 0x55, 0x55, 0x40, 0x05, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x01, 0x55, 0x55, 0x50, 0x05, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x15, 0x55, 0x54, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, + 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x05, 0x55, 0x50, 0x00, 0x05, 0x55, 0x55, 0x40, 0x01, + 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x15, 0x55, + 0x54, 0x15, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, + 0x05, 0x55, 0x50, 0x00, 0x05, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x05, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x15, 0x55, 0x55, 0x55, 0x01, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x05, 0x55, 0x50, 0x00, 0x15, 0x55, 0x54, 0x00, 0x00, 0x15, 0x55, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x00, 0x01, 0x55, 0x55, 0x41, + 0x55, 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x05, 0x55, + 0x50, 0x00, 0x55, 0x55, 0x54, 0x00, 0x00, 0x15, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x54, 0x00, 0x00, 0x55, 0x55, 0x50, 0x55, 0x54, 0x11, 0x41, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x05, 0x55, 0x50, 0x01, 0x55, 0x55, 0x50, 0x00, 0x00, 0x05, 0x55, 0x55, 0x40, + 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x00, 0x00, 0x15, 0x55, 0x54, 0x15, 0x51, + 0x45, 0x14, 0x55, 0x55, 0x55, 0x50, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x05, 0x55, 0x50, 0x05, + 0x55, 0x55, 0x40, 0x00, 0x00, 0x01, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x05, 0x51, 0x45, 0x14, 0x55, 0x05, 0x55, 0x40, 0x05, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x50, 0x00, 0x05, 0x55, 0x50, 0x15, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x54, 0x00, 0x00, + 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x01, 0x54, 0x15, 0x41, + 0x54, 0x50, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x01, 0x55, 0x50, 0x15, 0x55, 0x54, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x54, 0x51, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x55, 0x05, + 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x55, 0x55, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; const char chanceflurries[] PROGMEM = { 0x01, // Version: 1 0x02, // BitDepth: 2