From 90c66be5150f973e54e58fdcd82df86ad56a2ff6 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 03:07:52 +0300 Subject: [PATCH 01/26] WIP refactoring --- .gitignore | 1 + src/Main.cpp | 2 +- src/WatchFace.cpp | 107 +++++-------------- src/WatchFace.h | 11 +- src/WatchFacePages/Clock.cpp | 81 ++++++++++++++ src/WatchFacePages/Clock.h | 25 +++++ src/WatchFacePages/Page.h | 15 +++ src/WatchFeatures/Battery.cpp | 29 +++++ src/WatchFeatures/Battery.h | 16 +++ src/{WatchyRTC.cpp => WatchFeatures/RTC.cpp} | 28 ++--- src/{WatchyRTC.h => WatchFeatures/RTC.h} | 12 +-- src/WatchFeatures/StepCounter.cpp | 16 +++ src/WatchFeatures/StepCounter.h | 20 ++++ src/WatchFeatures/Storage.cpp | 58 ++++++++++ src/WatchFeatures/Storage.h | 16 +++ src/WatchFeatures/WatchFeatures.h | 24 +++++ src/Watchy.cpp | 76 +++++++------ src/Watchy.h | 17 ++- src/config.h | 21 +++- 19 files changed, 413 insertions(+), 162 deletions(-) create mode 100644 src/WatchFacePages/Clock.cpp create mode 100644 src/WatchFacePages/Clock.h create mode 100644 src/WatchFacePages/Page.h create mode 100644 src/WatchFeatures/Battery.cpp create mode 100644 src/WatchFeatures/Battery.h rename src/{WatchyRTC.cpp => WatchFeatures/RTC.cpp} (87%) rename src/{WatchyRTC.h => WatchFeatures/RTC.h} (77%) create mode 100644 src/WatchFeatures/StepCounter.cpp create mode 100644 src/WatchFeatures/StepCounter.h create mode 100644 src/WatchFeatures/Storage.cpp create mode 100644 src/WatchFeatures/Storage.h create mode 100644 src/WatchFeatures/WatchFeatures.h diff --git a/.gitignore b/.gitignore index 8da6879..9be5a91 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .pio .vscode/** +src/secrets.h diff --git a/src/Main.cpp b/src/Main.cpp index 4f911c7..7e1c1a9 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -5,7 +5,7 @@ WatchFace watchy; void setup() { Serial.begin(9600); - watchy.Init(); + watchy.Wake(); } void loop() diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index ed31646..2f04b4e 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -1,28 +1,34 @@ #include "WatchFace.h" -#include "SevenSegment.h" -#include "Icons.h" +#include "WatchFacePages/Clock.h" + #include -#include -#include -#include -RTC_DATA_ATTR bool WatchFace::m_menuSetup = false; RTC_DATA_ATTR bool WatchFace::m_inMenu = false; -RTC_DATA_ATTR int WatchFace::m_tzOffset = TZ_OFFSET; -Menu WatchFace::m_menu; +RTC_DATA_ATTR Menu WatchFace::m_menu; +RTC_DATA_ATTR uint8_t WatchFace::m_watchFacePage; -void WatchFace::Setup() // Called after hardware is set up +void WatchFace::InitBoot() { - if (!m_menuSetup) { - m_menu.Init(m_display); - } + m_menu.Init(m_display); + SetupVolatileMenuStuff(); + m_menu.Reset(); + ConnectWiFi(); + SyncNTPTime(); + DisconnectWiFi(); + + for (auto & page : m_pages) { + page->InitBoot(); + } +} + +void WatchFace::InitWake() +{ SetupVolatileMenuStuff(); - if (!m_menuSetup) { - m_menu.Reset(); - m_menuSetup = true; - } + for (auto & page : m_pages) { + page->InitWake(); + } } void WatchFace::HandleButtonPress(uint64_t buttonMask) @@ -86,68 +92,7 @@ void WatchFace::DrawWatchFace(bool partialRefresh) return; } - m_display.setFullWindow(); - - m_display.fillScreen(GxEPD_WHITE); - DrawBatteryIcon(); - - tmElements_t currentTime; - m_RTC.Get(currentTime, m_tzOffset); - SevenSegment sevenSegment(30, 60, 6, 5, 5); - - if (currentTime.Hour < 10) { - sevenSegment.DrawDigit(m_display, 0, 15, 75, GxEPD_BLACK); - } else { - sevenSegment.DrawDigit(m_display, currentTime.Hour / 10, 20, 75, GxEPD_BLACK); - } - - sevenSegment.DrawDigit(m_display, currentTime.Hour % 10, 60, 75, GxEPD_BLACK); - - if (currentTime.Minute < 10) { - sevenSegment.DrawDigit(m_display, 0, 110, 75, GxEPD_BLACK); - } else { - sevenSegment.DrawDigit(m_display, currentTime.Minute / 10, 110, 75, GxEPD_BLACK); - } - - sevenSegment.DrawDigit(m_display, currentTime.Minute % 10, 150, 75, GxEPD_BLACK); - - m_display.fillRect(97, 90, 5, 5, GxEPD_BLACK); - m_display.fillRect(97, 110, 5, 5, GxEPD_BLACK); - - m_display.display(partialRefresh); -} - -void WatchFace::DrawBatteryIcon() -{ - m_display.fillRect(200 - 48, 5, 43, 23, GxEPD_BLACK); - m_display.fillRect(200 - 46, 7, 39, 19, GxEPD_WHITE); - float VBAT = GetBatteryVoltage(); - float level = (VBAT - 3.6f) / 0.6f; - if (level > 1.0f) { - level = 1.0f; - } else if (level < 0.0f) { - level = 0.0f; - } - level = 0.5f - sin(asin(1.0f - 2.0f * level) / 3.0f); - - m_display.fillRect(200 - 44, 9, (int)std::round(35.0f * level), 15, GxEPD_BLACK); - - int x = 200 - 85; - int intLevel = (int)std::round(100.0f * level); - if (intLevel == 100) { - x -= 13; - } - - m_display.setFont(&FreeMonoBold9pt7b); - m_display.setCursor(x, 22); - m_display.setTextColor(GxEPD_BLACK); - m_display.print(intLevel); - m_display.print("%"); - - m_display.setFont(&FreeMonoBold12pt7b); - m_display.drawBitmap(10, 177, Icons::steps, 19, 23, GxEPD_BLACK); - m_display.setCursor(40, 195); - m_display.print(GetSteps()); + m_pages[0]->DrawPage(partialRefresh); } void WatchFace::SetupVolatileMenuStuff() @@ -269,7 +214,7 @@ void WatchFace::MenuNTPSyncSelected() ConnectWiFi(); SyncNTPTime(); DisconnectWiFi(); - m_RTC.Resync(); + m_features.rtc.Resync(); if (m_inMenu) { m_inMenu = false; @@ -280,7 +225,7 @@ void WatchFace::MenuNTPSyncSelected() void WatchFace::MenuTimeZoneSelected(int tzOffset) { - m_tzOffset = tzOffset; + m_features.storage.SetTzOffset(tzOffset); if (m_inMenu) { m_inMenu = false; @@ -291,7 +236,7 @@ void WatchFace::MenuTimeZoneSelected(int tzOffset) void WatchFace::MenuConfirmResetSteps() { - ResetSteps(); + m_features.stepCounter.ResetSteps(); if (m_inMenu) { m_inMenu = false; diff --git a/src/WatchFace.h b/src/WatchFace.h index dc4b5c5..96c331c 100644 --- a/src/WatchFace.h +++ b/src/WatchFace.h @@ -2,21 +2,26 @@ #include "Watchy.h" #include "Menu.h" +#include "WatchFacePages/Clock.h" +#include class WatchFace : public Watchy { public: - void Setup() override; // Called after hardware is set up + void InitBoot() override; // Called once when the watch starts up + void InitWake() override; // Called every time the watch wakes from sleep void HandleButtonPress(uint64_t buttonMask) override; void HandleDoubleTap() override; void HandleTilt() override; void DrawWatchFace(bool partialRefresh = false) override; private: - RTC_DATA_ATTR static bool m_menuSetup; RTC_DATA_ATTR static bool m_inMenu; RTC_DATA_ATTR static Menu m_menu; - RTC_DATA_ATTR static int m_tzOffset; + RTC_DATA_ATTR static uint8_t m_watchFacePage; + std::vector> m_pages = { + std::make_shared(m_display, m_features) + }; void SetupVolatileMenuStuff(); void DrawBatteryIcon(); diff --git a/src/WatchFacePages/Clock.cpp b/src/WatchFacePages/Clock.cpp new file mode 100644 index 0000000..4cbe910 --- /dev/null +++ b/src/WatchFacePages/Clock.cpp @@ -0,0 +1,81 @@ +#include "Clock.h" +#include "../SevenSegment.h" +#include "../Icons.h" +#include +#include +#include + +WatchFacePages::Clock::Clock(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) + : m_display(display), m_features(features) +{ +} + +void WatchFacePages::Clock::InitBoot() +{ +} + +void WatchFacePages::Clock::InitWake() +{ + +} + +void WatchFacePages::Clock::DrawPage(bool partialRefresh) +{ + m_display.setFullWindow(); + + m_display.fillScreen(GxEPD_WHITE); + DrawBatteryIcon(); + + tmElements_t currentTime; + m_features.rtc.Get(currentTime); + int tzOffset = m_features.storage.GetTzOffset(); + m_features.rtc.OffsetTime(currentTime, tzOffset); + SevenSegment sevenSegment(30, 60, 6, 5, 5); + + if (currentTime.Hour < 10) { + sevenSegment.DrawDigit(m_display, 0, 15, 75, GxEPD_BLACK); + } else { + sevenSegment.DrawDigit(m_display, currentTime.Hour / 10, 20, 75, GxEPD_BLACK); + } + + sevenSegment.DrawDigit(m_display, currentTime.Hour % 10, 60, 75, GxEPD_BLACK); + + if (currentTime.Minute < 10) { + sevenSegment.DrawDigit(m_display, 0, 110, 75, GxEPD_BLACK); + } else { + sevenSegment.DrawDigit(m_display, currentTime.Minute / 10, 110, 75, GxEPD_BLACK); + } + + sevenSegment.DrawDigit(m_display, currentTime.Minute % 10, 150, 75, GxEPD_BLACK); + + m_display.fillRect(97, 90, 5, 5, GxEPD_BLACK); + m_display.fillRect(97, 110, 5, 5, GxEPD_BLACK); + + m_display.display(partialRefresh); +} + +void WatchFacePages::Clock::DrawBatteryIcon() +{ + m_display.fillRect(200 - 48, 5, 43, 23, GxEPD_BLACK); + m_display.fillRect(200 - 46, 7, 39, 19, GxEPD_WHITE); + int intLevel = m_features.battery.GetPercentage(); + uint8_t level = intLevel / 100.0f; + + m_display.fillRect(200 - 44, 9, (int)std::round(35.0f * level), 15, GxEPD_BLACK); + + int x = 200 - 85; + if (intLevel == 100) { + x -= 13; + } + + m_display.setFont(&FreeMonoBold9pt7b); + m_display.setCursor(x, 22); + m_display.setTextColor(GxEPD_BLACK); + m_display.print(intLevel); + m_display.print("%"); + + m_display.setFont(&FreeMonoBold12pt7b); + m_display.drawBitmap(10, 177, Icons::steps, 19, 23, GxEPD_BLACK); + m_display.setCursor(40, 195); + m_display.print(m_features.stepCounter.GetSteps()); +} \ No newline at end of file diff --git a/src/WatchFacePages/Clock.h b/src/WatchFacePages/Clock.h new file mode 100644 index 0000000..dcf8c5c --- /dev/null +++ b/src/WatchFacePages/Clock.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Page.h" +#include "../WatchyDisplay.h" +#include "../WatchFeatures/WatchFeatures.h" + +namespace WatchFacePages +{ + class Clock; +} + +class WatchFacePages::Clock : public WatchFacePages::Page +{ +public: + Clock(WatchyDisplay & display, WatchFeatures::WatchFeatures & features); + void InitBoot() override; + void InitWake() override; + void DrawPage(bool partialRefresh = false) override; + +private: + void DrawBatteryIcon(); + + WatchyDisplay & m_display; + WatchFeatures::WatchFeatures & m_features; +}; \ No newline at end of file diff --git a/src/WatchFacePages/Page.h b/src/WatchFacePages/Page.h new file mode 100644 index 0000000..19fba66 --- /dev/null +++ b/src/WatchFacePages/Page.h @@ -0,0 +1,15 @@ +#pragma once + +namespace WatchFacePages +{ + class Page; +} + +class WatchFacePages::Page +{ +public: + Page() {}; + virtual void InitBoot() {}; + virtual void InitWake() {}; + virtual void DrawPage(bool partialRefresh = false) = 0; +}; \ No newline at end of file diff --git a/src/WatchFeatures/Battery.cpp b/src/WatchFeatures/Battery.cpp new file mode 100644 index 0000000..2bc0813 --- /dev/null +++ b/src/WatchFeatures/Battery.cpp @@ -0,0 +1,29 @@ +#include "../config.h" +#include "Battery.h" +#include +#include + +WatchFeatures::Battery::Battery() +{ +} + +float WatchFeatures::Battery::GetVoltage() +{ + return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; +} + +uint8_t WatchFeatures::Battery::GetPercentage() +{ + float voltage = GetVoltage(); + + float level = (GetVoltage() - 3.6f) / 0.6f; + if (level < 0.0f) { + level = 0.0f; + } else if (level > 1.0f) { + level = 1.0f; + } + + level = 0.5f - sin(asin(1.0f - 2.0f * level) / 3.0f); + + return std::round(level * 100.0f); +} diff --git a/src/WatchFeatures/Battery.h b/src/WatchFeatures/Battery.h new file mode 100644 index 0000000..5a6ad1f --- /dev/null +++ b/src/WatchFeatures/Battery.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace WatchFeatures +{ + class Battery; +} + +class WatchFeatures::Battery +{ +public: + Battery(); + float GetVoltage(); + uint8_t GetPercentage(); +}; \ No newline at end of file diff --git a/src/WatchyRTC.cpp b/src/WatchFeatures/RTC.cpp similarity index 87% rename from src/WatchyRTC.cpp rename to src/WatchFeatures/RTC.cpp index 8fee1b3..1834755 100644 --- a/src/WatchyRTC.cpp +++ b/src/WatchFeatures/RTC.cpp @@ -1,21 +1,14 @@ -#include "WatchyRTC.h" +#include "RTC.h" +#include #if (UPDATE_INTERVAL > 255) #error "UPDATE_INTERVAL must be either a multiple of 60, or less than 256 seconds" #endif -RTC_DATA_ATTR bool WatchyRTC::m_timerSet = false; -RTC_DATA_ATTR bool WatchyRTC::m_initialTimer = true; +RTC_DATA_ATTR bool WatchFeatures::RTC::m_timerSet = false; +RTC_DATA_ATTR bool WatchFeatures::RTC::m_initialTimer = true; -WatchyRTC::WatchyRTC() -{ -} - -void WatchyRTC::Init() -{ -} - -void WatchyRTC::Get(tmElements_t & tm, int offsetInSeconds) +void WatchFeatures::RTC::Get(tmElements_t & tm) { rtc_pcf.getDateTime(); tm.Year = y2kYearToTm(rtc_pcf.getYear()); @@ -25,10 +18,9 @@ void WatchyRTC::Get(tmElements_t & tm, int offsetInSeconds) tm.Hour = rtc_pcf.getHour(); tm.Minute = rtc_pcf.getMinute(); tm.Second = rtc_pcf.getSecond(); - OffsetTime(tm, offsetInSeconds); } -void WatchyRTC::Set(tmElements_t tm) +void WatchFeatures::RTC::Set(tmElements_t tm) { time_t t = makeTime(tm); // make and break to calculate tm.Wday breakTime(t, tm); @@ -36,14 +28,14 @@ void WatchyRTC::Set(tmElements_t tm) rtc_pcf.setDateTime(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year), tm.Hour, tm.Minute, tm.Second); } -void WatchyRTC::SetTimer() +void WatchFeatures::RTC::SetTimer() { if (!m_timerSet) { Resync(); } } -void WatchyRTC::OffsetTime(tmElements_t & tm, int offsetInSeconds) +void WatchFeatures::RTC::OffsetTime(tmElements_t & tm, int offsetInSeconds) { int year = tm.Year; int month = tm.Month; @@ -108,7 +100,7 @@ void WatchyRTC::OffsetTime(tmElements_t & tm, int offsetInSeconds) } // TODO: implement more advanced wakeup logic, i.e. > 255 seconds that are not a multiple of 60 -bool WatchyRTC::CheckWakeup() +bool WatchFeatures::RTC::CheckWakeup() { if(m_initialTimer) { m_initialTimer = false; @@ -132,7 +124,7 @@ bool WatchyRTC::CheckWakeup() return true; } -void WatchyRTC::Resync() +void WatchFeatures::RTC::Resync() { rtc_pcf.getDateTime(); // Sleep just long enough to get to a multiple of the update interval, makes updates happen on exact turn of the minute diff --git a/src/WatchyRTC.h b/src/WatchFeatures/RTC.h similarity index 77% rename from src/WatchyRTC.h rename to src/WatchFeatures/RTC.h index c745929..9abf79c 100644 --- a/src/WatchyRTC.h +++ b/src/WatchFeatures/RTC.h @@ -6,17 +6,17 @@ #include #include -#define RTC_PCF_ADDR 0x51 -#define YEAR_OFFSET_PCF 2000 +namespace WatchFeatures +{ + class RTC; +} -class WatchyRTC { +class WatchFeatures::RTC { public: Rtc_Pcf8563 rtc_pcf; public: - WatchyRTC(); - void Init(); - void Get(tmElements_t & tm, int offsetInSeconds = 0); + void Get(tmElements_t & tm); void Set(tmElements_t tm); void SetTimer(); bool CheckWakeup(); // Checks to really wake up or not, also resets the timer after the initial sleep diff --git a/src/WatchFeatures/StepCounter.cpp b/src/WatchFeatures/StepCounter.cpp new file mode 100644 index 0000000..e1e867f --- /dev/null +++ b/src/WatchFeatures/StepCounter.cpp @@ -0,0 +1,16 @@ +#include "StepCounter.h" + +WatchFeatures::StepCounter::StepCounter(BMA423 & sensor) : + m_sensor(sensor) +{ +} + +uint64_t WatchFeatures::StepCounter::GetSteps() +{ + return m_sensor.getCounter(); +} + +void WatchFeatures::StepCounter::ResetSteps() +{ + m_sensor.resetStepCounter(); +} \ No newline at end of file diff --git a/src/WatchFeatures/StepCounter.h b/src/WatchFeatures/StepCounter.h new file mode 100644 index 0000000..baa6d0e --- /dev/null +++ b/src/WatchFeatures/StepCounter.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include "../bma.h" + +namespace WatchFeatures +{ + class StepCounter; +} + +class WatchFeatures::StepCounter +{ +public: + StepCounter(BMA423 & sensor); + uint64_t GetSteps(); + void ResetSteps(); + +private: + BMA423 & m_sensor; +}; \ No newline at end of file diff --git a/src/WatchFeatures/Storage.cpp b/src/WatchFeatures/Storage.cpp new file mode 100644 index 0000000..5de2fb7 --- /dev/null +++ b/src/WatchFeatures/Storage.cpp @@ -0,0 +1,58 @@ +#include "../config.h" +#include "Storage.h" +#include + +WatchFeatures::Storage::Storage() +{ + +} + +void WatchFeatures::Storage::InitBoot() +{ + EEPROM.begin(512); + if (EEPROM.read(EEPROM_LOCATION_MAGIC) != EEPROM_MAGIC1 + || EEPROM.read(EEPROM_LOCATION_MAGIC + 1) != EEPROM_MAGIC2) + { + Serial.println("Initializing EEPROM"); + EEPROM.write(EEPROM_LOCATION_MAGIC, EEPROM_MAGIC1); + EEPROM.write(EEPROM_LOCATION_MAGIC + 1, EEPROM_MAGIC2); + uint16_t version = EEPROM_VERSION; + EEPROM.write(EEPROM_LOCATION_VERSION, version & 0xFF); + EEPROM.write(EEPROM_LOCATION_VERSION + 1, version >> 8); + + int offset = DEFAULT_TZ_OFFSET; + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET, offset & 0xFF); + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET + 1, (offset >> 8) & 0xFF); + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET + 2, (offset >> 16) & 0xFF); + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET + 3, (offset >> 24) & 0xFF); + EEPROM.commit(); + } + + uint16_t version = EEPROM.read(EEPROM_LOCATION_VERSION) | (EEPROM.read(EEPROM_LOCATION_VERSION + 1) << 8); + if (version != EEPROM_VERSION) + { + // TODO: Handle version mismatch + } +} + +void WatchFeatures::Storage::InitWake() +{ + EEPROM.begin(512); +} + +int32_t WatchFeatures::Storage::GetTzOffset() +{ + return EEPROM.read(EEPROM_LOCATION_TZ_OFFSET) + | (EEPROM.read(EEPROM_LOCATION_TZ_OFFSET + 1) << 8) + | (EEPROM.read(EEPROM_LOCATION_TZ_OFFSET + 2) << 16) + | (EEPROM.read(EEPROM_LOCATION_TZ_OFFSET + 3) << 24); +} + +void WatchFeatures::Storage::SetTzOffset(int offset) +{ + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET, offset & 0xFF); + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET + 1, (offset >> 8) & 0xFF); + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET + 2, (offset >> 16) & 0xFF); + EEPROM.write(EEPROM_LOCATION_TZ_OFFSET + 3, (offset >> 24) & 0xFF); + EEPROM.commit(); +} \ No newline at end of file diff --git a/src/WatchFeatures/Storage.h b/src/WatchFeatures/Storage.h new file mode 100644 index 0000000..b0e26c2 --- /dev/null +++ b/src/WatchFeatures/Storage.h @@ -0,0 +1,16 @@ +#pragma once + +namespace WatchFeatures +{ + class Storage; +} + +class WatchFeatures::Storage +{ +public: + Storage(); + void InitBoot(); + void InitWake(); + int GetTzOffset(); + void SetTzOffset(int offset); +}; \ No newline at end of file diff --git a/src/WatchFeatures/WatchFeatures.h b/src/WatchFeatures/WatchFeatures.h new file mode 100644 index 0000000..e5049ed --- /dev/null +++ b/src/WatchFeatures/WatchFeatures.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Battery.h" +#include "StepCounter.h" +#include "RTC.h" +#include "Storage.h" + +namespace WatchFeatures +{ + struct WatchFeatures; +} + +struct WatchFeatures::WatchFeatures +{ + WatchFeatures(BMA423 & sensor) + : battery(), stepCounter(sensor), rtc() + { + } + + Battery battery; + StepCounter stepCounter; + RTC rtc; + Storage storage; +}; \ No newline at end of file diff --git a/src/Watchy.cpp b/src/Watchy.cpp index 183e6ff..7e49b8b 100644 --- a/src/Watchy.cpp +++ b/src/Watchy.cpp @@ -3,44 +3,41 @@ WatchyDisplayBase Watchy::m_displayBase; WatchyDisplay Watchy::m_display(Watchy::m_displayBase); -WatchyRTC Watchy::m_RTC; RTC_DATA_ATTR BMA423 Watchy::m_sensor; RTC_DATA_ATTR bool g_displayFullInit = true; Watchy::Watchy() + : m_features(m_sensor) { } -void Watchy::Init() +void Watchy::Wake() { esp_sleep_wakeup_cause_t wakeup_reason; wakeup_reason = esp_sleep_get_wakeup_cause(); if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT0) { - if(!m_RTC.CheckWakeup()) { + if(!m_features.rtc.CheckWakeup()) { DeepSleep(); } } - Wire.begin(SDA, SCL); - m_display.epd2.selectSPI(SPI, SPISettings(20000000, MSBFIRST, SPI_MODE0)); - m_display.init(0, g_displayFullInit, 10, true); - SetBusyCallback(); - - Setup(); - switch(wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0: { // RTC interrupt + InitWakeInternal(); ShowWatchFace(true); break; } case ESP_SLEEP_WAKEUP_EXT1: { + // Button press or accelerometer interrupt + InitWakeInternal(); uint64_t wakeupBit = esp_sleep_get_ext1_wakeup_status(); if (wakeupBit & ACC_INT_MASK) { + // Accelerometer interrupt m_sensor.getINT(); uint8_t irqMask = m_sensor.getIRQMASK(); @@ -54,24 +51,14 @@ void Watchy::Init() m_sensor.getINT(); } else if (wakeupBit & BTN_PIN_MASK) { - // Button press HandleButtonPress(wakeupBit); - break; } - - // Button press - HandleButtonPress(wakeupBit); break; } default: { - BmaConfig(); - m_RTC.Init(); - ConnectWiFi(); - SyncNTPTime(); - DisconnectWiFi(); - + InitBootInternal(); ShowWatchFace(false); break; } @@ -102,7 +89,7 @@ void Watchy::DeepSleep() BTN_PIN_MASK | ACC_INT_MASK, ESP_EXT1_WAKEUP_ANY_HIGH); - m_RTC.SetTimer(); + m_features.rtc.SetTimer(); esp_deep_sleep_start(); } @@ -125,21 +112,6 @@ void Watchy::VibeMotor(uint8_t intervalMs, uint8_t length) } } -float Watchy::GetBatteryVoltage() -{ - return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; -} - -uint64_t Watchy::GetSteps() -{ - return m_sensor.getCounter(); -} - -void Watchy::ResetSteps() -{ - m_sensor.resetStepCounter(); -} - void Watchy::ConnectWiFi() { if(WiFi.begin(WIFI_SSID, WIFI_PASS) == WL_CONNECT_FAILED) { @@ -158,14 +130,14 @@ void Watchy::ConnectWiFi() void Watchy::SyncNTPTime() { WiFiUDP ntpUDP; - // GMT offset should be 0, RTC class will adjust to local time + // GMT offset should be 0, since RTC is set to UTC NTPClient timeClient(ntpUDP, NTP_SERVER, 0); timeClient.begin(); bool success = timeClient.forceUpdate(); if (success) { tmElements_t tm; breakTime((time_t)timeClient.getEpochTime(), tm); - m_RTC.Set(tm); + m_features.rtc.Set(tm); } else { Serial.begin(9600); Serial.println("Failed to get NTP time"); @@ -187,6 +159,29 @@ void Watchy::ClearBusyCallback() m_display.epd2.setBusyCallback(nullptr); } +void Watchy::InitBootInternal() +{ + Wire.begin(SDA, SCL); + m_display.epd2.selectSPI(SPI, SPISettings(20000000, MSBFIRST, SPI_MODE0)); + m_display.init(0, g_displayFullInit, 10, true); + SetBusyCallback(); + + BmaConfig(); + m_features.storage.InitBoot(); + InitBoot(); +} + +void Watchy::InitWakeInternal() +{ + Wire.begin(SDA, SCL); + m_display.epd2.selectSPI(SPI, SPISettings(20000000, MSBFIRST, SPI_MODE0)); + m_display.init(0, g_displayFullInit, 10, true); + SetBusyCallback(); + + m_features.storage.InitWake(); + InitWake(); +} + void Watchy::SetBusyCallback() { m_display.epd2.setBusyCallback(DisplayBusyCallback); @@ -308,4 +303,5 @@ void Watchy::BmaConfig() m_sensor.enableTiltInterrupt(); m_sensor.enableWakeupInterrupt(); } -} \ No newline at end of file +} + diff --git a/src/Watchy.h b/src/Watchy.h index 4c075ec..59137d1 100644 --- a/src/Watchy.h +++ b/src/Watchy.h @@ -2,7 +2,7 @@ #include "config.h" #include "WatchyDisplay.h" -#include "WatchyRTC.h" +#include "WatchFeatures/WatchFeatures.h" #include #include #include @@ -12,12 +12,10 @@ class Watchy { public: Watchy(); - void Init(); + void Wake(); void DeepSleep(); void VibeMotor(uint8_t intervalMs = 100, uint8_t length = 20); float GetBatteryVoltage(); - uint64_t GetSteps(); - void ResetSteps(); void ConnectWiFi(); void SyncNTPTime(); void DisconnectWiFi(); @@ -26,9 +24,8 @@ public: void ClearBusyCallback(); void SetBusyCallback(); - // Called after hardware is setup - virtual void Setup() = 0; - + virtual void InitBoot() {}; // Called on first boot + virtual void InitWake() {}; // Called every time the watch wakes from sleep virtual void HandleButtonPress(uint64_t buttonMask) = 0; virtual void HandleDoubleTap() {} virtual void HandleTilt() {} @@ -36,13 +33,15 @@ public: protected: + void InitBootInternal(); + void InitWakeInternal(); + static void DisplayBusyCallback(const void *); static WatchyDisplayBase m_displayBase; static WatchyDisplay m_display; - static WatchyRTC m_RTC; - static RTC_DATA_ATTR BMA423 m_sensor; + WatchFeatures::WatchFeatures m_features; private: void BmaConfig(); diff --git a/src/config.h b/src/config.h index 98847c1..a2b5b30 100644 --- a/src/config.h +++ b/src/config.h @@ -13,6 +13,8 @@ #define ACC_INT_2_PIN 12 #define VIB_MOTOR_PIN 13 #define RTC_INT_PIN 27 +#define RTC_PCF_ADDR 0x51 +#define YEAR_OFFSET_PCF 2000 #define MENU_BTN_MASK GPIO_SEL_26 #define BACK_BTN_MASK GPIO_SEL_25 @@ -24,11 +26,22 @@ #define DISPLAY_WIDTH 200 #define DISPLAY_HEIGHT 200 -#define WIFI_SSID "" -#define WIFI_PASS "" -#define TZ_OFFSET 3600 * 3 +#define EEPROM_LOCATION_MAGIC 0 +#define EEPROM_LOCATION_VERSION 2 +#define EEPROM_LOCATION_TZ_OFFSET 4 + +#define EEPROM_MAGIC1 0xf0 +#define EEPROM_MAGIC2 0x0d +#define EEPROM_VERSION 1 + +#include "secrets.h" +#if !defined(WIFI_SSID) || !defined(WIFI_PASS) +#error "Please define WIFI_SSID and WIFI_PASS in secrets.h" +#endif + +#define DEFAULT_TZ_OFFSET 3600 * 3 #define NTP_SERVER "pool.ntp.org" #define UPDATE_INTERVAL 60 // seconds -#define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute \ No newline at end of file +#define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute From 24e04577f821393e4d5496c5306cfcab6c9ad3fc Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 03:09:32 +0300 Subject: [PATCH 02/26] Cleaning up indentation in WatchFace.cpp --- src/WatchFace.cpp | 210 +++++++++++++++++++++++----------------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index 2f04b4e..6fd855f 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -24,7 +24,7 @@ void WatchFace::InitBoot() void WatchFace::InitWake() { - SetupVolatileMenuStuff(); + SetupVolatileMenuStuff(); for (auto & page : m_pages) { page->InitWake(); @@ -97,105 +97,105 @@ void WatchFace::DrawWatchFace(bool partialRefresh) void WatchFace::SetupVolatileMenuStuff() { - static const std::vector menuPages = { - { - 0, // backPageNum - "WATCHY", // title - ALIGNMENT_CENTER, // titleAlignment - "", // body - { // Menu items - { - "Sync NTP", // title - nullptr, // callback - 1 // pageNum - }, - { - "Set Timezone", // title - nullptr, // callback - 2 // pageNum - }, + static const std::vector menuPages = { + { + 0, // backPageNum + "WATCHY", // title + ALIGNMENT_CENTER, // titleAlignment + "", // body + { // Menu items + { + "Sync NTP", // title + nullptr, // callback + 1 // pageNum + }, + { + "Set Timezone", // title + nullptr, // callback + 2 // pageNum + }, { "Reset Steps", // title nullptr, // callback 3 // pageNum }, - { - "Back", // title - nullptr, // callback - 0 // pageNum - } - }, - }, - { - 0, // backPageNum - "SYNC NTP", // title - ALIGNMENT_CENTER, // titleAlignment - "Sync with:\n" NTP_SERVER, // body - { // Menu items - { - "Sync", // title - std::bind(&WatchFace::MenuNTPSyncSelected, this), // callback - 1 // pageNum - }, - { - "Back", // title - nullptr, // callback - 0 // pageNum - } - }, - }, - { - 0, // backPageNum - "TIMEZONE", // title - ALIGNMENT_CENTER, // titleAlignment - "", // body - { // Menu items - { - "+0", // title - std::bind(&WatchFace::MenuTimeZoneSelected, this, 0), // callback - 0 // pageNum - }, - { - "+1", // title - std::bind(&WatchFace::MenuTimeZoneSelected, this, 3600), // callback - 0 // pageNum - }, - { - "+2", // title - std::bind(&WatchFace::MenuTimeZoneSelected, this, 7200), // callback - 0 // pageNum - }, - { - "+3", // title - std::bind(&WatchFace::MenuTimeZoneSelected, this, 10800), // callback - 0 // pageNum - }, - { - "Back", // title - nullptr, // callback - 0 // pageNum - } - }, - }, - { - 0, // backPageNum - "RESET STEPS", // title - ALIGNMENT_CENTER, // titleAlignment - "Confirm?", // body - { // Menu items - { - "No", // title - nullptr, // callback - 0 // pageNum - }, - { - "Yes", // title - std::bind(&WatchFace::MenuConfirmResetSteps, this), // callback - 0 // pageNum - } - } - } - }; + { + "Back", // title + nullptr, // callback + 0 // pageNum + } + }, + }, + { + 0, // backPageNum + "SYNC NTP", // title + ALIGNMENT_CENTER, // titleAlignment + "Sync with:\n" NTP_SERVER, // body + { // Menu items + { + "Sync", // title + std::bind(&WatchFace::MenuNTPSyncSelected, this), // callback + 1 // pageNum + }, + { + "Back", // title + nullptr, // callback + 0 // pageNum + } + }, + }, + { + 0, // backPageNum + "TIMEZONE", // title + ALIGNMENT_CENTER, // titleAlignment + "", // body + { // Menu items + { + "+0", // title + std::bind(&WatchFace::MenuTimeZoneSelected, this, 0), // callback + 0 // pageNum + }, + { + "+1", // title + std::bind(&WatchFace::MenuTimeZoneSelected, this, 3600), // callback + 0 // pageNum + }, + { + "+2", // title + std::bind(&WatchFace::MenuTimeZoneSelected, this, 7200), // callback + 0 // pageNum + }, + { + "+3", // title + std::bind(&WatchFace::MenuTimeZoneSelected, this, 10800), // callback + 0 // pageNum + }, + { + "Back", // title + nullptr, // callback + 0 // pageNum + } + }, + }, + { + 0, // backPageNum + "RESET STEPS", // title + ALIGNMENT_CENTER, // titleAlignment + "Confirm?", // body + { // Menu items + { + "No", // title + nullptr, // callback + 0 // pageNum + }, + { + "Yes", // title + std::bind(&WatchFace::MenuConfirmResetSteps, this), // callback + 0 // pageNum + } + } + } + }; m_menu.SetPages(menuPages); m_menu.SetExitCallback(std::bind(&WatchFace::MenuExited, this)); @@ -216,22 +216,22 @@ void WatchFace::MenuNTPSyncSelected() DisconnectWiFi(); m_features.rtc.Resync(); - if (m_inMenu) { - m_inMenu = false; - m_menu.Reset(); - DrawWatchFace(false); - } + if (m_inMenu) { + m_inMenu = false; + m_menu.Reset(); + DrawWatchFace(false); + } } void WatchFace::MenuTimeZoneSelected(int tzOffset) { m_features.storage.SetTzOffset(tzOffset); - if (m_inMenu) { - m_inMenu = false; - m_menu.Reset(); - DrawWatchFace(false); - } + if (m_inMenu) { + m_inMenu = false; + m_menu.Reset(); + DrawWatchFace(false); + } } void WatchFace::MenuConfirmResetSteps() From 9e6f562287092f660c569fc339e7d42454c6889c Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 03:12:31 +0300 Subject: [PATCH 03/26] Add stub secrets to allow compile on CI --- .forgejo/workflows/compile.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.forgejo/workflows/compile.yml b/.forgejo/workflows/compile.yml index 31b3338..5cc42f5 100644 --- a/.forgejo/workflows/compile.yml +++ b/.forgejo/workflows/compile.yml @@ -11,4 +11,5 @@ jobs: - name: Compile run: | cd ${{ github.workspace }} + echo -en '#define WIFI_SSID ""\n#define WIFI_PASS ""\n' >src/secrets.h /root/.platformio/penv/bin/pio run From f87d62692536b289e22d66ba768adc5ef4a052c7 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 03:17:42 +0300 Subject: [PATCH 04/26] Fix for drawing battery icon --- src/WatchFacePages/Clock.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/WatchFacePages/Clock.cpp b/src/WatchFacePages/Clock.cpp index 4cbe910..602fec5 100644 --- a/src/WatchFacePages/Clock.cpp +++ b/src/WatchFacePages/Clock.cpp @@ -1,4 +1,4 @@ -#include "Clock.h" +#include "Clock.h" #include "../SevenSegment.h" #include "../Icons.h" #include @@ -16,7 +16,6 @@ void WatchFacePages::Clock::InitBoot() void WatchFacePages::Clock::InitWake() { - } void WatchFacePages::Clock::DrawPage(bool partialRefresh) @@ -59,7 +58,7 @@ void WatchFacePages::Clock::DrawBatteryIcon() m_display.fillRect(200 - 48, 5, 43, 23, GxEPD_BLACK); m_display.fillRect(200 - 46, 7, 39, 19, GxEPD_WHITE); int intLevel = m_features.battery.GetPercentage(); - uint8_t level = intLevel / 100.0f; + float level = intLevel / 100.0f; m_display.fillRect(200 - 44, 9, (int)std::round(35.0f * level), 15, GxEPD_BLACK); From 52478ec6021543595ce7645e237aa95ecd87d854 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 03:39:27 +0300 Subject: [PATCH 05/26] More formatting fixes --- src/WatchFacePages/Clock.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/WatchFacePages/Clock.cpp b/src/WatchFacePages/Clock.cpp index 602fec5..0788335 100644 --- a/src/WatchFacePages/Clock.cpp +++ b/src/WatchFacePages/Clock.cpp @@ -25,10 +25,13 @@ void WatchFacePages::Clock::DrawPage(bool partialRefresh) m_display.fillScreen(GxEPD_WHITE); DrawBatteryIcon(); - tmElements_t currentTime; - m_features.rtc.Get(currentTime); + // Get current time and offset by timezone + tmElements_t currentTime; + m_features.rtc.Get(currentTime); int tzOffset = m_features.storage.GetTzOffset(); m_features.rtc.OffsetTime(currentTime, tzOffset); + + SevenSegment sevenSegment(30, 60, 6, 5, 5); if (currentTime.Hour < 10) { From 3e7ddb805c0d25325310f7807ea3d554d905cf0e Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 04:24:49 +0300 Subject: [PATCH 06/26] Add blank page for weather for now --- src/WatchFace.cpp | 26 +++++++++++++++++++++++++- src/WatchFace.h | 4 +++- src/WatchFacePages/Weather.cpp | 26 ++++++++++++++++++++++++++ src/WatchFacePages/Weather.h | 26 ++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/WatchFacePages/Weather.cpp create mode 100644 src/WatchFacePages/Weather.h diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index 6fd855f..e17494c 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -70,6 +70,30 @@ void WatchFace::HandleButtonPress(uint64_t buttonMask) } } + delay(10); + } + } else if (buttonMask & UP_BTN_MASK) { + m_watchFacePage = (m_watchFacePage + 1) % m_pages.size(); + ShowWatchFace(true); + + while (true) { + // Wait for button release + if (digitalRead(UP_BTN_PIN) == LOW){ + break; + } + + delay(10); + } + } else if (buttonMask & DOWN_BTN_MASK) { + m_watchFacePage = (m_watchFacePage + m_pages.size() - 1) % m_pages.size(); + ShowWatchFace(true); + + while (true) { + // Wait for button release + if (digitalRead(DOWN_BTN_PIN) == LOW){ + break; + } + delay(10); } } @@ -92,7 +116,7 @@ void WatchFace::DrawWatchFace(bool partialRefresh) return; } - m_pages[0]->DrawPage(partialRefresh); + m_pages[m_watchFacePage]->DrawPage(partialRefresh); } void WatchFace::SetupVolatileMenuStuff() diff --git a/src/WatchFace.h b/src/WatchFace.h index 96c331c..fe4cb53 100644 --- a/src/WatchFace.h +++ b/src/WatchFace.h @@ -3,6 +3,7 @@ #include "Watchy.h" #include "Menu.h" #include "WatchFacePages/Clock.h" +#include "WatchFacePages/Weather.h" #include class WatchFace : public Watchy @@ -20,7 +21,8 @@ private: RTC_DATA_ATTR static Menu m_menu; RTC_DATA_ATTR static uint8_t m_watchFacePage; std::vector> m_pages = { - std::make_shared(m_display, m_features) + std::make_shared(m_display, m_features), + std::make_shared(m_display, m_features) }; void SetupVolatileMenuStuff(); diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp new file mode 100644 index 0000000..3053562 --- /dev/null +++ b/src/WatchFacePages/Weather.cpp @@ -0,0 +1,26 @@ +#include "Weather.h" +#include "../SevenSegment.h" +#include "../Icons.h" +#include +#include +#include + +WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) + : m_display(display), m_features(features) +{ +} + +void WatchFacePages::Weather::InitBoot() +{ +} + +void WatchFacePages::Weather::InitWake() +{ +} + +void WatchFacePages::Weather::DrawPage(bool partialRefresh) +{ + m_display.setFullWindow(); + m_display.fillScreen(GxEPD_WHITE); + m_display.display(partialRefresh); +} \ No newline at end of file diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h new file mode 100644 index 0000000..630e0f9 --- /dev/null +++ b/src/WatchFacePages/Weather.h @@ -0,0 +1,26 @@ +#pragma once + +#pragma once + +#include "Page.h" +#include "../WatchyDisplay.h" +#include "../WatchFeatures/WatchFeatures.h" + +namespace WatchFacePages +{ + class Weather; +} + +class WatchFacePages::Weather : public WatchFacePages::Page +{ +public: + Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features); + void InitBoot() override; + void InitWake() override; + void DrawPage(bool partialRefresh = false) override; + +private: + + WatchyDisplay & m_display; + WatchFeatures::WatchFeatures & m_features; +}; \ No newline at end of file From 32cd26fccf95402c09d83d2c1be163b4b423a7a8 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 15:12:39 +0300 Subject: [PATCH 07/26] Replace inverse smoothstep with regular smoothstep for battery curve --- src/WatchFeatures/Battery.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/WatchFeatures/Battery.cpp b/src/WatchFeatures/Battery.cpp index 2bc0813..c3ff043 100644 --- a/src/WatchFeatures/Battery.cpp +++ b/src/WatchFeatures/Battery.cpp @@ -15,6 +15,7 @@ float WatchFeatures::Battery::GetVoltage() uint8_t WatchFeatures::Battery::GetPercentage() { float voltage = GetVoltage(); + Serial.println(voltage); float level = (GetVoltage() - 3.6f) / 0.6f; if (level < 0.0f) { @@ -23,7 +24,7 @@ uint8_t WatchFeatures::Battery::GetPercentage() level = 1.0f; } - level = 0.5f - sin(asin(1.0f - 2.0f * level) / 3.0f); + level = level * level * (3.0f - 2.0f * level); return std::round(level * 100.0f); } From 5993fda85ead2677b4030c0a695a6a6fe5fce9f6 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 16:17:40 +0300 Subject: [PATCH 08/26] Add averaging to reading battery levels --- src/WatchFeatures/Battery.cpp | 14 ++++++++++++-- src/WatchFeatures/Battery.h | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/WatchFeatures/Battery.cpp b/src/WatchFeatures/Battery.cpp index c3ff043..c3705e8 100644 --- a/src/WatchFeatures/Battery.cpp +++ b/src/WatchFeatures/Battery.cpp @@ -2,6 +2,9 @@ #include "Battery.h" #include #include +#include + +float WatchFeatures::Battery::m_previousVoltage = std::numeric_limits::infinity(); WatchFeatures::Battery::Battery() { @@ -9,13 +12,20 @@ WatchFeatures::Battery::Battery() float WatchFeatures::Battery::GetVoltage() { - return analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; + float voltage = analogReadMilliVolts(BATT_ADC_PIN) / 1000.0f * 2.0f; + + if (m_previousVoltage == std::numeric_limits::infinity()) { + m_previousVoltage = voltage; + } + + float averageVoltage = (m_previousVoltage + voltage) / 2.0f; + m_previousVoltage = voltage; + return averageVoltage; } uint8_t WatchFeatures::Battery::GetPercentage() { float voltage = GetVoltage(); - Serial.println(voltage); float level = (GetVoltage() - 3.6f) / 0.6f; if (level < 0.0f) { diff --git a/src/WatchFeatures/Battery.h b/src/WatchFeatures/Battery.h index 5a6ad1f..8e70149 100644 --- a/src/WatchFeatures/Battery.h +++ b/src/WatchFeatures/Battery.h @@ -13,4 +13,7 @@ public: Battery(); float GetVoltage(); uint8_t GetPercentage(); + +private: + static float m_previousVoltage; }; \ No newline at end of file From 67ff0917759bd904b90c52907ad390fa78549d24 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 16:48:45 +0300 Subject: [PATCH 09/26] Fixed braindead style, added a 2038+ compatible timestamp --- lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp | 961 +++++++++++++++++--------------- lib/Rtc_Pcf8563/Rtc_Pcf8563.h | 4 +- 2 files changed, 521 insertions(+), 444 deletions(-) diff --git a/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp b/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp index 546b333..4338538 100644 --- a/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp +++ b/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp @@ -38,59 +38,59 @@ #include #include "Rtc_Pcf8563.h" -Rtc_Pcf8563::Rtc_Pcf8563(void) +Rtc_Pcf8563::Rtc_Pcf8563() { - Wire.begin(); - Rtcc_Addr = RTCC_R>>1; + Wire.begin(); + Rtcc_Addr = RTCC_R >> 1; } Rtc_Pcf8563::Rtc_Pcf8563(int sdaPin, int sdlPin) { - Wire.begin(sdaPin, sdlPin); - Rtcc_Addr = RTCC_R>>1; + Wire.begin(sdaPin, sdlPin); + Rtcc_Addr = RTCC_R >> 1; } /* Private internal functions, but useful to look at if you need a similar func. */ byte Rtc_Pcf8563::decToBcd(byte val) { - return ( (val/10*16) + (val%10) ); + return ((val / 10 * 16) + (val % 10)); } byte Rtc_Pcf8563::bcdToDec(byte val) { - return ( (val/16*10) + (val%16) ); + return ((val / 16 * 10) + (val % 16)); } void Rtc_Pcf8563::zeroClock() { - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)0x0); // start address + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)0x0); // start address - Wire.write((byte)0x0); //control/status1 - Wire.write((byte)0x0); //control/status2 - Wire.write((byte)0x00); //set seconds to 0 & VL to 0 - Wire.write((byte)0x00); //set minutes to 0 - Wire.write((byte)0x00); //set hour to 0 - Wire.write((byte)0x01); //set day to 1 - Wire.write((byte)0x00); //set weekday to 0 - Wire.write((byte)0x81); //set month to 1, century to 1900 - Wire.write((byte)0x00); //set year to 0 - Wire.write((byte)0x80); //minute alarm value reset to 00 - Wire.write((byte)0x80); //hour alarm value reset to 00 - Wire.write((byte)0x80); //day alarm value reset to 00 - Wire.write((byte)0x80); //weekday alarm value reset to 00 - Wire.write((byte)SQW_32KHZ); //set SQW to default, see: setSquareWave - Wire.write((byte)0x0); //timer off - Wire.endTransmission(); + Wire.write((byte)0x0); //control/status1 + Wire.write((byte)0x0); //control/status2 + Wire.write((byte)0x00); //set seconds to 0 & VL to 0 + Wire.write((byte)0x00); //set minutes to 0 + Wire.write((byte)0x00); //set hour to 0 + Wire.write((byte)0x01); //set day to 1 + Wire.write((byte)0x00); //set weekday to 0 + Wire.write((byte)0x81); //set month to 1, century to 1900 + Wire.write((byte)0x00); //set year to 0 + Wire.write((byte)0x80); //minute alarm value reset to 00 + Wire.write((byte)0x80); //hour alarm value reset to 00 + Wire.write((byte)0x80); //day alarm value reset to 00 + Wire.write((byte)0x80); //weekday alarm value reset to 00 + Wire.write((byte)SQW_32KHZ); //set SQW to default, see: setSquareWave + Wire.write((byte)0x0); //timer off + Wire.endTransmission(); } void Rtc_Pcf8563::clearStatus() { - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)0x0); - Wire.write((byte)0x0); //control/status1 - Wire.write((byte)0x0); //control/status2 - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)0x0); + Wire.write((byte)0x0); //control/status1 + Wire.write((byte)0x0); //control/status2 + Wire.endTransmission(); } /* @@ -98,91 +98,100 @@ void Rtc_Pcf8563::clearStatus() */ byte Rtc_Pcf8563::readStatus2() { - getDateTime(); - return getStatus2(); + getDateTime(); + return getStatus2(); } -void Rtc_Pcf8563::clearVoltLow(void) +void Rtc_Pcf8563::clearVoltLow() { - getDateTime(); - // Only clearing is possible on device (I tried) - setDateTime(getDay(), getWeekday(), getMonth(), - getCentury(), getYear(), getHour(), - getMinute(), getSecond()); + getDateTime(); + // Only clearing is possible on device (I tried) + setDateTime(getDay(), getWeekday(), getMonth(), + getCentury(), getYear(), getHour(), + getMinute(), getSecond()); } /* * Atomicly read all device registers in one operation */ -void Rtc_Pcf8563::getDateTime(void) +void Rtc_Pcf8563::getDateTime() { - /* Start at beginning, read entire memory in one go */ - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_STAT1_ADDR); - Wire.endTransmission(); + /* Start at beginning, read entire memory in one go */ + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_STAT1_ADDR); + Wire.endTransmission(); - /* As per data sheet, have to read everything all in one operation */ - uint8_t readBuffer[16] = {0}; - Wire.requestFrom(Rtcc_Addr, 16); - for (uint8_t i=0; i < 16; i++) - readBuffer[i] = Wire.read(); + /* As per data sheet, have to read everything all in one operation */ + uint8_t readBuffer[16] = {0}; + Wire.requestFrom(Rtcc_Addr, 16); + for (uint8_t i=0; i < 16; i++) { + readBuffer[i] = Wire.read(); + } - // status bytes - status1 = readBuffer[0]; - status2 = readBuffer[1]; + // status bytes + status1 = readBuffer[0]; + status2 = readBuffer[1]; - // time bytes - //0x7f = 0b01111111 - volt_low = readBuffer[2] & RTCC_VLSEC_MASK; //VL_Seconds - sec = bcdToDec(readBuffer[2] & ~RTCC_VLSEC_MASK); - minute = bcdToDec(readBuffer[3] & 0x7f); - //0x3f = 0b00111111 - hour = bcdToDec(readBuffer[4] & 0x3f); + // time bytes + //0x7f = 0b01111111 + volt_low = readBuffer[2] & RTCC_VLSEC_MASK; //VL_Seconds + sec = bcdToDec(readBuffer[2] & ~RTCC_VLSEC_MASK); + minute = bcdToDec(readBuffer[3] & 0x7f); + //0x3f = 0b00111111 + hour = bcdToDec(readBuffer[4] & 0x3f); - // date bytes - //0x3f = 0b00111111 - day = bcdToDec(readBuffer[5] & 0x3f); - //0x07 = 0b00000111 - weekday = bcdToDec(readBuffer[6] & 0x07); - //get raw month data byte and set month and century with it. - month = readBuffer[7]; - if (month & RTCC_CENTURY_MASK) - century = true; - else - century = false; - //0x1f = 0b00011111 - month = month & 0x1f; - month = bcdToDec(month); - year = bcdToDec(readBuffer[8]); + // date bytes + //0x3f = 0b00111111 + day = bcdToDec(readBuffer[5] & 0x3f); + //0x07 = 0b00000111 + weekday = bcdToDec(readBuffer[6] & 0x07); + //get raw month data byte and set month and century with it. + month = readBuffer[7]; + if (month & RTCC_CENTURY_MASK) { + century = true; + } else { + century = false; + } - // alarm bytes - alarm_minute = readBuffer[9]; - if(B10000000 & alarm_minute) - alarm_minute = RTCC_NO_ALARM; - else - alarm_minute = bcdToDec(alarm_minute & B01111111); - alarm_hour = readBuffer[10]; - if(B10000000 & alarm_hour) - alarm_hour = RTCC_NO_ALARM; - else - alarm_hour = bcdToDec(alarm_hour & B00111111); - alarm_day = readBuffer[11]; - if(B10000000 & alarm_day) - alarm_day = RTCC_NO_ALARM; - else - alarm_day = bcdToDec(alarm_day & B00111111); - alarm_weekday = readBuffer[12]; - if(B10000000 & alarm_weekday) - alarm_weekday = RTCC_NO_ALARM; - else - alarm_weekday = bcdToDec(alarm_weekday & B00000111); + //0x1f = 0b00011111 + month = month & 0x1f; + month = bcdToDec(month); + year = bcdToDec(readBuffer[8]); - // CLKOUT_control 0x03 = 0b00000011 - squareWave = readBuffer[13] & 0x03; + // alarm bytes + alarm_minute = readBuffer[9]; + if(B10000000 & alarm_minute) { + alarm_minute = RTCC_NO_ALARM; + } else { + alarm_minute = bcdToDec(alarm_minute & B01111111); + } - // timer bytes - timer_control = readBuffer[14] & 0x03; - timer_value = readBuffer[15]; // current value != set value when running + alarm_hour = readBuffer[10]; + if(B10000000 & alarm_hour) { + alarm_hour = RTCC_NO_ALARM; + } else { + alarm_hour = bcdToDec(alarm_hour & B00111111); + } + + alarm_day = readBuffer[11]; + if(B10000000 & alarm_day) { + alarm_day = RTCC_NO_ALARM; + } else { + alarm_day = bcdToDec(alarm_day & B00111111); + } + alarm_weekday = readBuffer[12]; + if(B10000000 & alarm_weekday) { + alarm_weekday = RTCC_NO_ALARM; + } else { + alarm_weekday = bcdToDec(alarm_weekday & B00000111); + } + + // CLKOUT_control 0x03 = 0b00000011 + squareWave = readBuffer[13] & 0x03; + + // timer bytes + timer_control = readBuffer[14] & 0x03; + timer_value = readBuffer[15]; // current value != set value when running } @@ -190,30 +199,32 @@ void Rtc_Pcf8563::setDateTime(byte day, byte weekday, byte month, bool century, byte year, byte hour, byte minute, byte sec) { - /* year val is 00 to 99, xx - with the highest bit of month = century - 0=20xx - 1=19xx - */ - month = decToBcd(month); - if (century) - month |= RTCC_CENTURY_MASK; - else - month &= ~RTCC_CENTURY_MASK; + /* year val is 00 to 99, xx + with the highest bit of month = century + 0=20xx + 1=19xx + */ + month = decToBcd(month); - /* As per data sheet, have to set everything all in one operation */ - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write(RTCC_SEC_ADDR); // send addr low byte, req'd - Wire.write(decToBcd(sec) &~RTCC_VLSEC_MASK); //set sec, clear VL bit - Wire.write(decToBcd(minute)); //set minutes - Wire.write(decToBcd(hour)); //set hour - Wire.write(decToBcd(day)); //set day - Wire.write(decToBcd(weekday)); //set weekday - Wire.write(month); //set month, century to 1 - Wire.write(decToBcd(year)); //set year to 99 - Wire.endTransmission(); - // Keep values in-sync with device - getDateTime(); + if (century) { + month |= RTCC_CENTURY_MASK; + } else { + month &= ~RTCC_CENTURY_MASK; + } + + /* As per data sheet, have to set everything all in one operation */ + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write(RTCC_SEC_ADDR); // send addr low byte, req'd + Wire.write(decToBcd(sec) &~RTCC_VLSEC_MASK); //set sec, clear VL bit + Wire.write(decToBcd(minute)); //set minutes + Wire.write(decToBcd(hour)); //set hour + Wire.write(decToBcd(day)); //set day + Wire.write(decToBcd(weekday)); //set weekday + Wire.write(month); //set month, century to 1 + Wire.write(decToBcd(year)); //set year to 99 + Wire.endTransmission(); + // Keep values in-sync with device + getDateTime(); } /** @@ -221,7 +232,7 @@ void Rtc_Pcf8563::setDateTime(byte day, byte weekday, byte month, */ void Rtc_Pcf8563::getAlarm() { - getDateTime(); + getDateTime(); } /* @@ -230,7 +241,7 @@ void Rtc_Pcf8563::getAlarm() */ bool Rtc_Pcf8563::alarmEnabled() { - return getStatus2() & RTCC_ALARM_AIE; + return getStatus2() & RTCC_ALARM_AIE; } /* @@ -239,7 +250,7 @@ bool Rtc_Pcf8563::alarmEnabled() */ bool Rtc_Pcf8563::alarmActive() { - return getStatus2() & RTCC_ALARM_AF; + return getStatus2() & RTCC_ALARM_AF; } /* enable alarm interrupt @@ -248,19 +259,19 @@ bool Rtc_Pcf8563::alarmActive() */ void Rtc_Pcf8563::enableAlarm() { - getDateTime(); // operate on current values - //set status2 AF val to zero - status2 &= ~RTCC_ALARM_AF; - //set TF to 1 masks it from changing, as per data-sheet - status2 |= RTCC_TIMER_TF; - //enable the interrupt - status2 |= RTCC_ALARM_AIE; + getDateTime(); // operate on current values + //set status2 AF val to zero + status2 &= ~RTCC_ALARM_AF; + //set TF to 1 masks it from changing, as per data-sheet + status2 |= RTCC_TIMER_TF; + //enable the interrupt + status2 |= RTCC_ALARM_AIE; - //enable the interrupt - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + //enable the interrupt + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); } /* set the alarm values @@ -269,68 +280,68 @@ void Rtc_Pcf8563::enableAlarm() */ void Rtc_Pcf8563::setAlarm(byte min, byte hour, byte day, byte weekday) { - getDateTime(); // operate on current values - if (min <99) { - min = constrain(min, 0, 59); - min = decToBcd(min); - min &= ~RTCC_ALARM; - } else { - min = 0x0; min |= RTCC_ALARM; - } + getDateTime(); // operate on current values + if (min < 99) { + min = constrain(min, 0, 59); + min = decToBcd(min); + min &= ~RTCC_ALARM; + } else { + min = 0x0; min |= RTCC_ALARM; + } - if (hour <99) { - hour = constrain(hour, 0, 23); - hour = decToBcd(hour); - hour &= ~RTCC_ALARM; - } else { - hour = 0x0; hour |= RTCC_ALARM; - } + if (hour <99) { + hour = constrain(hour, 0, 23); + hour = decToBcd(hour); + hour &= ~RTCC_ALARM; + } else { + hour = 0x0; hour |= RTCC_ALARM; + } - if (day <99) { - day = constrain(day, 1, 31); - day = decToBcd(day); day &= ~RTCC_ALARM; - } else { - day = 0x0; day |= RTCC_ALARM; - } + if (day <99) { + day = constrain(day, 1, 31); + day = decToBcd(day); day &= ~RTCC_ALARM; + } else { + day = 0x0; day |= RTCC_ALARM; + } - if (weekday <99) { - weekday = constrain(weekday, 0, 6); - weekday = decToBcd(weekday); - weekday &= ~RTCC_ALARM; - } else { - weekday = 0x0; weekday |= RTCC_ALARM; - } + if (weekday <99) { + weekday = constrain(weekday, 0, 6); + weekday = decToBcd(weekday); + weekday &= ~RTCC_ALARM; + } else { + weekday = 0x0; weekday |= RTCC_ALARM; + } - alarm_hour = hour; - alarm_minute = min; - alarm_weekday = weekday; - alarm_day = day; + alarm_hour = hour; + alarm_minute = min; + alarm_weekday = weekday; + alarm_day = day; - // First set alarm values, then enable - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)RTCC_ALRM_MIN_ADDR); - Wire.write((byte)alarm_minute); - Wire.write((byte)alarm_hour); - Wire.write((byte)alarm_day); - Wire.write((byte)alarm_weekday); - Wire.endTransmission(); + // First set alarm values, then enable + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)RTCC_ALRM_MIN_ADDR); + Wire.write((byte)alarm_minute); + Wire.write((byte)alarm_hour); + Wire.write((byte)alarm_day); + Wire.write((byte)alarm_weekday); + Wire.endTransmission(); - Rtc_Pcf8563::enableAlarm(); + Rtc_Pcf8563::enableAlarm(); } void Rtc_Pcf8563::clearAlarm() { - //set status2 AF val to zero to reset alarm - status2 &= ~RTCC_ALARM_AF; - //set TF to 1 masks it from changing, as per data-sheet - status2 |= RTCC_TIMER_TF; - //turn off the interrupt - status2 &= ~RTCC_ALARM_AIE; + //set status2 AF val to zero to reset alarm + status2 &= ~RTCC_ALARM_AF; + //set TF to 1 masks it from changing, as per data-sheet + status2 |= RTCC_TIMER_TF; + //turn off the interrupt + status2 &= ~RTCC_ALARM_AIE; - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); } /** @@ -338,127 +349,132 @@ void Rtc_Pcf8563::clearAlarm() */ void Rtc_Pcf8563::resetAlarm() { - //set status2 AF val to zero to reset alarm - status2 &= ~RTCC_ALARM_AF; - //set TF to 1 masks it from changing, as per data-sheet - status2 |= RTCC_TIMER_TF; + //set status2 AF val to zero to reset alarm + status2 &= ~RTCC_ALARM_AF; + //set TF to 1 masks it from changing, as per data-sheet + status2 |= RTCC_TIMER_TF; - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); } // true if timer interrupt and control is enabled bool Rtc_Pcf8563::timerEnabled() { - if (getStatus2() & RTCC_TIMER_TIE) - if (timer_control & RTCC_TIMER_TE) - return true; - return false; + if (getStatus2() & RTCC_TIMER_TIE) { + if (timer_control & RTCC_TIMER_TE) { + return true; + } + } + + return false; } // true if timer is active bool Rtc_Pcf8563::timerActive() { - return getStatus2() & RTCC_TIMER_TF; + return getStatus2() & RTCC_TIMER_TF; } // enable timer and interrupt -void Rtc_Pcf8563::enableTimer(void) +void Rtc_Pcf8563::enableTimer() { - getDateTime(); - //set TE to 1 - timer_control |= RTCC_TIMER_TE; - //set status2 TF val to zero - status2 &= ~RTCC_TIMER_TF; - //set AF to 1 masks it from changing, as per data-sheet - status2 |= RTCC_ALARM_AF; - //enable the interrupt - status2 |= RTCC_TIMER_TIE; + getDateTime(); + //set TE to 1 + timer_control |= RTCC_TIMER_TE; + //set status2 TF val to zero + status2 &= ~RTCC_TIMER_TF; + //set AF to 1 masks it from changing, as per data-sheet + status2 |= RTCC_ALARM_AF; + //enable the interrupt + status2 |= RTCC_TIMER_TIE; - // Enable interrupt first, then enable timer - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + // Enable interrupt first, then enable timer + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_TIMER1_ADDR); - Wire.write((byte)timer_control); // Timer starts ticking now! - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_TIMER1_ADDR); + Wire.write((byte)timer_control); // Timer starts ticking now! + Wire.endTransmission(); } // set count-down value and frequency void Rtc_Pcf8563::setTimer(byte value, byte frequency, bool is_pulsed) { - getDateTime(); - if (is_pulsed) - status2 |= 0x01 << 4; - else - status2 &= ~(0x01 << 4); - timer_value = value; - // TE set to 1 in enableTimer(), leave 0 for now - timer_control |= (frequency & RTCC_TIMER_TD10); // use only last 2 bits + getDateTime(); + if (is_pulsed) { + status2 |= 0x01 << 4; + } else { + status2 &= ~(0x01 << 4); + } - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_TIMER1_ADDR); - Wire.write((byte)timer_control); - Wire.write((byte)timer_value); - Wire.endTransmission(); + timer_value = value; + // TE set to 1 in enableTimer(), leave 0 for now + timer_control |= (frequency & RTCC_TIMER_TD10); // use only last 2 bits - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_TIMER1_ADDR); + Wire.write((byte)timer_control); + Wire.write((byte)timer_value); + Wire.endTransmission(); - enableTimer(); + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); + + enableTimer(); } // clear timer flag and interrupt -void Rtc_Pcf8563::clearTimer(void) +void Rtc_Pcf8563::clearTimer() { - getDateTime(); - //set status2 TF val to zero - status2 &= ~RTCC_TIMER_TF; - //set AF to 1 masks it from changing, as per data-sheet - status2 |= RTCC_ALARM_AF; - //turn off the interrupt - status2 &= ~RTCC_TIMER_TIE; - //turn off the timer - timer_control = 0; + getDateTime(); + //set status2 TF val to zero + status2 &= ~RTCC_TIMER_TF; + //set AF to 1 masks it from changing, as per data-sheet + status2 |= RTCC_ALARM_AF; + //turn off the interrupt + status2 &= ~RTCC_TIMER_TIE; + //turn off the timer + timer_control = 0; - // Stop timer first - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_TIMER1_ADDR); - Wire.write((byte)timer_control); - Wire.endTransmission(); + // Stop timer first + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_TIMER1_ADDR); + Wire.write((byte)timer_control); + Wire.endTransmission(); - // clear flag and interrupt - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + // clear flag and interrupt + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); } // clear timer flag but leave interrupt unchanged */ -void Rtc_Pcf8563::resetTimer(void) +void Rtc_Pcf8563::resetTimer() { - getDateTime(); - //set status2 TF val to zero to reset timer - status2 &= ~RTCC_TIMER_TF; - //set AF to 1 masks it from changing, as per data-sheet - status2 |= RTCC_ALARM_AF; + getDateTime(); + //set status2 TF val to zero to reset timer + status2 &= ~RTCC_TIMER_TF; + //set AF to 1 masks it from changing, as per data-sheet + status2 |= RTCC_ALARM_AF; - Wire.beginTransmission(Rtcc_Addr); - Wire.write((byte)RTCC_STAT2_ADDR); - Wire.write((byte)status2); - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); + Wire.write((byte)RTCC_STAT2_ADDR); + Wire.write((byte)status2); + Wire.endTransmission(); } /** @@ -466,41 +482,41 @@ void Rtc_Pcf8563::resetTimer(void) */ void Rtc_Pcf8563::setSquareWave(byte frequency) { - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)RTCC_SQW_ADDR); - Wire.write((byte)frequency); - Wire.endTransmission(); + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)RTCC_SQW_ADDR); + Wire.write((byte)frequency); + Wire.endTransmission(); } void Rtc_Pcf8563::clearSquareWave() { - Rtc_Pcf8563::setSquareWave(SQW_DISABLE); + Rtc_Pcf8563::setSquareWave(SQW_DISABLE); } const char *Rtc_Pcf8563::formatTime(byte style) { getTime(); switch (style) { - case RTCC_TIME_HM: - strOut[0] = '0' + (hour / 10); - strOut[1] = '0' + (hour % 10); - strOut[2] = ':'; - strOut[3] = '0' + (minute / 10); - strOut[4] = '0' + (minute % 10); - strOut[5] = '\0'; - break; - case RTCC_TIME_HMS: - default: - strOut[0] = '0' + (hour / 10); - strOut[1] = '0' + (hour % 10); - strOut[2] = ':'; - strOut[3] = '0' + (minute / 10); - strOut[4] = '0' + (minute % 10); - strOut[5] = ':'; - strOut[6] = '0' + (sec / 10); - strOut[7] = '0' + (sec % 10); - strOut[8] = '\0'; - break; + case RTCC_TIME_HM: + strOut[0] = '0' + (hour / 10); + strOut[1] = '0' + (hour % 10); + strOut[2] = ':'; + strOut[3] = '0' + (minute / 10); + strOut[4] = '0' + (minute % 10); + strOut[5] = '\0'; + break; + case RTCC_TIME_HMS: + default: + strOut[0] = '0' + (hour / 10); + strOut[1] = '0' + (hour % 10); + strOut[2] = ':'; + strOut[3] = '0' + (minute / 10); + strOut[4] = '0' + (minute % 10); + strOut[5] = ':'; + strOut[6] = '0' + (sec / 10); + strOut[7] = '0' + (sec % 10); + strOut[8] = '\0'; + break; } return strOut; } @@ -508,98 +524,97 @@ const char *Rtc_Pcf8563::formatTime(byte style) const char *Rtc_Pcf8563::formatDate(byte style) { - getDate(); - - switch (style) { - - case RTCC_DATE_ASIA: - //do the asian style, yyyy-mm-dd - if (century ){ - strDate[0] = '1'; - strDate[1] = '9'; - } - else { - strDate[0] = '2'; - strDate[1] = '0'; - } - strDate[2] = '0' + (year / 10 ); - strDate[3] = '0' + (year % 10); - strDate[4] = '-'; - strDate[5] = '0' + (month / 10); - strDate[6] = '0' + (month % 10); - strDate[7] = '-'; - strDate[8] = '0' + (day / 10); - strDate[9] = '0' + (day % 10); - strDate[10] = '\0'; - break; - case RTCC_DATE_US: - //the pitiful US style, mm/dd/yyyy - strDate[0] = '0' + (month / 10); - strDate[1] = '0' + (month % 10); - strDate[2] = '/'; - strDate[3] = '0' + (day / 10); - strDate[4] = '0' + (day % 10); - strDate[5] = '/'; - if (century){ - strDate[6] = '1'; - strDate[7] = '9'; - } - else { - strDate[6] = '2'; - strDate[7] = '0'; - } - strDate[8] = '0' + (year / 10 ); - strDate[9] = '0' + (year % 10); - strDate[10] = '\0'; - break; - case RTCC_DATE_WORLD: - default: - //do the world style, dd-mm-yyyy - strDate[0] = '0' + (day / 10); - strDate[1] = '0' + (day % 10); - strDate[2] = '-'; - strDate[3] = '0' + (month / 10); - strDate[4] = '0' + (month % 10); - strDate[5] = '-'; - - if (century){ - strDate[6] = '1'; - strDate[7] = '9'; - } - else { - strDate[6] = '2'; - strDate[7] = '0'; - } - strDate[8] = '0' + (year / 10 ); - strDate[9] = '0' + (year % 10); - strDate[10] = '\0'; - break; + getDate(); + switch (style) { + case RTCC_DATE_ISO8601: + if (century ) { + strDate[0] = '1'; + strDate[1] = '9'; + } else { + strDate[0] = '2'; + strDate[1] = '0'; } - return strDate; + + strDate[2] = '0' + (year / 10 ); + strDate[3] = '0' + (year % 10); + strDate[4] = '-'; + strDate[5] = '0' + (month / 10); + strDate[6] = '0' + (month % 10); + strDate[7] = '-'; + strDate[8] = '0' + (day / 10); + strDate[9] = '0' + (day % 10); + strDate[10] = '\0'; + break; + case RTCC_DATE_US: + // the utterly bonkers US style, mm/dd/yyyy + strDate[0] = '0' + (month / 10); + strDate[1] = '0' + (month % 10); + strDate[2] = '/'; + strDate[3] = '0' + (day / 10); + strDate[4] = '0' + (day % 10); + strDate[5] = '/'; + + if (century) { + strDate[6] = '1'; + strDate[7] = '9'; + } else { + strDate[6] = '2'; + strDate[7] = '0'; + } + + strDate[8] = '0' + (year / 10 ); + strDate[9] = '0' + (year % 10); + strDate[10] = '\0'; + break; + case RTCC_DATE_WORLD: + default: + //do the world style, dd-mm-yyyy + strDate[0] = '0' + (day / 10); + strDate[1] = '0' + (day % 10); + strDate[2] = '-'; + strDate[3] = '0' + (month / 10); + strDate[4] = '0' + (month % 10); + strDate[5] = '-'; + + if (century) { + strDate[6] = '1'; + strDate[7] = '9'; + } else { + strDate[6] = '2'; + strDate[7] = '0'; + } + + strDate[8] = '0' + (year / 10 ); + strDate[9] = '0' + (year % 10); + strDate[10] = '\0'; + break; + } + + return strDate; } void Rtc_Pcf8563::initClock() { - Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal - Wire.write((byte)0x0); // start address + Wire.beginTransmission(Rtcc_Addr); // Issue I2C start signal + Wire.write((byte)0x0); // start address - Wire.write((byte)0x0); //control/status1 - Wire.write((byte)0x0); //control/status2 - Wire.write((byte)0x81); //set seconds & VL - Wire.write((byte)0x01); //set minutes - Wire.write((byte)0x01); //set hour - Wire.write((byte)0x01); //set day - Wire.write((byte)0x01); //set weekday - Wire.write((byte)0x01); //set month, century to 1 - Wire.write((byte)0x01); //set year to 99 - Wire.write((byte)0x80); //minute alarm value reset to 00 - Wire.write((byte)0x80); //hour alarm value reset to 00 - Wire.write((byte)0x80); //day alarm value reset to 00 - Wire.write((byte)0x80); //weekday alarm value reset to 00 - Wire.write((byte)0x0); //set SQW, see: setSquareWave - Wire.write((byte)0x0); //timer off - Wire.endTransmission(); + Wire.write((byte)0x0); //control/status1 + Wire.write((byte)0x0); //control/status2 + Wire.write((byte)0x81); //set seconds & VL + Wire.write((byte)0x01); //set minutes + Wire.write((byte)0x01); //set hour + Wire.write((byte)0x01); //set day + Wire.write((byte)0x01); //set weekday + Wire.write((byte)0x01); //set month, century to 1 + Wire.write((byte)0x01); //set year to 99 + Wire.write((byte)0x80); //minute alarm value reset to 00 + Wire.write((byte)0x80); //hour alarm value reset to 00 + Wire.write((byte)0x80); //day alarm value reset to 00 + Wire.write((byte)0x80); //weekday alarm value reset to 00 + Wire.write((byte)0x0); //set SQW, see: setSquareWave + Wire.write((byte)0x0); //timer off + Wire.endTransmission(); } void Rtc_Pcf8563::setTime(byte hour, byte minute, byte sec) @@ -611,130 +626,190 @@ void Rtc_Pcf8563::setTime(byte hour, byte minute, byte sec) void Rtc_Pcf8563::setDate(byte day, byte weekday, byte month, bool century, byte year) { - getDateTime(); - setDateTime(day, weekday, month, century, year, - getHour(), getMinute(), getSecond()); + getDateTime(); + setDateTime(day, weekday, month, century, year, + getHour(), getMinute(), getSecond()); } void Rtc_Pcf8563::getDate() { - getDateTime(); + getDateTime(); } void Rtc_Pcf8563::getTime() { - getDateTime(); + getDateTime(); } -bool Rtc_Pcf8563::getVoltLow(void) +bool Rtc_Pcf8563::getVoltLow() { - return volt_low; + return volt_low; } -byte Rtc_Pcf8563::getSecond() { - return sec; +byte Rtc_Pcf8563::getSecond() +{ + return sec; } -byte Rtc_Pcf8563::getMinute() { - return minute; +byte Rtc_Pcf8563::getMinute() +{ + return minute; } -byte Rtc_Pcf8563::getHour() { - return hour; +byte Rtc_Pcf8563::getHour() +{ + return hour; } -byte Rtc_Pcf8563::getAlarmMinute() { - return alarm_minute; +byte Rtc_Pcf8563::getAlarmMinute() +{ + return alarm_minute; } -byte Rtc_Pcf8563::getAlarmHour() { - return alarm_hour; +byte Rtc_Pcf8563::getAlarmHour() +{ + return alarm_hour; } -byte Rtc_Pcf8563::getAlarmDay() { - return alarm_day; +byte Rtc_Pcf8563::getAlarmDay() +{ + return alarm_day; } -byte Rtc_Pcf8563::getAlarmWeekday() { - return alarm_weekday; +byte Rtc_Pcf8563::getAlarmWeekday() +{ + return alarm_weekday; } -byte Rtc_Pcf8563::getTimerControl() { - return timer_control; +byte Rtc_Pcf8563::getTimerControl() +{ + return timer_control; } -byte Rtc_Pcf8563::getTimerValue() { +byte Rtc_Pcf8563::getTimerValue() +{ // Impossible to freeze this value, it could // be changing during read. Multiple reads // required to check for consistency. uint8_t last_value; do { - last_value = timer_value; - getDateTime(); + last_value = timer_value; + getDateTime(); } while (timer_value != last_value); + return timer_value; } -byte Rtc_Pcf8563::getDay() { - return day; +byte Rtc_Pcf8563::getDay() +{ + return day; } -byte Rtc_Pcf8563::getMonth() { - return month; +byte Rtc_Pcf8563::getMonth() +{ + return month; } -byte Rtc_Pcf8563::getYear() { - return year; +byte Rtc_Pcf8563::getYear() +{ + return year; } -bool Rtc_Pcf8563::getCentury() { - return century; +bool Rtc_Pcf8563::getCentury() +{ + return century; } -byte Rtc_Pcf8563::getWeekday() { - return weekday; +byte Rtc_Pcf8563::getWeekday() +{ + return weekday; } -byte Rtc_Pcf8563::getStatus1() { - return status1; +byte Rtc_Pcf8563::getStatus1() +{ + return status1; } -byte Rtc_Pcf8563::getStatus2() { - return status2; +byte Rtc_Pcf8563::getStatus2() +{ + return status2; } -unsigned long Rtc_Pcf8563::getTimestamp(){ - getDateTime(); // update date and time - unsigned long timestamp = 0; +unsigned long Rtc_Pcf8563::getTimestamp() +{ + getDateTime(); // update date and time + unsigned long timestamp = 0; - // Convert years in days - timestamp = (year-epoch_year)*365; // convert years in days + // Convert years in days + timestamp = (year-epoch_year) * 365; // convert years in days - if((year-epoch_year)>1) // add a dy when it's a leap year - { - for(unsigned char i = epoch_year; i2&&isLeapYear(century, year)) timestamp++; // test for the year's febuary + if((year-epoch_year)>1) { // add a dy when it's a leap year + for(unsigned char i = epoch_year; i1) timestamp += months_days[month-2]; + if(month>2 && isLeapYear(century, year)) { + timestamp++; // test for the year's febuary + } - // add days - timestamp += (day-epoch_day); + // add months converted in days + if(month>1) timestamp += months_days[month-2]; - timestamp*= 86400; // convert days in seconds + // add days + timestamp += (day-epoch_day); - // convert time to second and add it to timestamp - unsigned long timeTemp = hour*60+ minute; - timeTemp *=60; - timeTemp += sec; + timestamp *= 86400; // convert days in seconds - timestamp += timeTemp; // add hours +minutes + seconds + // convert time to second and add it to timestamp + unsigned long timeTemp = hour*60+ minute; + timeTemp *= 60; + timeTemp += sec; - timestamp += EPOCH_TIMESTAMP; // add epoch reference + timestamp += timeTemp; // add hours +minutes + seconds - return timestamp; + timestamp += EPOCH_TIMESTAMP; // add epoch reference + + return timestamp; } + +uint64_t Rtc_Pcf8563::getTimestamp64() +{ + getDateTime(); // update date and time + uint64_t timestamp = 0; + + // Convert years in days + timestamp = (year - epoch_year) * 365; // convert years to days + + if((year - epoch_year) > 1) { // add a day when it's a leap year + for(unsigned char i = epoch_year; i 2 && isLeapYear(century, year)) { + timestamp++; // test for the year's febuary + } + + // add months converted in days + if(month > 1) { + timestamp += months_days[month-2]; + } + + // add days + timestamp += (day-epoch_day); + + timestamp *= 86400; // convert days in seconds + + // convert time to second and add it to timestamp + unsigned long timeTemp = hour * 60 + minute; + timeTemp *= 60; + timeTemp += sec; + + timestamp += timeTemp; // add hours +minutes + seconds + timestamp += EPOCH_TIMESTAMP; // add epoch reference + + return timestamp; +} \ No newline at end of file diff --git a/lib/Rtc_Pcf8563/Rtc_Pcf8563.h b/lib/Rtc_Pcf8563/Rtc_Pcf8563.h index 3096030..99a0870 100644 --- a/lib/Rtc_Pcf8563/Rtc_Pcf8563.h +++ b/lib/Rtc_Pcf8563/Rtc_Pcf8563.h @@ -102,7 +102,8 @@ /* date format flags */ #define RTCC_DATE_WORLD 0x01 -#define RTCC_DATE_ASIA 0x02 +#define RTCC_DATE_ISO8601 0x02 +#define RTCC_DATE_ASIA 0x02 // It's not "asian", it's ISO8601, that anybody with any sense uses #define RTCC_DATE_US 0x04 /* time format flags */ #define RTCC_TIME_HMS 0x01 @@ -198,6 +199,7 @@ class Rtc_Pcf8563 { byte getTimerValue(); unsigned long getTimestamp(); // return unix timestamp + uint64_t getTimestamp64(); // Fixed for 2038+ // Sets date/time to static fixed values, disable all alarms // use zeroClock() above to guarantee lowest possible values instead. From 93602ebb7726109e79a9cb98404d4835e9013081 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 16:49:57 +0300 Subject: [PATCH 10/26] Timestamp bugfix --- lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp b/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp index 4338538..9c508b5 100644 --- a/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp +++ b/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp @@ -804,7 +804,7 @@ uint64_t Rtc_Pcf8563::getTimestamp64() timestamp *= 86400; // convert days in seconds // convert time to second and add it to timestamp - unsigned long timeTemp = hour * 60 + minute; + uint64_t timeTemp = hour * 60 + minute; timeTemp *= 60; timeTemp += sec; From 07e83e7557c80678ddc7d95c28edf1699f30b184 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 17:17:57 +0300 Subject: [PATCH 11/26] Move wifi code into a watch feature --- src/WatchFace.cpp | 17 +++++++++++------ src/WatchFeatures/WatchFeatures.h | 2 ++ src/WatchFeatures/Wifi.cpp | 28 ++++++++++++++++++++++++++++ src/WatchFeatures/Wifi.h | 12 ++++++++++++ src/Watchy.cpp | 20 -------------------- 5 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 src/WatchFeatures/Wifi.cpp create mode 100644 src/WatchFeatures/Wifi.h diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index e17494c..009d909 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -13,9 +13,10 @@ void WatchFace::InitBoot() SetupVolatileMenuStuff(); m_menu.Reset(); - ConnectWiFi(); - SyncNTPTime(); - DisconnectWiFi(); + if(m_features.wifi.Connect()) { + SyncNTPTime(); + m_features.wifi.Disconnect(); + } for (auto & page : m_pages) { page->InitBoot(); @@ -235,16 +236,20 @@ void WatchFace::MenuExited() void WatchFace::MenuNTPSyncSelected() { - ConnectWiFi(); + if (!m_features.wifi.Connect()) { + return; + } + SyncNTPTime(); - DisconnectWiFi(); - m_features.rtc.Resync(); + m_features.wifi.Disconnect(); if (m_inMenu) { m_inMenu = false; m_menu.Reset(); DrawWatchFace(false); } + + m_features.rtc.Resync(); } void WatchFace::MenuTimeZoneSelected(int tzOffset) diff --git a/src/WatchFeatures/WatchFeatures.h b/src/WatchFeatures/WatchFeatures.h index e5049ed..e14b5c6 100644 --- a/src/WatchFeatures/WatchFeatures.h +++ b/src/WatchFeatures/WatchFeatures.h @@ -4,6 +4,7 @@ #include "StepCounter.h" #include "RTC.h" #include "Storage.h" +#include "Wifi.h" namespace WatchFeatures { @@ -21,4 +22,5 @@ struct WatchFeatures::WatchFeatures StepCounter stepCounter; RTC rtc; Storage storage; + Wifi wifi; }; \ No newline at end of file diff --git a/src/WatchFeatures/Wifi.cpp b/src/WatchFeatures/Wifi.cpp new file mode 100644 index 0000000..8eff1e0 --- /dev/null +++ b/src/WatchFeatures/Wifi.cpp @@ -0,0 +1,28 @@ +#include +#include "Wifi.h" +#include "config.h" + +bool WatchFeatures::Wifi::Connect() +{ + if (WiFi.begin(WIFI_SSID, WIFI_PASS) == WL_CONNECT_FAILED) { + WiFi.mode(WIFI_OFF); + return false; + } + + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + WiFi.mode(WIFI_OFF); + return false; + } + + return true; +} + +void WatchFeatures::Wifi::Disconnect() +{ + +} + +bool WatchFeatures::Wifi::IsConnected() +{ + return true; +} \ No newline at end of file diff --git a/src/WatchFeatures/Wifi.h b/src/WatchFeatures/Wifi.h new file mode 100644 index 0000000..f173389 --- /dev/null +++ b/src/WatchFeatures/Wifi.h @@ -0,0 +1,12 @@ +#pragma once + +namespace WatchFeatures +{ + class Wifi + { + public: + bool Connect(); + void Disconnect(); + bool IsConnected(); + }; +} \ No newline at end of file diff --git a/src/Watchy.cpp b/src/Watchy.cpp index 7e49b8b..8c3796b 100644 --- a/src/Watchy.cpp +++ b/src/Watchy.cpp @@ -112,21 +112,6 @@ void Watchy::VibeMotor(uint8_t intervalMs, uint8_t length) } } -void Watchy::ConnectWiFi() -{ - if(WiFi.begin(WIFI_SSID, WIFI_PASS) == WL_CONNECT_FAILED) { - Serial.begin(9600); - Serial.println("Failed to connect to WiFi"); - return; - } - - if(WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.begin(9600); - Serial.println("Failed to connect to WiFi"); - return; - } -} - void Watchy::SyncNTPTime() { WiFiUDP ntpUDP; @@ -144,11 +129,6 @@ void Watchy::SyncNTPTime() } } -void Watchy::DisconnectWiFi() -{ - WiFi.mode(WIFI_OFF); -} - void Watchy::ShowWatchFace(bool partialRefresh) { DrawWatchFace(partialRefresh); From 23b1328cba055cb688bd8bd360b94c0b9f0bf5af Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 17:22:37 +0300 Subject: [PATCH 12/26] Add WIP weather stuff --- src/WatchFacePages/Weather.cpp | 15 +++++++++++++++ src/WatchFacePages/Weather.h | 2 ++ src/WatchFeatures/RTC.cpp | 35 +++++++++++++++++++--------------- src/WatchFeatures/RTC.h | 5 ++--- src/config.h | 3 +++ 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index 3053562..bb96bc3 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -5,6 +5,8 @@ #include #include +RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncTime = 0; + WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) : m_display(display), m_features(features) { @@ -23,4 +25,17 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) m_display.setFullWindow(); m_display.fillScreen(GxEPD_WHITE); m_display.display(partialRefresh); +} + +void WatchFacePages::Weather::Resync() +{ + // if(!m_features.wifi.Connect()) { + // return; + // } + + // uint64_t currentTime = m_features.rtc.GetTimestamp(); + + // if(m_lastSyncTime == 0 || m_lastSyncTime + 60 * 60 * 1000 < millis()) { + // m_lastSyncTime = millis(); + // } } \ No newline at end of file diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h index 630e0f9..051525d 100644 --- a/src/WatchFacePages/Weather.h +++ b/src/WatchFacePages/Weather.h @@ -20,7 +20,9 @@ public: void DrawPage(bool partialRefresh = false) override; private: + void Resync(); WatchyDisplay & m_display; WatchFeatures::WatchFeatures & m_features; + static RTC_DATA_ATTR uint64_t m_lastSyncTime; }; \ No newline at end of file diff --git a/src/WatchFeatures/RTC.cpp b/src/WatchFeatures/RTC.cpp index 1834755..7fbe6b4 100644 --- a/src/WatchFeatures/RTC.cpp +++ b/src/WatchFeatures/RTC.cpp @@ -10,14 +10,14 @@ RTC_DATA_ATTR bool WatchFeatures::RTC::m_initialTimer = true; void WatchFeatures::RTC::Get(tmElements_t & tm) { - rtc_pcf.getDateTime(); - tm.Year = y2kYearToTm(rtc_pcf.getYear()); - tm.Month = rtc_pcf.getMonth(); - tm.Day = rtc_pcf.getDay(); - tm.Wday = rtc_pcf.getWeekday() + 1; // TimeLib has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range - tm.Hour = rtc_pcf.getHour(); - tm.Minute = rtc_pcf.getMinute(); - tm.Second = rtc_pcf.getSecond(); + m_rtcPcf.getDateTime(); + tm.Year = y2kYearToTm(m_rtcPcf.getYear()); + tm.Month = m_rtcPcf.getMonth(); + tm.Day = m_rtcPcf.getDay(); + tm.Wday = m_rtcPcf.getWeekday() + 1; // TimeLib has Wday range of 1-7, but PCF8563 stores day of week in 0-6 range + tm.Hour = m_rtcPcf.getHour(); + tm.Minute = m_rtcPcf.getMinute(); + tm.Second = m_rtcPcf.getSecond(); } void WatchFeatures::RTC::Set(tmElements_t tm) @@ -25,7 +25,12 @@ void WatchFeatures::RTC::Set(tmElements_t tm) time_t t = makeTime(tm); // make and break to calculate tm.Wday breakTime(t, tm); // day, weekday, month, century(1=1900, 0=2000), year(0-99) - rtc_pcf.setDateTime(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year), tm.Hour, tm.Minute, tm.Second); + m_rtcPcf.setDateTime(tm.Day, tm.Wday - 1, tm.Month, 0, tmYearToY2k(tm.Year), tm.Hour, tm.Minute, tm.Second); +} + +uint64_t WatchFeatures::RTC::GetTimestamp() +{ + return m_rtcPcf.getTimestamp64(); } void WatchFeatures::RTC::SetTimer() @@ -115,8 +120,8 @@ bool WatchFeatures::RTC::CheckWakeup() } // Timer doesn't work reliably unless it's cleared first - rtc_pcf.clearTimer(); - rtc_pcf.setTimer(interval, frequency, true); + m_rtcPcf.clearTimer(); + m_rtcPcf.setTimer(interval, frequency, true); return true; } @@ -126,16 +131,16 @@ bool WatchFeatures::RTC::CheckWakeup() void WatchFeatures::RTC::Resync() { - rtc_pcf.getDateTime(); + m_rtcPcf.getDateTime(); // Sleep just long enough to get to a multiple of the update interval, makes updates happen on exact turn of the minute - int seconds = UPDATE_INTERVAL - (rtc_pcf.getSecond() % UPDATE_INTERVAL); + int seconds = UPDATE_INTERVAL - (m_rtcPcf.getSecond() % UPDATE_INTERVAL); if (seconds < 0) { seconds = 0; } // Timer doesn't work reliably unless it's cleared first - rtc_pcf.clearTimer(); + m_rtcPcf.clearTimer(); if (seconds == 0) { // If there's no time to wait, just call CheckWakeup() immediately and it'll set the repeating timer @@ -143,7 +148,7 @@ void WatchFeatures::RTC::Resync() m_initialTimer = true; CheckWakeup(); } else { - rtc_pcf.setTimer(seconds, TMR_1Hz, false); + m_rtcPcf.setTimer(seconds, TMR_1Hz, false); m_timerSet = true; m_initialTimer = true; diff --git a/src/WatchFeatures/RTC.h b/src/WatchFeatures/RTC.h index 9abf79c..1c2bcd0 100644 --- a/src/WatchFeatures/RTC.h +++ b/src/WatchFeatures/RTC.h @@ -12,12 +12,10 @@ namespace WatchFeatures } class WatchFeatures::RTC { -public: - Rtc_Pcf8563 rtc_pcf; - public: void Get(tmElements_t & tm); void Set(tmElements_t tm); + uint64_t GetTimestamp(); void SetTimer(); bool CheckWakeup(); // Checks to really wake up or not, also resets the timer after the initial sleep void Resync(); // Resync the timer cycle, both initially and after RTC resync @@ -25,6 +23,7 @@ public: static void OffsetTime(tmElements_t & tm, int offsetInSeconds); private: + Rtc_Pcf8563 m_rtcPcf; static RTC_DATA_ATTR bool m_timerSet, m_initialTimer; }; diff --git a/src/config.h b/src/config.h index a2b5b30..ea206b8 100644 --- a/src/config.h +++ b/src/config.h @@ -34,6 +34,7 @@ #define EEPROM_MAGIC2 0x0d #define EEPROM_VERSION 1 +#define OPENWEATHERMAP_API_KEY "" #include "secrets.h" #if !defined(WIFI_SSID) || !defined(WIFI_PASS) #error "Please define WIFI_SSID and WIFI_PASS in secrets.h" @@ -45,3 +46,5 @@ #define UPDATE_INTERVAL 60 // seconds #define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute + +#define WEATHER_UPDATE_INTERVAL 3600 // seconds \ No newline at end of file From f718c01d80b87cdd04252f849c5b0e43828b796d Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 18:16:20 +0300 Subject: [PATCH 13/26] Add date/day to clock, proportional fonts --- lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp | 2 +- src/WatchFacePages/Clock.cpp | 69 +++++++++++++++++++++++---------- src/WatchFeatures/RTC.cpp | 5 +++ src/WatchFeatures/RTC.h | 1 + 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp b/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp index 9c508b5..5311e68 100644 --- a/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp +++ b/lib/Rtc_Pcf8563/Rtc_Pcf8563.cpp @@ -522,7 +522,7 @@ const char *Rtc_Pcf8563::formatTime(byte style) } -const char *Rtc_Pcf8563::formatDate(byte style) +const char * Rtc_Pcf8563::formatDate(byte style) { getDate(); diff --git a/src/WatchFacePages/Clock.cpp b/src/WatchFacePages/Clock.cpp index 0788335..a2f106f 100644 --- a/src/WatchFacePages/Clock.cpp +++ b/src/WatchFacePages/Clock.cpp @@ -2,8 +2,8 @@ #include "../SevenSegment.h" #include "../Icons.h" #include -#include -#include +#include +#include WatchFacePages::Clock::Clock(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) : m_display(display), m_features(features) @@ -28,6 +28,7 @@ void WatchFacePages::Clock::DrawPage(bool partialRefresh) // Get current time and offset by timezone tmElements_t currentTime; m_features.rtc.Get(currentTime); + std::string date = m_features.rtc.GetDateString(); int tzOffset = m_features.storage.GetTzOffset(); m_features.rtc.OffsetTime(currentTime, tzOffset); @@ -35,23 +36,48 @@ void WatchFacePages::Clock::DrawPage(bool partialRefresh) SevenSegment sevenSegment(30, 60, 6, 5, 5); if (currentTime.Hour < 10) { - sevenSegment.DrawDigit(m_display, 0, 15, 75, GxEPD_BLACK); + sevenSegment.DrawDigit(m_display, 0, 15, 65, GxEPD_BLACK); } else { - sevenSegment.DrawDigit(m_display, currentTime.Hour / 10, 20, 75, GxEPD_BLACK); + sevenSegment.DrawDigit(m_display, currentTime.Hour / 10, 20, 65, GxEPD_BLACK); } - sevenSegment.DrawDigit(m_display, currentTime.Hour % 10, 60, 75, GxEPD_BLACK); + sevenSegment.DrawDigit(m_display, currentTime.Hour % 10, 60, 65, GxEPD_BLACK); if (currentTime.Minute < 10) { - sevenSegment.DrawDigit(m_display, 0, 110, 75, GxEPD_BLACK); + sevenSegment.DrawDigit(m_display, 0, 110, 65, GxEPD_BLACK); } else { - sevenSegment.DrawDigit(m_display, currentTime.Minute / 10, 110, 75, GxEPD_BLACK); + sevenSegment.DrawDigit(m_display, currentTime.Minute / 10, 110, 65, GxEPD_BLACK); } - sevenSegment.DrawDigit(m_display, currentTime.Minute % 10, 150, 75, GxEPD_BLACK); + sevenSegment.DrawDigit(m_display, currentTime.Minute % 10, 150, 65, GxEPD_BLACK); - m_display.fillRect(97, 90, 5, 5, GxEPD_BLACK); - m_display.fillRect(97, 110, 5, 5, GxEPD_BLACK); + m_display.fillRect(97, 80, 5, 5, GxEPD_BLACK); + m_display.fillRect(97, 100, 5, 5, GxEPD_BLACK); + + // Print day and date + const char * weekDays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; + const char * dow = weekDays[currentTime.Wday - 1]; + + m_display.setFont(&FreeSans9pt7b); + m_display.setTextColor(GxEPD_BLACK); + m_display.setCursor(15, 150); + m_display.print(dow); + + int16_t x, y; + uint16_t w, h; + m_display.getTextBounds(date.c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(180 - w, 150); + m_display.print(m_features.rtc.GetDateString().c_str()); + + // Seperator + m_display.fillRect(15, 127, 170, 2, GxEPD_BLACK); + + // Steps + m_display.setFont(&FreeSans12pt7b); + m_display.setTextColor(GxEPD_BLACK); + m_display.drawBitmap(10, 177, Icons::steps, 19, 23, GxEPD_BLACK); + m_display.setCursor(40, 195); + m_display.print(m_features.stepCounter.GetSteps()); m_display.display(partialRefresh); } @@ -65,19 +91,22 @@ void WatchFacePages::Clock::DrawBatteryIcon() m_display.fillRect(200 - 44, 9, (int)std::round(35.0f * level), 15, GxEPD_BLACK); - int x = 200 - 85; + int16_t x = 200 - 85; if (intLevel == 100) { x -= 13; } - m_display.setFont(&FreeMonoBold9pt7b); - m_display.setCursor(x, 22); - m_display.setTextColor(GxEPD_BLACK); - m_display.print(intLevel); - m_display.print("%"); + std::ostringstream oss; + oss << intLevel << "%"; - m_display.setFont(&FreeMonoBold12pt7b); - m_display.drawBitmap(10, 177, Icons::steps, 19, 23, GxEPD_BLACK); - m_display.setCursor(40, 195); - m_display.print(m_features.stepCounter.GetSteps()); + m_display.setFont(&FreeSans9pt7b); + m_display.setTextColor(GxEPD_BLACK); + + + int16_t y; + uint16_t w, h; + m_display.getTextBounds(oss.str().c_str(), 0, 0, &x, &y, &w, &h); + + m_display.setCursor(142 - w, 22); + m_display.print(oss.str().c_str()); } \ No newline at end of file diff --git a/src/WatchFeatures/RTC.cpp b/src/WatchFeatures/RTC.cpp index 7fbe6b4..fb40f85 100644 --- a/src/WatchFeatures/RTC.cpp +++ b/src/WatchFeatures/RTC.cpp @@ -129,6 +129,11 @@ bool WatchFeatures::RTC::CheckWakeup() return true; } +std::string WatchFeatures::RTC::GetDateString() +{ + return std::string(m_rtcPcf.formatDate(RTCC_DATE_ISO8601)); +} + void WatchFeatures::RTC::Resync() { m_rtcPcf.getDateTime(); diff --git a/src/WatchFeatures/RTC.h b/src/WatchFeatures/RTC.h index 1c2bcd0..66110dd 100644 --- a/src/WatchFeatures/RTC.h +++ b/src/WatchFeatures/RTC.h @@ -16,6 +16,7 @@ public: void Get(tmElements_t & tm); void Set(tmElements_t tm); uint64_t GetTimestamp(); + std::string GetDateString(); void SetTimer(); bool CheckWakeup(); // Checks to really wake up or not, also resets the timer after the initial sleep void Resync(); // Resync the timer cycle, both initially and after RTC resync From 36510ace7a4408365b91a2a22adc62a547d7bc67 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 18:24:23 +0300 Subject: [PATCH 14/26] Do a full refresh on page switch --- src/WatchFace.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index 009d909..900cc93 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -75,7 +75,7 @@ void WatchFace::HandleButtonPress(uint64_t buttonMask) } } else if (buttonMask & UP_BTN_MASK) { m_watchFacePage = (m_watchFacePage + 1) % m_pages.size(); - ShowWatchFace(true); + ShowWatchFace(false); while (true) { // Wait for button release @@ -87,7 +87,7 @@ void WatchFace::HandleButtonPress(uint64_t buttonMask) } } else if (buttonMask & DOWN_BTN_MASK) { m_watchFacePage = (m_watchFacePage + m_pages.size() - 1) % m_pages.size(); - ShowWatchFace(true); + ShowWatchFace(false); while (true) { // Wait for button release From 4e3800e3323012853b2debd1aa76cb58994b2333 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 18:24:54 +0300 Subject: [PATCH 15/26] Weather WIP --- src/WatchFacePages/Weather.cpp | 35 ++++++++++++++++++++++++---------- src/WatchFacePages/Weather.h | 1 + 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index bb96bc3..5ea15ab 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -1,11 +1,10 @@ #include "Weather.h" #include "../SevenSegment.h" #include "../Icons.h" -#include -#include -#include +#include RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncTime = 0; +RTC_DATA_ATTR int WatchFacePages::Weather::m_lastCalculatedDay = 0XFFFFFFFF; WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) : m_display(display), m_features(features) @@ -24,18 +23,34 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) { m_display.setFullWindow(); m_display.fillScreen(GxEPD_WHITE); - m_display.display(partialRefresh); + m_display.setTextColor(GxEPD_BLACK); + + if (m_lastSyncTime == 0) { + m_display.setFont(&FreeSans12pt7b); + int16_t x, y; + uint16_t w, h; + m_display.getTextBounds("Have not synced", 0, 0, &x, &y, &w, &h); + m_display.setCursor(DISPLAY_WIDTH / 2 - w / 2, 110); + m_display.print("Have not synced"); + m_display.display(partialRefresh); + return; + } else if (m_features.rtc.GetTimestamp() - m_lastSyncTime > 86400) { + m_display.setFont(&FreeSans12pt7b); + m_display.setCursor(20, 110); + m_display.print("Last sync > 1 day"); + m_display.display(partialRefresh); + return; + } } void WatchFacePages::Weather::Resync() { + uint64_t currentTime = m_features.rtc.GetTimestamp(); + + if(m_lastSyncTime == 0 || currentTime - m_lastSyncTime > WEATHER_UPDATE_INTERVAL) { + } + // if(!m_features.wifi.Connect()) { // return; // } - - // uint64_t currentTime = m_features.rtc.GetTimestamp(); - - // if(m_lastSyncTime == 0 || m_lastSyncTime + 60 * 60 * 1000 < millis()) { - // m_lastSyncTime = millis(); - // } } \ No newline at end of file diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h index 051525d..f84db95 100644 --- a/src/WatchFacePages/Weather.h +++ b/src/WatchFacePages/Weather.h @@ -25,4 +25,5 @@ private: WatchyDisplay & m_display; WatchFeatures::WatchFeatures & m_features; static RTC_DATA_ATTR uint64_t m_lastSyncTime; + static RTC_DATA_ATTR int m_lastCalculatedDay; }; \ No newline at end of file From b0e5d281e0e06dbfa21e89c3087b63fa28d955c2 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 19:55:35 +0300 Subject: [PATCH 16/26] Add city name display --- platformio.ini | 1 + src/Icons.h | 15 ++++++- src/WatchFace.cpp | 5 +++ src/WatchFacePages/Clock.cpp | 1 - src/WatchFacePages/Weather.cpp | 78 +++++++++++++++++++++++++++++----- src/WatchFacePages/Weather.h | 5 ++- 6 files changed, 91 insertions(+), 14 deletions(-) diff --git a/platformio.ini b/platformio.ini index 8b9076c..ae12590 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,6 +17,7 @@ lib_deps = GxEPD2 Time NTPClient + ArduinoJson lib_ldf_mode = deep+ board_build.partitions = min_spiffs.csv diff --git a/src/Icons.h b/src/Icons.h index 2427196..f1b9d4d 100644 --- a/src/Icons.h +++ b/src/Icons.h @@ -2,11 +2,22 @@ namespace Icons { - const unsigned char steps [] PROGMEM = { + // 19x23 + const unsigned char steps[] PROGMEM = { 0x00, 0x03, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x0f, 0xe0, 0x78, 0x0f, 0xe0, 0xfc, 0x0f, 0xe0, 0xfc, 0x0f, 0xe0, 0xfc, 0x0f, 0xe0, 0xfe, 0x0f, 0xe0, 0xfe, 0x07, 0xc0, 0xfe, 0x07, 0xc0, 0xfe, 0x07, 0x80, 0xfe, 0x00, 0x00, 0x7c, 0x0e, 0x00, 0x7c, 0x0f, 0x80, 0x7c, 0x1f, 0x80, 0x20, 0x1f, 0x00, 0x06, 0x0f, 0x00, 0x3e, 0x0e, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00 }; -}; \ No newline at end of file + + // 29x23 + const unsigned char city[] PROGMEM = { + 0x00, 0x07, 0xf8, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x0e, 0x07, 0x1c, 0x00, + 0x1f, 0x87, 0x1c, 0x00, 0x3f, 0xc7, 0x1c, 0xc0, 0x3f, 0xc7, 0xfc, 0xc0, 0x3f, 0xc7, 0x1c, 0xc0, + 0x7f, 0xc7, 0x1c, 0xc0, 0x7f, 0xe7, 0x1f, 0xf8, 0xff, 0xe7, 0xff, 0xf8, 0xff, 0xe7, 0x1e, 0x38, + 0xff, 0xe7, 0x1e, 0x38, 0xff, 0xe7, 0x1e, 0x38, 0x06, 0x07, 0x1e, 0x38, 0x06, 0x07, 0xff, 0xf8, + 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xff, 0xf8, + 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8 + }; +} \ No newline at end of file diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index 900cc93..4aed098 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -18,6 +18,8 @@ void WatchFace::InitBoot() m_features.wifi.Disconnect(); } + static_cast(m_pages[1].get())->Resync(); + for (auto & page : m_pages) { page->InitBoot(); } @@ -118,6 +120,9 @@ void WatchFace::DrawWatchFace(bool partialRefresh) } m_pages[m_watchFacePage]->DrawPage(partialRefresh); + + // Resync weather on matter what + static_cast(m_pages[1].get())->Resync(); } void WatchFace::SetupVolatileMenuStuff() diff --git a/src/WatchFacePages/Clock.cpp b/src/WatchFacePages/Clock.cpp index a2f106f..8a499db 100644 --- a/src/WatchFacePages/Clock.cpp +++ b/src/WatchFacePages/Clock.cpp @@ -102,7 +102,6 @@ void WatchFacePages::Clock::DrawBatteryIcon() m_display.setFont(&FreeSans9pt7b); m_display.setTextColor(GxEPD_BLACK); - int16_t y; uint16_t w, h; m_display.getTextBounds(oss.str().c_str(), 0, 0, &x, &y, &w, &h); diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index 5ea15ab..dcc6334 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -1,10 +1,17 @@ #include "Weather.h" #include "../SevenSegment.h" #include "../Icons.h" +#include +#include #include +#include +#include RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncTime = 0; RTC_DATA_ATTR int WatchFacePages::Weather::m_lastCalculatedDay = 0XFFFFFFFF; +RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLat = 0.0f; +RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLon = 0.0f; +RTC_DATA_ATTR char WatchFacePages::Weather::m_locationCity[128]; WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) : m_display(display), m_features(features) @@ -21,6 +28,11 @@ void WatchFacePages::Weather::InitWake() void WatchFacePages::Weather::DrawPage(bool partialRefresh) { + Serial.println("Weather:DrawPage"); + if (m_lastSyncTime == 0) { + Resync(); + } + m_display.setFullWindow(); m_display.fillScreen(GxEPD_WHITE); m_display.setTextColor(GxEPD_BLACK); @@ -34,23 +46,69 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) m_display.print("Have not synced"); m_display.display(partialRefresh); return; - } else if (m_features.rtc.GetTimestamp() - m_lastSyncTime > 86400) { - m_display.setFont(&FreeSans12pt7b); - m_display.setCursor(20, 110); - m_display.print("Last sync > 1 day"); - m_display.display(partialRefresh); - return; } + + bool weatherOutdated = false; + + if (m_features.rtc.GetTimestamp() - m_lastSyncTime > 86400) { + weatherOutdated = true; + } + + m_display.setFont(&FreeSansBold9pt7b); + int16_t x, y; + uint16_t w, h; + + m_display.drawBitmap(5, 5, Icons::city, 29, 23, GxEPD_BLACK); + + m_display.setCursor(39, 21); + m_display.print(m_locationCity); + m_display.display(partialRefresh); } void WatchFacePages::Weather::Resync() { uint64_t currentTime = m_features.rtc.GetTimestamp(); - if(m_lastSyncTime == 0 || currentTime - m_lastSyncTime > WEATHER_UPDATE_INTERVAL) { + if(m_lastSyncTime > 0 && currentTime - m_lastSyncTime < WEATHER_UPDATE_INTERVAL) { + return; } - // if(!m_features.wifi.Connect()) { - // return; - // } + if(!m_features.wifi.Connect()) { + return; + } + + HTTPClient client; + client.setConnectTimeout(3000); // 3 second max timeout + + client.begin("http://ip-api.com/json/"); + int httpCode = client.GET(); + if (httpCode != 200) { + m_features.wifi.Disconnect(); + return; + } + + String payload = client.getString(); + client.end(); + + DynamicJsonDocument json(1024); + DeserializationError error = deserializeJson(json, payload); + if (error) { + m_features.wifi.Disconnect(); + return; + } + + if (!json.containsKey("lat") || !json.containsKey("lon")) { + m_features.wifi.Disconnect(); + return; + } + + std::string location = json["city"].as(); + location = location.substr(0, 127); + memcpy(m_locationCity, location.c_str(), location.length()); + m_locationCity[location.length()] = '\0'; + m_locationLat = json["lat"]; + m_locationLon = json["lon"]; + m_features.wifi.Disconnect(); + + m_lastSyncTime = currentTime; } \ No newline at end of file diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h index f84db95..29720f6 100644 --- a/src/WatchFacePages/Weather.h +++ b/src/WatchFacePages/Weather.h @@ -5,6 +5,7 @@ #include "Page.h" #include "../WatchyDisplay.h" #include "../WatchFeatures/WatchFeatures.h" +#include namespace WatchFacePages { @@ -18,12 +19,14 @@ public: void InitBoot() override; void InitWake() override; void DrawPage(bool partialRefresh = false) override; + void Resync(); private: - void Resync(); WatchyDisplay & m_display; WatchFeatures::WatchFeatures & m_features; static RTC_DATA_ATTR uint64_t m_lastSyncTime; static RTC_DATA_ATTR int m_lastCalculatedDay; + static RTC_DATA_ATTR char m_locationCity[128]; + static RTC_DATA_ATTR float m_locationLat, m_locationLon; }; \ No newline at end of file From 5863b0db2c353b232d217b9626f6b40ab28fc348 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 21:27:58 +0300 Subject: [PATCH 17/26] Add #if!def fallback for OPENWEATHERMAP_API_KEY, and compiler warning --- src/config.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/config.h b/src/config.h index ea206b8..ff8ae08 100644 --- a/src/config.h +++ b/src/config.h @@ -34,12 +34,16 @@ #define EEPROM_MAGIC2 0x0d #define EEPROM_VERSION 1 -#define OPENWEATHERMAP_API_KEY "" #include "secrets.h" #if !defined(WIFI_SSID) || !defined(WIFI_PASS) #error "Please define WIFI_SSID and WIFI_PASS in secrets.h" #endif +#if !defined(OPENWEATHERMAP_API_KEY) +#define OPENWEATHERMAP_API_KEY "" // Put the actual key in secrets.h. NOT HERE. +#warning "OPENWEATHERMAP_API_KEY not defined in secrets.h" +#endif + #define DEFAULT_TZ_OFFSET 3600 * 3 #define NTP_SERVER "pool.ntp.org" From 5dea52ebe422038d9b4876d2a173dc681c68e730 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Thu, 1 Jun 2023 21:33:44 +0300 Subject: [PATCH 18/26] Move secrets.h stuff to the bottom so it can override everything --- src/config.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/config.h b/src/config.h index ff8ae08..d243f96 100644 --- a/src/config.h +++ b/src/config.h @@ -34,6 +34,15 @@ #define EEPROM_MAGIC2 0x0d #define EEPROM_VERSION 1 +#define DEFAULT_TZ_OFFSET 3600 * 3 + +#define NTP_SERVER "pool.ntp.org" + +#define UPDATE_INTERVAL 60 // seconds +#define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute + +#define WEATHER_UPDATE_INTERVAL 3600 // seconds + #include "secrets.h" #if !defined(WIFI_SSID) || !defined(WIFI_PASS) #error "Please define WIFI_SSID and WIFI_PASS in secrets.h" @@ -42,13 +51,4 @@ #if !defined(OPENWEATHERMAP_API_KEY) #define OPENWEATHERMAP_API_KEY "" // Put the actual key in secrets.h. NOT HERE. #warning "OPENWEATHERMAP_API_KEY not defined in secrets.h" -#endif - -#define DEFAULT_TZ_OFFSET 3600 * 3 - -#define NTP_SERVER "pool.ntp.org" - -#define UPDATE_INTERVAL 60 // seconds -#define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute - -#define WEATHER_UPDATE_INTERVAL 3600 // seconds \ No newline at end of file +#endif \ No newline at end of file From 33dc87dfd093970909482d73ddc902d7eaf94bc1 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 00:04:53 +0300 Subject: [PATCH 19/26] Use newline geolocation api. make geolocation optional. --- platformio.ini | 1 - src/Icons.h | 126 +++++++++++++++++++++++++++++++++ src/WatchFace.cpp | 4 +- src/WatchFacePages/Weather.cpp | 107 +++++++++++++++++++--------- src/config.h | 5 ++ 5 files changed, 208 insertions(+), 35 deletions(-) diff --git a/platformio.ini b/platformio.ini index ae12590..8b9076c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,6 @@ lib_deps = GxEPD2 Time NTPClient - ArduinoJson lib_ldf_mode = deep+ board_build.partitions = min_spiffs.csv diff --git a/src/Icons.h b/src/Icons.h index f1b9d4d..f1b12c2 100644 --- a/src/Icons.h +++ b/src/Icons.h @@ -20,4 +20,130 @@ namespace Icons 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8 }; + + namespace Weather + { + const unsigned char wind[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 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 unsigned char humidity[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x3f, 0xb0, 0x00, + 0x00, 0x47, 0xb8, 0x00, 0x00, 0xdb, 0x78, 0x00, 0x00, 0xdb, 0x7c, 0x00, 0x00, 0xc2, 0xfc, 0x00, + 0x00, 0xe6, 0xdc, 0x00, 0x01, 0xfd, 0x8c, 0x00, 0x00, 0xfd, 0x2c, 0x00, 0x00, 0xfb, 0x2c, 0x00, + 0x00, 0xfb, 0x8c, 0x00, 0x00, 0x77, 0xd8, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // 50x50 + const unsigned char day_clear[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, + 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x80, 0x7f, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0xf0, 0x78, 0x00, 0x01, 0xc1, 0xfe, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x70, 0x00, 0x01, 0xc1, 0xff, + 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x78, 0x00, 0x01, 0xc1, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x07, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf1, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, + 0x0e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_clear [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0xe7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xe0, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, + 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x1f, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, + 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7f, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + } } \ No newline at end of file diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index 4aed098..0545867 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -18,11 +18,11 @@ void WatchFace::InitBoot() m_features.wifi.Disconnect(); } - static_cast(m_pages[1].get())->Resync(); - for (auto & page : m_pages) { page->InitBoot(); } + + static_cast(m_pages[1].get())->Resync(); } void WatchFace::InitWake() diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index dcc6334..8845c7a 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -4,13 +4,13 @@ #include #include #include +#include #include -#include RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncTime = 0; RTC_DATA_ATTR int WatchFacePages::Weather::m_lastCalculatedDay = 0XFFFFFFFF; -RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLat = 0.0f; -RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLon = 0.0f; +RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLat = DEFAULT_LATITUDE; +RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLon = DEFAULT_LONGITUDE; RTC_DATA_ATTR char WatchFacePages::Weather::m_locationCity[128]; WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) @@ -20,6 +20,7 @@ WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFe void WatchFacePages::Weather::InitBoot() { + memcpy(m_locationCity, DEFAULT_CITY_NAME, sizeof(DEFAULT_CITY_NAME)); } void WatchFacePages::Weather::InitWake() @@ -28,7 +29,6 @@ void WatchFacePages::Weather::InitWake() void WatchFacePages::Weather::DrawPage(bool partialRefresh) { - Serial.println("Weather:DrawPage"); if (m_lastSyncTime == 0) { Resync(); } @@ -54,14 +54,49 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) weatherOutdated = true; } - m_display.setFont(&FreeSansBold9pt7b); + // City name and icon + m_display.setFont(&FreeSans9pt7b); int16_t x, y; uint16_t w, h; m_display.drawBitmap(5, 5, Icons::city, 29, 23, GxEPD_BLACK); - m_display.setCursor(39, 21); + m_display.setCursor(39, 22); m_display.print(m_locationCity); + // Separator + m_display.fillRect(10, 35, DISPLAY_WIDTH - 20, 2, GxEPD_BLACK); + + // Temperature and weather icon + // Separator + m_display.fillRect(10, 118, DISPLAY_WIDTH - 20, 2, GxEPD_BLACK); + + m_display.drawBitmap(0, 120, Icons::Weather::day_clear, 75, 75, GxEPD_BLACK); + m_display.setFont(&FreeSans12pt7b); + + std::string temperature = "-20.5 C"; + + m_display.getTextBounds(temperature.c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(190 - w, 142); + m_display.print(temperature.c_str()); + // Hacky degree symbol + m_display.fillCircle(190 - 23, 129, 3, GxEPD_BLACK); + m_display.fillCircle(190 - 23, 129, 1, GxEPD_WHITE); + + // Wind speed + m_display.drawBitmap(165, 145, Icons::Weather::wind, 30, 30, GxEPD_BLACK); + std::string windSpeed = "99 m/s"; + m_display.setFont(&FreeSans9pt7b); + m_display.getTextBounds(windSpeed.c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(160 - w, 165); + m_display.print(windSpeed.c_str()); + + // Humidity + m_display.drawBitmap(165, 170, Icons::Weather::humidity, 30, 30, GxEPD_BLACK); + std::string humidity = "100"; + m_display.getTextBounds(humidity.c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(160 - w, 190); + m_display.print(humidity.c_str()); + m_display.display(partialRefresh); } @@ -77,37 +112,45 @@ void WatchFacePages::Weather::Resync() return; } - HTTPClient client; - client.setConnectTimeout(3000); // 3 second max timeout + if (DO_GEOLOCATION) { + HTTPClient client; + client.setConnectTimeout(3000); // 3 second max timeout - client.begin("http://ip-api.com/json/"); - int httpCode = client.GET(); - if (httpCode != 200) { - m_features.wifi.Disconnect(); - return; - } + client.begin("http://ip-api.com/line/"); + int httpCode = client.GET(); + if (httpCode != 200) { + m_features.wifi.Disconnect(); + return; + } - String payload = client.getString(); - client.end(); + String payload = client.getString(); + client.end(); + std::string reponse(payload.c_str()); - DynamicJsonDocument json(1024); - DeserializationError error = deserializeJson(json, payload); - if (error) { - m_features.wifi.Disconnect(); - return; + // Split into lines + std::vector lines; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + char delimiter = '\n'; + while ((pos = reponse.find(delimiter, prev)) != std::string::npos) { + lines.push_back(reponse.substr(prev, pos - prev)); + prev = pos + 1; + } + + // Check if we got enough lines + if (lines.size() < 14) { + m_features.wifi.Disconnect(); + return; + } + + std::string location = lines[5]; + location = location.substr(0, 127); + m_locationCity[location.length()] = '\0'; + memcpy(m_locationCity, location.c_str(), location.length()); + m_locationLat = std::stof(lines[7]); + m_locationLon = std::stof(lines[8]); } - if (!json.containsKey("lat") || !json.containsKey("lon")) { - m_features.wifi.Disconnect(); - return; - } - - std::string location = json["city"].as(); - location = location.substr(0, 127); - memcpy(m_locationCity, location.c_str(), location.length()); - m_locationCity[location.length()] = '\0'; - m_locationLat = json["lat"]; - m_locationLon = json["lon"]; m_features.wifi.Disconnect(); m_lastSyncTime = currentTime; diff --git a/src/config.h b/src/config.h index d243f96..6120290 100644 --- a/src/config.h +++ b/src/config.h @@ -42,6 +42,11 @@ #define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute #define WEATHER_UPDATE_INTERVAL 3600 // seconds +#define DO_GEOLOCATION true // if false then use defaults below + +#define DEFAULT_LATITUDE 60.170833 +#define DEFAULT_LONGITUDE 24.9375 +#define DEFAULT_CITY_NAME "Helsinki" #include "secrets.h" #if !defined(WIFI_SSID) || !defined(WIFI_PASS) From e91c194b984ad0a86848e40c259bae0bf8b979b3 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 00:15:59 +0300 Subject: [PATCH 20/26] Fix for Wday when offsetting time --- src/WatchFeatures/RTC.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WatchFeatures/RTC.cpp b/src/WatchFeatures/RTC.cpp index fb40f85..cd0aef3 100644 --- a/src/WatchFeatures/RTC.cpp +++ b/src/WatchFeatures/RTC.cpp @@ -102,6 +102,8 @@ void WatchFeatures::RTC::OffsetTime(tmElements_t & tm, int offsetInSeconds) tm.Hour = hour; tm.Minute = minute; tm.Second = second; + time_t t = makeTime(tm); // make and break to calculate tm.Wday + breakTime(t, tm); } // TODO: implement more advanced wakeup logic, i.e. > 255 seconds that are not a multiple of 60 From e11bcdc9cd6a4ce3d7c0d651f810d21f3153bec8 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 00:19:37 +0300 Subject: [PATCH 21/26] Slight visual tweaks to weather display --- src/WatchFacePages/Weather.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index 8845c7a..b023be4 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -68,9 +68,9 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) // Temperature and weather icon // Separator - m_display.fillRect(10, 118, DISPLAY_WIDTH - 20, 2, GxEPD_BLACK); + m_display.fillRect(10, 116, DISPLAY_WIDTH - 20, 2, GxEPD_BLACK); - m_display.drawBitmap(0, 120, Icons::Weather::day_clear, 75, 75, GxEPD_BLACK); + m_display.drawBitmap(5, 125, Icons::Weather::day_clear, 75, 75, GxEPD_BLACK); m_display.setFont(&FreeSans12pt7b); std::string temperature = "-20.5 C"; From 1b6f89faeab24be36b3563aa3be6b434c7ed15a0 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 18:45:26 +0300 Subject: [PATCH 22/26] Add fetching from wttr.in and moon display --- src/Icons.h | 39 ++++- src/WatchFacePages/Weather.cpp | 286 ++++++++++++++++++++++++++++----- src/WatchFacePages/Weather.h | 17 +- src/WatchFeatures/RTC.cpp | 43 +++++ src/WatchFeatures/RTC.h | 2 + 5 files changed, 344 insertions(+), 43 deletions(-) diff --git a/src/Icons.h b/src/Icons.h index f1b12c2..e50351d 100644 --- a/src/Icons.h +++ b/src/Icons.h @@ -23,6 +23,7 @@ namespace Icons namespace Weather { + // 30x30 const unsigned char wind[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -34,6 +35,7 @@ namespace Icons 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + // 30x30 const unsigned char humidity[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, @@ -45,6 +47,41 @@ namespace Icons 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + // 30x30 + const unsigned char sunrise [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x80, 0x06, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x18, 0x60, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x60, 0x18, 0x00, 0x1e, 0x60, 0x19, 0xe0, + 0x00, 0x60, 0x18, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x70, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // 30x30 + const unsigned char sunset [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x01, 0x80, 0x06, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x1c, 0xe0, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x60, 0x18, 0x00, 0x1e, 0x60, 0x19, 0xe0, + 0x00, 0x60, 0x18, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x78, 0x00, 0x00, 0x7c, 0xf8, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 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 unsigned char noon [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x73, 0x38, 0x00, 0x00, 0xc3, 0x0c, 0x00, + 0x01, 0x83, 0x06, 0x00, 0x03, 0x03, 0x03, 0x00, 0x02, 0x03, 0x01, 0x00, 0x06, 0x03, 0x01, 0x80, + 0x06, 0x03, 0x00, 0x80, 0x04, 0x03, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, + 0x04, 0x00, 0x00, 0x80, 0x06, 0x00, 0x01, 0x80, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x80, 0x06, 0x00, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x3f, 0xf0, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + // 50x50 const unsigned char day_clear[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -96,7 +133,7 @@ namespace Icons 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const unsigned char night_clear [] PROGMEM = { + const unsigned char night_clear [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index b023be4..bcbf2a4 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -6,13 +6,30 @@ #include #include #include +#include +#include +#include RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncTime = 0; RTC_DATA_ATTR int WatchFacePages::Weather::m_lastCalculatedDay = 0XFFFFFFFF; -RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLat = DEFAULT_LATITUDE; -RTC_DATA_ATTR float WatchFacePages::Weather::m_locationLon = DEFAULT_LONGITUDE; +RTC_DATA_ATTR double WatchFacePages::Weather::m_locationLat = DEFAULT_LATITUDE; +RTC_DATA_ATTR double WatchFacePages::Weather::m_locationLon = DEFAULT_LONGITUDE; RTC_DATA_ATTR char WatchFacePages::Weather::m_locationCity[128]; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_sunriseHour; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_sunriseMinute; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_noonHour; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_noonMinute; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_sunsetHour; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_sunsetMinute; +RTC_DATA_ATTR double WatchFacePages::Weather::m_moonPhase; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_moonBitmap[8 * 64]; + +RTC_DATA_ATTR double WatchFacePages::Weather::m_currentTemperature; +RTC_DATA_ATTR float WatchFacePages::Weather::m_currentWindSpeed; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_currentHumidity; +RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_currentWeatherIcon; + WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) : m_display(display), m_features(features) { @@ -37,20 +54,10 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) m_display.fillScreen(GxEPD_WHITE); m_display.setTextColor(GxEPD_BLACK); - if (m_lastSyncTime == 0) { - m_display.setFont(&FreeSans12pt7b); - int16_t x, y; - uint16_t w, h; - m_display.getTextBounds("Have not synced", 0, 0, &x, &y, &w, &h); - m_display.setCursor(DISPLAY_WIDTH / 2 - w / 2, 110); - m_display.print("Have not synced"); - m_display.display(partialRefresh); - return; - } - bool weatherOutdated = false; - if (m_features.rtc.GetTimestamp() - m_lastSyncTime > 86400) { + // If it hasn't synced in 24 hours, assume weather is outdated + if (m_lastSyncTime == 0 || m_features.rtc.GetTimestamp() - m_lastSyncTime > 86400) { weatherOutdated = true; } @@ -60,42 +67,78 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) uint16_t w, h; m_display.drawBitmap(5, 5, Icons::city, 29, 23, GxEPD_BLACK); - m_display.setCursor(39, 22); m_display.print(m_locationCity); // Separator m_display.fillRect(10, 35, DISPLAY_WIDTH - 20, 2, GxEPD_BLACK); + // Moon + m_display.drawBitmap(200 - 64 - 10, 45, m_moonBitmap, 64, 64, GxEPD_BLACK); + m_display.drawCircle(200 - 64 - 10 + 32, 45 + 32, 32, GxEPD_BLACK); + + // Sunrise, solar noon and sunset + m_display.drawBitmap(10, 38, Icons::Weather::sunrise, 30, 30, GxEPD_BLACK); + std::ostringstream sunrise; + sunrise << std::setfill('0') << std::setw(2) << (int)m_sunriseHour << ":" << std::setw(2) << (int)m_sunriseMinute; + m_display.setFont(&FreeSans9pt7b); + m_display.setCursor(45, 56); + m_display.setTextColor(GxEPD_BLACK); + m_display.print(sunrise.str().c_str()); + + m_display.drawBitmap(10, 62, Icons::Weather::noon, 30, 30, GxEPD_BLACK); + std::ostringstream noon; + noon << std::setfill('0') << std::setw(2) << (int)m_noonHour << ":" << std::setw(2) << (int)m_noonMinute; + m_display.setCursor(45, 80); + m_display.print(noon.str().c_str()); + + m_display.drawBitmap(10, 87, Icons::Weather::sunset, 30, 30, GxEPD_BLACK); + std::ostringstream sunset; + sunset << std::setfill('0') << std::setw(2) << (int)m_sunsetHour << ":" << std::setw(2) << (int)m_sunsetMinute; + m_display.setFont(&FreeSans9pt7b); + m_display.setCursor(45, 106); + m_display.print(sunset.str().c_str()); + // Temperature and weather icon - // Separator + // Separator m_display.fillRect(10, 116, DISPLAY_WIDTH - 20, 2, GxEPD_BLACK); - m_display.drawBitmap(5, 125, Icons::Weather::day_clear, 75, 75, GxEPD_BLACK); - m_display.setFont(&FreeSans12pt7b); + if (weatherOutdated) { + m_display.setFont(&FreeSans9pt7b); + m_display.getTextBounds("No Weather Data", 0, 0, &x, &y, &w, &h); + m_display.setCursor(DISPLAY_WIDTH / 2 - w / 2, 162); + m_display.print("No Weather Data"); + } else { + m_display.drawBitmap(5, 125, Icons::Weather::day_clear, 75, 75, GxEPD_BLACK); + m_display.setFont(&FreeSans12pt7b); - std::string temperature = "-20.5 C"; + std::ostringstream temperature; + temperature << (int)m_currentTemperature << " C"; - m_display.getTextBounds(temperature.c_str(), 0, 0, &x, &y, &w, &h); - m_display.setCursor(190 - w, 142); - m_display.print(temperature.c_str()); - // Hacky degree symbol - m_display.fillCircle(190 - 23, 129, 3, GxEPD_BLACK); - m_display.fillCircle(190 - 23, 129, 1, GxEPD_WHITE); + m_display.getTextBounds(temperature.str().c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(190 - w, 142); + m_display.print(temperature.str().c_str()); + // Hacky degree symbol + m_display.fillCircle(190 - 23, 129, 3, GxEPD_BLACK); + m_display.fillCircle(190 - 23, 129, 1, GxEPD_WHITE); - // Wind speed - m_display.drawBitmap(165, 145, Icons::Weather::wind, 30, 30, GxEPD_BLACK); - std::string windSpeed = "99 m/s"; - m_display.setFont(&FreeSans9pt7b); - m_display.getTextBounds(windSpeed.c_str(), 0, 0, &x, &y, &w, &h); - m_display.setCursor(160 - w, 165); - m_display.print(windSpeed.c_str()); + // Wind speed + m_display.drawBitmap(165, 145, Icons::Weather::wind, 30, 30, GxEPD_BLACK); + std::ostringstream windSpeed; + windSpeed << std::fixed << std::setprecision(1) << m_currentWindSpeed << " m/s"; - // Humidity - m_display.drawBitmap(165, 170, Icons::Weather::humidity, 30, 30, GxEPD_BLACK); - std::string humidity = "100"; - m_display.getTextBounds(humidity.c_str(), 0, 0, &x, &y, &w, &h); - m_display.setCursor(160 - w, 190); - m_display.print(humidity.c_str()); + m_display.setFont(&FreeSans9pt7b); + m_display.getTextBounds(windSpeed.str().c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(160 - w, 165); + m_display.print(windSpeed.str().c_str()); + + // Humidity + m_display.drawBitmap(165, 170, Icons::Weather::humidity, 30, 30, GxEPD_BLACK); + std::ostringstream humidity; + humidity << (int)m_currentHumidity; + m_display.getTextBounds(humidity.str().c_str(), 0, 0, &x, &y, &w, &h); + m_display.setCursor(160 - w, 190); + m_display.print(humidity.str().c_str()); + } m_display.display(partialRefresh); } @@ -112,10 +155,11 @@ void WatchFacePages::Weather::Resync() return; } - if (DO_GEOLOCATION) { - HTTPClient client; - client.setConnectTimeout(3000); // 3 second max timeout + HTTPClient client; + client.setConnectTimeout(3000); // 3 second max timeout + // Get geolocation from IP + if (DO_GEOLOCATION) { client.begin("http://ip-api.com/line/"); int httpCode = client.GET(); if (httpCode != 200) { @@ -151,7 +195,167 @@ void WatchFacePages::Weather::Resync() m_locationLon = std::stof(lines[8]); } + // https://wttr.in/60.170833,24.9375?0Q&format=+%x:%t:%h + std::ostringstream url; + url << "http://wttr.in/" << m_locationLat << "," << m_locationLon << "?0Q&format=%x:%t:%h:%w"; + // Grr. wttr.in does a redirect to HTTPS if your agent isn't curl + client.setUserAgent("curl/8.0.1"); + + client.begin(url.str().c_str()); + int httpCode = client.GET(); m_features.wifi.Disconnect(); + if (httpCode != 200) { + return; + } + + String payload = client.getString(); + client.end(); + std::string reponse(payload.c_str()); + // Split on : + std::vector parts; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + char delimiter = ':'; + while ((pos = reponse.find(delimiter, prev)) != std::string::npos) { + parts.push_back(reponse.substr(prev, pos - prev)); + prev = pos + 1; + } + + parts.push_back(reponse.substr(prev)); + + if (parts.size() != 4) { + return; + } + + // Unknown, Cloudy, Fog, Heavy Rain, Heavy Showers, Heavy Snow, Heavy Snow Showers, Light Rain, Light Showers, Light Sleet, Light Sleet Showers, Light Snow, Light Snow Showers, Partly Cloudy, Sunny, Thundery Heavy Rain, Thundery Showers, Thundery Snow Showers, Very Cloudy + std::vector iconLookupTable = {"?", "mm", "=", "///", "//", "**", "/*/", "/", ".", "x", "x/", "*", "*/", "m", "o", "/!/", "!/", "*!*", "mmm"}; + std::string iconName = parts[1]; + for (int i = 0; i < iconLookupTable.size(); i++) { + if (iconName == iconLookupTable[i]) { + m_currentWeatherIcon = i; + } + } + + std::string temperature = parts[2].substr(0, parts[2].length() - 2); + m_currentTemperature = std::stoi(temperature); + + std::string humidity = parts[2].substr(0, parts[2].length() - 1); + m_currentHumidity = std::stoi(humidity); + + std::string windSpeed = parts[3].substr(3, parts[3].length() - 7); + float windSpeedKmh = std::stof(windSpeed); + + // Convert to m/s + m_currentWindSpeed = std::round(windSpeedKmh * 0.277778); + + m_features.wifi.Disconnect(); + Recalc(); m_lastSyncTime = currentTime; +} + +void WatchFacePages::Weather::Recalc() +{ + tmElements_t tm; + m_features.rtc.Get(tm); + + if (m_lastCalculatedDay == tm.Day) { + return; + } + + unsigned int dayOfYear = m_features.rtc.GetDayOfYear(tm); + double denominator = tm.Year / 4 ? 366.0 : 365.0; + double fractionalYear = (2.0 * M_PI / denominator) * (dayOfYear - 1 + ((0 - 12.0) / 24.0)); + + double eqtime = 229.18 * (0.000075 + 0.001868 * cos(fractionalYear) - 0.032077 * sin(fractionalYear) - 0.014615 * cos(2.0 * fractionalYear) - 0.040849 * sin(2.0 * fractionalYear)); + double declination = 0.006918 - 0.399912 * cos(fractionalYear) + 0.070257 * sin(fractionalYear) - 0.006758 * cos(2.0 * fractionalYear) + 0.000907 * sin(2.0 * fractionalYear) - 0.002697 * cos(3.0 * fractionalYear) + 0.00148 * sin(3.0 * fractionalYear); + + const double latitudeRadians = (double)m_locationLat * M_PI / 180.0; + const double longitudeRadians = (double)m_locationLon * M_PI / 180.0; + const double sunriseSunsetAngle = 1.5853349200000815; + + double timeOffset = eqtime + 4.0 * (double)m_locationLon - 60.0; + double trueSolarTime = tm.Hour * 60.0 + tm.Minute + tm.Second / 60.0 + timeOffset; + double hourAngle = acos(cos(sunriseSunsetAngle) / (cos(latitudeRadians) * cos(declination)) - tan(latitudeRadians) * tan(declination)); + hourAngle = hourAngle * 180.0 / M_PI; + double sunrise = 720 - 4.0 * ((double)m_locationLon + hourAngle) - eqtime; + double sunset = 720 - 4.0 * ((double)m_locationLon - hourAngle) - eqtime; + double noon = 720 - 4.0 * ((double)m_locationLon) - eqtime; + + sunrise += m_features.storage.GetTzOffset() / 60; + sunset += m_features.storage.GetTzOffset() / 60; + noon += m_features.storage.GetTzOffset() / 60; + + m_sunriseHour = sunrise / 60; + m_sunriseMinute = sunrise - m_sunriseHour * 60; + m_sunsetHour = sunset / 60; + m_sunsetMinute = sunset - m_sunsetHour * 60; + m_noonHour = noon / 60; + m_noonMinute = noon - m_noonHour * 60; + + tmElements_t newMoon; + newMoon.Year = 2023 - 1970; + newMoon.Month = 5; + newMoon.Day = 19; + + unsigned int daysDifference = m_features.rtc.DaysDifference(newMoon, tm); + m_moonPhase = fmod((double)daysDifference, 29.530588853) / 29.530588853; + + // Draw a 1-bit bitmap with the moon phase + bool pixels[64 * 64]; + for (int i = 0; i < 64 * 64; i++) { + pixels[i] = false; + } + + for (int x = 0; x < 64; x++) { + for (int y = 0; y < 64; y++) { + float distance = sqrt(powf(fabsf(x - 32), 2) + powf(fabsf(y - 32), 2)); + if (distance < 32) { + float inclination = asinf(((float)y - 32.0f) / 32.0f); + float azimuth = acosf((float)(x - 32) / (-32.0f * cosf(inclination))); + + azimuth += M_PI; + + azimuth += (m_moonPhase) * M_PI * 2.0f; + while (azimuth > M_PI * 2.0f) { + azimuth -= M_PI * 2.0f; + } + + while (azimuth < 0) { + azimuth += M_PI * 2.0f; + } + + if (azimuth > M_PI) { + pixels[x + y * 64] = true; + } + } else { + pixels[x + y * 64] = false; + } + } + } + + // Needs to be split into two parts because pio does too aggressive optimisation + for (unsigned int y = 0; y < 32; y++) { + for (unsigned int x = 0; x < 8; x++) { + uint8_t value = 0; + for (unsigned int i = 0; i < 8; i++) { + value |= pixels[(x * 8 + i) + (y * 64)] << (7 - i); + } + + m_moonBitmap[x + y * 8] = value; + } + } + + for (unsigned int y = 32; y < 64; y++) { + for (unsigned int x = 0; x < 8; x++) { + uint8_t value = 0; + for (unsigned int i = 0; i < 8; i++) { + value |= pixels[(x * 8 + i) + (y * 64)] << (7 - i); + } + + m_moonBitmap[x + y * 8] = value; + } + } + + m_lastCalculatedDay = tm.Day; } \ No newline at end of file diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h index 29720f6..7c8ebee 100644 --- a/src/WatchFacePages/Weather.h +++ b/src/WatchFacePages/Weather.h @@ -22,11 +22,26 @@ public: void Resync(); private: + void Recalc(); // Offline daily ephemeris like sunrise/sunset WatchyDisplay & m_display; WatchFeatures::WatchFeatures & m_features; static RTC_DATA_ATTR uint64_t m_lastSyncTime; static RTC_DATA_ATTR int m_lastCalculatedDay; static RTC_DATA_ATTR char m_locationCity[128]; - static RTC_DATA_ATTR float m_locationLat, m_locationLon; + static RTC_DATA_ATTR double m_locationLat, m_locationLon; + + static RTC_DATA_ATTR uint8_t m_sunriseHour; + static RTC_DATA_ATTR uint8_t m_sunriseMinute; + static RTC_DATA_ATTR uint8_t m_noonHour; + static RTC_DATA_ATTR uint8_t m_noonMinute; + static RTC_DATA_ATTR uint8_t m_sunsetHour; + static RTC_DATA_ATTR uint8_t m_sunsetMinute; + static RTC_DATA_ATTR double m_moonPhase; + static RTC_DATA_ATTR uint8_t m_moonBitmap[8 * 64]; + + static RTC_DATA_ATTR double m_currentTemperature; + static RTC_DATA_ATTR float m_currentWindSpeed; + static RTC_DATA_ATTR uint8_t m_currentHumidity; + static RTC_DATA_ATTR uint8_t m_currentWeatherIcon; }; \ No newline at end of file diff --git a/src/WatchFeatures/RTC.cpp b/src/WatchFeatures/RTC.cpp index cd0aef3..de5048d 100644 --- a/src/WatchFeatures/RTC.cpp +++ b/src/WatchFeatures/RTC.cpp @@ -106,6 +106,49 @@ void WatchFeatures::RTC::OffsetTime(tmElements_t & tm, int offsetInSeconds) breakTime(t, tm); } +unsigned int WatchFeatures::RTC::GetDayOfYear(tmElements_t & tm) +{ + unsigned int dayOfYear = 1; + for (int i = 1; i < tm.Month; i++) { + switch (i) { + case 2: + dayOfYear += (tm.Year % 4 == 0) ? 29 : 28; + break; + case 4: + case 6: + case 9: + case 11: + dayOfYear += 30; + break; + default: + dayOfYear += 31; + break; + } + } + + dayOfYear += tm.Day; + return dayOfYear; +} + +unsigned int WatchFeatures::RTC::DaysDifference(tmElements_t & tm1, tmElements_t & tm2) +{ + unsigned int dayOfYear1 = GetDayOfYear(tm1); + unsigned int dayOfYear2 = GetDayOfYear(tm2); + unsigned int days = 0; + + if (tm1.Year == tm2.Year) { + days = dayOfYear2 - dayOfYear1; + } else { + days = 365 - dayOfYear1 + dayOfYear2; + for (int i = tm1.Year + 1; i < tm2.Year; i++) { + days += (i % 4 == 0) ? 366 : 365; + } + } + + return days; +} + + // TODO: implement more advanced wakeup logic, i.e. > 255 seconds that are not a multiple of 60 bool WatchFeatures::RTC::CheckWakeup() { diff --git a/src/WatchFeatures/RTC.h b/src/WatchFeatures/RTC.h index 66110dd..a22fa37 100644 --- a/src/WatchFeatures/RTC.h +++ b/src/WatchFeatures/RTC.h @@ -22,6 +22,8 @@ public: void Resync(); // Resync the timer cycle, both initially and after RTC resync static void OffsetTime(tmElements_t & tm, int offsetInSeconds); + static unsigned int GetDayOfYear(tmElements_t & tm); + static unsigned int DaysDifference(tmElements_t & tm1, tmElements_t & tm2); private: Rtc_Pcf8563 m_rtcPcf; From aa8a9193b0a6706e271073ae82e4b088bd31cdb8 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 21:05:51 +0300 Subject: [PATCH 23/26] Add icons for current weather, split weather icons into seperate file --- src/Icons.h | 165 +-------------------------------- src/WatchFacePages/Weather.cpp | 81 ++++++++++++++-- src/WatchFacePages/Weather.h | 2 +- 3 files changed, 74 insertions(+), 174 deletions(-) diff --git a/src/Icons.h b/src/Icons.h index e50351d..974a0f9 100644 --- a/src/Icons.h +++ b/src/Icons.h @@ -20,167 +20,6 @@ namespace Icons 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xfe, 0x38, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8, 0x06, 0x07, 0xff, 0xf8 }; +} - namespace Weather - { - // 30x30 - const unsigned char wind[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, - 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - // 30x30 - const unsigned char humidity[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x3f, 0xb0, 0x00, - 0x00, 0x47, 0xb8, 0x00, 0x00, 0xdb, 0x78, 0x00, 0x00, 0xdb, 0x7c, 0x00, 0x00, 0xc2, 0xfc, 0x00, - 0x00, 0xe6, 0xdc, 0x00, 0x01, 0xfd, 0x8c, 0x00, 0x00, 0xfd, 0x2c, 0x00, 0x00, 0xfb, 0x2c, 0x00, - 0x00, 0xfb, 0x8c, 0x00, 0x00, 0x77, 0xd8, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - // 30x30 - const unsigned char sunrise [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x01, 0x80, 0x06, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x18, 0x60, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x60, 0x18, 0x00, 0x1e, 0x60, 0x19, 0xe0, - 0x00, 0x60, 0x18, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x70, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - // 30x30 - const unsigned char sunset [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, - 0x01, 0x80, 0x06, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x1c, 0xe0, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x60, 0x18, 0x00, 0x1e, 0x60, 0x19, 0xe0, - 0x00, 0x60, 0x18, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x78, 0x00, 0x00, 0x7c, 0xf8, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, - 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 unsigned char noon [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x73, 0x38, 0x00, 0x00, 0xc3, 0x0c, 0x00, - 0x01, 0x83, 0x06, 0x00, 0x03, 0x03, 0x03, 0x00, 0x02, 0x03, 0x01, 0x00, 0x06, 0x03, 0x01, 0x80, - 0x06, 0x03, 0x00, 0x80, 0x04, 0x03, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, - 0x04, 0x00, 0x00, 0x80, 0x06, 0x00, 0x01, 0x80, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x01, 0x80, 0x06, 0x00, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x3f, 0xf0, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - // 50x50 - const unsigned char day_clear[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, - 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x7f, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x3e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, - 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0xf0, 0x78, 0x00, 0x01, 0xc1, 0xfe, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x70, 0x00, 0x01, 0xc1, 0xff, - 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x78, 0x00, 0x01, 0xc1, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, - 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x07, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x3e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf1, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, - 0x0e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_clear [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0xe7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xe0, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, - 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0x80, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x1f, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, - 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7f, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0xff, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - } -} \ No newline at end of file +#include "WeatherIcons.h" \ No newline at end of file diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index bcbf2a4..2cc1940 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -28,7 +28,7 @@ RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_moonBitmap[8 * 64]; RTC_DATA_ATTR double WatchFacePages::Weather::m_currentTemperature; RTC_DATA_ATTR float WatchFacePages::Weather::m_currentWindSpeed; RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_currentHumidity; -RTC_DATA_ATTR uint8_t WatchFacePages::Weather::m_currentWeatherIcon; +RTC_DATA_ATTR char WatchFacePages::Weather::m_currentWeatherCondition[4]; WatchFacePages::Weather::Weather(WatchyDisplay & display, WatchFeatures::WatchFeatures & features) : m_display(display), m_features(features) @@ -108,7 +108,75 @@ void WatchFacePages::Weather::DrawPage(bool partialRefresh) m_display.setCursor(DISPLAY_WIDTH / 2 - w / 2, 162); m_display.print("No Weather Data"); } else { - m_display.drawBitmap(5, 125, Icons::Weather::day_clear, 75, 75, GxEPD_BLACK); + // Unknown, Cloudy, Fog, Heavy Rain, Heavy Showers, Heavy Snow, Heavy Snow Showers, Light Rain, Light Showers, Light Sleet, Light Sleet Showers, Light Snow, Light Snow Showers, Partly Cloudy, Sunny, Thundery Heavy Rain, Thundery Showers, Thundery Snow Showers, Very Cloudy + std::vector iconLookupCondition = {"?", "mm", "=", "///", "//", "**", "/*/", "/", ".", "x", "x/", "*", "*/", "m", "o", "/!/", "!/", "*!*", "mmm"}; + + std::string iconName = m_currentWeatherCondition; + int iconNum = 0; + for (int i = 0; i < iconLookupCondition.size(); i++) { + if (iconName == iconLookupCondition[i]) { + iconNum = i; + break; + } + } + + // Get current time to see if it's day or night + tmElements_t currentTime; + m_features.rtc.Get(currentTime); + m_features.rtc.OffsetTime(currentTime, m_features.storage.GetTzOffset()); + + const unsigned char * iconBitmap = nullptr; + if (currentTime.Hour >= m_sunriseHour && currentTime.Hour < m_sunsetHour) { + const std::vector dayIconLookupBitmap = { + Icons::Weather::alien, + Icons::Weather::day_cloudy, + Icons::Weather::day_fog, + Icons::Weather::day_rain_wind, + Icons::Weather::day_rain_mix, + Icons::Weather::day_snow, + Icons::Weather::day_snow_wind, + Icons::Weather::day_rain, + Icons::Weather::day_showers, + Icons::Weather::day_sleet, + Icons::Weather::day_sleet, + Icons::Weather::day_snow, + Icons::Weather::day_snow, + Icons::Weather::day_cloudy, + Icons::Weather::day_sunny, + Icons::Weather::day_thunderstorm, + Icons::Weather::day_thunderstorm, + Icons::Weather::day_snow_thunderstorm, + Icons::Weather::cloudy + }; + + iconBitmap = dayIconLookupBitmap[iconNum]; + } else { + const std::vector nightIconLookupBitmap = { + Icons::Weather::alien, + Icons::Weather::night_cloudy, + Icons::Weather::night_fog, + Icons::Weather::night_rain_wind, + Icons::Weather::night_rain_mix, + Icons::Weather::night_snow, + Icons::Weather::night_snow_wind, + Icons::Weather::night_rain, + Icons::Weather::night_showers, + Icons::Weather::night_sleet, + Icons::Weather::night_sleet, + Icons::Weather::night_snow, + Icons::Weather::night_snow, + Icons::Weather::night_cloudy, + Icons::Weather::night_clear, + Icons::Weather::night_thunderstorm, + Icons::Weather::night_thunderstorm, + Icons::Weather::night_snow_thunderstorm, + Icons::Weather::cloudy + }; + + iconBitmap = nightIconLookupBitmap[iconNum]; + } + + m_display.drawBitmap(5, 125, iconBitmap, 75, 75, GxEPD_BLACK); m_display.setFont(&FreeSans12pt7b); std::ostringstream temperature; @@ -227,14 +295,7 @@ void WatchFacePages::Weather::Resync() return; } - // Unknown, Cloudy, Fog, Heavy Rain, Heavy Showers, Heavy Snow, Heavy Snow Showers, Light Rain, Light Showers, Light Sleet, Light Sleet Showers, Light Snow, Light Snow Showers, Partly Cloudy, Sunny, Thundery Heavy Rain, Thundery Showers, Thundery Snow Showers, Very Cloudy - std::vector iconLookupTable = {"?", "mm", "=", "///", "//", "**", "/*/", "/", ".", "x", "x/", "*", "*/", "m", "o", "/!/", "!/", "*!*", "mmm"}; - std::string iconName = parts[1]; - for (int i = 0; i < iconLookupTable.size(); i++) { - if (iconName == iconLookupTable[i]) { - m_currentWeatherIcon = i; - } - } + memcpy(m_currentWeatherCondition, parts[0].c_str(), parts[0].length()); std::string temperature = parts[2].substr(0, parts[2].length() - 2); m_currentTemperature = std::stoi(temperature); diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h index 7c8ebee..c0f77bc 100644 --- a/src/WatchFacePages/Weather.h +++ b/src/WatchFacePages/Weather.h @@ -43,5 +43,5 @@ private: static RTC_DATA_ATTR double m_currentTemperature; static RTC_DATA_ATTR float m_currentWindSpeed; static RTC_DATA_ATTR uint8_t m_currentHumidity; - static RTC_DATA_ATTR uint8_t m_currentWeatherIcon; + static RTC_DATA_ATTR char m_currentWeatherCondition[4]; }; \ No newline at end of file From f7094077f775d9274d1a88b6f9848781dff71bc0 Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 21:14:23 +0300 Subject: [PATCH 24/26] Add WeatherIcons.h --- src/WeatherIcons.h | 1469 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1469 insertions(+) create mode 100644 src/WeatherIcons.h diff --git a/src/WeatherIcons.h b/src/WeatherIcons.h new file mode 100644 index 0000000..aba789b --- /dev/null +++ b/src/WeatherIcons.h @@ -0,0 +1,1469 @@ +#pragma once + +namespace Icons +{ + namespace Weather + { + // 30x30 + const unsigned char wind[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // 30x30 + const unsigned char humidity[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x3f, 0xb0, 0x00, + 0x00, 0x47, 0xb8, 0x00, 0x00, 0xdb, 0x78, 0x00, 0x00, 0xdb, 0x7c, 0x00, 0x00, 0xc2, 0xfc, 0x00, + 0x00, 0xe6, 0xdc, 0x00, 0x01, 0xfd, 0x8c, 0x00, 0x00, 0xfd, 0x2c, 0x00, 0x00, 0xfb, 0x2c, 0x00, + 0x00, 0xfb, 0x8c, 0x00, 0x00, 0x77, 0xd8, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // 30x30 + const unsigned char sunrise [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x80, 0x06, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x18, 0x60, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x60, 0x18, 0x00, 0x1e, 0x60, 0x19, 0xe0, + 0x00, 0x60, 0x18, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x70, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // 30x30 + const unsigned char sunset [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x01, 0x80, 0x06, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x1c, 0xe0, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x60, 0x18, 0x00, 0x1e, 0x60, 0x19, 0xe0, + 0x00, 0x60, 0x18, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x78, 0x00, 0x00, 0x7c, 0xf8, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 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 unsigned char noon [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x73, 0x38, 0x00, 0x00, 0xc3, 0x0c, 0x00, + 0x01, 0x83, 0x06, 0x00, 0x03, 0x03, 0x03, 0x00, 0x02, 0x03, 0x01, 0x00, 0x06, 0x03, 0x01, 0x80, + 0x06, 0x03, 0x00, 0x80, 0x04, 0x03, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, + 0x04, 0x00, 0x00, 0x80, 0x06, 0x00, 0x01, 0x80, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x80, 0x06, 0x00, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x3f, 0xf0, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + const unsigned char alien [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x3f, 0xff, 0xff, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0f, 0xff, 0xfe, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0xff, 0xf8, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0xff, 0xf0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x7f, 0xc0, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x3f, 0xc0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x1f, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x80, 0x0f, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x0f, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x0e, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x03, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x8e, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_cloudy [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x81, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x81, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x01, 0xff, 0xe7, 0x80, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x0f, 0x00, 0x00, + 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + + // Unknown, Cloudy, Fog, Heavy Rain, Heavy Showers, Heavy Snow, Heavy Snow Showers, Light Rain, Light Showers, Light Sleet, Light Sleet Showers, Light Snow, Light Snow Showers, Partly Cloudy, Sunny, Thundery Heavy Rain, Thundery Showers, Thundery Snow Showers, Very Cloudy + + const unsigned char day_fog [] PROGMEM = { + 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x80, 0x01, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xf9, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xff, 0xc0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x1f, 0xc0, 0x03, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x80, 0x07, 0xe0, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0xf0, + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0xf8, 0x00, 0xf0, 0x3f, 0xc0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x78, 0x00, 0xf8, + 0x7f, 0xc0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7c, 0x00, 0xf8, 0x7f, 0xc0, 0x00, 0x00, 0xf8, 0x00, + 0x00, 0x7f, 0xc0, 0xf0, 0x3f, 0x80, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x3f, 0xf8, 0xf0, 0x00, 0x00, + 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x3f, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x3f, + 0xff, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, + 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, + 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_rain_wind [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xdf, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc1, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0xc1, 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x07, 0xc0, 0x07, 0xc3, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0xc1, 0xfe, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x01, 0xff, 0xe7, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x00, 0xe0, 0x18, 0x00, 0x3e, 0x0f, 0x00, 0x00, + 0x07, 0xe0, 0x01, 0xf0, 0x3c, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x03, 0xf0, 0x03, 0xf0, 0x7c, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x03, 0xe0, 0xfc, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x07, 0xc1, 0xf8, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x0f, 0xc1, 0xf0, 0x7f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x1f, 0x83, 0xe0, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x07, + 0xc1, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x0f, 0xc1, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x1f, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1f, 0x07, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7e, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0xfc, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x80, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc1, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0xe0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_showers [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc3, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x81, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x03, 0xc0, 0x07, 0x83, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x01, 0xff, 0xef, 0x80, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x03, 0x80, 0x01, 0xc0, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x80, 0x07, 0xc0, 0x03, 0xc0, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x03, 0xc0, 0x1e, 0x3f, 0x00, 0x00, 0x07, 0x80, 0x07, 0x80, + 0x03, 0xc0, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x07, 0x80, 0x03, 0xc0, 0x7e, 0x0f, 0x00, 0x00, + 0x03, 0xe0, 0x07, 0x00, 0x03, 0x80, 0xfc, 0x06, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x06, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x0f, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x0f, 0x00, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x1f, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_rain [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3e, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x9f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x07, 0xc0, 0x07, 0xc3, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x81, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x01, 0xff, 0xef, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x03, 0x83, 0xc1, 0xc0, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x83, 0xc3, 0xc0, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x07, 0x83, 0xc3, 0xc0, 0x1e, 0x3f, 0x00, 0x00, 0x07, 0x80, 0x07, 0x87, + 0xc3, 0xc0, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x0f, 0x87, 0x87, 0xc0, 0x7e, 0x0f, 0x00, 0x00, + 0x07, 0xe0, 0x0f, 0x87, 0x87, 0x80, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x0f, 0x0f, 0x87, 0x81, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x0f, 0x0f, 0x8f, 0x8f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x1f, 0x0f, 0x0f, 0x9f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x1e, 0x0f, 0x0f, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x1e, 0x1f, 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1e, 0x1e, + 0x1f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x1e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x1e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3e, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x3c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x7c, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_rain_mix [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x9f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc3, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfc, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x7f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x00, + 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0x80, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x07, 0xc0, 0x07, 0x83, + 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x03, 0xfc, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x03, 0xff, 0xcf, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x03, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x03, 0x80, 0x03, 0xc0, 0x1e, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x03, 0xc0, 0x1e, 0x3f, 0x00, 0x00, 0x0f, 0x80, 0x07, 0x80, + 0x07, 0xc0, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x07, 0x80, 0x07, 0x80, 0x7c, 0x0e, 0x00, 0x00, + 0x07, 0xe0, 0x07, 0x00, 0x03, 0x80, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x04, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x1e, 0x0f, 0x0e, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x1e, 0x1f, 0x0f, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x1e, 0x1f, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x1e, + 0x06, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x38, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_snow [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x03, 0xc0, 0x07, 0x83, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x01, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0xc0, 0x00, 0x01, 0xff, 0xef, 0x80, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x07, 0x80, 0x00, 0x06, + 0x00, 0x00, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, + 0x03, 0xe0, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x0e, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x04, 0x00, 0x04, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x0f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x0f, 0x00, 0x0f, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x0f, 0x00, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_snow_wind [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x03, 0xc0, 0x07, 0x83, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x01, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0xc0, 0x00, 0x01, 0xff, 0xef, 0x80, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x07, 0x80, 0x00, 0x06, + 0x00, 0x00, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, + 0x03, 0xe0, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x0e, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x04, 0x00, 0x04, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x0f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x0f, 0x00, 0x0f, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x0f, 0x00, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_sleet [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0x9f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x81, 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x07, 0xc0, 0x07, 0xc3, + 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x81, 0xfe, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x01, 0xff, 0xe7, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x0f, 0x00, 0x00, + 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x04, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0e, 0x0f, 0x0e, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x1e, 0x1f, 0x0f, 0x1f, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x1e, 0x1f, 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0e, 0x1e, + 0x06, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x38, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char cloudy [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x81, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xf0, 0x7f, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0x80, 0x0f, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x80, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, + 0x07, 0xc0, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0xc0, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x00, 0x01, 0xe0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x01, 0xf8, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0xff, 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, + 0xf8, 0x00, 0x00, 0xff, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0xff, 0xe0, 0x03, + 0x80, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x80, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x07, 0x80, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x07, 0x80, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x1f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xfe, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x1c, 0xfc, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf8, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xc0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, + 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_storm_showers [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xdf, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, + 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x81, 0xfe, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0xff, 0x80, 0x00, 0x01, 0xff, 0xe7, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x7f, 0x80, 0x01, 0xe0, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x01, 0xe0, 0x1f, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0xff, 0x00, 0x03, 0xe0, 0x1e, 0x3f, 0x00, 0x00, 0x0f, 0x80, 0xfe, 0x00, + 0x03, 0xe0, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc1, 0xfe, 0x00, 0x03, 0xc0, 0x7e, 0x0f, 0x00, 0x00, + 0x07, 0xe1, 0xfc, 0x00, 0x01, 0xc0, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xfb, 0xfc, 0x00, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x06, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf8, 0x0f, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x0f, 0x00, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x0f, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x0f, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x8f, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xc0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_thunderstorm [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0x9f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, 0xfc, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x07, 0xc0, 0x07, 0xc3, + 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x81, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0x7f, 0x80, 0x00, 0x01, 0xff, 0xe7, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x7f, 0x83, 0xc1, 0xc0, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0xff, 0x03, 0xc3, 0xc0, 0x1e, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0xff, 0x07, 0xc3, 0xc0, 0x1e, 0x3f, 0x00, 0x00, 0x07, 0x80, 0xfe, 0x07, + 0xc3, 0xc0, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc1, 0xfe, 0x07, 0x87, 0xc0, 0x7e, 0x0f, 0x00, 0x00, + 0x03, 0xe1, 0xfc, 0x07, 0x87, 0x80, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xfb, 0xfc, 0x0f, 0x87, 0x81, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x0f, 0x07, 0x8f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf8, 0x0f, 0x0f, 0x9f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x0f, 0x0f, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x1f, 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x1e, + 0x1f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x9e, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0x1e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x3e, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x3c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7c, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xc0, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_snow_thunderstorm [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xdf, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc1, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x1f, 0x80, + 0x07, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x0f, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x03, + 0xe0, 0x00, 0x07, 0xc0, 0x07, 0x83, 0xfe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, + 0xfe, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x03, 0xc0, 0x07, 0xc3, 0xfe, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x03, 0xfe, 0x07, 0x81, 0xfe, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xff, 0x87, 0x80, 0x00, 0x00, + 0x00, 0xff, 0x80, 0x00, 0x01, 0xff, 0xe7, 0x80, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x01, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x7f, 0x80, 0x00, 0x00, 0x1f, 0x1c, 0x00, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x00, 0x1f, 0x3e, + 0x00, 0x00, 0x0f, 0x80, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x0f, 0x80, 0xfe, 0x06, + 0x00, 0x00, 0x3e, 0x1f, 0x00, 0x00, 0x07, 0xc1, 0xfe, 0x0f, 0x00, 0x00, 0x7e, 0x0f, 0x00, 0x00, + 0x07, 0xe1, 0xfc, 0x0f, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xfb, 0xfc, 0x0e, 0x00, 0x01, + 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf8, 0x00, 0x0f, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x0f, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, + 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xc0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char day_sunny [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1f, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x0e, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, + 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x80, 0x7f, 0xc0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x78, 0x00, 0x03, 0xc0, 0xfc, 0x00, 0x00, 0x00, 0x1f, + 0xf0, 0x78, 0x00, 0x03, 0xc1, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xf0, 0xf8, 0x00, 0x03, 0xc1, 0xff, + 0x00, 0x00, 0x00, 0x1f, 0xf0, 0x78, 0x00, 0x03, 0xc1, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x78, + 0x00, 0x03, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x07, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x80, 0xff, 0xe0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x0e, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, + 0x0e, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_cloudy [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x83, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_fog [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0xfb, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1f, 0xc3, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xff, 0xff, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x01, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0xff, 0xfe, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x7f, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x1f, 0x80, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x0f, + 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x07, 0xc0, 0x7f, 0x80, 0x00, 0x00, 0x00, + 0x01, 0xf0, 0x00, 0x03, 0xe0, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x03, 0xe0, 0x0f, + 0xe0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x01, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xe0, + 0x00, 0x01, 0xff, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x01, 0xff, 0xc7, 0xc0, 0x00, + 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xc0, 0x00, 0x00, + 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x01, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_rain_wind [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x83, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xfc, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x01, 0xfc, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3f, + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x80, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x80, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x07, 0xfc, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0xcf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x0f, + 0xe0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x01, 0x80, 0x30, 0x00, 0x7c, 0x00, 0x00, + 0x00, 0x0f, 0x80, 0x03, 0xc0, 0x78, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x07, 0xc0, 0xf8, + 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x0f, 0xc1, 0xf8, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x03, + 0xfc, 0x1f, 0x83, 0xf0, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x3f, 0x07, 0xe0, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x7e, 0x0f, 0xc1, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, + 0x0f, 0x83, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x07, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x3f, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x1f, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x01, 0xf8, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0xf0, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x03, + 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x81, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_showers [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x87, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x03, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x07, 0x00, 0x03, 0x80, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x0f, + 0x00, 0x0f, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0x00, 0x0f, 0x80, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x0e, 0x00, 0x07, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x08, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xfe, 0x00, 0x1e, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x3e, 0x00, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x3c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x3c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x7c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_rain [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x83, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x00, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x07, 0x07, 0x07, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x07, 0x87, 0x80, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x0f, 0x0f, 0x87, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x0f, + 0x0f, 0x0f, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0x0f, 0x0f, 0x80, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x1f, 0x0f, 0x0f, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x1e, 0x1f, 0x0f, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x1e, 0x1e, 0x1f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xfe, 0x3e, 0x1e, 0x1e, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0x3e, 0x1e, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3c, 0x3e, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7c, + 0x3c, 0x3e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x7c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x78, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_rain_mix [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x03, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xf8, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x3f, + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x80, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x0f, + 0xc0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x0f, 0x00, 0x07, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x3c, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x00, 0x0f, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x0f, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1e, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x0e, 0x00, 0x07, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x08, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xfe, 0x38, 0x3c, 0x1c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0x3c, 0x3c, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3c, 0x3c, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x18, + 0x3c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xf0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_snow [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x03, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x1e, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x1c, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xfe, 0x1c, 0x00, 0x1c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1e, 0x00, 0x1e, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x1c, 0x00, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_snow_wind [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x03, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x1c, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x3e, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x1c, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x08, 0x00, 0x08, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xfe, 0x1c, 0x00, 0x1c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3e, 0x00, 0x3e, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x1c, 0x00, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_sleet [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc7, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xfc, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, + 0x00, 0x07, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x00, 0x07, 0xff, 0xcf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x01, + 0xfe, 0x1c, 0x1c, 0x1c, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0x3e, 0x1e, 0x3f, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x3c, 0x3c, 0x1e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, + 0x3c, 0x1c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0x70, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf0, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_storm_showers [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x03, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3f, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xc0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0xff, 0x00, 0x03, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x01, 0xfe, 0x00, 0x03, 0xc0, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x01, 0xfe, 0x00, 0x07, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x03, 0xfc, + 0x00, 0x07, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x83, 0xfc, 0x00, 0x07, 0x80, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc3, 0xf8, 0x00, 0x03, 0x81, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe7, 0xf8, 0x00, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x0c, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xf0, 0x1e, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x1e, 0x00, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x1e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, + 0x3e, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x1c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0xfe, 0x1c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf8, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x80, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_thunderstorm [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xff, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x87, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xf8, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0xfe, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3e, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0xff, 0x07, 0x07, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x01, 0xfe, 0x07, 0x87, 0x80, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x01, 0xfe, 0x0f, 0x87, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x03, 0xfc, + 0x0f, 0x0f, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x83, 0xfc, 0x0f, 0x0f, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc3, 0xf8, 0x1f, 0x0f, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe7, 0xf8, 0x1f, 0x0f, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x1e, 0x1f, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xf0, 0x1e, 0x1e, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x3e, 0x1e, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x3c, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, + 0x3c, 0x3e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0xfe, 0x7c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x78, 0x7c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf8, 0xf8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0xf8, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x81, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_snow_thunderstorm [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xbf, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x83, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xf8, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x01, 0xfc, 0x00, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf8, 0x00, 0x7e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x3f, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xc0, 0x00, 0x0f, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0f, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x07, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x00, 0x03, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x03, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x07, + 0xc0, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1e, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x1f, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x1f, 0x03, 0xfc, + 0x0c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0f, 0x83, 0xfc, 0x1e, 0x00, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x0f, 0xc3, 0xf8, 0x1e, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xe7, 0xf8, 0x1c, 0x00, + 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xf0, 0x00, 0x1c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x1e, 0x3f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0xfe, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 unsigned char night_clear [] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x03, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xf0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x01, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, + 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x1f, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xe0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, + 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7f, 0x80, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfb, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + } +} \ No newline at end of file From 74695597cf02f3f0ce52851fd90e2ba680025abe Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 21:15:09 +0300 Subject: [PATCH 25/26] Removed unused openweathermap stuff now using wttr.in --- src/config.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/config.h b/src/config.h index 6120290..8b9d793 100644 --- a/src/config.h +++ b/src/config.h @@ -51,9 +51,4 @@ #include "secrets.h" #if !defined(WIFI_SSID) || !defined(WIFI_PASS) #error "Please define WIFI_SSID and WIFI_PASS in secrets.h" -#endif - -#if !defined(OPENWEATHERMAP_API_KEY) -#define OPENWEATHERMAP_API_KEY "" // Put the actual key in secrets.h. NOT HERE. -#warning "OPENWEATHERMAP_API_KEY not defined in secrets.h" #endif \ No newline at end of file From 8d6edca411e4e0db7e1f882373810cc25ab1e89f Mon Sep 17 00:00:00 2001 From: Lewis Jackson <> Date: Fri, 2 Jun 2023 22:24:00 +0300 Subject: [PATCH 26/26] Added backoff time in case weather updates fail --- src/WatchFace.cpp | 6 ++++-- src/WatchFacePages/Weather.cpp | 20 +++++++++++++++----- src/WatchFacePages/Weather.h | 1 + src/config.h | 1 + 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/WatchFace.cpp b/src/WatchFace.cpp index 0545867..65df974 100644 --- a/src/WatchFace.cpp +++ b/src/WatchFace.cpp @@ -121,8 +121,10 @@ void WatchFace::DrawWatchFace(bool partialRefresh) m_pages[m_watchFacePage]->DrawPage(partialRefresh); - // Resync weather on matter what - static_cast(m_pages[1].get())->Resync(); + // Resync weather in background + if (m_watchFacePage != 1) { + static_cast(m_pages[1].get())->Resync(); + } } void WatchFace::SetupVolatileMenuStuff() diff --git a/src/WatchFacePages/Weather.cpp b/src/WatchFacePages/Weather.cpp index 2cc1940..c4641ab 100644 --- a/src/WatchFacePages/Weather.cpp +++ b/src/WatchFacePages/Weather.cpp @@ -11,6 +11,7 @@ #include RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncTime = 0; +RTC_DATA_ATTR uint64_t WatchFacePages::Weather::m_lastSyncAttemptTime = 0; RTC_DATA_ATTR int WatchFacePages::Weather::m_lastCalculatedDay = 0XFFFFFFFF; RTC_DATA_ATTR double WatchFacePages::Weather::m_locationLat = DEFAULT_LATITUDE; RTC_DATA_ATTR double WatchFacePages::Weather::m_locationLon = DEFAULT_LONGITUDE; @@ -46,9 +47,8 @@ void WatchFacePages::Weather::InitWake() void WatchFacePages::Weather::DrawPage(bool partialRefresh) { - if (m_lastSyncTime == 0) { - Resync(); - } + Resync(); + Recalc(); m_display.setFullWindow(); m_display.fillScreen(GxEPD_WHITE); @@ -219,7 +219,12 @@ void WatchFacePages::Weather::Resync() return; } + if (m_lastSyncTime > 0 && currentTime - m_lastSyncAttemptTime < WEATHER_UPDATE_BACKOFF) { + return; + } + if(!m_features.wifi.Connect()) { + m_lastSyncAttemptTime = currentTime; return; } @@ -232,6 +237,7 @@ void WatchFacePages::Weather::Resync() int httpCode = client.GET(); if (httpCode != 200) { m_features.wifi.Disconnect(); + m_lastSyncAttemptTime = currentTime; return; } @@ -252,6 +258,7 @@ void WatchFacePages::Weather::Resync() // Check if we got enough lines if (lines.size() < 14) { m_features.wifi.Disconnect(); + m_lastSyncAttemptTime = currentTime; return; } @@ -261,9 +268,11 @@ void WatchFacePages::Weather::Resync() memcpy(m_locationCity, location.c_str(), location.length()); m_locationLat = std::stof(lines[7]); m_locationLon = std::stof(lines[8]); + + // Force recalculation next time + m_lastCalculatedDay = 0xFFFFFFFF; } - // https://wttr.in/60.170833,24.9375?0Q&format=+%x:%t:%h std::ostringstream url; url << "http://wttr.in/" << m_locationLat << "," << m_locationLon << "?0Q&format=%x:%t:%h:%w"; // Grr. wttr.in does a redirect to HTTPS if your agent isn't curl @@ -273,6 +282,7 @@ void WatchFacePages::Weather::Resync() int httpCode = client.GET(); m_features.wifi.Disconnect(); if (httpCode != 200) { + m_lastSyncAttemptTime = currentTime; return; } @@ -292,6 +302,7 @@ void WatchFacePages::Weather::Resync() parts.push_back(reponse.substr(prev)); if (parts.size() != 4) { + m_lastSyncAttemptTime = currentTime; return; } @@ -310,7 +321,6 @@ void WatchFacePages::Weather::Resync() m_currentWindSpeed = std::round(windSpeedKmh * 0.277778); m_features.wifi.Disconnect(); - Recalc(); m_lastSyncTime = currentTime; } diff --git a/src/WatchFacePages/Weather.h b/src/WatchFacePages/Weather.h index c0f77bc..905047b 100644 --- a/src/WatchFacePages/Weather.h +++ b/src/WatchFacePages/Weather.h @@ -27,6 +27,7 @@ private: WatchyDisplay & m_display; WatchFeatures::WatchFeatures & m_features; static RTC_DATA_ATTR uint64_t m_lastSyncTime; + static RTC_DATA_ATTR uint64_t m_lastSyncAttemptTime; static RTC_DATA_ATTR int m_lastCalculatedDay; static RTC_DATA_ATTR char m_locationCity[128]; static RTC_DATA_ATTR double m_locationLat, m_locationLon; diff --git a/src/config.h b/src/config.h index 8b9d793..0f29096 100644 --- a/src/config.h +++ b/src/config.h @@ -42,6 +42,7 @@ #define WAKE_ON_ACCEL_EVENTS false // useful if saving battery by not updating every minute #define WEATHER_UPDATE_INTERVAL 3600 // seconds +#define WEATHER_UPDATE_BACKOFF 900 // If weather update fails, how long to wait before trying again #define DO_GEOLOCATION true // if false then use defaults below #define DEFAULT_LATITUDE 60.170833