From 7c9a0623fd5c7fd3b7616cb398fac6e871f4654a Mon Sep 17 00:00:00 2001 From: Matthew Colvin <35540398+MatthewColvin@users.noreply.github.com> Date: Sun, 22 Oct 2023 13:35:49 -0500 Subject: [PATCH] UI refactor (#50) --- Platformio/.vscode/settings.json | 2 +- Platformio/HAL/HardwareAbstract.hpp | 13 +- Platformio/HAL/HardwareFactory.cpp | 20 + Platformio/HAL/HardwareFactory.hpp | 11 + .../HAL/HardwareModules/KeyPressAbstract.cpp | 8 + .../HAL/HardwareModules/KeyPressAbstract.hpp | 73 + .../HardwareModules/wifiHandlerInterface.h | 67 +- Platformio/HAL/Interface/HardwareInterface.h | 27 - Platformio/HAL/Notification.hpp | 95 +- Platformio/HAL/Targets/ESP32/HardwareRevX.cpp | 88 +- Platformio/HAL/Targets/ESP32/HardwareRevX.hpp | 54 +- .../HAL/Targets/ESP32/display/display.cpp | 140 +- .../HAL/Targets/ESP32/display/display.hpp | 111 +- Platformio/HAL/Targets/ESP32/keys/keys.cpp | 61 + Platformio/HAL/Targets/ESP32/keys/keys.hpp | 76 ++ Platformio/HAL/Targets/ESP32/omoteconfig.h | 4 +- .../Targets/ESP32/wifiHandler/wifihandler.cpp | 310 ++--- .../Targets/ESP32/wifiHandler/wifihandler.hpp | 126 +- .../Targets/Simulator/HardwareSimulator.cpp | 100 +- .../Targets/Simulator/HardwareSimulator.hpp | 30 +- .../HAL/Targets/Simulator/KeyPressSim.cpp | 44 + .../HAL/Targets/Simulator/KeyPressSim.hpp | 59 + .../HAL/Targets/Simulator/SDLDisplay.cpp | 52 +- .../HAL/Targets/Simulator/SDLDisplay.hpp | 28 +- .../Targets/Simulator/SimulatorSPSCQueue.cpp | 2 +- .../wifiHandlerSim/wifiHandlerSim.cpp | 83 +- .../wifiHandlerSim/wifiHandlerSim.hpp | 42 +- Platformio/OmoteUI/Images.cpp | 1154 ---------------- Platformio/OmoteUI/Images.hpp | 50 - .../OmoteUI/{ => UIs/Basic}/OmoteUI.cpp | 282 ++-- .../OmoteUI/{ => UIs/Basic}/OmoteUI.hpp | 169 +-- .../{ => UIs/Basic}/displaySettings.cpp | 63 +- .../OmoteUI/{ => UIs/Basic}/wifiSettings.cpp | 2 + .../OmoteUI/UIs/BasicRefactored/BasicUI.cpp | 21 + .../OmoteUI/UIs/BasicRefactored/BasicUI.hpp | 11 + .../OmoteUI/UIs/BasicRefactored/page/Demo.cpp | 51 + .../OmoteUI/UIs/BasicRefactored/page/Demo.hpp | 20 + .../BasicRefactored/page/DisplaySettings.cpp | 16 + .../BasicRefactored/page/DisplaySettings.hpp | 21 + .../UIs/BasicRefactored/page/SettingsPage.cpp | 43 + .../UIs/BasicRefactored/page/SettingsPage.hpp | 28 + .../BasicRefactored/page/SystemSettings.cpp | 27 + .../BasicRefactored/page/SystemSettings.hpp | 23 + .../UIs/BasicRefactored/page/WifiSettings.cpp | 79 ++ .../UIs/BasicRefactored/page/WifiSettings.hpp | 37 + .../UIs/BasicRefactored/screen/HomeScreen.cpp | 28 + .../UIs/BasicRefactored/screen/HomeScreen.hpp | 23 + .../widget/BrightnessSlider.cpp | 44 + .../widget/BrightnessSlider.hpp | 25 + Platformio/OmoteUI/UIs/Images.cpp | 1180 +++++++++++++++++ Platformio/OmoteUI/UIs/Images.hpp | 48 + .../OmoteUI/UIs/LvglResourceManager.hpp | 49 + Platformio/OmoteUI/UIs/UIBase.cpp | 15 + Platformio/OmoteUI/UIs/UIBase.hpp | 19 + Platformio/OmoteUI/core/Animation.cpp | 40 + Platformio/OmoteUI/core/Animation.hpp | 31 + .../OmoteUI/core/BorderOutlinePadding.hpp | 110 ++ Platformio/OmoteUI/core/Colors.hpp | 16 + Platformio/OmoteUI/core/ScreenManager.cpp | 62 + Platformio/OmoteUI/core/ScreenManager.hpp | 33 + Platformio/OmoteUI/core/TextStyle.hpp | 52 + Platformio/OmoteUI/core/UIElement.cpp | 333 +++++ Platformio/OmoteUI/core/UIElement.hpp | 176 +++ Platformio/OmoteUI/core/UIElementIds.hpp | 45 + Platformio/OmoteUI/core/page/PageBase.cpp | 13 + Platformio/OmoteUI/core/page/PageBase.hpp | 36 + Platformio/OmoteUI/core/page/TabView.cpp | 62 + Platformio/OmoteUI/core/page/TabView.hpp | 45 + Platformio/OmoteUI/core/poller.cpp | 28 + Platformio/OmoteUI/core/poller.hpp | 29 + .../OmoteUI/core/screen/BackgroundScreen.cpp | 18 + .../OmoteUI/core/screen/BackgroundScreen.hpp | 16 + .../OmoteUI/core/screen/PopUpScreen.cpp | 35 + .../OmoteUI/core/screen/PopUpScreen.hpp | 23 + Platformio/OmoteUI/core/screen/ScreenBase.cpp | 26 + Platformio/OmoteUI/core/screen/ScreenBase.hpp | 35 + Platformio/OmoteUI/core/widget/Button.cpp | 14 + Platformio/OmoteUI/core/widget/Button.hpp | 15 + Platformio/OmoteUI/core/widget/DropDown.hpp | 47 + Platformio/OmoteUI/core/widget/Keyboard.cpp | 57 + Platformio/OmoteUI/core/widget/Keyboard.hpp | 32 + Platformio/OmoteUI/core/widget/Label.cpp | 22 + Platformio/OmoteUI/core/widget/Label.hpp | 16 + Platformio/OmoteUI/core/widget/List.cpp | 34 + Platformio/OmoteUI/core/widget/List.hpp | 32 + Platformio/OmoteUI/core/widget/Slider.cpp | 31 + Platformio/OmoteUI/core/widget/Slider.hpp | 19 + Platformio/OmoteUI/core/widget/WidgetBase.cpp | 23 + Platformio/OmoteUI/core/widget/WidgetBase.hpp | 34 + Platformio/OmoteUI/poller.cpp | 26 - Platformio/OmoteUI/poller.hpp | 23 - Platformio/platformio.ini | 27 +- Platformio/src/OmoteSetup.hpp | 18 + Platformio/src/main.cpp | 24 +- Platformio/src/simMain.cpp | 21 +- 95 files changed, 4726 insertions(+), 2307 deletions(-) create mode 100644 Platformio/HAL/HardwareFactory.cpp create mode 100644 Platformio/HAL/HardwareFactory.hpp create mode 100644 Platformio/HAL/HardwareModules/KeyPressAbstract.cpp create mode 100644 Platformio/HAL/HardwareModules/KeyPressAbstract.hpp delete mode 100644 Platformio/HAL/Interface/HardwareInterface.h create mode 100644 Platformio/HAL/Targets/ESP32/keys/keys.cpp create mode 100644 Platformio/HAL/Targets/ESP32/keys/keys.hpp create mode 100644 Platformio/HAL/Targets/Simulator/KeyPressSim.cpp create mode 100644 Platformio/HAL/Targets/Simulator/KeyPressSim.hpp delete mode 100644 Platformio/OmoteUI/Images.cpp delete mode 100644 Platformio/OmoteUI/Images.hpp rename Platformio/OmoteUI/{ => UIs/Basic}/OmoteUI.cpp (68%) rename Platformio/OmoteUI/{ => UIs/Basic}/OmoteUI.hpp (65%) rename Platformio/OmoteUI/{ => UIs/Basic}/displaySettings.cpp (53%) rename Platformio/OmoteUI/{ => UIs/Basic}/wifiSettings.cpp (99%) create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.hpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/widget/BrightnessSlider.cpp create mode 100644 Platformio/OmoteUI/UIs/BasicRefactored/widget/BrightnessSlider.hpp create mode 100644 Platformio/OmoteUI/UIs/Images.cpp create mode 100644 Platformio/OmoteUI/UIs/Images.hpp create mode 100644 Platformio/OmoteUI/UIs/LvglResourceManager.hpp create mode 100644 Platformio/OmoteUI/UIs/UIBase.cpp create mode 100644 Platformio/OmoteUI/UIs/UIBase.hpp create mode 100644 Platformio/OmoteUI/core/Animation.cpp create mode 100644 Platformio/OmoteUI/core/Animation.hpp create mode 100644 Platformio/OmoteUI/core/BorderOutlinePadding.hpp create mode 100644 Platformio/OmoteUI/core/Colors.hpp create mode 100644 Platformio/OmoteUI/core/ScreenManager.cpp create mode 100644 Platformio/OmoteUI/core/ScreenManager.hpp create mode 100644 Platformio/OmoteUI/core/TextStyle.hpp create mode 100644 Platformio/OmoteUI/core/UIElement.cpp create mode 100644 Platformio/OmoteUI/core/UIElement.hpp create mode 100644 Platformio/OmoteUI/core/UIElementIds.hpp create mode 100644 Platformio/OmoteUI/core/page/PageBase.cpp create mode 100644 Platformio/OmoteUI/core/page/PageBase.hpp create mode 100644 Platformio/OmoteUI/core/page/TabView.cpp create mode 100644 Platformio/OmoteUI/core/page/TabView.hpp create mode 100644 Platformio/OmoteUI/core/poller.cpp create mode 100644 Platformio/OmoteUI/core/poller.hpp create mode 100644 Platformio/OmoteUI/core/screen/BackgroundScreen.cpp create mode 100644 Platformio/OmoteUI/core/screen/BackgroundScreen.hpp create mode 100644 Platformio/OmoteUI/core/screen/PopUpScreen.cpp create mode 100644 Platformio/OmoteUI/core/screen/PopUpScreen.hpp create mode 100644 Platformio/OmoteUI/core/screen/ScreenBase.cpp create mode 100644 Platformio/OmoteUI/core/screen/ScreenBase.hpp create mode 100644 Platformio/OmoteUI/core/widget/Button.cpp create mode 100644 Platformio/OmoteUI/core/widget/Button.hpp create mode 100644 Platformio/OmoteUI/core/widget/DropDown.hpp create mode 100644 Platformio/OmoteUI/core/widget/Keyboard.cpp create mode 100644 Platformio/OmoteUI/core/widget/Keyboard.hpp create mode 100644 Platformio/OmoteUI/core/widget/Label.cpp create mode 100644 Platformio/OmoteUI/core/widget/Label.hpp create mode 100644 Platformio/OmoteUI/core/widget/List.cpp create mode 100644 Platformio/OmoteUI/core/widget/List.hpp create mode 100644 Platformio/OmoteUI/core/widget/Slider.cpp create mode 100644 Platformio/OmoteUI/core/widget/Slider.hpp create mode 100644 Platformio/OmoteUI/core/widget/WidgetBase.cpp create mode 100644 Platformio/OmoteUI/core/widget/WidgetBase.hpp delete mode 100644 Platformio/OmoteUI/poller.cpp delete mode 100644 Platformio/OmoteUI/poller.hpp create mode 100644 Platformio/src/OmoteSetup.hpp diff --git a/Platformio/.vscode/settings.json b/Platformio/.vscode/settings.json index 0745d47..0639d84 100644 --- a/Platformio/.vscode/settings.json +++ b/Platformio/.vscode/settings.json @@ -81,6 +81,6 @@ "variant": "cpp" }, "cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO", - "editor.formatOnSave": false, + "editor.formatOnSave": true, "idf.portWin": "COM8" } \ No newline at end of file diff --git a/Platformio/HAL/HardwareAbstract.hpp b/Platformio/HAL/HardwareAbstract.hpp index 8d163eb..784a3f1 100644 --- a/Platformio/HAL/HardwareAbstract.hpp +++ b/Platformio/HAL/HardwareAbstract.hpp @@ -3,6 +3,7 @@ #pragma once #include "BatteryInterface.h" #include "DisplayAbstract.h" +#include "KeyPressAbstract.hpp" #include "wifiHandlerInterface.h" #include "Notification.hpp" @@ -16,24 +17,24 @@ public: /// @brief Override in order to do setup of hardware devices post construction virtual void init() = 0; + /// @brief Override to processing in main thread + virtual void loopHandler() = 0; /// @brief Override to allow printing of a message for debugging /// @param message - Debug message - virtual void debugPrint(const char* fmt, ...) = 0; + virtual void debugPrint(const char *fmt, ...) = 0; - virtual std::shared_ptr battery() = 0; + virtual std::shared_ptr battery() = 0; virtual std::shared_ptr display() = 0; virtual std::shared_ptr wifi() = 0; + virtual std::shared_ptr keys() = 0; virtual char getCurrentDevice() = 0; virtual void setCurrentDevice(char currentDevice) = 0; - + virtual bool getWakeupByIMUEnabled() = 0; virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) = 0; virtual uint16_t getSleepTimeout() = 0; virtual void setSleepTimeout(uint16_t sleepTimeout) = 0; - - protected: - }; \ No newline at end of file diff --git a/Platformio/HAL/HardwareFactory.cpp b/Platformio/HAL/HardwareFactory.cpp new file mode 100644 index 0000000..e289393 --- /dev/null +++ b/Platformio/HAL/HardwareFactory.cpp @@ -0,0 +1,20 @@ +#include "HardwareFactory.hpp" + +#if OMOTE_SIM +#include "HardwareSimulator.hpp" +#endif + +#if OMOTE_ESP32 +#include "HardwareRevX.hpp" +#endif + +#if OMOTE_SIM +std::unique_ptr HardwareFactory::mHardware = + std::make_unique(); +#endif +#if OMOTE_ESP32 +std::unique_ptr HardwareFactory::mHardware = + std::make_unique(); +#endif + +HardwareAbstract &HardwareFactory::getAbstract() { return *mHardware; } \ No newline at end of file diff --git a/Platformio/HAL/HardwareFactory.hpp b/Platformio/HAL/HardwareFactory.hpp new file mode 100644 index 0000000..b840f39 --- /dev/null +++ b/Platformio/HAL/HardwareFactory.hpp @@ -0,0 +1,11 @@ +#include "HardwareAbstract.hpp" +#include +/** + * @brief The HardwareFactory is responsible for making the + */ +class HardwareFactory { +public: + static HardwareAbstract &getAbstract(); + + static std::unique_ptr mHardware; +}; diff --git a/Platformio/HAL/HardwareModules/KeyPressAbstract.cpp b/Platformio/HAL/HardwareModules/KeyPressAbstract.cpp new file mode 100644 index 0000000..d929c9f --- /dev/null +++ b/Platformio/HAL/HardwareModules/KeyPressAbstract.cpp @@ -0,0 +1,8 @@ +#include "KeyPressAbstract.hpp" + +KeyPressAbstract::KeyPressAbstract() {} + +void KeyPressAbstract::RegisterKeyPressHandler( + std::function aKeyEventHandler) { + mKeyEventHandler = std::move(aKeyEventHandler); +} \ No newline at end of file diff --git a/Platformio/HAL/HardwareModules/KeyPressAbstract.hpp b/Platformio/HAL/HardwareModules/KeyPressAbstract.hpp new file mode 100644 index 0000000..8b6e022 --- /dev/null +++ b/Platformio/HAL/HardwareModules/KeyPressAbstract.hpp @@ -0,0 +1,73 @@ +#pragma once +#include "Notification.hpp" + +#include +class KeyPressAbstract { +public: + // Keys from Top Down left to right. + enum class KeyId { + Power, + // Top 4 Buttons left to right + Stop, + Rewind, + Play, + FastForward, + // Buttons around D Pad + Menu, + Info, + Back, + Source, + // D Pad + Up, + Down, + Left, + Right, + Center, + // Volume Channel and 2 between + VolUp, + VolDown, + Mute, + Record, + ChannelUp, + ChannelDown, + // Bottom 4 buttons left to right + Aux1, + Aux2, + Aux3, + Aux4, + INVALID + }; + + class KeyEvent { + public: + enum class Type { Press, Release, INVALID }; + + KeyEvent() = default; + KeyEvent(const KeyId aId, const Type aType) : mId(aId), mType(aType) {} + + KeyId mId = KeyId::INVALID; + Type mType = Type::INVALID; + }; + + KeyPressAbstract(); + + /// @brief Register a SINGLE handler to be used for proccessing keys + /// @param aKeyEventHandler - Callable the Handles KeyEvent + void RegisterKeyPressHandler(std::function aKeyEventHandler); + +protected: + /// @brief Function ment to be called regularly to allow + /// proccesssing of key presses by calling mKeyEventHandler + /// best case this is done on a seprate thread/task + /// since it could take a while to handle a KeyPress + virtual void HandleKeyPresses() = 0; + + /// @brief Function to queue up Key events to be handled later on by + /// HandleKeyPresses() hopefully on a seprate thread or task + /// This function should be implemented in a way that makes it ISR + /// safe + /// @param aJustOccuredKeyEvent - A Key even that just occured + virtual void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) = 0; + + std::function mKeyEventHandler; +}; \ No newline at end of file diff --git a/Platformio/HAL/HardwareModules/wifiHandlerInterface.h b/Platformio/HAL/HardwareModules/wifiHandlerInterface.h index f6c2f80..71e5b95 100644 --- a/Platformio/HAL/HardwareModules/wifiHandlerInterface.h +++ b/Platformio/HAL/HardwareModules/wifiHandlerInterface.h @@ -1,25 +1,54 @@ #pragma once -#include -#include #include +#include +#include -typedef struct { - std::string ssid; - int rssi; -} WifiInfo; +class wifiHandlerInterface { +public: + wifiHandlerInterface() = default; + struct WifiInfo { + WifiInfo() = default; + WifiInfo(std::string aSsid, int aRssi) : ssid(aSsid), rssi(aRssi) {} -typedef struct { - bool isConnected; - std::string IP; - std::string ssid; -}wifiStatus; + std::string ssid = ""; + int rssi = 0; + }; -class wifiHandlerInterface{ - public: - virtual bool isAvailable() = 0; - virtual void scan() = 0; - virtual void connect(std::shared_ptr ssid, std::shared_ptr password) = 0; - virtual void onScanDone(std::function>)> function) = 0; - virtual void onStatusUpdate(std::function)> function) = 0; - virtual void begin() = 0; + struct wifiStatus { + wifiStatus() = default; + wifiStatus(bool aConnected, std::string aIp, std::string aSsid) + : isConnected(aConnected), IP(aIp), ssid(aSsid){}; + + bool isConnected = false; + std::string IP = ""; + std::string ssid = ""; + }; + + typedef std::vector ScanDoneDataTy; + typedef Notification ScanNotificationTy; + + /// @brief Initialize the wifi handler + virtual void begin() = 0; + /// @brief Trigger a scan scan for wifi networks + virtual void scan() = 0; + /// @brief Attempt a connection to the wifi using the provided credentials + virtual void connect(std::string ssid, std::string password) = 0; + /// @brief Get the status of the current wifi connection + virtual wifiStatus GetStatus() = 0; + + // Register for Scan Notification to handle when scans are completed + std::shared_ptr ScanCompleteNotification() { + return mScanNotification; + }; + + // Register for Status notifications to handle changes in status + std::shared_ptr> WifiStatusNotification() { + return mStatusUpdate; + }; + +protected: + std::shared_ptr mScanNotification = + std::make_shared(); + std::shared_ptr> mStatusUpdate = + std::make_shared>(); }; \ No newline at end of file diff --git a/Platformio/HAL/Interface/HardwareInterface.h b/Platformio/HAL/Interface/HardwareInterface.h deleted file mode 100644 index 71a455f..0000000 --- a/Platformio/HAL/Interface/HardwareInterface.h +++ /dev/null @@ -1,27 +0,0 @@ -// OMOTE Hardware Abstraction -// 2023 Matthew Colvin - -#pragma once -#include -#include - -class HardwareInterface { -public: - struct batteryStatus { - /// @brief Percent of battery remaining (0-100] - int percentage; - /// @brief Voltage of battery in millivolts - int voltage; - /// @brief True - Battery is Charging - /// False - Battery discharging - bool isCharging; - }; - - HardwareInterface() = default; - - virtual void init() = 0; - virtual void sendIR() = 0; - virtual void MQTTPublish(const char *topic, const char *payload) = 0; - virtual batteryStatus getBatteryPercentage() = 0; - virtual void debugPrint(std::string message) = 0; -}; diff --git a/Platformio/HAL/Notification.hpp b/Platformio/HAL/Notification.hpp index 6b8920f..1665f25 100644 --- a/Platformio/HAL/Notification.hpp +++ b/Platformio/HAL/Notification.hpp @@ -1,29 +1,90 @@ #pragma once -#include #include +#include +#include -template -class Notification{ - public: - typedef std::function HandlerTy; +template class Handler; +template class Notification { + friend class Handler; - Notification() = default; - void onNotify(HandlerTy aHandler); - void notify(notifyData... notifySendData); +public: + typedef std::function HandlerTy; + typedef int HandlerID; - private: - std::vector mFunctionHandlers; + Notification() { mIdMaker = 0; }; + void notify(notifyData... notifySendData); + +protected: + HandlerID onNotify(HandlerTy aHandler); + void unregister(HandlerID aHandler); + +private: + std::map mFunctionHandlers; + HandlerID mIdMaker; }; - template -void Notification::onNotify(HandlerTy aHandler){ - mFunctionHandlers.push_back(std::move(aHandler)); +int Notification::onNotify(HandlerTy aHandler) { + if (aHandler) { + mFunctionHandlers[++mIdMaker] = std::move(aHandler); + return mIdMaker; + } else { + return -1; + } } template -void Notification::notify(outboundData... notifySendData){ - for (auto handler : mFunctionHandlers){ - handler(notifySendData...); +void Notification::notify(outboundData... notifySendData) { + for (auto handler : mFunctionHandlers) { + handler.second(notifySendData...); + } +} + +template +void Notification::unregister(HandlerID aHandlerId) { + auto handlerToUnRegister = + std::find_if(mFunctionHandlers.begin(), mFunctionHandlers.end(), + [aHandlerId](auto registeredHandler) { + return aHandlerId == registeredHandler.first; + }); + if (handlerToUnRegister != mFunctionHandlers.end()) { + mFunctionHandlers.erase(handlerToUnRegister); + } +} + +template class Handler { +public: + typedef std::function callableTy; + void operator=(Handler &other) = delete; + + Handler() = default; + Handler(std::shared_ptr> aNotification, + callableTy aCallable = nullptr) + : mNotification(aNotification), + mHandlerId(aNotification->onNotify(aCallable)) {} + + virtual ~Handler() { + if (mHandlerId >= 0) { + mNotification->unregister(mHandlerId); } -} \ No newline at end of file + } + + void operator=(callableTy aHandler) { + if (mHandlerId >= 0) { + mNotification->unregister(mHandlerId); + mHandlerId = -1; + } + if (aHandler) { + mHandlerId = mNotification->onNotify(aHandler); + } + } + + void + SetNotification(std::shared_ptr> aNotification) { + mNotification = aNotification; + } + +private: + std::shared_ptr> mNotification = nullptr; + int mHandlerId = -1; +}; \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp b/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp index 9451423..fe3ae2d 100644 --- a/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp +++ b/Platformio/HAL/Targets/ESP32/HardwareRevX.cpp @@ -2,8 +2,6 @@ #include "display.hpp" #include "wifihandler.hpp" -std::shared_ptr HardwareRevX::mInstance = nullptr; - void HardwareRevX::initIO() { // Button Pin Definition pinMode(SW_1, OUTPUT); @@ -50,9 +48,7 @@ void HardwareRevX::initIO() { gpio_deep_sleep_hold_dis(); } -HardwareRevX::HardwareRevX(): - HardwareAbstract(){ - } +HardwareRevX::HardwareRevX() : HardwareAbstract() {} HardwareRevX::WakeReason getWakeReason() { // Find out wakeup cause @@ -74,11 +70,15 @@ void HardwareRevX::init() { Serial.begin(115200); mDisplay = Display::getInstance(); - mBattery = std::make_shared(ADC_BAT,CRG_STAT); + mBattery = std::make_shared(ADC_BAT, CRG_STAT); mWifiHandler = wifiHandler::getInstance(); + mKeys = std::make_shared(); restorePreferences(); - mDisplay->onTouch([this]([[maybe_unused]] auto touchPoint){ standbyTimer = this->getSleepTimeout();}); + mTouchHandler.SetNotification(mDisplay->TouchNotification()); + mTouchHandler = [this]([[maybe_unused]] auto touchPoint) { + standbyTimer = this->getSleepTimeout(); + }; setupIMU(); setupIR(); @@ -86,37 +86,26 @@ void HardwareRevX::init() { debugPrint("Finished Hardware Setup in %d", millis()); } -void HardwareRevX::debugPrint(const char* fmt, ...) -{ +void HardwareRevX::debugPrint(const char *fmt, ...) { char result[100]; va_list arguments; va_start(arguments, fmt); vsnprintf(result, 100, fmt, arguments); - va_end (arguments); + va_end(arguments); Serial.print(result); } -std::shared_ptr HardwareRevX::getInstance(){ - if (!mInstance) { - mInstance = std::shared_ptr(new HardwareRevX()); - } - return mInstance; -} - -std::shared_ptr HardwareRevX::wifi() -{ +std::shared_ptr HardwareRevX::wifi() { return mWifiHandler; } -std::shared_ptr HardwareRevX::battery(){ - return mBattery; -} +std::shared_ptr HardwareRevX::battery() { return mBattery; } -std::shared_ptr HardwareRevX::display(){ - return mDisplay; -} +std::shared_ptr HardwareRevX::display() { return mDisplay; } + +std::shared_ptr HardwareRevX::keys() { return mKeys; } void HardwareRevX::activityDetection() { static int accXold; @@ -142,27 +131,21 @@ void HardwareRevX::activityDetection() { accZold = accZ; } -char HardwareRevX::getCurrentDevice(){ - return currentDevice; -} +char HardwareRevX::getCurrentDevice() { return currentDevice; } -void HardwareRevX::setCurrentDevice(char currentDevice){ +void HardwareRevX::setCurrentDevice(char currentDevice) { this->currentDevice = currentDevice; } -bool HardwareRevX::getWakeupByIMUEnabled(){ - return wakeupByIMUEnabled; -} +bool HardwareRevX::getWakeupByIMUEnabled() { return wakeupByIMUEnabled; } -void HardwareRevX::setWakeupByIMUEnabled(bool wakeupByIMUEnabled){ +void HardwareRevX::setWakeupByIMUEnabled(bool wakeupByIMUEnabled) { this->wakeupByIMUEnabled = wakeupByIMUEnabled; } -uint16_t HardwareRevX::getSleepTimeout(){ - return sleepTimeout; -} +uint16_t HardwareRevX::getSleepTimeout() { return sleepTimeout; } -void HardwareRevX::setSleepTimeout(uint16_t sleepTimeout){ +void HardwareRevX::setSleepTimeout(uint16_t sleepTimeout) { this->sleepTimeout = sleepTimeout; standbyTimer = sleepTimeout; } @@ -287,7 +270,7 @@ void HardwareRevX::restorePreferences() { currentDevice = preferences.getUChar("currentDevice"); sleepTimeout = preferences.getUInt("sleepTimeout"); // setting the default to prevent a 0ms sleep timeout - if(sleepTimeout == 0){ + if (sleepTimeout == 0) { sleepTimeout = SLEEP_TIMEOUT; } } @@ -320,7 +303,7 @@ void HardwareRevX::startTasks() {} void HardwareRevX::loopHandler() { standbyTimer < 2000 ? mDisplay->sleep() : mDisplay->wake(); - + // TODO move to debug task // Blink debug LED at 1 Hz digitalWrite(USER_LED, millis() % 1000 > 500); @@ -335,31 +318,4 @@ void HardwareRevX::loopHandler() { } IMUTaskTimer = millis(); } - - // Keypad Handling - customKeypad.getKey(); // Populate key list - for (int i = 0; i < LIST_MAX; - i++) { // Handle multiple keys (Not really necessary in this case) - if (customKeypad.key[i].kstate == PRESSED || - customKeypad.key[i].kstate == HOLD) { - standbyTimer = - sleepTimeout; // Reset the sleep timer when a button is pressed - int keyCode = customKeypad.key[i].kcode; - Serial.println(customKeypad.key[i].kchar); - // Send IR codes depending on the current device (tabview page) - if (currentDevice == 1) { - IrSender.sendRC5(IrSender.encodeRC5X( - 0x00, keyMapTechnisat[keyCode / ROWS][keyCode % ROWS])); - } else if (currentDevice == 2) { - IrSender.sendSony((keyCode / ROWS) * (keyCode % ROWS), 15); - } - } - } - // IR Test - // tft.drawString("IR Command: ", 10, 90, 1); - // decode_results results; - // if (IrReceiver.decode(&results)) { - // IrReceiver.resume(); // Enable receiving of the next value - //} //tft.drawString(String(results.command) + " ", 80, 90, 1); - // } \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp b/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp index 455e896..4043db2 100644 --- a/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp +++ b/Platformio/HAL/Targets/ESP32/HardwareRevX.hpp @@ -2,44 +2,44 @@ #include "SparkFunLIS3DH.h" #include "HardwareAbstract.hpp" -#include "lvgl.h" #include "battery.hpp" +#include "lvgl.h" +#include "wifihandler.hpp" +#include #include #include #include #include -#include // modified for inverted logic #include #include #include #include -#include "wifihandler.hpp" - - #include "omoteconfig.h" + #include "BatteryInterface.h" -#include "wifiHandlerInterface.h" #include "display.hpp" +#include "keys.hpp" +#include "wifiHandlerInterface.h" class HardwareRevX : public HardwareAbstract { public: enum class WakeReason { RESET, IMU, KEYPAD }; - static std::shared_ptr getInstance(); - static std::weak_ptr getRefrence() { return getInstance(); } + HardwareRevX(); // HardwareAbstract virtual void init() override; - virtual void debugPrint(const char* fmt, ...) override; + virtual void debugPrint(const char *fmt, ...) override; virtual std::shared_ptr battery() override; virtual std::shared_ptr display() override; virtual std::shared_ptr wifi() override; + virtual std::shared_ptr keys() override; virtual char getCurrentDevice() override; virtual void setCurrentDevice(char currentDevice) override; - + virtual bool getWakeupByIMUEnabled() override; virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override; @@ -48,7 +48,8 @@ public: /// @brief To be ran in loop out in main // TODO move to a freertos task - void loopHandler(); + void loopHandler() override; + protected: // Init Functions to setup hardware void initIO(); @@ -65,11 +66,10 @@ protected: void startTasks(); private: - HardwareRevX(); - std::shared_ptr mBattery; std::shared_ptr mDisplay; std::shared_ptr mWifiHandler; + std::shared_ptr mKeys; // IMU Motion Detection LIS3DH IMU = LIS3DH(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19. int standbyTimer = SLEEP_TIMEOUT; @@ -86,32 +86,6 @@ private: IRsend IrSender = IRsend(IR_LED, true); IRrecv IrReceiver = IRrecv(IR_RX); - - // Keypad declarations - static const byte ROWS = 5; // four rows - static const byte COLS = 5; // four columns - // define the symbols on the buttons of the keypads - char hexaKeys[ROWS][COLS] = { - {'s', '^', '-', 'm', 'r'}, // source, channel+, Volume-, mute, record - {'i', 'r', '+', 'k', 'd'}, // info, right, Volume+, OK, down - {'4', 'v', '1', '3', '2'}, // blue, channel-, red, yellow, green - {'>', 'o', 'b', 'u', 'l'}, // forward, off, back, up, left - {'?', 'p', 'c', '<', '='} // ?, play, config, rewind, stop - }; - byte rowPins[ROWS] = {SW_A, SW_B, SW_C, SW_D, - SW_E}; // connect to the row pinouts of the keypad - byte colPins[COLS] = {SW_1, SW_2, SW_3, SW_4, - SW_5}; // connect to the column pinouts of the keypad - Keypad customKeypad = - Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); - - byte keyMapTechnisat[ROWS][COLS] = {{0x69, 0x20, 0x11, 0x0D, 0x56}, - {0x4F, 0x37, 0x10, 0x57, 0x51}, - {0x6E, 0x21, 0x6B, 0x6D, 0x6C}, - {0x34, 0x0C, 0x22, 0x50, 0x55}, - {'?', 0x35, 0x2F, 0x32, 0x36}}; - byte virtualKeyMapTechnisat[10] = {0x1, 0x2, 0x3, 0x4, 0x5, - 0x6, 0x7, 0x8, 0x9, 0x0}; - static std::shared_ptr mInstance; + Handler mTouchHandler; }; \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/display/display.cpp b/Platformio/HAL/Targets/ESP32/display/display.cpp index a8941cc..41dd16d 100644 --- a/Platformio/HAL/Targets/ESP32/display/display.cpp +++ b/Platformio/HAL/Targets/ESP32/display/display.cpp @@ -1,43 +1,39 @@ #include "display.hpp" -#include "omoteconfig.h" #include "Wire.h" #include "driver/ledc.h" +#include "omoteconfig.h" -std::shared_ptr Display::getInstance() -{ - if (DisplayAbstract::mInstance == nullptr) - { - DisplayAbstract::mInstance = std::shared_ptr(new Display(LCD_BL, LCD_EN)); - } - return std::static_pointer_cast(mInstance); +std::shared_ptr Display::getInstance() { + if (DisplayAbstract::mInstance == nullptr) { + DisplayAbstract::mInstance = + std::shared_ptr(new Display(LCD_BL, LCD_EN)); + } + return std::static_pointer_cast(mInstance); } -Display::Display(int backlight_pin, int enable_pin): DisplayAbstract(), - mBacklightPin(backlight_pin), - mEnablePin(enable_pin), - tft(TFT_eSPI()), - touch(Adafruit_FT6206()) -{ - pinMode(mEnablePin, OUTPUT); - digitalWrite(mEnablePin, HIGH); - pinMode(mBacklightPin, OUTPUT); - digitalWrite(mBacklightPin, HIGH); +Display::Display(int backlight_pin, int enable_pin) + : DisplayAbstract(), mBacklightPin(backlight_pin), mEnablePin(enable_pin), + tft(TFT_eSPI()), touch(Adafruit_FT6206()) { + pinMode(mEnablePin, OUTPUT); + digitalWrite(mEnablePin, HIGH); + pinMode(mBacklightPin, OUTPUT); + digitalWrite(mBacklightPin, HIGH); - setupBacklight(); // This eliminates the flash of the backlight + setupBacklight(); // This eliminates the flash of the backlight - // Slowly charge the VSW voltage to prevent a brownout - // Workaround for hardware rev 1! - for(int i = 0; i < 100; i++){ - digitalWrite(this->mEnablePin, HIGH); // LCD Logic off - delayMicroseconds(1); - digitalWrite(this->mEnablePin, LOW); // LCD Logic on - } + // Slowly charge the VSW voltage to prevent a brownout + // Workaround for hardware rev 1! + for (int i = 0; i < 100; i++) { + digitalWrite(this->mEnablePin, HIGH); // LCD Logic off + delayMicroseconds(1); + digitalWrite(this->mEnablePin, LOW); // LCD Logic on + } - setupTFT(); - setupTouchScreen(); - mFadeTaskMutex = xSemaphoreCreateBinary(); - xSemaphoreGive(mFadeTaskMutex); + setupTFT(); + setupTouchScreen(); + mFadeTaskMutex = xSemaphoreCreateBinary(); + xSemaphoreGive(mFadeTaskMutex); } void Display::setupBacklight() { @@ -62,10 +58,6 @@ void Display::setupBacklight() { ledc_timer_config(&ledc_timer); } -void Display::onTouch(Notification::HandlerTy aTouchHandler){ - mTouchEvent.onNotify(std::move(aTouchHandler)); -} - void Display::setupTFT() { delay(100); tft.init(); @@ -75,25 +67,22 @@ void Display::setupTFT() { tft.setSwapBytes(true); } -void Display::setupTouchScreen(){ - // Configure i2c pins and set frequency to 400kHz - Wire.begin(SDA, SCL, 400000); - touch.begin(128); // Initialize touchscreen and set sensitivity threshold +void Display::setupTouchScreen() { + // Configure i2c pins and set frequency to 400kHz + Wire.begin(TFT_SDA, TFT_SCL, 400000); + touch.begin(128); // Initialize touchscreen and set sensitivity threshold } -void Display::setBrightness(uint8_t brightness) -{ +void Display::setBrightness(uint8_t brightness) { mAwakeBrightness = brightness; Serial.print("Set Brightness:"); Serial.println(mAwakeBrightness); startFade(); } -uint8_t Display::getBrightness(){ - return mAwakeBrightness; -} +uint8_t Display::getBrightness() { return mAwakeBrightness; } -void Display::setCurrentBrightness(uint8_t brightness){ +void Display::setCurrentBrightness(uint8_t brightness) { mBrightness = brightness; auto duty = static_cast(mBrightness); ledcWrite(LCD_BACKLIGHT_LEDC_CHANNEL, duty); @@ -101,25 +90,24 @@ void Display::setCurrentBrightness(uint8_t brightness){ // Serial.println(mBrightness); } -void Display::turnOff() -{ - digitalWrite(this->mBacklightPin, HIGH); - digitalWrite(this->mEnablePin, HIGH); - pinMode(this->mBacklightPin, INPUT); - pinMode(this->mEnablePin, INPUT); - gpio_hold_en((gpio_num_t) mBacklightPin); - gpio_hold_en((gpio_num_t) mEnablePin); +void Display::turnOff() { + digitalWrite(this->mBacklightPin, HIGH); + digitalWrite(this->mEnablePin, HIGH); + pinMode(this->mBacklightPin, INPUT); + pinMode(this->mEnablePin, INPUT); + gpio_hold_en((gpio_num_t)mBacklightPin); + gpio_hold_en((gpio_num_t)mEnablePin); } -void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){ - // int16_t touchX, touchY; +void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) { + // int16_t touchX, touchY; touchPoint = touch.getPoint(); int16_t touchX = touchPoint.x; int16_t touchY = touchPoint.y; bool touched = false; if ((touchX > 0) || (touchY > 0)) { touched = true; - mTouchEvent.notify(touchPoint); + mTouchEvent->notify(touchPoint); } if (!touched) { @@ -140,48 +128,50 @@ void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){ } } -void Display::fadeImpl(void* ){ +void Display::fadeImpl(void *) { bool fadeDone = false; - while(!fadeDone){ + while (!fadeDone) { fadeDone = getInstance()->fade(); - vTaskDelay(3 / portTICK_PERIOD_MS); // 3 miliseconds between steps - // 0 - 255 will take about .75 seconds to fade up. + vTaskDelay(3 / portTICK_PERIOD_MS); // 3 miliseconds between steps + // 0 - 255 will take about .75 seconds to fade up. } - - xSemaphoreTake(getInstance()->mFadeTaskMutex,portMAX_DELAY); + + xSemaphoreTake(getInstance()->mFadeTaskMutex, portMAX_DELAY); getInstance()->mDisplayFadeTask = nullptr; xSemaphoreGive(getInstance()->mFadeTaskMutex); vTaskDelete(nullptr); // Delete Fade Task } -bool Display::fade(){ - //Early return no fade needed. - if (mBrightness == mAwakeBrightness || - isAsleep && mBrightness == 0){return true;} - - bool fadeDown = isAsleep || mBrightness > mAwakeBrightness; - if (fadeDown){ +bool Display::fade() { + // Early return no fade needed. + if (mBrightness == mAwakeBrightness || isAsleep && mBrightness == 0) { + return true; + } + + bool fadeDown = isAsleep || mBrightness > mAwakeBrightness; + if (fadeDown) { setCurrentBrightness(mBrightness - 1); auto setPoint = isAsleep ? 0 : mAwakeBrightness; return mBrightness == setPoint; - }else{ + } else { setCurrentBrightness(mBrightness + 1); return mBrightness == mAwakeBrightness; } } -void Display::startFade(){ - xSemaphoreTake(mFadeTaskMutex,portMAX_DELAY); +void Display::startFade() { + xSemaphoreTake(mFadeTaskMutex, portMAX_DELAY); // Only Create Task if it is needed - if(mDisplayFadeTask == nullptr){ - xTaskCreate(&Display::fadeImpl, "Display Fade Task", - 1024, nullptr, 5, &mDisplayFadeTask); + if (mDisplayFadeTask == nullptr) { + xTaskCreate(&Display::fadeImpl, "Display Fade Task", 1024, nullptr, 5, + &mDisplayFadeTask); } xSemaphoreGive(mFadeTaskMutex); } -void Display::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { +void Display::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, + lv_color_t *color_p) { uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); diff --git a/Platformio/HAL/Targets/ESP32/display/display.hpp b/Platformio/HAL/Targets/ESP32/display/display.hpp index 214c8b8..a0abe3a 100644 --- a/Platformio/HAL/Targets/ESP32/display/display.hpp +++ b/Platformio/HAL/Targets/ESP32/display/display.hpp @@ -2,10 +2,10 @@ #include "DisplayAbstract.h" #include "HardwareAbstract.hpp" #include "Notification.hpp" -#include -#include -#include #include "driver/ledc.h" +#include +#include +#include /*LEDC Channel to use for the LCD backlight*/ #define LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_5 @@ -16,58 +16,71 @@ #define DEFAULT_BACKLIGHT_BRIGHTNESS 128 +class Display : public DisplayAbstract { +public: + static std::shared_ptr getInstance(); -class Display: public DisplayAbstract -{ - public: - static std::shared_ptr getInstance(); - - /// @brief Set brightness setting and fade to it - /// @param brightness - virtual void setBrightness(uint8_t brightness) override; - virtual uint8_t getBrightness() override; - virtual void turnOff() override; - - void onTouch(Notification::HandlerTy aTouchHandler); + /// @brief Set brightness setting and fade to it + /// @param brightness + virtual void setBrightness(uint8_t brightness) override; + virtual uint8_t getBrightness() override; + virtual void turnOff() override; - inline void wake() {if(isAsleep) {isAsleep = false; startFade();}} - inline void sleep() {if(!isAsleep){isAsleep = true; startFade();}} + std::shared_ptr> TouchNotification() { + return mTouchEvent; + } - protected: - virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p); - virtual void screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) override; - - /// @brief Fade toward brightness based on isAwake - /// @return True - Fade complete - /// False - Fade set point not reached - bool fade(); - /// @brief Start the Fade task - void startFade(); + inline void wake() { + if (isAsleep) { + isAsleep = false; + startFade(); + } + } + inline void sleep() { + if (!isAsleep) { + isAsleep = true; + startFade(); + } + } - /// @brief Set the actual display brightness right now - /// @param brightness - void setCurrentBrightness(uint8_t brightness); +protected: + virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, + lv_color_t *color_p); + virtual void screenInput(lv_indev_drv_t *indev_driver, + lv_indev_data_t *data) override; - private: - Display(int backlight_pin, int enable_pin); - void setupTFT(); - void setupTouchScreen(); - void setupBacklight(); - - int mEnablePin; - int mBacklightPin; - TFT_eSPI tft; + /// @brief Fade toward brightness based on isAwake + /// @return True - Fade complete + /// False - Fade set point not reached + bool fade(); + /// @brief Start the Fade task + void startFade(); - Adafruit_FT6206 touch; - TS_Point touchPoint; - TS_Point oldPoint; - Notification mTouchEvent; + /// @brief Set the actual display brightness right now + /// @param brightness + void setCurrentBrightness(uint8_t brightness); - TaskHandle_t mDisplayFadeTask = nullptr; - SemaphoreHandle_t mFadeTaskMutex = nullptr; - static void fadeImpl(void* aBrightness); +private: + Display(int backlight_pin, int enable_pin); + void setupTFT(); + void setupTouchScreen(); + void setupBacklight(); - uint8_t mBrightness = 0; // Current display brightness - uint8_t mAwakeBrightness = 100; // Current setting for brightness when awake - bool isAsleep = false; + int mEnablePin; + int mBacklightPin; + TFT_eSPI tft; + + Adafruit_FT6206 touch; + TS_Point touchPoint; + TS_Point oldPoint; + std::shared_ptr> mTouchEvent = + std::make_shared>(); + + TaskHandle_t mDisplayFadeTask = nullptr; + SemaphoreHandle_t mFadeTaskMutex = nullptr; + static void fadeImpl(void *aBrightness); + + uint8_t mBrightness = 0; // Current display brightness + uint8_t mAwakeBrightness = 100; // Current setting for brightness when awake + bool isAsleep = false; }; \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/keys/keys.cpp b/Platformio/HAL/Targets/ESP32/keys/keys.cpp new file mode 100644 index 0000000..27b5936 --- /dev/null +++ b/Platformio/HAL/Targets/ESP32/keys/keys.cpp @@ -0,0 +1,61 @@ +#include "keys.hpp" + +Keys::Keys() { + static constexpr auto MaxQueueableKeyPresses = 5; + mKeyPressQueueHandle = xQueueCreate(MaxQueueableKeyPresses, sizeof(KeyEvent)); + xTaskCreate(KeyGrabberTask, "KeyGrabber", 1024, this, 1, &mKeyGrabbingTask); + xTaskCreate(KeyProccessor, "KeyProccessor", 4096, this, 1, &mKeyHandlingTask); +} + +void Keys::KeyGrabberTask(void *aSelf) { + auto self = reinterpret_cast(aSelf); + while (true) { + self->GrabKeys(); + vTaskDelay(5 / portTICK_PERIOD_MS); // 5 ms between key grabs + } +} +void Keys::KeyProccessor(void *aSelf) { + auto self = reinterpret_cast(aSelf); + while (true) { + self->HandleKeyPresses(); + vTaskDelay(50 / portTICK_PERIOD_MS); + } +} + +void Keys::HandleKeyPresses() { + KeyPressAbstract::KeyEvent eventToHandle; + while (xQueueReceive(mKeyPressQueueHandle, &eventToHandle, 0) == pdTRUE) { + if (mKeyEventHandler) { + mKeyEventHandler(eventToHandle); + } + } +}; + +void Keys::QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) { + BaseType_t higherPriorityTaskAwoke; + xQueueSendFromISR(mKeyPressQueueHandle, &aJustOccuredKeyEvent, + &higherPriorityTaskAwoke); +}; + +void Keys::GrabKeys() { + if (!customKeypad.getKeys()) { + return; // no activity return early. + } + for (int i = 0; i < LIST_MAX; i++) { + if (customKeypad.key[i].kstate == PRESSED || + customKeypad.key[i].kstate == RELEASED) { + // May need to think about resetting sleep timer in key handler.... + // standbyTimer = + // sleepTimeout; // Reset the sleep timer when a button is + // pressed + auto eventType = customKeypad.key[i].kstate == PRESSED + ? KeyEvent::Type::Press + : KeyEvent::Type::Release; + const auto keyChar = customKeypad.key[i].kchar; + auto stateChange = customKeypad.key[i].stateChanged; + if (charKeyToKeyIds.count(keyChar) > 0 && stateChange) { + QueueKeyEvent(KeyEvent(charKeyToKeyIds.at(keyChar), eventType)); + } + } + } +} \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/keys/keys.hpp b/Platformio/HAL/Targets/ESP32/keys/keys.hpp new file mode 100644 index 0000000..98cc13e --- /dev/null +++ b/Platformio/HAL/Targets/ESP32/keys/keys.hpp @@ -0,0 +1,76 @@ +#pragma once +#include "KeyPressAbstract.hpp" +#include "omoteconfig.h" +#include // modified for inverted logic +#include + +class Keys : public KeyPressAbstract { +public: + Keys(); + void HandleKeyPresses() override; + void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) override; + +protected: + void GrabKeys(); + +private: + static void KeyGrabberTask(void *aSelf); + static void KeyProccessor(void *aSelf); + + QueueHandle_t mKeyPressQueueHandle; + TaskHandle_t mKeyGrabbingTask; + TaskHandle_t mKeyHandlingTask; + + // Keypad declarations + static const byte ROWS = 5; // four rows + static const byte COLS = 5; // four columns + // define the symbols on the buttons of the keypads + char hexaKeys[ROWS][COLS] = { + {'s', '^', '-', 'm', 'r'}, // source, channel+, Volume-, mute, record + {'i', 'R', '+', 'k', 'd'}, // info, right, Volume+, OK, down + {'4', 'v', '1', '3', '2'}, // blue, channel-, red, yellow, green + {'>', 'o', 'b', 'u', 'L'}, // forward, off, back, up, left + {'?', 'p', 'c', '<', '='} // ?, play, config, rewind, stop + }; + // TODO what is '?' lol + + // TODO Should be able to optomize this out by reordering Ids at some point + // or even using interrupts to trigger key press queueing + static inline const std::map charKeyToKeyIds{ + {'o', KeyId::Power}, + // Top 4 Buttons left to right + {'=', KeyId::Stop}, + {'<', KeyId::Rewind}, + {'p', KeyId::Play}, + {'>', KeyId::FastForward}, + // Buttons around D Pad + {'c', KeyId::Menu}, + {'i', KeyId::Info}, + {'b', KeyId::Back}, + {'s', KeyId::Source}, + // D Pad + {'u', KeyId::Up}, + {'d', KeyId::Down}, + {'L', KeyId::Left}, + {'R', KeyId::Right}, + {'k', KeyId::Center}, + // Volume Channel and 2 between + {'+', KeyId::VolUp}, + {'-', KeyId::VolDown}, + {'m', KeyId::Mute}, + {'r', KeyId::Record}, + {'^', KeyId::ChannelUp}, + {'v', KeyId::ChannelDown}, + // Bottom 4 buttons left to right + {'1', KeyId::Aux1}, + {'2', KeyId::Aux2}, + {'3', KeyId::Aux3}, + {'4', KeyId::Aux4}}; + + byte rowPins[ROWS] = {SW_A, SW_B, SW_C, SW_D, + SW_E}; // connect to the row pinouts of the keypad + byte colPins[COLS] = {SW_1, SW_2, SW_3, SW_4, + SW_5}; // connect to the column pinouts of the keypad + Keypad customKeypad = + Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); +}; \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/omoteconfig.h b/Platformio/HAL/Targets/ESP32/omoteconfig.h index 462abe7..88e077c 100644 --- a/Platformio/HAL/Targets/ESP32/omoteconfig.h +++ b/Platformio/HAL/Targets/ESP32/omoteconfig.h @@ -45,8 +45,8 @@ #define IR_VCC 25 // IR receiver power #define IR_LED 33 // IR LED output -#define SCL 22 -#define SDA 19 +#define TFT_SCL 22 +#define TFT_SDA 19 #define ACC_INT 20 #define CRG_STAT 21 // battery charger feedback \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.cpp b/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.cpp index 7b55a67..5cd318b 100644 --- a/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.cpp +++ b/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.cpp @@ -1,230 +1,116 @@ #include "wifihandler.hpp" +#include "HardwareAbstract.hpp" #include #include -#include "HardwareAbstract.hpp" -#include "WiFi.h" +#include std::shared_ptr wifiHandler::mInstance = nullptr; - -// WiFi status event -void wifiHandler::WiFiEvent(WiFiEvent_t event){ - int no_networks = 0; - switch (event) - { - case ARDUINO_EVENT_WIFI_SCAN_DONE: - { - Serial.println("WIFI scan done\n"); - no_networks = WiFi.scanComplete(); - std::vector *vec = new std::vector(); - std::shared_ptr> info = std::shared_ptr>(vec); - - for (int i = 0; i < no_networks; i++) - { - info->push_back(WifiInfo { - .ssid = std::string(WiFi.SSID(i).c_str()), - .rssi = WiFi.RSSI(i) - }); - } - if (no_networks < 0) - { - Serial.println("Scan failed"); - } - else - { - // TODO Convert To callbacks - //this->display.clear_wifi_networks(); - Serial.print(no_networks); - Serial.print(" found\n"); - //this->display.wifi_scan_complete( no_networks); - } - this->scan_notification.notify(info); - if (WiFi.isConnected() == false) - { - WiFi.reconnect(); - } - break; - } - case ARDUINO_EVENT_WIFI_STA_GOT_IP: - case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - this->update_credentials(); - case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - case ARDUINO_EVENT_WIFI_STA_LOST_IP: - case ARDUINO_EVENT_WIFI_STA_STOP: - this->update_status(); - default: - Serial.print("Wifi Status: "); - Serial.println(WiFi.status()); - break; - } - if (WiFi.status() == WL_CONNECT_FAILED) - { - Serial.println("connection failed."); - WiFi.disconnect(); - } - Serial.println(WiFi.status()); -} - -bool wifiHandler::isAvailable(){ - return true; -} -std::shared_ptr wifiHandler::getInstance() -{ - if(mInstance) - { - return mInstance; - } - mInstance = std::shared_ptr(new wifiHandler()); +std::shared_ptr wifiHandler::getInstance() { + if (mInstance) { return mInstance; + } + mInstance = std::shared_ptr(new wifiHandler()); + return mInstance; }; -wifiHandler::wifiHandler() -{ - this->password = ""; - this->SSID = ""; -} - -void wifiHandler::update_status() -{ - Serial.println("update_status"); - std::shared_ptr status = std::make_shared(wifiStatus()); - //wifiStatus *status = new wifiStatus(); - status->isConnected = WiFi.isConnected(); - //status->IP = WiFi.localIP(); - IPAddress ip = WiFi.localIP(); - String ip_str = ip.toString(); - status->IP = ip.toString().c_str(); - - //ip.copy(status->IP, ip.length()); - String ssid = WiFi.SSID(); - status->ssid = WiFi.SSID().c_str(); - - //this->wifi_status.isConnected = WiFi.isConnected(); - //this->wifi_status.IP = WiFi.localIP(); - //this->wifi_status.isConnected = true; - - - //Serial.println(WiFi.localIP()); - this->status_update.notify(status); -} - -void wifiHandler::update_credentials() -{ - // No connection was attempted so don't try to to save the creds - if(!this->connect_attempt) return; -#if 0 - if (strcmp(temporary_password, wifiHandler::password) != 0 || strcmp(temporary_ssid, wifiHandler::SSID) != 0) - { - strcpy(wifiHandler::password, temporary_password); - strcpy(wifiHandler::SSID, temporary_ssid); - - Preferences preferences; - preferences.begin("wifiSettings", false); - String tempString = wifiHandler::password; - preferences.putString("password", tempString); - tempString = wifiHandler::SSID; - preferences.putString("SSID", tempString); - preferences.end(); +void wifiHandler::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t aEventInfo) { + int no_networks = 0; + switch (event) { + case ARDUINO_EVENT_WIFI_SCAN_DONE: { + no_networks = WiFi.scanComplete(); + auto info = std::vector(no_networks); + for (int i = 0; i < no_networks; i++) { + auto ssid = + WiFi.SSID(i).c_str() ? std::string(WiFi.SSID(i).c_str()) : "No SSID"; + info[i] = WifiInfo(ssid, WiFi.RSSI(i)); } -#else - if (this->temporary_password->compare(this->password) != 0 || this->temporary_ssid->compare(this->SSID)) - { - this->password = *(this->temporary_password); - this->SSID = *(this->temporary_ssid); - - Preferences preferences; - preferences.begin("wifiSettings", false); - String tempString = this->temporary_password->c_str(); - preferences.putString("password", tempString); - tempString = this->temporary_ssid->c_str(); - preferences.putString("SSID", tempString); - preferences.end(); + mScanNotification->notify(info); + if (WiFi.isConnected() == false) { + WiFi.reconnect(); + } + break; + } + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + StoreCredentials(); + WiFi.setAutoConnect(true); + UpdateStatus(); + break; + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + case ARDUINO_EVENT_WIFI_STA_STOP: + UpdateStatus(); + break; + default: + break; } -#endif -this->connect_attempt = false; } -void wifiHandler::scan() -{ +void wifiHandler::UpdateStatus() { + Serial.println("UpdateStatus"); + mCurrentStatus.isConnected = WiFi.isConnected(); + mCurrentStatus.IP = WiFi.localIP().toString().c_str(); + mCurrentStatus.ssid = + mCurrentStatus.isConnected ? WiFi.SSID().c_str() : mConnectionAttemptSSID; + + mStatusUpdate->notify(mCurrentStatus); +} + +void wifiHandler::StoreCredentials() { + // No connection was attempted so don't try to to save the creds + if (!mIsConnectionAttempt) { + return; + } + mPassword = mConnectionAttemptPassword; + mSSID = mConnectionAttemptSSID; + + Preferences preferences; + preferences.begin("wifiSettings", false); + preferences.putString("password", mPassword.c_str()); + preferences.putString("SSID", mSSID.c_str()); + preferences.end(); + + mConnectionAttemptPassword.clear(); + mConnectionAttemptSSID.clear(); + mIsConnectionAttempt = false; +} + +void wifiHandler::scan() { Serial.println("scan called"); - /* If the */ - WiFi.status(); - if (WiFi.isConnected() != true) - { + WiFi.setAutoReconnect(false); + WiFi.scanNetworks(true); +} + +void wifiHandler::begin() { + WiFi.setHostname("OMOTE"); + WiFi.mode(WIFI_STA); + WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t aEventInfo) { + mInstance->WiFiEvent(event, aEventInfo); + }); + + Preferences preferences; + preferences.begin("wifiSettings", false); + String ssid = preferences.getString("SSID"); + String password = preferences.getString("password"); + preferences.end(); + + // Attempt Connection with stored Credentials + if (!ssid.isEmpty()) { + connect(ssid.c_str(), password.c_str()); + } else { + Serial.println("no SSID or password stored"); WiFi.disconnect(); } - WiFi.scanNetworks(true); + + WiFi.setSleep(true); } - -void wifiHandler::begin() -{ - //this->display = display; - WiFi.setHostname("OMOTE"); - WiFi.mode(WIFI_STA); - //WiFi.onEvent([this] (WiFiEvent_t event) {mInstance->WiFiEvent(event);}); - WiFi.onEvent([] (WiFiEvent_t event) {mInstance->WiFiEvent(event);}); - - Preferences preferences; - preferences.begin("wifiSettings",false); - String ssid = preferences.getString("SSID"); - String password = preferences.getString("password"); - preferences.end(); - - /* If the SSID is not empty, there was a value stored in the preferences and we try to use it.*/ - if (!ssid.isEmpty()) - { - Serial.print("Connecting to wifi "); - Serial.println(ssid); - //strcpy(this->SSID, ssid.c_str()); - //strcpy(this->password, password.c_str()); - this->SSID = ssid.c_str(); - this->password = password.c_str(); - this->connect(std::make_shared(std::string(this->SSID)), std::make_shared(std::string(this->password))); - } - else - { - Serial.println("no SSID or password stored"); - /*Set first character to \0 indicates an empty string*/ - this->SSID[0] = '\0'; - this->password[0] = '\0'; - WiFi.disconnect(); - } - - WiFi.setSleep(true); +void wifiHandler::connect(std::string ssid, std::string password) { + Serial.printf("Attempting Wifi Connection To %s \n", ssid.c_str()); + mIsConnectionAttempt = true; + mConnectionAttemptPassword = password; + mConnectionAttemptSSID = ssid; + auto status = WiFi.begin(mConnectionAttemptSSID.c_str(), + mConnectionAttemptPassword.c_str()); } - -void wifiHandler::onScanDone(std::function>)> function){ - this->scan_notification.onNotify(std::move(function)); -} - -void wifiHandler::onStatusUpdate(std::function)> function){ - this->status_update.onNotify(std::move(function)); -} - -void wifiHandler::connect(std::shared_ptr ssid, std::shared_ptr password) -{ - this->connect_attempt = true; - this->temporary_password = password; - this->temporary_ssid = ssid; - WiFi.begin(ssid->c_str(), password->c_str()); -} - -void wifiHandler::turnOff() -{ - WiFi.disconnect(); - WiFi.mode(WIFI_OFF); -} - -void wifiHandler::disconnect(){ - WiFi.disconnect(); -} - -bool wifiHandler::isConnected() -{ - return WiFi.isConnected(); -} - -std::string wifiHandler::getIP() -{ - return std::string(WiFi.localIP().toString().c_str()); -} \ No newline at end of file diff --git a/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.hpp b/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.hpp index b9a855f..18c196e 100644 --- a/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.hpp +++ b/Platformio/HAL/Targets/ESP32/wifiHandler/wifihandler.hpp @@ -1,99 +1,53 @@ #pragma once -#include "wifiHandlerInterface.h" #include "Notification.hpp" #include "memory.h" +#include "wifiHandlerInterface.h" #include -#define STRING_SIZE 50 +class wifiHandler : public wifiHandlerInterface { +public: + static std::shared_ptr getInstance(); -class wifiHandler: public wifiHandlerInterface { - public: - wifiHandler(); - static std::shared_ptr getInstance(); - /** - * @brief Function to initialize the wifi handler - * - */ - void begin(); + // wifiHandlerInterface Implementation + void begin() override; + void scan() override; + void connect(std::string ssid, std::string password) override; + wifiStatus GetStatus() override { return mCurrentStatus; }; + // - /** - * @brief Connect to the wifi using the provided credetials - * - * @param SSID - * @param password - */ - void connect(std::shared_ptr ssid, std::shared_ptr password); - //void connect(const char* SSID, const char* password); +protected: + wifiHandler() = default; + static std::shared_ptr mInstance; + /** + * @brief Function to store the credentials when we have had a + * successful connection + */ + void StoreCredentials(); +private: + /** + * @brief Handler for incoming arduino wifi events + * @param event - a Wifi event + */ + void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t aEventInfo); - /** - * @brief function to trigger asynchronous scan for wifi networks - * - */ - void scan(); - bool isAvailable(); - void onScanDone(std::function>)> function); - void onStatusUpdate(std::function)> function); + /** + * @brief Update Internal status and send out a notification + */ + void UpdateStatus(); + wifiStatus mCurrentStatus; + /** + * @brief Variables used to track wifi connection attempts + */ + bool mIsConnectionAttempt = false; + std::string mConnectionAttemptPassword; + std::string mConnectionAttemptSSID; - private: - - Notification>> scan_notification; - Notification> status_update; - /** - * @brief Function to update the wifi credentials. This function is called in the wifi event callback function - * after a connection is established. Only then is the new credentials stored and the old stored credentials - * overwritten. - * - * @param temporary_ssid - * @param temporary_password - */ - void update_credentials(); - - void WiFiEvent(WiFiEvent_t event); - - /** - * @brief Function to turn off wifi - * - */ - void turnOff(); - /** - * @brief Function to get the IP address of this device - * - * @return String IP Address of the device - */ - std::string getIP(); - wifiStatus wifi_status; - static std::shared_ptr mInstance; - bool connect_attempt = false; - std::shared_ptr temporary_password; - std::shared_ptr temporary_ssid; - - void update_status(); - /** - * @brief Internal variable to store the wifi password - * - */ - std::string password; - - /** - * @brief Function to disconnect from the network - * - */ - void disconnect(); - - /** - * @brief Function to determine wether or not we are connected to a network - * - * @return true Device is connected to wifi network - * @return false Device is not connected to wifi network - */ - bool isConnected(); - /** - * @brief Internal variable to store the wifi SSID - * - */ - std::string SSID; - + /** + * @brief Verified Working User and Pass to Wifi network + */ + std::string mPassword; + std::string mSSID; }; \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp b/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp index e3ed62c..f39e434 100644 --- a/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp +++ b/Platformio/HAL/Targets/Simulator/HardwareSimulator.cpp @@ -3,70 +3,60 @@ #include "SDLDisplay.hpp" #include -HardwareSimulator::HardwareSimulator(): HardwareAbstract(), - mTickThread([](){ - while(true){ - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - lv_tick_inc(2); /*Tell lvgl that 2 milliseconds were elapsed*/ - }}), - mBattery(std::make_shared()), - mDisplay(SDLDisplay::getInstance()), - mWifiHandler(std::make_shared()) -{ - mHardwareStatusTitleUpdate = std::thread([this] { - int dataToShow = 0; - while (true) - { - std::stringstream title; - switch (dataToShow){ - case 0: - title << "Batt:" << mBattery->getPercentage() << "%" << std::endl; - break; - case 1: - title << "BKLght: " << static_cast(mDisplay->getBrightness()) << std::endl; - dataToShow = -1; - break; - default: - dataToShow = -1; - } - dataToShow++; - - mDisplay->setTitle(title.str()); - std::this_thread::sleep_for(std::chrono::seconds(2)); +HardwareSimulator::HardwareSimulator() + : HardwareAbstract(), mTickThread([]() { + while (true) { + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + lv_tick_inc(2); /*Tell lvgl that 2 milliseconds were elapsed*/ } - }); + }), + mBattery(std::make_shared()), + mDisplay(SDLDisplay::getInstance()), + mWifiHandler(std::make_shared()), + mKeys(std::make_shared()) { + mHardwareStatusTitleUpdate = std::thread([this] { + int dataToShow = 0; + while (true) { + std::stringstream title; + switch (dataToShow) { + case 0: + title << "Batt:" << mBattery->getPercentage() << "%" << std::endl; + break; + case 1: + title << "BKLght: " << static_cast(mDisplay->getBrightness()) + << std::endl; + dataToShow = -1; + break; + default: + dataToShow = -1; + } + dataToShow++; + + mDisplay->setTitle(title.str()); + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + }); } -std::shared_ptr HardwareSimulator::battery(){ - return mBattery; +std::shared_ptr HardwareSimulator::battery() { + return mBattery; } -std::shared_ptr HardwareSimulator::display(){ - return mDisplay; +std::shared_ptr HardwareSimulator::display() { + return mDisplay; } -std::shared_ptr HardwareSimulator::wifi(){ - return mWifiHandler; +std::shared_ptr HardwareSimulator::wifi() { + return mWifiHandler; } +std::shared_ptr HardwareSimulator::keys() { return mKeys; } -char HardwareSimulator::getCurrentDevice(){ - return 0; -} +char HardwareSimulator::getCurrentDevice() { return 0; } -void HardwareSimulator::setCurrentDevice(char currentDevice){ +void HardwareSimulator::setCurrentDevice(char currentDevice) {} -} +bool HardwareSimulator::getWakeupByIMUEnabled() { return true; } -bool HardwareSimulator::getWakeupByIMUEnabled(){ - return true; -} +void HardwareSimulator::setWakeupByIMUEnabled(bool wakeupByIMUEnabled) {} -void HardwareSimulator::setWakeupByIMUEnabled(bool wakeupByIMUEnabled){ +uint16_t HardwareSimulator::getSleepTimeout() { return 20000; } -} - -uint16_t HardwareSimulator::getSleepTimeout(){ - return 20000; -} - -void HardwareSimulator::setSleepTimeout(uint16_t sleepTimeout){ - -} +void HardwareSimulator::setSleepTimeout(uint16_t sleepTimeout) {} diff --git a/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp b/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp index c1ec999..cd6d966 100644 --- a/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp +++ b/Platformio/HAL/Targets/Simulator/HardwareSimulator.hpp @@ -1,8 +1,9 @@ #pragma once #include "HardwareAbstract.hpp" -#include "batterySimulator.hpp" +#include "KeyPressSim.hpp" #include "SDLDisplay.hpp" +#include "batterySimulator.hpp" #include "wifiHandlerSim.hpp" #include @@ -10,28 +11,30 @@ class HardwareSimulator : public HardwareAbstract { public: HardwareSimulator(); - - virtual void init() override {}; - virtual void debugPrint(const char* fmt, ...) override { + void init() override{}; + void loopHandler() override{}; + + void debugPrint(const char *fmt, ...) override { va_list arguments; va_start(arguments, fmt); vprintf(fmt, arguments); va_end(arguments); } - virtual std::shared_ptr battery() override; - virtual std::shared_ptr display() override; - virtual std::shared_ptr wifi() override; + std::shared_ptr battery() override; + std::shared_ptr display() override; + std::shared_ptr wifi() override; + std::shared_ptr keys() override; - virtual char getCurrentDevice() override; - virtual void setCurrentDevice(char currentDevice) override; + char getCurrentDevice() override; + void setCurrentDevice(char currentDevice) override; - virtual bool getWakeupByIMUEnabled() override; - virtual void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override; + bool getWakeupByIMUEnabled() override; + void setWakeupByIMUEnabled(bool wakeupByIMUEnabled) override; - virtual uint16_t getSleepTimeout() override; - virtual void setSleepTimeout(uint16_t sleepTimeout) override; + uint16_t getSleepTimeout() override; + void setSleepTimeout(uint16_t sleepTimeout) override; private: std::thread mTickThread; @@ -40,4 +43,5 @@ private: std::shared_ptr mBattery; std::shared_ptr mDisplay; std::shared_ptr mWifiHandler; + std::shared_ptr mKeys; }; diff --git a/Platformio/HAL/Targets/Simulator/KeyPressSim.cpp b/Platformio/HAL/Targets/Simulator/KeyPressSim.cpp new file mode 100644 index 0000000..12a9ac6 --- /dev/null +++ b/Platformio/HAL/Targets/Simulator/KeyPressSim.cpp @@ -0,0 +1,44 @@ +#include "KeyPressSim.hpp" + +#include + +KeyPressSim::KeyPressSim() + : mKeyHandlerThread([this] { + while (true) { + HandleKeyPresses(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + }) { + SDL_AddEventWatch(KeyPressSim::GrabKeyImpl, this); +}; + +int KeyPressSim::GrabKeyImpl(void *aSelf, SDL_Event *aEvent) { + reinterpret_cast(aSelf)->GrabKeys(aEvent); + return 0; +} + +void KeyPressSim::GrabKeys(SDL_Event *aEvent) { + if (aEvent->type == SDL_KEYDOWN || aEvent->type == SDL_KEYUP) { + auto keyEventType = aEvent->type == SDL_KEYDOWN ? KeyEvent::Type::Press + : KeyEvent::Type::Release; + const auto SDLK_key = aEvent->key.keysym.sym; + if (KeyMap.count(SDLK_key) > 0) { + QueueKeyEvent(KeyEvent(KeyMap.at(SDLK_key), keyEventType)); + } + } +}; + +void KeyPressSim::HandleKeyPresses() { + std::lock_guard lock(mQueueGaurd); + while (!mKeyEventQueue.empty()) { + if (mKeyEventHandler) { + mKeyEventHandler(mKeyEventQueue.front()); + } + mKeyEventQueue.pop(); + } +}; + +void KeyPressSim::QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) { + std::lock_guard lock(mQueueGaurd); + mKeyEventQueue.push(aJustOccuredKeyEvent); +}; diff --git a/Platformio/HAL/Targets/Simulator/KeyPressSim.hpp b/Platformio/HAL/Targets/Simulator/KeyPressSim.hpp new file mode 100644 index 0000000..1f7aff3 --- /dev/null +++ b/Platformio/HAL/Targets/Simulator/KeyPressSim.hpp @@ -0,0 +1,59 @@ +#include "KeyPressAbstract.hpp" +#include "SDL2/SDL.h" + +#include +#include +#include +#include + +class KeyPressSim : public KeyPressAbstract { +public: + static constexpr auto MaxQueueableKeyEvents = 3; + + KeyPressSim(); + + static int GrabKeyImpl(void *aSelf, SDL_Event *aEvent); + void GrabKeys(SDL_Event *aEvent); + + void HandleKeyPresses() override; + void QueueKeyEvent(KeyEvent aJustOccuredKeyEvent) override; + +private: + std::thread mKeyGrabberThread; + std::thread mKeyHandlerThread; + std::queue mKeyEventQueue; + std::mutex mQueueGaurd; + + using Key = KeyPressAbstract::KeyId; + static inline const std::map KeyMap{ + {SDLK_p, Key::Power}, + // Video Control row + {SDLK_5, Key::Stop}, + {SDLK_6, Key::Rewind}, + {SDLK_7, Key::Play}, + {SDLK_8, Key::FastForward}, + // D-Pad + {SDLK_UP, Key::Up}, + {SDLK_DOWN, Key::Down}, + {SDLK_LEFT, Key::Left}, + {SDLK_RIGHT, Key::Right}, + {SDLK_SPACE, Key::Center}, + // General Keys + {SDLK_h, Key::Menu}, + {SDLK_j, Key::Info}, + {SDLK_l, Key::Back}, + {SDLK_k, Key::Source}, + // Volume/ Channel UP and down + {SDLK_w, Key::VolUp}, + {SDLK_s, Key::VolDown}, + {SDLK_e, Key::ChannelUp}, + {SDLK_d, Key::ChannelDown}, + // Mute & record + {SDLK_x, Key::Mute}, + {SDLK_c, Key::Record}, + // Aux Keys + {SDLK_1, Key::Aux1}, + {SDLK_2, Key::Aux2}, + {SDLK_3, Key::Aux3}, + {SDLK_4, Key::Aux4}}; +}; \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/SDLDisplay.cpp b/Platformio/HAL/Targets/Simulator/SDLDisplay.cpp index 461cf61..1552e7d 100644 --- a/Platformio/HAL/Targets/Simulator/SDLDisplay.cpp +++ b/Platformio/HAL/Targets/Simulator/SDLDisplay.cpp @@ -1,39 +1,39 @@ #include "SDLDisplay.hpp" #include "sdl/sdl.h" -#include +#include -std::shared_ptr SDLDisplay::getInstance(){ - if (!DisplayAbstract::mInstance){ - DisplayAbstract::mInstance = std::shared_ptr(new SDLDisplay()); - } - return std::static_pointer_cast(mInstance); +std::shared_ptr SDLDisplay::getInstance() { + if (!DisplayAbstract::mInstance) { + DisplayAbstract::mInstance = std::shared_ptr(new SDLDisplay()); + } + return std::static_pointer_cast(mInstance); } -void SDLDisplay::setBrightness(uint8_t brightness){ - mBrightness = brightness; +void SDLDisplay::setBrightness(uint8_t brightness) { mBrightness = brightness; } + +uint8_t SDLDisplay::getBrightness() { return mBrightness; } + +void SDLDisplay::turnOff() {} + +void SDLDisplay::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, + lv_color_t *color_p) { + sdl_display_flush(disp, area, color_p); } -uint8_t SDLDisplay::getBrightness(){ - return mBrightness; +void SDLDisplay::screenInput(lv_indev_drv_t *indev_driver, + lv_indev_data_t *data) { + sdl_mouse_read(indev_driver, data); } -void SDLDisplay::turnOff(){ - +void SDLDisplay::setTitle(std::string aNewTitle) { + SDL_SetWindowTitle(mSimWindow, aNewTitle.c_str()); } -void SDLDisplay::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p){ - sdl_display_flush(disp,area,color_p); -} +SDLDisplay::SDLDisplay() : DisplayAbstract() { + sdl_init(); -void SDLDisplay::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){ - sdl_mouse_read(indev_driver,data); -} - -void SDLDisplay::setTitle(std::string aNewTitle){ - SDL_SetWindowTitle(mSimWindow,aNewTitle.c_str()); -} - -SDLDisplay::SDLDisplay(): DisplayAbstract() { - sdl_init(); - mSimWindow = SDL_GetWindowFromID(1); // Get the SDL window via ID hopefully it is always 1... + // Get the SDL window via an event + SDL_Event aWindowIdFinder; + SDL_PollEvent(&aWindowIdFinder); + mSimWindow = SDL_GetWindowFromID(aWindowIdFinder.window.windowID); } \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/SDLDisplay.hpp b/Platformio/HAL/Targets/Simulator/SDLDisplay.hpp index 98f58b2..f88c189 100644 --- a/Platformio/HAL/Targets/Simulator/SDLDisplay.hpp +++ b/Platformio/HAL/Targets/Simulator/SDLDisplay.hpp @@ -1,25 +1,27 @@ #pragma once -#include -#include "SDL2/SDL.h" #include "DisplayAbstract.h" +#include "SDL2/SDL.h" +#include -class SDLDisplay : public DisplayAbstract{ +class SDLDisplay : public DisplayAbstract { public: - static std::shared_ptr getInstance(); + static std::shared_ptr getInstance(); - virtual void setBrightness(uint8_t brightness) override; - virtual uint8_t getBrightness() override; - virtual void turnOff() override; + virtual void setBrightness(uint8_t brightness) override; + virtual uint8_t getBrightness() override; + virtual void turnOff() override; - void setTitle(std::string aNewTitle); + void setTitle(std::string aNewTitle); protected: - virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) override; - virtual void screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) override; + virtual void flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area, + lv_color_t *color_p) override; + virtual void screenInput(lv_indev_drv_t *indev_driver, + lv_indev_data_t *data) override; private: - SDLDisplay(); - uint8_t mBrightness; - SDL_Window* mSimWindow; + SDLDisplay(); + uint8_t mBrightness; + SDL_Window *mSimWindow; }; \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/SimulatorSPSCQueue.cpp b/Platformio/HAL/Targets/Simulator/SimulatorSPSCQueue.cpp index 4f8bcd2..a78eee4 100644 --- a/Platformio/HAL/Targets/Simulator/SimulatorSPSCQueue.cpp +++ b/Platformio/HAL/Targets/Simulator/SimulatorSPSCQueue.cpp @@ -4,7 +4,7 @@ template SimulatorSPSCQueue::SimulatorSPSCQueue(uint32_t size) { this->size = size; - this->data = new T[](this->size + 1); + this->data = new T[this->size + 1]; this->rd_index = 0; this->wr_index = 0; } diff --git a/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.cpp b/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.cpp index 7534534..8b3bab5 100644 --- a/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.cpp +++ b/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.cpp @@ -1,68 +1,35 @@ #include "wifiHandlerSim.hpp" -std::shared_ptr mInstance; +using WifiInfo = wifiHandlerInterface::WifiInfo; -std::shared_ptr wifiHandlerSim::getInstance() -{ - if(mInstance) - { - return mInstance; - } - mInstance = std::make_shared(wifiHandlerSim()); - return mInstance; -}; +wifiHandlerSim::wifiHandlerSim() {} -wifiHandlerSim::wifiHandlerSim(){ +void wifiHandlerSim::begin() {} -} - -void wifiHandlerSim::begin(){ - -} - -static wifiStatus status = { - .isConnected = true - , .IP = "172.0.0.1" -}; - -void wifiHandlerSim::connect(std::shared_ptr ssid, std::shared_ptr password){ - status.ssid = *ssid; - std::shared_ptr new_status = std::make_shared (wifiStatus(std::move(status))); - this->status_update.notify(new_status); +void wifiHandlerSim::connect(std::string ssid, std::string password) { + if (mFakeStatusThread.joinable()) { + mFakeStatusThread.join(); + mCurrentStatus.ssid = ssid; + mCurrentStatus.isConnected = true; + mFakeStatusThread = std::thread([this] { + std::this_thread::sleep_for(std::chrono::seconds(1)); + mStatusUpdate->notify(mCurrentStatus); + }); + } } static const WifiInfo wifis[] = { - { - .ssid = "High Signal Wifi" - , .rssi = -49 - } - , { - .ssid = "Mid Signal Wifi" - , .rssi = -55 - } - , { - .ssid = "Low Signal Wifi" - , .rssi = -65 - } - , { - .ssid = "No Signal Wifi" - , .rssi = -90 - } -}; + WifiInfo("High Signal Wifi", -49), WifiInfo("Mid Signal Wifi", -55), + WifiInfo("Low Signal Wifi", -65), WifiInfo("No Signal Wifi", -90)}; -void wifiHandlerSim::scan(){ - std::shared_ptr> info = std::make_shared>(std::vector(std::begin(wifis), std::end(wifis))); - this->scan_notification.notify(info); +void wifiHandlerSim::scan() { + if (mFakeScanThread.joinable()) { + mFakeScanThread.join(); + mFakeScanThread = std::thread([this] { + std::vector info = + std::vector(std::begin(wifis), std::end(wifis)); + std::this_thread::sleep_for(std::chrono::seconds(2)); + mScanNotification->notify(info); + }); + } } - -bool wifiHandlerSim::isAvailable(){ - return false; -} - -void wifiHandlerSim::onScanDone(std::function>)> function){ - this->scan_notification.onNotify(std::move(function)); -} - -void wifiHandlerSim::onStatusUpdate(std::function)> function){ - this->status_update.onNotify(std::move(function)); -} \ No newline at end of file diff --git a/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.hpp b/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.hpp index e994450..ee5022b 100644 --- a/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.hpp +++ b/Platformio/HAL/Targets/Simulator/wifiHandlerSim/wifiHandlerSim.hpp @@ -1,35 +1,21 @@ #pragma once -#include "wifiHandlerInterface.h" #include "Notification.hpp" +#include "wifiHandlerInterface.h" +#include #include +#include -class wifiHandlerSim: public wifiHandlerInterface { - public: - wifiHandlerSim(); - static std::shared_ptr getInstance(); +class wifiHandlerSim : public wifiHandlerInterface { +public: + wifiHandlerSim(); - - /** - * @brief Connect to the wifi using the provided credetials - * - * @param SSID - * @param password - */ - void connect(std::shared_ptr ssid, std::shared_ptr password); - //void connect(const char* SSID, const char* password); + void begin() override; + void scan() override; + void connect(std::string ssid, std::string password) override; + wifiStatus GetStatus() override { return mCurrentStatus; }; - - - /** - * @brief function to trigger asynchronous scan for wifi networks - * - */ - void scan(); - bool isAvailable(); - void begin(); - void onScanDone(std::function>)> function); - void onStatusUpdate(std::function)> function); - private: - Notification>> scan_notification; - Notification> status_update; +private: + std::thread mFakeScanThread = std::thread([] {}); + std::thread mFakeStatusThread = std::thread([] {}); + wifiStatus mCurrentStatus = wifiStatus(true, "172.0.0.1", "FakeNet"); }; \ No newline at end of file diff --git a/Platformio/OmoteUI/Images.cpp b/Platformio/OmoteUI/Images.cpp deleted file mode 100644 index 0a32e1a..0000000 --- a/Platformio/OmoteUI/Images.cpp +++ /dev/null @@ -1,1154 +0,0 @@ -#include "Images.hpp" - -static void update_default_image_color(lv_obj_t* image) -{ - lv_obj_set_style_img_recolor(image, lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_img_recolor_opa(image, LV_OPA_COVER, LV_PART_MAIN); -} - -Images::Images(){ - setupImageDescriptions(); -} - -lv_obj_t* Images::addAppleTVIcon(lv_obj_t* parent) { - return this->addImg(parent, &this->appleTvIcon); -} -lv_obj_t* Images::addAppleDisplayImage(lv_obj_t* parent) { - lv_obj_t* appleImg = this->addImg(parent, &this->appleDisplayIcon); - lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN); - return appleImg; -} -lv_obj_t* Images::addAppleBackIcon(lv_obj_t* parent) { - return this->addImg(parent, &this->appleBackIcon); -} - -lv_obj_t* Images::addLowBrightnessIcon(lv_obj_t* parent) { - lv_obj_t* lowBrightnessIcon = this->addImg(parent, &this->low_brightness); - lv_obj_set_style_img_recolor(lowBrightnessIcon, lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_img_recolor_opa(lowBrightnessIcon, LV_OPA_COVER, LV_PART_MAIN); - return lowBrightnessIcon; -} -lv_obj_t* Images::addHighBrightnessIcon(lv_obj_t* parent) { - lv_obj_t* highBrightnessIcon = this->addImg(parent, &this->high_brightness); - lv_obj_set_style_img_recolor(highBrightnessIcon, lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_img_recolor_opa(highBrightnessIcon, LV_OPA_COVER, LV_PART_MAIN); - return highBrightnessIcon; -} -lv_obj_t* Images::addLightBulbIcon(lv_obj_t* parent){ - lv_obj_t* bulbIcon = this->addImg(parent, &this->lightbulb_icon); - lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN); - return bulbIcon; -} - -lv_obj_t* Images::addWifiNoSignal(lv_obj_t* parent){ - lv_obj_t* noSignal = this->addImg(parent, &this->wifiNoSignal); - update_default_image_color(noSignal); - return noSignal; -} -lv_obj_t* Images::addWifiLowSignal(lv_obj_t* parent){ - lv_obj_t* lowSignal = this->addImg(parent, &this->wifiLowSignal); - update_default_image_color(lowSignal); - return lowSignal; -} -lv_obj_t* Images::addWifiMidSignal(lv_obj_t* parent){ - lv_obj_t* lowSignal = this->addImg(parent, &this->wifiMidSignal); - update_default_image_color(lowSignal); - return lowSignal; -} -lv_obj_t* Images::addWifiHighSignal(lv_obj_t* parent){ - lv_obj_t* lowSignal = this->addImg(parent, &this->wifiHighSignal); - update_default_image_color(lowSignal); - return lowSignal; -} - -lv_obj_t* Images::addLeftGradiant(lv_obj_t* parent){ - return this->addImg(parent, &this->gradientLeft); -} - -lv_obj_t* Images::addRightGradiant(lv_obj_t* parent){ - return this->addImg(parent, &this->gradientRight); -} - -lv_obj_t* Images::addImg(lv_obj_t* parent, lv_img_dsc_t* anImgDesc) { - lv_obj_t* img = lv_img_create(parent); - lv_img_set_src(img, anImgDesc); - return img; -} - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - gradientLeft_map[] = { - 0xfa, 0xf2, 0xea, 0xe2, 0xda, 0xd1, 0xc7, 0xbe, 0xb7, 0xae, - 0xa6, 0x9e, 0x95, 0x8d, 0x84, 0x7d, 0x74, 0x6c, 0x62, 0x5a, - 0x51, 0x48, 0x41, 0x38, 0x2f, 0x28, 0x1f, 0x17, 0x0f, 0x07, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - gradientRight_map[] = { - 0x07, 0x0f, 0x17, 0x1f, 0x28, 0x2f, 0x38, 0x41, 0x48, 0x51, - 0x5a, 0x62, 0x6c, 0x74, 0x7d, 0x84, 0x8d, 0x95, 0x9e, 0xa6, - 0xae, 0xb7, 0xbe, 0xc7, 0xd1, 0xda, 0xe2, 0xea, 0xf2, 0xfa, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - appleTvIcon_map[] = { - /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x42, 0x55, 0xad, 0xdb, 0xde, 0x1c, 0xe7, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0xad, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x5d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xce, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, - 0x21, 0x34, 0xa5, 0x55, 0xad, 0x55, 0xad, 0x55, 0xad, 0x55, 0xad, - 0x55, 0xad, 0x55, 0xad, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x76, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, - 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x8c, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x69, 0x4a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0x65, 0x29, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, - 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, - 0x8a, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xce, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x9a, 0xd6, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0xad, 0x9a, 0xd6, 0xd7, 0xbd, 0x8e, 0x73, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xd7, - 0xbd, 0xbb, 0xde, 0x3c, 0xe7, 0xfc, 0xe6, 0x39, 0xce, 0x72, 0x94, - 0xa7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xa3, 0x18, 0x8e, 0x73, 0xd7, 0xbd, 0x1c, 0xe7, 0x9e, 0xf7, - 0xbe, 0xf7, 0x5d, 0xef, 0x9a, 0xd6, 0x34, 0xa5, 0x28, 0x42, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, - 0x6b, 0xfb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x7a, 0xd6, 0x71, - 0x8c, 0xa6, 0x31, 0x2d, 0x6b, 0xb6, 0xb5, 0x7d, 0xef, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xff, 0xd7, 0xbd, 0xa3, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xb3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x3c, 0xe7, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xe7, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x69, 0x4a, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, - 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf7, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x14, - 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x9c, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, - 0xef, 0x24, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x45, 0x29, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x1c, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x63, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0xeb, 0x5a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x9c, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x10, 0x84, 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, 0xc6, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xde, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, - 0x86, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xce, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x86, 0x31, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xce, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xe7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x8e, - 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x3d, 0xef, 0x86, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x59, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x73, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xd6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xce, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0x3c, 0xe7, 0x3c, - 0xe7, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x3c, 0xe7, 0x3c, - 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x96, 0xb5, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x71, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7a, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x18, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xec, 0x62, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x8c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xbd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, - 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, - 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x9c, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xe4, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x5d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xbf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xa5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, - 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xeb, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0xb5, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xa5, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x28, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2d, 0x6b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, - 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x29, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x92, 0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xae, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, - 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, - 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x96, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xde, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, - 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x94, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0xe7, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd3, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x8a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x28, 0x42, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x52, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x45, 0x29, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, - 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x7a, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 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, 0xc6, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x75, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x59, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xd6, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, - 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x29, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x7b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf4, 0xa4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x86, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x55, 0xad, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, - 0xef, 0xa3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x31, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0xef, 0x7b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xb5, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, - 0x00, 0x00, 0x00, 0x00, 0xfb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xbd, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x9a, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0c, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0x00, 0x00, 0x29, 0x4a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xeb, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xce, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xde, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe7, 0x39, 0xf3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xe7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x7d, 0xef, 0x24, 0x21, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x86, 0x31, 0x29, 0x4a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xbb, 0xde, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, - 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x51, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0xe6, 0xd3, 0x9c, 0x51, 0x8c, 0x34, 0xa5, 0x9a, 0xd6, 0xdf, - 0xff, 0xf7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, - 0x31, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xff, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xe6, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, - 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0xe7, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xce, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xd6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xec, 0x62, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x79, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xe7, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xe7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x51, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x55, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0xe7, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xb7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, - 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xce, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbd, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x18, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xd6, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, 0x94, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 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, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x39, 0xce, 0x72, 0x94, 0xcb, - 0x5a, 0xa3, 0x18, 0x4d, 0x6b, 0x34, 0xa5, 0xfb, 0xde, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x72, - 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xaf, 0x7b, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7d, 0xef, 0xd7, 0xbd, 0xeb, 0x5a, 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, 0xe7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x5d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6e, 0x73, 0xf8, 0xc5, 0xba, 0xd6, 0xd7, 0xbd, 0xf0, 0x83, 0xa3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x4a, 0xf3, 0x9c, 0xf8, 0xc5, 0x59, - 0xce, 0x55, 0xad, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xae, 0x73, 0x76, 0xb5, 0x39, 0xce, 0x7a, 0xd6, 0x39, 0xce, - 0xd7, 0xbd, 0xd3, 0x9c, 0xec, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x29, 0x4a, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, - 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x49, 0x4a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - appleDisplayIcon_map[] = { - 0x23, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd8, 0x3d, 0xaa, 0xfd, 0xad, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0xa1, 0xf7, 0xd8, 0xd0, 0xd1, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xff, 0xd2, 0xcb, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, - 0xff, 0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x9a, 0xff, 0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xd2, 0xcb, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xd2, - 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9a, 0xff, 0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x9a, 0xff, 0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xd2, 0xcb, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, - 0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x9a, 0xff, 0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xd2, 0xcb, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, 0xc6, 0xea, - 0x2a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1f, 0xcc, - 0xf6, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x98, 0x00, 0x44, 0x7b, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x7d, 0x56, 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, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xb7, 0xc4, 0xc4, 0xc4, 0xc4, - 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc0, 0x2c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd3, 0xde, - 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdb, 0x36, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - appleBackIcon_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3d, 0xbe, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xff, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xfa, 0xff, 0xf5, 0x31, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0xfc, 0xff, 0xea, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0xee, 0xff, 0xe6, - 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x50, 0xed, 0xff, - 0xe9, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xfc, - 0xff, 0xe7, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, - 0xff, 0xff, 0xe0, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5e, 0xf6, 0xff, 0xdb, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x64, 0xf4, 0xff, 0xd9, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4d, 0xff, 0xff, 0xce, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6b, 0xff, 0xff, 0x9e, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xa8, - 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x8f, - 0xff, 0xff, 0xb5, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x91, 0xff, 0xff, 0xba, 0x12, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xff, 0xff, 0xbb, 0x0a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0xfc, 0xff, - 0xbf, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xfb, 0xff, 0xc5, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x78, 0xff, 0xff, 0xca, 0x1e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xff, 0xff, 0xd0, 0x11, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6e, 0xfb, - 0xff, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x68, 0xea, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x28, 0x18, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - high_brightness_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, - 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00, 0x00, - 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, - 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa9, 0xf5, - 0x0d, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x42, 0xd4, 0xff, - 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbd, 0xcc, 0xbd, 0xbd, 0xcc, 0xbd, - 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, - 0x0d, 0xbd, 0xcc, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x0a, 0x00, 0x40, 0xd3, 0xff, 0xfe, 0xd2, 0x3f, 0x00, 0x0a, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, - 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, - 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8e, 0x04, - 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, - 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - low_brightness_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x43, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, - 0x72, 0x28, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, - 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x0b, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, - 0x00, 0x00, 0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbc, 0x44, 0x43, 0xbd, 0x0d, 0x11, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x11, 0x0d, 0xbc, - 0x44, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x0b, 0x00, 0x40, 0xd3, 0xfe, 0xff, 0xd2, 0x3f, - 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, - 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00, 0x00, - 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, - 0x72, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t - lightbulb_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x1c, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x95, 0xee, 0xff, 0xff, 0xee, 0x94, 0x15, - 0x00, 0x00, 0x00, 0x27, 0xe3, 0xff, 0xcc, 0x8d, 0x8d, 0xcd, 0xff, - 0xe1, 0x26, 0x00, 0x07, 0xd9, 0xfa, 0x5d, 0x00, 0x00, 0x00, 0x00, - 0x5f, 0xfa, 0xd7, 0x06, 0x65, 0xff, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7a, 0xff, 0x63, 0xb1, 0xf8, 0x0c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0xf8, 0xaf, 0xcc, 0xdc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xcd, 0xb1, 0xf5, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf1, 0xbd, 0x73, 0xff, 0x74, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xff, 0x74, 0x0b, 0xd5, - 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfb, 0xd9, 0x0b, 0x00, - 0x24, 0xef, 0xdc, 0x01, 0x00, 0x00, 0x01, 0xdd, 0xee, 0x24, 0x00, - 0x00, 0x00, 0x83, 0xff, 0x30, 0x00, 0x00, 0x30, 0xff, 0x81, 0x00, - 0x00, 0x00, 0x00, 0x12, 0x6c, 0x06, 0x00, 0x00, 0x06, 0x6c, 0x12, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, - 0xc7, 0x25, 0x00, 0x00, 0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, - 0xcc, 0xc7, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x76, - 0x77, 0x77, 0x76, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, - 0xff, 0xff, 0xff, 0xff, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x21, 0x22, 0x22, 0x21, 0x01, 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t WiFi_No_Signal_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t WiFi_Mid_Signal_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t WiFi_Low_Signal_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -inline static const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t WiFi_High_Signal_map[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void Images::setupImageDescriptions(){ - this->low_brightness.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->low_brightness.header.always_zero = 0; - this->low_brightness.header.reserved = 0; - this->low_brightness.header.w = 16; - this->low_brightness.header.h = 16; - this->low_brightness.data_size = 256; - this->low_brightness.data = low_brightness_map; - - this->high_brightness.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->high_brightness.header.always_zero = 0; - this->high_brightness.header.reserved = 0; - this->high_brightness.header.w = 18; - this->high_brightness.header.h = 18; - this->high_brightness.data_size = 352; - this->high_brightness.data = high_brightness_map; - - this->appleTvIcon.header.cf = LV_IMG_CF_TRUE_COLOR; - this->appleTvIcon.header.always_zero = 0; - this->appleTvIcon.header.reserved = 0; - this->appleTvIcon.header.w = 91; - this->appleTvIcon.header.h = 42; - this->appleTvIcon.data_size = 3822 * LV_COLOR_SIZE / 8; - this->appleTvIcon.data = appleTvIcon_map; - - this->appleDisplayIcon.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->appleDisplayIcon.header.always_zero = 0; - this->appleDisplayIcon.header.reserved = 0; - this->appleDisplayIcon.header.w = 25; - this->appleDisplayIcon.header.h = 20; - this->appleDisplayIcon.data_size = 500; - this->appleDisplayIcon.data = appleDisplayIcon_map; - - this->appleBackIcon.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->appleBackIcon.header.always_zero = 0; - this->appleBackIcon.header.reserved = 0; - this->appleBackIcon.header.w = 13; - this->appleBackIcon.header.h = 25; - this->appleBackIcon.data_size = 325; - this->appleBackIcon.data = appleBackIcon_map; - - this->lightbulb_icon.header.cf = LV_IMG_CF_ALPHA_8BIT, lightbulb_icon.header.always_zero = 0, - this->lightbulb_icon.header.reserved = 0, lightbulb_icon.header.w = 12, - this->lightbulb_icon.header.h = 20, lightbulb_icon.data_size = 240, - this->lightbulb_icon.data = lightbulb_map; - - this->gradientLeft.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->gradientLeft.header.always_zero = 0; - this->gradientLeft.header.reserved = 0; - this->gradientLeft.header.w = 30; - this->gradientLeft.header.h = 1; - this->gradientLeft.data_size = 30; - this->gradientLeft.data = gradientLeft_map; - - this->gradientRight.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->gradientRight.header.always_zero = 0; - this->gradientRight.header.reserved = 0; - this->gradientRight.header.w = 30; - this->gradientRight.header.h = 1; - this->gradientRight.data_size = 30; - this->gradientRight.data = gradientRight_map; - - this->wifiNoSignal.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->wifiNoSignal.header.always_zero = 0; - this->wifiNoSignal.header.reserved = 0; - this->wifiNoSignal.header.w = 25; - this->wifiNoSignal.header.h = 21; - this->wifiNoSignal.data_size = 525; - this->wifiNoSignal.data = WiFi_No_Signal_map; - - this->wifiLowSignal.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->wifiLowSignal.header.always_zero = 0; - this->wifiLowSignal.header.reserved = 0; - this->wifiLowSignal.header.w = 25; - this->wifiLowSignal.header.h = 21; - this->wifiLowSignal.data_size = 525; - this->wifiLowSignal.data = WiFi_Low_Signal_map; - - this->wifiMidSignal.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->wifiMidSignal.header.always_zero = 0; - this->wifiMidSignal.header.reserved = 0; - this->wifiMidSignal.header.w = 25; - this->wifiMidSignal.header.h = 21; - this->wifiMidSignal.data_size = 525; - this->wifiMidSignal.data = WiFi_Mid_Signal_map; - - this->wifiHighSignal.header.cf = LV_IMG_CF_ALPHA_8BIT; - this->wifiHighSignal.header.always_zero = 0; - this->wifiHighSignal.header.reserved = 0; - this->wifiHighSignal.header.w = 25; - this->wifiHighSignal.header.h = 21; - this->wifiHighSignal.data_size = 525; - this->wifiHighSignal.data = WiFi_High_Signal_map; - -} \ No newline at end of file diff --git a/Platformio/OmoteUI/Images.hpp b/Platformio/OmoteUI/Images.hpp deleted file mode 100644 index be23311..0000000 --- a/Platformio/OmoteUI/Images.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// OMOTE UI Images -// 2023 Matthew Colvin -#pragma once -#include "lvgl.h" - -class Images{ - -public: - Images(); - - lv_obj_t* addAppleTVIcon(lv_obj_t* parent); - lv_obj_t* addAppleDisplayImage(lv_obj_t* parent); - lv_obj_t* addAppleBackIcon(lv_obj_t* parent); - - lv_obj_t* addLowBrightnessIcon(lv_obj_t* parent); - lv_obj_t* addHighBrightnessIcon(lv_obj_t* parent); - lv_obj_t* addLightBulbIcon(lv_obj_t* parent); - - lv_obj_t* addLeftGradiant(lv_obj_t* parent); - lv_obj_t* addRightGradiant(lv_obj_t* parent); - - lv_obj_t* addWifiNoSignal(lv_obj_t* parent); - lv_obj_t* addWifiLowSignal(lv_obj_t* parent); - lv_obj_t* addWifiMidSignal(lv_obj_t* parent); - lv_obj_t* addWifiHighSignal(lv_obj_t* parent); - - -private: - // Make Image based on anImageDesc then - // add that image to parent. - lv_obj_t* addImg(lv_obj_t* parent, lv_img_dsc_t* anImgDesc); - void setupImageDescriptions(); - - lv_img_dsc_t appleTvIcon; - lv_img_dsc_t appleDisplayIcon; - lv_img_dsc_t appleBackIcon; - - lv_img_dsc_t low_brightness; - lv_img_dsc_t high_brightness; - lv_img_dsc_t lightbulb_icon; - - lv_img_dsc_t gradientLeft; - lv_img_dsc_t gradientRight; - - lv_img_dsc_t wifiNoSignal; - lv_img_dsc_t wifiLowSignal; - lv_img_dsc_t wifiMidSignal; - lv_img_dsc_t wifiHighSignal; - -}; \ No newline at end of file diff --git a/Platformio/OmoteUI/OmoteUI.cpp b/Platformio/OmoteUI/UIs/Basic/OmoteUI.cpp similarity index 68% rename from Platformio/OmoteUI/OmoteUI.cpp rename to Platformio/OmoteUI/UIs/Basic/OmoteUI.cpp index ebeada7..750d9cf 100644 --- a/Platformio/OmoteUI/OmoteUI.cpp +++ b/Platformio/OmoteUI/UIs/Basic/OmoteUI.cpp @@ -3,13 +3,16 @@ #include "omoteconfig.h" #include +using namespace UI::Basic; + std::shared_ptr OmoteUI::mInstance = nullptr; // This can be used to flag out specific code for SIM only // #if defined(IS_SIMULATOR) && (IS_SIMULATOR == true) // #endif -OmoteUI::OmoteUI(std::shared_ptr aHardware) : mHardware(aHardware){} +OmoteUI::OmoteUI(std::shared_ptr aHardware) + : UIBase(aHardware) {} // Set the page indicator scroll position relative to the tabview scroll // position @@ -37,17 +40,18 @@ void OmoteUI::bl_slider_event_cb(lv_event_t *e) { // Apple Key Event handler void OmoteUI::appleKey_event_cb(lv_event_t *e) { // Send IR command based on the event user data - //mHardware->debugPrint(std::to_string(50 + (int)e->user_data)); + // mHardware->debugPrint(std::to_string(50 + (int)e->user_data)); } // Wakeup by IMU Switch Event handler void OmoteUI::WakeEnableSetting_event_cb(lv_event_t *e) { - this->mHardware->setWakeupByIMUEnabled(lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED)); + this->mHardware->setWakeupByIMUEnabled( + lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED)); } // Wakeup timeout dropdown Event handler -void OmoteUI::wakeTimeoutSetting_event_cb(lv_event_t *e){ - lv_obj_t * drop = lv_event_get_target(e); +void OmoteUI::wakeTimeoutSetting_event_cb(lv_event_t *e) { + lv_obj_t *drop = lv_event_get_target(e); int sleepTimeout = sleepTimeoutMap[lv_dropdown_get_selected(drop)]; mHardware->setSleepTimeout(sleepTimeout); @@ -97,13 +101,14 @@ void OmoteUI::virtualKeypad_event_cb(lv_event_t *e) { // mHardware->debugPrint(buffer); } -void OmoteUI::loopHandler(){ +void OmoteUI::loopHandler() { lv_timer_handler(); + lv_task_handler(); } -void OmoteUI::create_status_bar(){ +void OmoteUI::create_status_bar() { // Create a status bar - lv_obj_t* statusbar = lv_btn_create(lv_scr_act()); + lv_obj_t *statusbar = lv_btn_create(lv_scr_act()); lv_obj_set_size(statusbar, 240, 20); lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN); lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN); @@ -113,32 +118,41 @@ void OmoteUI::create_status_bar(){ this->WifiLabel = lv_label_create(statusbar); lv_label_set_text(this->WifiLabel, ""); lv_obj_align(this->WifiLabel, LV_ALIGN_LEFT_MID, -8, 0); - lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN); + lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12, + LV_PART_MAIN); this->objBattPercentage = lv_label_create(statusbar); lv_label_set_text(this->objBattPercentage, ""); lv_obj_align(this->objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0); - lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN); + lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12, + LV_PART_MAIN); this->objBattIcon = lv_label_create(statusbar); lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY); lv_obj_align(this->objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0); - lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN); + lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16, + LV_PART_MAIN); - batteryPoller = std::make_unique([&batteryIcon = objBattIcon, battery = mHardware->battery()](){ - auto percent = battery->getPercentage(); - if(percent > 95) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_FULL); - else if(percent > 75) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_3); - else if(percent > 50) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_2); - else if(percent > 25) lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_1); - else lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_EMPTY); - }); + batteryPoller = std::make_unique( + [&batteryIcon = objBattIcon, battery = mHardware->battery()]() { + auto percent = battery->getPercentage(); + if (percent > 95) + lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_FULL); + else if (percent > 75) + lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_3); + else if (percent > 50) + lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_2); + else if (percent > 25) + lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_1); + else + lv_label_set_text(batteryIcon, LV_SYMBOL_BATTERY_EMPTY); + }); } -void OmoteUI::setup_settings(lv_obj_t* parent) -{ +void OmoteUI::setup_settings(lv_obj_t *parent) { // Add content to the settings tab - // With a flex layout, setting groups/boxes will position themselves automatically + // With a flex layout, setting groups/boxes will position themselves + // automatically lv_obj_set_layout(parent, LV_LAYOUT_FLEX); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lv_obj_set_scrollbar_mode(parent, LV_SCROLLBAR_MODE_ACTIVE); @@ -148,19 +162,19 @@ void OmoteUI::setup_settings(lv_obj_t* parent) /* Create main page for settings this->settingsMenu*/ this->settingsMainPage = lv_menu_page_create(this->settingsMenu, NULL); - lv_obj_t* cont = lv_menu_cont_create(this->settingsMainPage); + lv_obj_t *cont = lv_menu_cont_create(this->settingsMainPage); lv_obj_set_layout(cont, LV_LAYOUT_FLEX); lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE); - //lv_obj_set_width(cont, lv_obj_get_width(parent)); + // lv_obj_set_width(cont, lv_obj_get_width(parent)); this->display_settings(cont); this->create_wifi_settings(this->settingsMenu, cont); // Another setting for the battery - lv_obj_t* menuLabel = lv_label_create(cont); + lv_obj_t *menuLabel = lv_label_create(cont); lv_label_set_text(menuLabel, "Battery"); - lv_obj_t* menuBox = lv_obj_create(cont); + lv_obj_t *menuBox = lv_obj_create(cont); lv_obj_set_size(menuBox, lv_pct(100), 125); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); @@ -168,79 +182,81 @@ void OmoteUI::setup_settings(lv_obj_t* parent) lv_menu_set_page(this->settingsMenu, this->settingsMainPage); } -void OmoteUI::ta_kb_event_cb(lv_event_t* e) -{ +void OmoteUI::ta_kb_event_cb(lv_event_t *e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * ta = lv_event_get_target(e); - lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e); - switch(code){ - case LV_EVENT_FOCUSED: - lv_keyboard_set_textarea(kb, ta); - lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN); - lv_obj_move_foreground(kb); - break; - case LV_EVENT_DEFOCUSED: - lv_keyboard_set_textarea(kb, NULL); - lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN); - break; - default: - break; + lv_obj_t *ta = lv_event_get_target(e); + lv_obj_t *kb = (lv_obj_t *)lv_event_get_user_data(e); + switch (code) { + case LV_EVENT_FOCUSED: + lv_keyboard_set_textarea(kb, ta); + lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN); + lv_obj_move_foreground(kb); + break; + case LV_EVENT_DEFOCUSED: + lv_keyboard_set_textarea(kb, NULL); + lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN); + break; + default: + break; } } -void OmoteUI::create_keyboard() -{ +void OmoteUI::create_keyboard() { this->kb = lv_keyboard_create(lv_scr_act()); lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN); lv_obj_set_y(this->kb, 0); } -void OmoteUI::hide_keyboard() -{ - lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN); -} +void OmoteUI::hide_keyboard() { lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN); } -void OmoteUI::reset_settings_menu() -{ +void OmoteUI::reset_settings_menu() { lv_menu_set_page(this->settingsMenu, this->settingsMainPage); } -void OmoteUI::attach_keyboard(lv_obj_t* textarea) -{ - if (this->kb == NULL) - { +void OmoteUI::attach_keyboard(lv_obj_t *textarea) { + if (this->kb == NULL) { this->create_keyboard(); } lv_keyboard_set_textarea(this->kb, textarea); - lv_obj_add_event_cb(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_FOCUSED, this->kb); - lv_obj_add_event_cb(textarea, [] (lv_event_t* e) {mInstance->ta_kb_event_cb(e);}, LV_EVENT_DEFOCUSED, this->kb); + lv_obj_add_event_cb( + textarea, [](lv_event_t *e) { mInstance->ta_kb_event_cb(e); }, + LV_EVENT_FOCUSED, this->kb); + lv_obj_add_event_cb( + textarea, [](lv_event_t *e) { mInstance->ta_kb_event_cb(e); }, + LV_EVENT_DEFOCUSED, this->kb); } void OmoteUI::layout_UI() { -// Set the background color + // Set the background color lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN); this->create_keyboard(); // Setup a scrollable tabview for devices and settings - lv_obj_t* tabview; - tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0 + lv_obj_t *tabview; + tabview = + lv_tabview_create(lv_scr_act(), LV_DIR_TOP, + 0); // Hide tab labels by setting their height to 0 lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN); - lv_obj_set_size(tabview, SCREEN_WIDTH, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20) + lv_obj_set_size(tabview, SCREEN_WIDTH, + 270); // 270 = screenHeight(320) - panel(30) - statusbar(20) lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20); // Add 4 tabs (names are irrelevant since the labels are hidden) - lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Settings"); - lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Technisat"); - lv_obj_t* tab3 = lv_tabview_add_tab(tabview, "Apple TV"); - lv_obj_t* tab4 = lv_tabview_add_tab(tabview, "Smart Home"); + lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Settings"); + lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Technisat"); + lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Apple TV"); + lv_obj_t *tab4 = lv_tabview_add_tab(tabview, "Smart Home"); - // Configure number button grid - static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution - static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit + // Configure number button grid + static lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; // equal x distribution + static lv_coord_t row_dsc[] = { + 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST}; // manual y distribution to + // compress the grid a bit // Create a container with grid for tab2 lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN); - lv_obj_t* cont = lv_obj_create(tab2); + lv_obj_t *cont = lv_obj_create(tab2); lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN); lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN); lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN); @@ -251,48 +267,57 @@ void OmoteUI::layout_UI() { lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0); lv_obj_set_style_radius(cont, 0, LV_PART_MAIN); - lv_obj_t* buttonLabel; - lv_obj_t* obj; + lv_obj_t *buttonLabel; + lv_obj_t *obj; // Iterate through grid buttons configure them for (int i = 0; i < 12; i++) { uint8_t col = i % 3; uint8_t row = i / 3; // Create the button object - if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button + if ((row == 3) && ((col == 0) || (col == 2))) + continue; // Do not create a complete fourth row, only a 0 button obj = lv_btn_create(cont); - lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1); + lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, + LV_GRID_ALIGN_STRETCH, row, 1); lv_obj_set_style_bg_color(obj, this->color_primary, LV_PART_MAIN); lv_obj_set_style_radius(obj, 14, LV_PART_MAIN); lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN); - lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container + lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes + // a event in its container // Create Labels for each button - buttonLabel = lv_label_create(obj); - if(i < 9){ - lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row); - lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event - } - else{ + buttonLabel = lv_label_create(obj); + if (i < 9) { + lv_label_set_text_fmt(buttonLabel, std::to_string(i + 1).c_str(), col, + row); + lv_obj_set_user_data(obj, + (void *)i); // Add user data so we can identify which + // button caused the container event + } else { lv_label_set_text_fmt(buttonLabel, "0", col, row); - lv_obj_set_user_data(obj, (void*)9); - } - lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN); + lv_obj_set_user_data(obj, (void *)9); + } + lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, + LV_PART_MAIN); lv_obj_center(buttonLabel); } // Create a shared event for all button inside container - lv_obj_add_event_cb(cont, [] (lv_event_t* e) {mInstance->virtualKeypad_event_cb(e);}, LV_EVENT_CLICKED, NULL); - + lv_obj_add_event_cb( + cont, [](lv_event_t *e) { mInstance->virtualKeypad_event_cb(e); }, + LV_EVENT_CLICKED, NULL); // Add content to the Apple TV tab (3) // Add a nice apple tv logo - lv_obj_t* appleImg = imgs.addAppleTVIcon(tab3); + lv_obj_t *appleImg = imgs.addAppleTVIcon(tab3); // create two buttons and add their icons accordingly - lv_obj_t* button = lv_btn_create(tab3); + lv_obj_t *button = lv_btn_create(tab3); lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0); lv_obj_set_size(button, 60, 60); lv_obj_set_style_radius(button, 30, LV_PART_MAIN); lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); - lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)1); + lv_obj_add_event_cb( + button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); }, + LV_EVENT_CLICKED, (void *)1); appleImg = imgs.addAppleDisplayImage(button); lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0); @@ -305,7 +330,9 @@ void OmoteUI::layout_UI() { lv_obj_set_size(button, 60, 60); lv_obj_set_style_radius(button, 30, LV_PART_MAIN); lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); - lv_obj_add_event_cb(button, [] (lv_event_t* e) {mInstance->appleKey_event_cb(e);}, LV_EVENT_CLICKED, (void*)2); + lv_obj_add_event_cb( + button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); }, + LV_EVENT_CLICKED, (void *)2); appleImg = imgs.addAppleDisplayImage(button); lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0); @@ -321,39 +348,49 @@ void OmoteUI::layout_UI() { lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE); // Add a label, then a box for the light controls - lv_obj_t* menuLabel = lv_label_create(tab4); + lv_obj_t *menuLabel = lv_label_create(tab4); lv_label_set_text(menuLabel, "Living Room"); - lv_obj_t* menuBox = lv_obj_create(tab4); + lv_obj_t *menuBox = lv_obj_create(tab4); lv_obj_set_size(menuBox, lv_pct(100), 79); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); - lv_obj_t* bulbIcon = imgs.addLightBulbIcon(menuBox); + lv_obj_t *bulbIcon = imgs.addLightBulbIcon(menuBox); lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0); menuLabel = lv_label_create(menuBox); lv_label_set_text(menuLabel, "Floor Lamp"); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); - lv_obj_t* lightToggleA = lv_switch_create(menuBox); + lv_obj_t *lightToggleA = lv_switch_create(menuBox); lv_obj_set_size(lightToggleA, 40, 22); lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0); - lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN); + lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), + LV_PART_MAIN); lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR); - lv_obj_add_event_cb(lightToggleA, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1); + lv_obj_add_event_cb( + lightToggleA, + [](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, (void *)1); lv_obj_t *slider = lv_slider_create(menuBox); lv_slider_set_range(slider, 0, 100); - lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR); - lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR); + lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), + LV_PART_INDICATOR); + lv_obj_set_style_bg_grad_color( + slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), + LV_PART_INDICATOR); lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); - lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); + lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), + LV_PART_MAIN); lv_slider_set_value(slider, 255, LV_ANIM_OFF); lv_obj_set_size(slider, lv_pct(90), 10); lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); - lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)1); + lv_obj_add_event_cb( + slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, (void *)1); // Add another this->settingsMenu box for a second appliance menuBox = lv_obj_create(tab4); @@ -367,26 +404,35 @@ void OmoteUI::layout_UI() { menuLabel = lv_label_create(menuBox); lv_label_set_text(menuLabel, "Ceiling Light"); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); - lv_obj_t* lightToggleB = lv_switch_create(menuBox); + lv_obj_t *lightToggleB = lv_switch_create(menuBox); lv_obj_set_size(lightToggleB, 40, 22); lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0); - lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN); + lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), + LV_PART_MAIN); lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR); - lv_obj_add_event_cb(lightToggleB, [] (lv_event_t* e) {mInstance->smartHomeToggle_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2); + lv_obj_add_event_cb( + lightToggleB, + [](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, (void *)2); slider = lv_slider_create(menuBox); lv_slider_set_range(slider, 0, 100); - lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR); - lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR); + lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), + LV_PART_INDICATOR); + lv_obj_set_style_bg_grad_color( + slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), + LV_PART_INDICATOR); lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); - lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); + lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), + LV_PART_MAIN); lv_slider_set_value(slider, 255, LV_ANIM_OFF); lv_obj_set_size(slider, lv_pct(90), 10); lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); - lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->smartHomeSlider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, (void*)2); - + lv_obj_add_event_cb( + slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, (void *)2); // Add another room (empty for now) menuLabel = lv_label_create(tab4); @@ -397,21 +443,20 @@ void OmoteUI::layout_UI() { lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); - // Set current page according to the current Device currentDevice = this->mHardware->getCurrentDevice(); lv_tabview_set_act(tabview, currentDevice, LV_ANIM_OFF); - // Create a page indicator panel = lv_obj_create(lv_scr_act()); - lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable + lv_obj_clear_flag( + panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable lv_obj_set_size(panel, SCREEN_WIDTH, 30); lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW); lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0); lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF); // This small hidden button enables the page indicator to scroll further - lv_obj_t* btn = lv_btn_create(panel); + lv_obj_t *btn = lv_btn_create(panel); lv_obj_set_size(btn, 50, lv_pct(100)); lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); @@ -419,7 +464,7 @@ void OmoteUI::layout_UI() { btn = lv_btn_create(panel); lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); lv_obj_set_size(btn, 150, lv_pct(100)); - lv_obj_t* label = lv_label_create(btn); + lv_obj_t *label = lv_label_create(btn); lv_label_set_text_fmt(label, "Settings"); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); @@ -456,10 +501,15 @@ void OmoteUI::layout_UI() { lv_obj_set_size(btn, 50, lv_pct(100)); lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); - + // Make the indicator scroll together with the tabs by creating a scroll event - lv_obj_add_event_cb(lv_tabview_get_content(tabview), [] (lv_event_t* e) {mInstance->store_scroll_value_event_cb(e);}, LV_EVENT_SCROLL, NULL); - lv_obj_add_event_cb(tabview, [] (lv_event_t* e) {mInstance->tabview_device_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb( + lv_tabview_get_content(tabview), + [](lv_event_t *e) { mInstance->store_scroll_value_event_cb(e); }, + LV_EVENT_SCROLL, NULL); + lv_obj_add_event_cb( + tabview, [](lv_event_t *e) { mInstance->tabview_device_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, NULL); // Initialize scroll position for the indicator lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL); @@ -472,10 +522,10 @@ void OmoteUI::layout_UI() { lv_obj_add_style(panel, &style_btn, 0); // Make the indicator fade out at the sides using gradient bitmaps - lv_obj_t* img1 = imgs.addLeftGradiant(lv_scr_act()); + lv_obj_t *img1 = imgs.addLeftGradiant(lv_scr_act()); lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0); lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px - lv_obj_t* img2 = imgs.addRightGradiant(lv_scr_act()); + lv_obj_t *img2 = imgs.addRightGradiant(lv_scr_act()); lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0); lv_obj_set_size(img2, 30, 30); diff --git a/Platformio/OmoteUI/OmoteUI.hpp b/Platformio/OmoteUI/UIs/Basic/OmoteUI.hpp similarity index 65% rename from Platformio/OmoteUI/OmoteUI.hpp rename to Platformio/OmoteUI/UIs/Basic/OmoteUI.hpp index 1114a47..b14212c 100644 --- a/Platformio/OmoteUI/OmoteUI.hpp +++ b/Platformio/OmoteUI/UIs/Basic/OmoteUI.hpp @@ -2,18 +2,19 @@ // 2023 Matthew Colvin #pragma once -#include "HardwareAbstract.hpp" #include "Images.hpp" +#include "UIBase.hpp" #include "lvgl.h" +#include "poller.hpp" #include #include #include #include -#include "poller.hpp" +namespace UI::Basic { /// @brief Singleton to allow UI code to live separately from the Initialization /// of resources. -class OmoteUI { +class OmoteUI : public UIBase { public: OmoteUI(std::shared_ptr aHardware); @@ -47,86 +48,88 @@ public: void smartHomeSlider_event_cb(lv_event_t *e); // Virtual Keypad Event handler void virtualKeypad_event_cb(lv_event_t *e); - void wifi_settings_cb(lv_event_t* event); + void wifi_settings_cb(lv_event_t *event); - void connect_btn_cb(lv_event_t* event); + void connect_btn_cb(lv_event_t *event); - void password_field_event_cb(lv_event_t* e); + void password_field_event_cb(lv_event_t *e); // Use LVGL to layout the ui and register the callbacks void layout_UI(); - void ta_kb_event_cb(lv_event_t* e); + void ta_kb_event_cb(lv_event_t *e); void wifi_scan_done(std::shared_ptr> info); void loopHandler(); /** - * @brief Function to hide the keyboard. If the keyboard is attached to a text area, it will be hidden when the - * text area is defocused. This function can be used if the keyboard need to be hidden due to some script event. - * + * @brief Function to hide the keyboard. If the keyboard is attached to a text + * area, it will be hidden when the text area is defocused. This function can + * be used if the keyboard need to be hidden due to some script event. + * */ void hide_keyboard(); /** - * @brief Function to show the keyboard. If a text area needs the keybaord, it should be attached to the text area - * using the approbiate function. The keyboard will then show up when the text area is focused. This function is + * @brief Function to show the keyboard. If a text area needs the keybaord, it + * should be attached to the text area using the approbiate function. The + * keyboard will then show up when the text area is focused. This function is * needed if the keyboard should be shown due to some script or other trigger. - * + * */ void show_keyboard(); private: static std::shared_ptr mInstance; - std::shared_ptr mHardware; - + std::unique_ptr batteryPoller; - + int sleepTimeoutMap[5] = {10000,30000,60000,180000,600000}; void reset_settings_menu(); - void attach_keyboard(lv_obj_t* textarea); + void attach_keyboard(lv_obj_t *textarea); std::shared_ptr> found_wifi_networks; - /** - * @brief Keyboard object used whenever a keyboard is needed. - * - */ -lv_obj_t* kb; + /** + * @brief Keyboard object used whenever a keyboard is needed. + * + */ + lv_obj_t *kb; -/** - * @brief Function to create the keyboard object which can then be attached to different text areas. - * - */ -void create_keyboard(); + /** + * @brief Function to create the keyboard object which can then be attached to + * different text areas. + * + */ + void create_keyboard(); /** * @brief Set the up settings object - * - * @param parent + * + * @param parent */ - void setup_settings(lv_obj_t* parent); + void setup_settings(lv_obj_t *parent); - /** + /** * @brief LVGL Menu for settings pages as needed. - * + * */ - lv_obj_t* settingsMenu; + lv_obj_t *settingsMenu; /** - * @brief Main page of the settings menu - * + * @brief Main page of the settings menu + * */ - lv_obj_t* settingsMainPage; + lv_obj_t *settingsMainPage; /** - * @brief Battery percentage label - * + * @brief Battery percentage label + * */ - lv_obj_t* objBattPercentage; + lv_obj_t *objBattPercentage; /** - * @brief Battery icon object in the status bar - * + * @brief Battery icon object in the status bar + * */ - lv_obj_t* objBattIcon; + lv_obj_t *objBattIcon; void create_status_bar(); @@ -138,104 +141,110 @@ void create_keyboard(); inline static const uint_fast8_t virtualKeyMapTechnisat[10] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0}; -/************************************** WIFI Settings Menu *******************************************************/ + /************************************** WIFI Settings Menu + * *******************************************************/ /** * @brief Container within the wifi selection page */ - lv_obj_t* wifi_setting_cont; + lv_obj_t *wifi_setting_cont; /** * @brief Wifi settings entry point on the settings tab - * + * */ - lv_obj_t* wifiOverview; + lv_obj_t *wifiOverview; /** - * @brief Label in the wifi password page. This label is updated with the selected SSID when the credentials for - * a wifi network is entered. - * + * @brief Label in the wifi password page. This label is updated with the + * selected SSID when the credentials for a wifi network is entered. + * */ - lv_obj_t* wifi_password_label; + lv_obj_t *wifi_password_label; /** * @brief Menu Subpage for the wifi password */ - lv_obj_t* wifi_password_page; + lv_obj_t *wifi_password_page; /** * @brief Menu Subpage for wifi selection */ - lv_obj_t* wifi_selection_page; + lv_obj_t *wifi_selection_page; /** * @brief Wifi Label shown in the top status bar */ - lv_obj_t* WifiLabel; + lv_obj_t *WifiLabel; /** * @brief Number of wifi subpage needed to display the found wifi networks - * + * */ unsigned int no_subpages; /** * @brief number of wifi networks found - * + * */ unsigned int no_wifi_networks; - void wifi_status(std::shared_ptr status); /** - * @brief callback function to get next wifi subpage. This callback can be used to get the next or previous page - * - * @param e lvgl event object + * @brief callback function to get next wifi subpage. This callback can be + * used to get the next or previous page + * + * @param e lvgl event object */ - void next_wifi_selection_subpage(lv_event_t* e); + void next_wifi_selection_subpage(lv_event_t *e); /** * @brief Create a wifi selection sub page object - * - * @param menu LVGL Menu where the sub page should be added to + * + * @param menu LVGL Menu where the sub page should be added to * @return lv_obj_t* Menu sub page object pointer */ - lv_obj_t* create_wifi_selection_page(lv_obj_t* menu); + lv_obj_t *create_wifi_selection_page(lv_obj_t *menu); /** * @brief Method to create the wifi password sub page - * - * @param menu Menu where the sub page should be created + * + * @param menu Menu where the sub page should be created * @return lv_obj_t* menu sub page object pointer */ - lv_obj_t* create_wifi_password_page(lv_obj_t* menu); + lv_obj_t *create_wifi_password_page(lv_obj_t *menu); /** * @brief Method to create the wifi settings on the main page - * - * @param parent lv object parent where the main settings page should be added to + * + * @param parent lv object parent where the main settings page should be + * added to */ - void create_wifi_main_page(lv_obj_t* parent); + void create_wifi_main_page(lv_obj_t *parent); /** - * @brief Method to create wifi settings. This method will call the create_wifi_selection_page, - * the create_wifi_password_page, and the create_wifi_main_page - * - * @param menu Settings menu where the sub pages should be added to - * @param parent lv object parent where the main settings page should be added to + * @brief Method to create wifi settings. This method will call the + * create_wifi_selection_page, the create_wifi_password_page, and the + * create_wifi_main_page + * + * @param menu Settings menu where the sub pages should be added to + * @param parent lv object parent where the main settings page should be + * added to */ - void create_wifi_settings(lv_obj_t* menu, lv_obj_t* parent); - + void create_wifi_settings(lv_obj_t *menu, lv_obj_t *parent); + /** * @brief Function to update the wifi selection sub page - * - * @param page index of the page to display + * + * @param page index of the page to display */ void update_wifi_selection_subpage(int page); /** * @brief Function to create the display settings page. - * + * * @param parent LVGL object acting as a parent for the display settings page */ - void display_settings(lv_obj_t* parent); + void display_settings(lv_obj_t *parent); }; + +} // namespace UI::Basic \ No newline at end of file diff --git a/Platformio/OmoteUI/displaySettings.cpp b/Platformio/OmoteUI/UIs/Basic/displaySettings.cpp similarity index 53% rename from Platformio/OmoteUI/displaySettings.cpp rename to Platformio/OmoteUI/UIs/Basic/displaySettings.cpp index a20efb9..6515230 100644 --- a/Platformio/OmoteUI/displaySettings.cpp +++ b/Platformio/OmoteUI/UIs/Basic/displaySettings.cpp @@ -1,61 +1,78 @@ #include "OmoteUI.hpp" -void OmoteUI::display_settings(lv_obj_t* parent) -{ +using namespace UI::Basic; - lv_obj_t* menuLabel = lv_label_create(parent); +void OmoteUI::display_settings(lv_obj_t *parent) { + + lv_obj_t *menuLabel = lv_label_create(parent); lv_label_set_text(menuLabel, "Display"); - - lv_obj_t* menuBox = lv_obj_create(parent); + + lv_obj_t *menuBox = lv_obj_create(parent); lv_obj_set_size(menuBox, lv_pct(100), 109); lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); - lv_obj_t* brightnessIcon = imgs.addLowBrightnessIcon(menuBox); + lv_obj_t *brightnessIcon = imgs.addLowBrightnessIcon(menuBox); lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0); - lv_obj_t* slider = lv_slider_create(menuBox); + lv_obj_t *slider = lv_slider_create(menuBox); lv_slider_set_range(slider, 0, 255); lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN); - lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); - lv_slider_set_value(slider, mHardware->display()->getBrightness() , LV_ANIM_OFF); + lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), + LV_PART_MAIN); + lv_slider_set_value(slider, mHardware->display()->getBrightness(), + LV_ANIM_OFF); lv_obj_set_size(slider, lv_pct(66), 10); lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3); brightnessIcon = imgs.addHighBrightnessIcon(menuBox); lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1); - lv_obj_add_event_cb(slider, [] (lv_event_t* e) {mInstance->bl_slider_event_cb(e);}, LV_EVENT_VALUE_CHANGED, nullptr); - + lv_obj_add_event_cb( + slider, [](lv_event_t *e) { mInstance->bl_slider_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, nullptr); + menuLabel = lv_label_create(menuBox); lv_label_set_text(menuLabel, "Lift to Wake"); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32); - lv_obj_t* wakeToggle = lv_switch_create(menuBox); + lv_obj_t *wakeToggle = lv_switch_create(menuBox); lv_obj_set_size(wakeToggle, 40, 22); lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29); lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN); - lv_obj_add_event_cb(wakeToggle, [] (lv_event_t* e) {mInstance->WakeEnableSetting_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL); - if(mHardware->getWakeupByIMUEnabled()) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state + lv_obj_add_event_cb( + wakeToggle, + [](lv_event_t *e) { mInstance->WakeEnableSetting_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, NULL); + if (mHardware->getWakeupByIMUEnabled()) + lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state menuLabel = lv_label_create(menuBox); lv_label_set_text(menuLabel, "Timeout"); lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64); - lv_obj_t* drop = lv_dropdown_create(menuBox); + lv_obj_t *drop = lv_dropdown_create(menuBox); lv_dropdown_set_options(drop, "10s\n" "30s\n" "1m\n" "3m"); lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61); lv_obj_set_size(drop, 70, 22); - //lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN); - //lv_obj_set_style_text_font(lv_dropdown_get_list(drop), &lv_font_montserrat_12, LV_PART_MAIN); + // lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN); + // lv_obj_set_style_text_font(lv_dropdown_get_list(drop), + // &lv_font_montserrat_12, LV_PART_MAIN); lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN); lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN); - lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, LV_PART_MAIN); + lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, + LV_PART_MAIN); lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN); - lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_hex(0x505050), LV_PART_MAIN); - int sleepTimeoutMapSize = sizeof(sleepTimeoutMap)/sizeof(sleepTimeoutMap[0]); + lv_obj_set_style_border_color(lv_dropdown_get_list(drop), + lv_color_hex(0x505050), LV_PART_MAIN); + + int sleepTimeoutMapSize = + sizeof(sleepTimeoutMap) / sizeof(sleepTimeoutMap[0]); int currentTimeout = mHardware->getSleepTimeout(); - for(int i = 0; i < sleepTimeoutMapSize; i++){ - if(currentTimeout == sleepTimeoutMap[i]) lv_dropdown_set_selected(drop, i); + for (int i = 0; i < sleepTimeoutMapSize; i++) { + if (currentTimeout == sleepTimeoutMap[i]) + lv_dropdown_set_selected(drop, i); } - lv_obj_add_event_cb(drop, [] (lv_event_t* e) {mInstance->wakeTimeoutSetting_event_cb(e);}, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb( + drop, [](lv_event_t *e) { mInstance->wakeTimeoutSetting_event_cb(e); }, + LV_EVENT_VALUE_CHANGED, NULL); } \ No newline at end of file diff --git a/Platformio/OmoteUI/wifiSettings.cpp b/Platformio/OmoteUI/UIs/Basic/wifiSettings.cpp similarity index 99% rename from Platformio/OmoteUI/wifiSettings.cpp rename to Platformio/OmoteUI/UIs/Basic/wifiSettings.cpp index d5f67eb..a7c76ca 100644 --- a/Platformio/OmoteUI/wifiSettings.cpp +++ b/Platformio/OmoteUI/UIs/Basic/wifiSettings.cpp @@ -3,6 +3,8 @@ #define WIFI_SUBPAGE_SIZE 3 static char* ssid; +using namespace UI::Basic; + lv_obj_t* OmoteUI::create_wifi_selection_page(lv_obj_t* menu) { /* Create sub page for wifi*/ diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.cpp new file mode 100644 index 0000000..a66c5f5 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.cpp @@ -0,0 +1,21 @@ +#include "BasicUI.hpp" +#include "HardwareFactory.hpp" +#include "HomeScreen.hpp" +#include "ScreenManager.hpp" + +using namespace UI; + +BasicUI::BasicUI() : UIBase() { + + HardwareFactory::getAbstract().keys()->RegisterKeyPressHandler( + [](auto aKeyEvent) { + return Screen::Manager::getInstance().distributeKeyEvent(aKeyEvent); + // Could potentially add a check here and display that a key event was + // unused. + }); + + Screen::Manager::getInstance().pushScreen( + std::make_unique()); + + HardwareFactory::getAbstract().wifi()->begin(); +} \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.hpp new file mode 100644 index 0000000..62a05d9 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/BasicUI.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "UIBase.hpp" + +namespace UI { + +class BasicUI : public UIBase { +public: + BasicUI(); +}; + +} // namespace UI \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.cpp new file mode 100644 index 0000000..a70c4ec --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.cpp @@ -0,0 +1,51 @@ +#include "Demo.hpp" +#include "Slider.hpp" + +using namespace UI::Page; + +Demo::Demo() : Base(ID::Pages::Demo) {} + +void Demo::AddSlider() { + auto fakeSlider = std::make_unique([](auto data) {}); + fakeSlider->SetHeight(lv_pct(10)); + fakeSlider->SetWidth(GetContentWidth()); + if (sliders.empty()) { + fakeSlider->AlignTo(this, LV_ALIGN_TOP_MID); + } else { + auto nextY = sliders.back()->GetY() + sliders.back()->GetHeight(); + fakeSlider->SetY(nextY + 10); + } + + sliders.push_back(AddElement(std::move(fakeSlider))); +} + +bool Demo::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { + using id = KeyPressAbstract::KeyId; + using eventType = KeyPressAbstract::KeyEvent::Type; + bool used = true; + switch (aKeyEvent.mId) { + case id::Aux1: + if (aKeyEvent.mType == eventType::Press) { + AddSlider(); + } + break; + case id::Aux2: + if (aKeyEvent.mType == eventType::Release) { + if (sliders.size() > 0) { + RemoveElement(sliders[0]); + sliders.erase( + sliders.begin()); // sliders is non owning so after removing delete + // it from non owning array + } + } + break; + case id::Aux3: + break; + case id::Aux4: + break; + default: + used = Page::Base::OnKeyEvent(aKeyEvent); + break; + } + return used; +} \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.hpp new file mode 100644 index 0000000..5e01009 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/Demo.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "PageBase.hpp" + +namespace UI::Page { + +class Demo : public Base { +public: + Demo(); + + void AddSlider(); + + void OnShow() override{}; + void OnHide() override{}; + bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent); + +private: + std::vector sliders; +}; + +} // namespace UI::Page \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.cpp new file mode 100644 index 0000000..817dc0a --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.cpp @@ -0,0 +1,16 @@ +#include "DisplaySettings.hpp" +#include "BrightnessSlider.hpp" +#include "Label.hpp" + +using namespace UI::Page; + +DisplaySettings::DisplaySettings(std::shared_ptr aDisplay) + : Base(UI::ID::Pages::DisplaySettings), mDisplay(aDisplay), + mBrightnessSlider(AddElement( + std::make_unique(mDisplay))) { + SetBgColor(Color::GREY); + + mBrightnessSlider->SetWidth(GetContentWidth()); + mBrightnessSlider->SetHeight(80); + mBrightnessSlider->AlignTo(this, LV_ALIGN_TOP_MID); +} diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.hpp new file mode 100644 index 0000000..d398331 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/DisplaySettings.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "DisplayAbstract.h" +#include "DropDown.hpp" +#include "PageBase.hpp" + +namespace UI::Widget { +class BrightnessSlider; +} // namespace UI::Widget + +namespace UI::Page { +class DisplaySettings : public Base { +public: + DisplaySettings(std::shared_ptr aDisplay); + + std::string GetTitle() override { return "Display Settings"; }; + +private: + std::shared_ptr mDisplay; + Widget::BrightnessSlider *mBrightnessSlider; +}; +} // namespace UI::Page diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.cpp new file mode 100644 index 0000000..bcac6e9 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.cpp @@ -0,0 +1,43 @@ +#include "SettingsPage.hpp" +#include "BackgroundScreen.hpp" +#include "Button.hpp" +#include "Colors.hpp" +#include "DisplaySettings.hpp" +#include "HardwareFactory.hpp" +#include "List.hpp" +#include "PopUpScreen.hpp" +#include "ScreenManager.hpp" +#include "Slider.hpp" +#include "SystemSettings.hpp" +#include "WifiSettings.hpp" + +using namespace UI::Page; +using namespace UI::Color; + +SettingsPage::SettingsPage() + : Base(ID::Pages::Settings), mSettingsList(AddElement( + std::make_unique())) { + + mSettingsList->AddItem("Display", LV_SYMBOL_EYE_OPEN, + [this] { PushDisplaySettings(); }); + mSettingsList->AddItem("Wifi", LV_SYMBOL_WIFI, + [this] { PushWifiSettings(); }); + mSettingsList->AddItem("System", LV_SYMBOL_SETTINGS, + [this] { PushSystemSettings(); }); +} + +void SettingsPage::PushDisplaySettings() { + UI::Screen::Manager::getInstance().pushPopUp( + std::make_unique( + HardwareFactory::getAbstract().display())); +} + +void SettingsPage::PushSystemSettings() { + UI::Screen::Manager::getInstance().pushPopUp( + std::make_unique()); +} + +void SettingsPage::PushWifiSettings() { + UI::Screen::Manager::getInstance().pushPopUp( + std::make_unique(HardwareFactory::getAbstract().wifi())); +} diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.hpp new file mode 100644 index 0000000..18675b2 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/SettingsPage.hpp @@ -0,0 +1,28 @@ +#include "HardwareAbstract.hpp" +#include "PageBase.hpp" + +namespace UI::Widget { +class Button; +class List; +} // namespace UI::Widget +namespace UI::Page { +class SettingsPage : public Base { +public: + SettingsPage(); + + bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override { + return false; + }; + + void PushDisplaySettings(); + void PushSystemSettings(); + void PushWifiSettings(); + +protected: + void OnShow() override{}; + void OnHide() override{}; + + Widget::Button *mButton; + Widget::List *mSettingsList; +}; +} // namespace UI::Page diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.cpp new file mode 100644 index 0000000..983d4e8 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.cpp @@ -0,0 +1,27 @@ +#include "SystemSettings.hpp" +#include "HardwareFactory.hpp" +#include "Label.hpp" + +using namespace UI::Page; + +SystemSettings::SystemSettings() + : Base(ID::Pages::SystemSettings), + mTimeoutLabel(AddElement( + std::make_unique("TimeOut"))), + mScreenTimeOutDropDown(AddElement>( + std::make_unique>([this](int aTimeout) { + HardwareFactory::getAbstract().setSleepTimeout(aTimeout); + }))) { + + mTimeoutLabel->AlignTo(this, LV_ALIGN_TOP_MID); + mTimeoutLabel->SetHeight(15); + + mScreenTimeOutDropDown->SetHeight(30); + mScreenTimeOutDropDown->SetWidth(GetContentWidth()); + mScreenTimeOutDropDown->AddItem("10 Seconds", 10000); + mScreenTimeOutDropDown->AddItem("15 Seconds", 15000); + mScreenTimeOutDropDown->AddItem("20 Seconds", 20000); + mScreenTimeOutDropDown->AlignTo(mTimeoutLabel, LV_ALIGN_OUT_BOTTOM_MID); + mScreenTimeOutDropDown->SetSelected( + HardwareFactory::getAbstract().getSleepTimeout()); +} \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.hpp new file mode 100644 index 0000000..ef17278 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/SystemSettings.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "DropDown.hpp" +#include "PageBase.hpp" + +namespace UI::Widget { +class Label; +} + +namespace UI::Page { + +class SystemSettings : public Base { +public: + SystemSettings(); + +protected: + std::string GetTitle() override { return "System Settings"; } + +private: + Widget::Label *mTimeoutLabel; + Widget::DropDown *mScreenTimeOutDropDown; +}; + +} // namespace UI::Page \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp new file mode 100644 index 0000000..55c20d2 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.cpp @@ -0,0 +1,79 @@ +#include "WifiSettings.hpp" +#include "Keyboard.hpp" +#include "Label.hpp" +#include "List.hpp" +#include "LvglResourceManager.hpp" + +using namespace UI; +using namespace UI::Page; + +WifiSettings::WifiSettings(std::shared_ptr aWifi) + : Base(ID::Pages::WifiSettings), mWifi(aWifi), + mScanCompleteHandler(mWifi->ScanCompleteNotification()), + mScanStatusHandler(mWifi->WifiStatusNotification()), + mScanningText(AddElement( + std::make_unique("Scanning..."))), + mWifiNetworks(AddElement(std::make_unique())), + mPasswordGetter(nullptr) { + + // Set Handler for when the wifi scan is done + mScanCompleteHandler = [this](auto aWifiInfos) { + if (aWifiInfos.empty()) { + mScanningText->SetText("No Networks Found"); + return; + } + mScanningText->SetText("Networks Found"); + // Create List of wifi infos that when pressed a Keyboard opens + for (WifiInfo wifiInfo : aWifiInfos) { + mWifiNetworks->AddItem(wifiInfo.ssid, LV_SYMBOL_WIFI, [this, wifiInfo] { + OpenPasswordKeyboard(wifiInfo); + }); + } + }; + + mWifi->scan(); +} + +void WifiSettings::OpenPasswordKeyboard(WifiInfo aNetworkToConnectTo) { + // We already have a Keyboard don't launch another one. + if (mPasswordGetter) { + return; + } + auto keyboard = std::make_unique( + [this, aNetworkToConnectTo](auto aUserEnteredPassword) { + // Attempt Connection when user finishes up with keyboard input + mWifi->connect(aNetworkToConnectTo.ssid, aUserEnteredPassword); + mScanningText->SetText("Attempting Connection to " + + aNetworkToConnectTo.ssid); + mPasswordGetter->AnimateOut(); + StartHandlingStatusUpdates(); + }, + "Password:"); + keyboard->OnKeyboardAnimatedOut([this] { + // Keyboard is done animating out remove it and null the ref + RemoveElement(mPasswordGetter); + mPasswordGetter = nullptr; + }); + mPasswordGetter = AddElement(std::move(keyboard)); +} + +void WifiSettings::StartHandlingStatusUpdates() { + mScanStatusHandler = [this](auto aWifiStatus) { + if (aWifiStatus.isConnected) { + mScanningText->SetText("Connected to " + aWifiStatus.ssid); + } else { + mScanningText->SetText("Failed To Connect To " + aWifiStatus.ssid); + } + }; +} + +void WifiSettings::SetHeight(lv_coord_t aHeight) { + Base::SetHeight(aHeight); + mScanningText->AlignTo(this, LV_ALIGN_TOP_MID); + mScanningText->SetHeight(20); + mScanningText->SetLongMode(LV_LABEL_LONG_SCROLL); + const auto padding = 10; + mWifiNetworks->AlignTo(mScanningText, LV_ALIGN_OUT_BOTTOM_MID, 0, padding); + mWifiNetworks->SetHeight(GetContentHeight() - mScanningText->GetBottom() - + padding); +}; diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp new file mode 100644 index 0000000..cb938f8 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/page/WifiSettings.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "PageBase.hpp" +#include "wifiHandlerInterface.h" + +namespace UI::Widget { +class List; +class Label; +class Keyboard; +} // namespace UI::Widget + +namespace UI::Page { +class WifiSettings : public Base { +using WifiInfo = wifiHandlerInterface::WifiInfo; +public: + WifiSettings(std::shared_ptr aWifi); + + std::string GetTitle() override { return "Wifi Settings"; }; + + void SetHeight(lv_coord_t aHeight) override; + +protected: + void StartHandlingStatusUpdates(); + + void OpenPasswordKeyboard(WifiInfo aNetworkToConnectTo); + +private: + + std::shared_ptr mWifi; + Handler mScanCompleteHandler; + Handler mScanStatusHandler; + + UI::Widget::Label *mScanningText; + UI::Widget::List *mWifiNetworks; + UI::Widget::Keyboard *mPasswordGetter; +}; + +} // namespace UI::Page \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.cpp new file mode 100644 index 0000000..4b3f521 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.cpp @@ -0,0 +1,28 @@ +#include "HomeScreen.hpp" +#include "Colors.hpp" +#include "Demo.hpp" +#include "SettingsPage.hpp" + +using namespace UI::Screen; + +HomeScreen::HomeScreen() + : Base(UI::ID::Screens::Home), + mTabView(AddElement( + std::make_unique(ID(ID::Pages::INVALID_PAGE_ID)))) { + + SetBgColor(UI::Color::BLACK); + SetPushAnimation(LV_SCR_LOAD_ANIM_FADE_IN); + + // Adds pages to the Tab view + mTabView->AddTab(std::make_unique()); + mTabView->AddTab(std::make_unique()); +} + +void HomeScreen::SetBgColor(lv_color_t value, lv_style_selector_t selector) { + mTabView->SetBgColor(value, selector); + UI::UIElement::SetBgColor(value, selector); +} + +bool HomeScreen::OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) { + return false; +}; diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.hpp b/Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.hpp new file mode 100644 index 0000000..a10ddb6 --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/screen/HomeScreen.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "HardwareAbstract.hpp" +#include "PageBase.hpp" +#include "ScreenBase.hpp" +#include "TabView.hpp" +#include +namespace UI::Screen { + +class HomeScreen : public Base { +public: + HomeScreen(); + + void SetBgColor(lv_color_t value, + lv_style_selector_t selector = LV_PART_MAIN) override; + +protected: + bool OnKeyEvent(KeyPressAbstract::KeyEvent aKeyEvent) override; + +private: + Page::TabView *mTabView; +}; + +} // namespace UI::Screen \ No newline at end of file diff --git a/Platformio/OmoteUI/UIs/BasicRefactored/widget/BrightnessSlider.cpp b/Platformio/OmoteUI/UIs/BasicRefactored/widget/BrightnessSlider.cpp new file mode 100644 index 0000000..3e6150f --- /dev/null +++ b/Platformio/OmoteUI/UIs/BasicRefactored/widget/BrightnessSlider.cpp @@ -0,0 +1,44 @@ +#include "BrightnessSlider.hpp" +#include "Label.hpp" +#include "Slider.hpp" + +using namespace UI::Widget; + +BrightnessSlider::BrightnessSlider(std::shared_ptr aDisplay) + : Base(ID::Widgets::BrightnessSlider), mDisplay(aDisplay), + mSlider(AddElement(std::make_unique( + [this](auto aNewBrightness) { + mDisplay->setBrightness(aNewBrightness); + }, + 0, 255))), + mLabel(AddElement(std::make_unique