diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b16c31 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +.DS_Store \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cbe5ad1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,437 @@ +Attribution-NonCommercial-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/README.md b/README.md index ed07541..dfa0405 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ -# focus-dial \ No newline at end of file +

+ +

+ +Watch the build video ↓ + +[](https://youtu.be/nZa-Vqu-_fU) + +Tired of constant distractions, I built the Focus Dial—a DIY take on the failed TimeChi crowdfunding project. It helps me work in time blocks by activating a Do Not Disturb mode on my phone and integrates with Home Assistant via webhook triggers to set lighting scenes and block distracting apps at the network level during focus sessions. + +Build instructions → (coming soon) + +[![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa] + +[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa] + +[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/ +[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png +[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg \ No newline at end of file diff --git a/cad/Focus Dial.f3z b/cad/Focus Dial.f3z new file mode 100644 index 0000000..99cde02 Binary files /dev/null and b/cad/Focus Dial.f3z differ diff --git a/cad/STLs/Bezel.stl b/cad/STLs/Bezel.stl new file mode 100644 index 0000000..bf79ef0 Binary files /dev/null and b/cad/STLs/Bezel.stl differ diff --git a/cad/STLs/Bottom Button.stl b/cad/STLs/Bottom Button.stl new file mode 100644 index 0000000..eba8b2e Binary files /dev/null and b/cad/STLs/Bottom Button.stl differ diff --git a/cad/STLs/Bottom.stl b/cad/STLs/Bottom.stl new file mode 100644 index 0000000..f1a4d88 Binary files /dev/null and b/cad/STLs/Bottom.stl differ diff --git a/cad/STLs/Button Cap.stl b/cad/STLs/Button Cap.stl new file mode 100644 index 0000000..1defd51 Binary files /dev/null and b/cad/STLs/Button Cap.stl differ diff --git a/cad/STLs/Button Holder.stl b/cad/STLs/Button Holder.stl new file mode 100644 index 0000000..7684d73 Binary files /dev/null and b/cad/STLs/Button Holder.stl differ diff --git a/cad/STLs/Central Ring.stl b/cad/STLs/Central Ring.stl new file mode 100644 index 0000000..2a1aaa0 Binary files /dev/null and b/cad/STLs/Central Ring.stl differ diff --git a/cad/STLs/Central Shaft.stl b/cad/STLs/Central Shaft.stl new file mode 100644 index 0000000..2e47ab0 Binary files /dev/null and b/cad/STLs/Central Shaft.stl differ diff --git a/cad/STLs/Diffuser Mold.stl b/cad/STLs/Diffuser Mold.stl new file mode 100644 index 0000000..9b7dfe2 Binary files /dev/null and b/cad/STLs/Diffuser Mold.stl differ diff --git a/cad/STLs/Encoder Bottom.stl b/cad/STLs/Encoder Bottom.stl new file mode 100644 index 0000000..76fc269 Binary files /dev/null and b/cad/STLs/Encoder Bottom.stl differ diff --git a/cad/STLs/Face.stl b/cad/STLs/Face.stl new file mode 100644 index 0000000..7e90f90 Binary files /dev/null and b/cad/STLs/Face.stl differ diff --git a/cad/STLs/Screen Backing.stl b/cad/STLs/Screen Backing.stl new file mode 100644 index 0000000..40ec2ae Binary files /dev/null and b/cad/STLs/Screen Backing.stl differ diff --git a/firmware/include/Animation.h b/firmware/include/Animation.h new file mode 100644 index 0000000..7129af5 --- /dev/null +++ b/firmware/include/Animation.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +#define DEFAULT_FRAME_WIDTH 48 +#define DEFAULT_FRAME_HEIGHT 48 +#define DEFAULT_FRAME_DELAY 42 + +class Animation +{ +public: + Animation(Adafruit_SSD1306 *display); + void start(const byte *frames, int frameCount, bool loop, bool reverse, unsigned long durationMs, int width, int height); // Moved reverse parameter + void update(); + bool isRunning(); + +private: + Adafruit_SSD1306 *oled; + const byte *animationFrames; + int totalFrames; + int currentFrame; + int frameWidth; + int frameHeight; + int frameX; + int frameY; + bool animationRunning; + bool loopAnimation; + bool playInReverse; + unsigned long animationStartTime; + unsigned long lastFrameTime; + unsigned long animationDuration; + unsigned long frameDelay; +}; \ No newline at end of file diff --git a/firmware/include/Config.h b/firmware/include/Config.h new file mode 100644 index 0000000..fe0c348 --- /dev/null +++ b/firmware/include/Config.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +// --- Hardware --- +#define OLED_WIDTH 128 +#define OLED_HEIGHT 64 +#define OLED_ADDR 0x3C + +#define LED_PIN 15 +#define NUM_LEDS 16 +#define LED_BRIGHTNESS 100 + +#define ENCODER_A_PIN 27 +#define ENCODER_B_PIN 25 +#define BUTTON_PIN 26 + +// --- LED Colors --- +#define BLUE 0x0000FF +#define AMBER 0xFFBF00 +#define RED 0xFF0000 +#define GREEN 0x00FF00 +#define YELLOW 0xFFFF00 +#define MAGENTA 0xFF00FF +#define TEAL 0x008080 + +// --- Defaults --- +#define DEFAULT_TIMER 25 // min - Default to 25 minutes if no value in NVS +#define MIN_TIMER 5 // min - Minimum timer +#define MAX_TIMER 240 // min - Maximum timer (4 hours) + +#define SPLASH_DURATION 2 // sec - 2 seconds splash state +#define CHANGE_TIMEOUT 5 // sec - 5 seconds adjust timeout +#define SLEEP_TIMOUT 5 // min - 5 minutes to transition to sleep +#define PAUSE_TIMEOUT 10 // min - 10 minutes to cancel the timer if stayed paused \ No newline at end of file diff --git a/firmware/include/Controllers.h b/firmware/include/Controllers.h new file mode 100644 index 0000000..e4ee0fb --- /dev/null +++ b/firmware/include/Controllers.h @@ -0,0 +1,14 @@ +#pragma once + +#include "controllers/DisplayController.h" +#include "controllers/LEDController.h" +#include "controllers/InputController.h" +#include "controllers/NetworkController.h" +#include + +// Declare global controller instances +extern DisplayController displayController; +extern LEDController ledController; +extern InputController inputController; +extern NetworkController networkController; +extern Preferences preferences; \ No newline at end of file diff --git a/firmware/include/State.h b/firmware/include/State.h new file mode 100644 index 0000000..e939d6a --- /dev/null +++ b/firmware/include/State.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Config.h" + +// Base class +class State { +public: + virtual ~State() {} + + virtual void enter() = 0; + virtual void update() = 0; + virtual void exit() = 0; +}; \ No newline at end of file diff --git a/firmware/include/StateMachine.h b/firmware/include/StateMachine.h new file mode 100644 index 0000000..41a6aea --- /dev/null +++ b/firmware/include/StateMachine.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include "State.h" +#include "states/AdjustState.h" +#include "states/DoneState.h" +#include "states/IdleState.h" +#include "states/PausedState.h" +#include "states/ProvisionState.h" +#include "states/ResetState.h" +#include "states/SleepState.h" +#include "states/StartupState.h" +#include "states/TimerState.h" + +class StateMachine { +public: + StateMachine(); + ~StateMachine(); + + void changeState(State* newState); + void update(); + + // Static states + static AdjustState adjustState; + static SleepState sleepState; + static DoneState doneState; + static IdleState idleState; + static PausedState pausedState; + static ProvisionState provisionState; + static ResetState resetState; + static StartupState startupState; + static TimerState timerState; + +private: + State* currentState; // Pointer to the current state + SemaphoreHandle_t stateMutex; // Mutex to protect transitions + bool transition = false; +}; + +extern StateMachine stateMachine; // Global instance of the StateMachine \ No newline at end of file diff --git a/firmware/include/bitmaps.h b/firmware/include/bitmaps.h new file mode 100644 index 0000000..29e1a21 --- /dev/null +++ b/firmware/include/bitmaps.h @@ -0,0 +1,198 @@ +#pragma once + +#include + +// --- Bitmap icons and UI elements --- + +static const unsigned char PROGMEM icon_wifi_on[] = {0xe0, 0x10, 0xc8, 0x28, 0xa8}; +static const unsigned char PROGMEM icon_wifi_off[] = {0x88, 0x50, 0x20, 0x50, 0x88}; +static const unsigned char PROGMEM icon_star[] = {0x92, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x92}; +static const unsigned char PROGMEM icon_pause[] = {0x3e, 0x00, 0x41, 0x00, 0x80, 0x80, 0x94, 0x80, 0x94, 0x80, 0x94, 0x80, 0x80, 0x80, 0x41, 0x00, 0x3e, 0x00}; +static const unsigned char PROGMEM icon_reset[] = {0x00, 0x00, 0x00, 0x00, 0x04, 0xf8, 0x18, 0xe0, 0x20, 0xe0, 0x40, 0x90, 0x40, 0x90, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x40, 0x10, 0x40, 0x10, 0x20, 0x20, 0x18, 0xc0, 0x07, 0x00, 0x00, 0x00}; +static const unsigned char PROGMEM icon_arrow_down[] = {0x20, 0x20, 0x20, 0x20, 0xa8, 0x70, 0x20}; +static const unsigned char PROGMEM image_change_left[] = {0x0c, 0x1e, 0x1e, 0x3e, 0x3c, 0x3c, 0x3c, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x78, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x1e, 0x1e, 0x0c}; +static const unsigned char PROGMEM image_change_right[] = {0x60, 0xf0, 0xf0, 0xf8, 0x78, 0x78, 0x78, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x3e, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x78, 0x78, 0x78, 0x78, 0xf0, 0xf0, 0x60}; +static const unsigned char PROGMEM provision_logo[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x40, 0x18, 0x30, 0x00, 0x02, 0x00, 0x40, 0x40, 0x20, 0x08, 0x00, 0x03, 0x00, 0x40, 0xc0, 0x43, 0x84, 0x00, 0x12, 0x80, 0x60, 0x80, 0x8c, 0x62, 0x08, 0x0a, 0x40, 0x20, 0x80, 0x10, 0x10, 0x08, 0x06, 0x80, 0x20, 0x80, 0x21, 0x08, 0x3e, 0x03, 0x00, 0x20, 0x80, 0x06, 0xc0, 0x08, 0x06, 0x80, 0x20, 0x80, 0x08, 0x20, 0x08, 0x0a, 0x40, 0x20, 0x80, 0x01, 0x00, 0x00, 0x12, 0x80, 0x20, 0x40, 0x02, 0x80, 0x00, 0x03, 0x00, 0x40, 0x40, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00}; +static const unsigned char PROGMEM focusdial_logo[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x81, 0xf8, 0x1f, 0x8e, 0x38, 0x1f, 0x8f, 0xc0, 0xe0, 0x70, 0x38, 0x00, 0x1f, 0x81, 0xf8, 0x1f, 0x8e, 0x38, 0x1f, 0x8f, 0xc0, 0xe0, 0x70, 0x38, 0x00, 0x1f, 0x81, 0xf8, 0x1f, 0x8e, 0x38, 0x1f, 0x8f, 0xc0, 0xe0, 0x70, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x0e, 0x38, 0xff, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x0e, 0x38, 0xff, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x0e, 0x38, 0xff, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0x03, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0x03, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0x03, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0f, 0xc0, 0x1f, 0x81, 0xc0, 0xfc, 0x0f, 0xc0, 0xe3, 0x8e, 0x3f, 0xe0, 0xe0, 0x0f, 0xc0, 0x1f, 0x81, 0xc0, 0xfc, 0x0f, 0xc0, 0xe3, 0x8e, 0x3f, 0xe0, 0xe0, 0x0f, 0xc0, 0x1f, 0x81, 0xc0, 0xfc, 0x0f, 0xc0, 0xe3, 0x8e, 0x3f, 0xe0}; + +// --- Animation frames --- + +static const byte PROGMEM animation_tick[][288] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 4, 0, 0, 0, 48, 28, 6, 0, 0, 0, 48, 28, 6, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 6, 0, 0, 0, 48, 28, 6, 0, 0, 0, 24, 24, 7, 0, 0, 0, 24, 24, 3, 128, 0, 0, 24, 24, 1, 128, 0, 0, 24, 24, 1, 192, 0, 0, 24, 24, 0, 192, 0, 0, 24, 24, 0, 64, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 6, 0, 0, 0, 24, 24, 6, 0, 0, 0, 24, 24, 7, 0, 0, 0, 24, 24, 3, 128, 0, 0, 24, 24, 1, 192, 0, 0, 24, 24, 0, 224, 0, 0, 24, 24, 0, 99, 0, 0, 24, 24, 0, 119, 0, 0, 24, 24, 0, 62, 0, 0, 24, 24, 0, 28, 0, 0, 56, 12, 0, 8, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 2, 0, 0, 0, 24, 24, 7, 0, 48, 0, 24, 24, 3, 128, 112, 0, 24, 24, 1, 192, 112, 0, 24, 24, 0, 224, 224, 0, 24, 24, 0, 225, 192, 0, 24, 24, 0, 115, 128, 0, 24, 24, 0, 63, 0, 0, 24, 24, 0, 30, 0, 0, 56, 12, 0, 14, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 7, 0, 48, 28, 0, 0, 14, 0, 24, 24, 0, 0, 12, 0, 24, 24, 2, 0, 28, 0, 24, 24, 3, 0, 56, 0, 24, 24, 3, 128, 112, 0, 24, 24, 1, 192, 112, 0, 24, 24, 0, 224, 224, 0, 24, 24, 0, 113, 192, 0, 24, 24, 0, 59, 128, 0, 24, 24, 0, 31, 128, 0, 56, 12, 0, 15, 0, 0, 56, 12, 0, 6, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 1, 128, 112, 12, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 0, 28, 0, 24, 24, 3, 128, 56, 0, 24, 24, 1, 192, 112, 0, 24, 24, 0, 224, 96, 0, 24, 24, 0, 112, 224, 0, 24, 24, 0, 57, 192, 0, 24, 24, 0, 31, 128, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 0, 0, 48, 14, 0, 2, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 192, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 128, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 14, 0, 24, 24, 1, 0, 28, 0, 24, 24, 3, 128, 56, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 224, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 1, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 56, 0, 24, 24, 0, 32, 112, 0, 24, 24, 0, 48, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 56, 0, 24, 24, 0, 0, 112, 0, 24, 24, 0, 0, 96, 0, 24, 24, 0, 0, 224, 0, 24, 24, 0, 5, 192, 0, 56, 12, 0, 7, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 56, 0, 24, 24, 0, 0, 112, 0, 24, 24, 0, 0, 96, 0, 24, 24, 0, 0, 96, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 6, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 0, 192, 112, 12, 0, 0, 0, 128, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + +static const byte PROGMEM animation_reset[][288] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 4, 0, 0, 120, 0, 0, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 15, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 132, 3, 176, 0, 0, 1, 220, 3, 48, 0, 0, 0, 220, 7, 16, 0, 0, 14, 248, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 240, 14, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 32, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 7, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 2, 60, 7, 192, 0, 0, 0, 63, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 6, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 15, 224, 0, 0, 14, 0, 15, 224, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 152, 3, 176, 0, 0, 1, 216, 3, 48, 0, 0, 0, 248, 7, 48, 0, 0, 15, 248, 6, 0, 0, 0, 15, 240, 14, 0, 0, 0, 3, 240, 14, 0, 0, 0, 0, 96, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 128, 28, 0, 0, 30, 7, 128, 120, 0, 0, 15, 15, 1, 240, 0, 0, 3, 28, 7, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 2, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 14, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 3, 224, 0, 0, 14, 0, 15, 224, 0, 0, 7, 0, 15, 224, 0, 0, 3, 128, 1, 224, 0, 0, 1, 152, 3, 176, 0, 0, 1, 248, 7, 48, 0, 0, 0, 248, 7, 48, 0, 0, 15, 240, 6, 32, 0, 0, 15, 240, 6, 0, 0, 0, 1, 224, 14, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 128, 28, 0, 0, 30, 3, 128, 120, 0, 0, 15, 135, 1, 240, 0, 0, 3, 158, 15, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 6, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 7, 224, 0, 0, 14, 0, 15, 224, 0, 0, 7, 0, 13, 224, 0, 0, 3, 128, 1, 240, 0, 0, 1, 152, 3, 176, 0, 0, 1, 216, 3, 48, 0, 0, 0, 248, 7, 48, 0, 0, 15, 240, 6, 0, 0, 0, 15, 240, 14, 0, 0, 0, 1, 240, 14, 0, 0, 0, 0, 96, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 128, 28, 0, 0, 30, 3, 128, 120, 0, 0, 15, 15, 1, 240, 0, 0, 3, 158, 15, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 4, 0, 0, 120, 0, 0, 112, 0, 0, 60, 0, 7, 240, 0, 0, 14, 0, 7, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 220, 3, 48, 0, 0, 0, 216, 7, 48, 0, 0, 14, 248, 6, 0, 0, 0, 7, 248, 14, 0, 0, 0, 3, 240, 14, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 32, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 0, 28, 0, 0, 30, 7, 128, 120, 0, 0, 14, 15, 1, 240, 0, 0, 2, 60, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 1, 0, 1, 240, 0, 0, 24, 0, 0, 120, 0, 3, 248, 0, 0, 28, 0, 7, 248, 0, 0, 14, 0, 0, 248, 0, 0, 7, 0, 1, 248, 0, 0, 3, 0, 1, 184, 0, 0, 1, 128, 3, 176, 0, 0, 1, 192, 3, 16, 0, 0, 0, 204, 7, 0, 0, 0, 2, 124, 6, 0, 0, 0, 7, 124, 6, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 248, 12, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 1, 128, 0, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 7, 0, 120, 0, 0, 12, 62, 0, 224, 0, 0, 0, 248, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 127, 248, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 128, 0, 0, 0, 240, 15, 192, 0, 0, 126, 0, 1, 240, 0, 1, 254, 0, 0, 120, 0, 1, 252, 0, 0, 60, 0, 0, 124, 0, 0, 14, 0, 0, 252, 0, 0, 7, 0, 1, 220, 0, 0, 3, 128, 1, 216, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 100, 6, 0, 0, 0, 3, 110, 14, 0, 0, 0, 3, 252, 12, 0, 0, 0, 1, 252, 12, 0, 0, 0, 0, 248, 12, 0, 0, 0, 0, 120, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 24, 60, 0, 120, 0, 0, 3, 252, 1, 240, 0, 0, 3, 240, 15, 192, 0, 0, 1, 255, 255, 0, 0, 0, 0, 255, 248, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 31, 255, 0, 0, 0, 127, 128, 15, 192, 0, 0, 127, 128, 1, 240, 0, 0, 31, 0, 0, 120, 0, 0, 63, 0, 0, 28, 0, 0, 119, 0, 0, 14, 0, 0, 230, 0, 0, 7, 0, 1, 198, 0, 0, 3, 0, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 3, 54, 12, 0, 0, 0, 3, 190, 12, 0, 0, 0, 1, 252, 12, 0, 0, 0, 0, 252, 12, 0, 0, 0, 0, 120, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 96, 0, 0, 14, 0, 0, 0, 240, 0, 28, 0, 0, 15, 248, 0, 120, 0, 0, 7, 128, 1, 224, 0, 0, 7, 240, 7, 192, 0, 0, 3, 255, 255, 0, 0, 0, 1, 191, 248, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 7, 248, 0, 0, 0, 31, 231, 255, 128, 0, 0, 3, 224, 15, 192, 0, 0, 15, 224, 1, 240, 0, 0, 31, 192, 0, 120, 0, 0, 57, 128, 0, 60, 0, 0, 115, 128, 0, 14, 0, 0, 225, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 3, 176, 12, 0, 0, 0, 1, 182, 12, 0, 0, 0, 1, 254, 12, 0, 0, 0, 0, 254, 12, 0, 0, 0, 0, 124, 12, 0, 0, 0, 0, 120, 14, 0, 0, 0, 0, 48, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 192, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 128, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 63, 192, 0, 14, 0, 0, 63, 192, 0, 28, 0, 0, 30, 128, 0, 120, 0, 0, 31, 128, 1, 240, 0, 0, 15, 240, 15, 192, 0, 0, 13, 255, 255, 0, 0, 0, 6, 31, 248, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 3, 224, 0, 0, 0, 0, 1, 252, 248, 0, 0, 0, 0, 252, 255, 0, 0, 0, 3, 248, 15, 192, 0, 0, 7, 120, 1, 240, 0, 0, 30, 112, 0, 120, 0, 0, 56, 224, 0, 28, 0, 0, 112, 64, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 0, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 1, 48, 12, 0, 0, 0, 1, 176, 12, 0, 0, 0, 1, 178, 12, 0, 0, 0, 1, 254, 12, 0, 0, 0, 0, 254, 6, 0, 0, 0, 0, 248, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 3, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 0, 240, 0, 0, 3, 128, 0, 255, 0, 0, 7, 0, 0, 127, 0, 0, 14, 0, 0, 120, 0, 0, 28, 0, 0, 126, 0, 0, 120, 0, 0, 63, 128, 0, 224, 0, 0, 51, 240, 7, 192, 0, 0, 48, 255, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 31, 140, 0, 0, 0, 0, 255, 159, 0, 0, 0, 3, 239, 15, 192, 0, 0, 15, 142, 1, 240, 0, 0, 30, 28, 0, 120, 0, 0, 56, 24, 0, 60, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 3, 48, 12, 0, 0, 0, 3, 112, 6, 0, 0, 0, 3, 240, 4, 0, 0, 0, 1, 236, 0, 0, 0, 0, 1, 252, 3, 0, 0, 0, 1, 248, 3, 224, 0, 0, 1, 224, 1, 248, 0, 0, 0, 128, 1, 252, 0, 0, 0, 0, 1, 232, 0, 0, 6, 0, 1, 240, 0, 0, 14, 0, 1, 188, 0, 0, 28, 0, 1, 158, 0, 0, 120, 0, 0, 15, 128, 1, 240, 0, 0, 3, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 224, 0, 0, 0, 0, 31, 240, 0, 0, 0, 0, 255, 249, 0, 0, 0, 3, 241, 227, 192, 0, 0, 15, 131, 193, 240, 0, 0, 30, 3, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 112, 6, 0, 0, 0, 6, 96, 7, 0, 0, 0, 6, 96, 7, 192, 0, 0, 6, 224, 7, 240, 0, 0, 6, 192, 7, 240, 0, 0, 7, 200, 7, 160, 0, 0, 7, 248, 7, 192, 0, 0, 7, 240, 6, 224, 0, 0, 3, 128, 4, 112, 0, 0, 0, 0, 0, 56, 0, 0, 16, 0, 0, 30, 0, 0, 120, 0, 0, 15, 128, 1, 240, 0, 0, 3, 240, 15, 192, 0, 0, 1, 255, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 254, 0, 0, 0, 3, 224, 31, 0, 0, 0, 7, 0, 252, 112, 0, 0, 30, 0, 96, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 0, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 48, 15, 0, 0, 0, 0, 112, 15, 192, 0, 0, 0, 112, 31, 224, 0, 0, 0, 96, 30, 224, 0, 0, 4, 224, 27, 0, 0, 0, 12, 192, 27, 128, 0, 0, 13, 192, 1, 128, 0, 0, 13, 128, 0, 192, 0, 0, 31, 128, 0, 224, 0, 0, 31, 0, 0, 112, 0, 0, 31, 224, 0, 56, 0, 0, 31, 192, 0, 30, 0, 0, 24, 0, 0, 15, 128, 1, 192, 0, 0, 3, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 31, 255, 128, 0, 0, 0, 255, 255, 128, 0, 0, 3, 224, 15, 192, 0, 0, 15, 128, 7, 224, 0, 0, 30, 0, 31, 128, 0, 0, 56, 0, 24, 12, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 48, 31, 0, 0, 0, 0, 48, 31, 0, 0, 0, 0, 48, 63, 128, 0, 0, 0, 48, 61, 192, 0, 0, 0, 112, 54, 192, 0, 0, 0, 112, 38, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 51, 128, 1, 192, 0, 0, 51, 128, 0, 224, 0, 0, 55, 0, 0, 112, 0, 0, 126, 0, 0, 60, 0, 0, 124, 0, 0, 30, 0, 0, 127, 0, 0, 15, 128, 0, 255, 0, 0, 3, 240, 14, 30, 0, 0, 0, 255, 254, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 31, 248, 96, 0, 0, 0, 255, 255, 96, 0, 0, 3, 240, 15, 240, 0, 0, 15, 128, 1, 240, 0, 0, 30, 0, 1, 248, 0, 0, 56, 0, 7, 248, 0, 0, 112, 0, 3, 0, 0, 0, 224, 0, 0, 3, 0, 1, 192, 0, 0, 3, 128, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 96, 4, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 125, 128, 0, 0, 0, 48, 109, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 1, 128, 1, 192, 0, 0, 67, 128, 0, 224, 0, 0, 231, 0, 0, 112, 0, 0, 206, 0, 0, 56, 0, 1, 220, 0, 0, 30, 0, 1, 248, 0, 0, 15, 128, 3, 240, 0, 0, 3, 240, 3, 240, 0, 0, 0, 255, 243, 248, 0, 0, 0, 31, 240, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 8, 0, 0, 0, 255, 255, 12, 0, 0, 3, 224, 15, 204, 0, 0, 15, 128, 1, 252, 0, 0, 30, 0, 0, 124, 0, 0, 56, 0, 0, 62, 0, 0, 112, 0, 1, 254, 0, 0, 224, 0, 0, 254, 0, 1, 192, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 192, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 30, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 127, 0, 0, 0, 0, 48, 125, 128, 0, 0, 0, 48, 77, 128, 0, 0, 0, 48, 13, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 3, 14, 0, 0, 60, 0, 7, 28, 0, 0, 30, 0, 7, 120, 0, 0, 15, 128, 15, 240, 0, 0, 3, 240, 31, 192, 0, 0, 0, 255, 159, 0, 0, 0, 0, 63, 159, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 255, 255, 128, 0, 0, 3, 240, 15, 193, 0, 0, 15, 128, 1, 243, 0, 0, 30, 0, 0, 123, 0, 0, 56, 0, 0, 63, 0, 0, 112, 0, 0, 15, 0, 0, 224, 0, 0, 127, 128, 0, 192, 0, 0, 63, 128, 0, 0, 0, 0, 31, 128, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 96, 31, 0, 0, 0, 0, 96, 63, 128, 0, 0, 0, 96, 127, 128, 0, 0, 0, 112, 13, 128, 0, 0, 0, 48, 13, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 4, 14, 0, 0, 60, 0, 12, 28, 0, 0, 30, 0, 28, 120, 0, 0, 15, 128, 57, 240, 0, 0, 3, 240, 127, 192, 0, 0, 0, 252, 255, 0, 0, 0, 0, 28, 248, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 30, 0, 0, 120, 64, 0, 56, 0, 0, 60, 192, 0, 48, 0, 0, 14, 192, 0, 0, 0, 0, 7, 192, 0, 128, 0, 0, 11, 192, 3, 128, 0, 0, 31, 192, 7, 128, 0, 0, 31, 192, 31, 128, 0, 0, 3, 192, 63, 128, 0, 0, 0, 128, 55, 192, 0, 0, 0, 0, 14, 192, 0, 0, 0, 32, 14, 192, 0, 0, 0, 48, 12, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 0, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 0, 16, 28, 0, 0, 30, 0, 120, 120, 0, 0, 15, 128, 241, 240, 0, 0, 3, 225, 199, 192, 0, 0, 0, 243, 255, 0, 0, 0, 0, 3, 248, 0, 0, 0, 0, 1, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 30, 0, 0, 120, 0, 0, 24, 0, 0, 28, 0, 0, 0, 0, 0, 14, 32, 0, 192, 0, 0, 7, 112, 3, 192, 0, 0, 3, 240, 15, 192, 0, 0, 1, 224, 31, 192, 0, 0, 15, 224, 19, 192, 0, 0, 15, 224, 7, 192, 0, 0, 7, 224, 6, 192, 0, 0, 0, 224, 6, 64, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 1, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 96, 28, 0, 0, 30, 0, 224, 120, 0, 0, 15, 131, 193, 240, 0, 0, 3, 199, 135, 192, 0, 0, 0, 207, 255, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 7, 128, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 6, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 0, 224, 0, 0, 14, 0, 7, 224, 0, 0, 7, 0, 15, 224, 0, 0, 3, 152, 9, 224, 0, 0, 1, 184, 3, 224, 0, 0, 1, 248, 3, 96, 0, 0, 14, 240, 7, 96, 0, 0, 15, 240, 6, 32, 0, 0, 7, 240, 14, 0, 0, 0, 1, 224, 14, 0, 0, 0, 0, 96, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 0, 128, 28, 0, 0, 30, 3, 192, 120, 0, 0, 15, 7, 1, 240, 0, 0, 3, 158, 7, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 0, 112, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 15, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 136, 3, 176, 0, 0, 1, 220, 3, 48, 0, 0, 0, 220, 7, 48, 0, 0, 14, 248, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 3, 240, 14, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 32, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 128, 28, 0, 0, 30, 7, 128, 120, 0, 0, 14, 30, 1, 240, 0, 0, 2, 60, 7, 192, 0, 0, 0, 63, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}}; + +static const byte PROGMEM animation_cancel[][288] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 48, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 2, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 2, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 56, 4, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 24, 28, 0, 0, 0, 0, 16, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 48, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + +static const byte PROGMEM animation_resume[][288] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 31, 248, 62, 0, 0, 0, 24, 24, 63, 224, 0, 0, 24, 24, 55, 248, 0, 0, 24, 24, 48, 124, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 60, 0, 0, 24, 24, 51, 252, 0, 0, 24, 24, 63, 192, 0, 0, 31, 248, 60, 0, 0, 0, 31, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 31, 192, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 24, 124, 192, 0, 0, 0, 24, 12, 240, 0, 0, 0, 24, 12, 252, 0, 0, 0, 24, 12, 255, 0, 0, 0, 24, 12, 199, 224, 0, 0, 24, 12, 193, 248, 0, 0, 24, 12, 192, 126, 0, 0, 24, 12, 192, 30, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 14, 0, 0, 24, 12, 192, 62, 0, 0, 24, 12, 193, 240, 0, 0, 24, 12, 199, 192, 0, 0, 24, 12, 223, 0, 0, 0, 24, 12, 252, 0, 0, 0, 24, 12, 224, 0, 0, 0, 24, 60, 128, 0, 0, 0, 27, 248, 0, 0, 0, 0, 31, 192, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, 128, 0, 0, 0, 0, 55, 224, 0, 0, 0, 0, 49, 248, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 248, 0, 0, 0, 48, 7, 190, 0, 0, 0, 48, 7, 143, 128, 0, 0, 48, 7, 131, 224, 0, 0, 48, 7, 1, 248, 0, 0, 48, 7, 0, 124, 0, 0, 48, 7, 0, 31, 0, 0, 48, 7, 0, 7, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 60, 0, 0, 48, 15, 0, 240, 0, 0, 48, 15, 3, 192, 0, 0, 48, 15, 15, 128, 0, 0, 48, 15, 62, 0, 0, 0, 48, 15, 248, 0, 0, 0, 48, 15, 224, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 248, 0, 0, 0, 0, 51, 224, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 48, 124, 0, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 248, 0, 0, 0, 48, 7, 124, 0, 0, 0, 48, 7, 31, 0, 0, 0, 48, 7, 7, 192, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 0, 248, 0, 0, 48, 7, 0, 62, 0, 0, 48, 7, 0, 15, 128, 0, 48, 7, 0, 7, 128, 0, 48, 7, 0, 3, 128, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 30, 0, 0, 48, 7, 0, 120, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 7, 128, 0, 0, 48, 7, 15, 0, 0, 0, 48, 7, 60, 0, 0, 0, 48, 7, 240, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 128, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 120, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 7, 3, 224, 0, 0, 112, 7, 0, 240, 0, 0, 112, 7, 0, 124, 0, 0, 112, 6, 0, 31, 0, 0, 112, 2, 0, 7, 128, 0, 112, 6, 0, 7, 128, 0, 112, 6, 0, 31, 0, 0, 112, 6, 0, 60, 0, 0, 112, 6, 0, 240, 0, 0, 112, 6, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 2, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 1, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 56, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 30, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 1, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 56, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 30, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 3, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 2, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 7, 3, 224, 0, 0, 112, 3, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 2, 0, 60, 0, 0, 112, 6, 0, 240, 0, 0, 112, 6, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 7, 3, 224, 0, 0, 112, 7, 0, 240, 0, 0, 112, 7, 0, 124, 0, 0, 112, 6, 0, 31, 0, 0, 112, 6, 0, 7, 128, 0, 112, 6, 0, 7, 128, 0, 112, 6, 0, 31, 0, 0, 112, 6, 0, 60, 0, 0, 112, 6, 0, 240, 0, 0, 112, 6, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 48, 124, 0, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 7, 128, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 248, 0, 0, 0, 48, 7, 124, 0, 0, 0, 48, 7, 31, 0, 0, 0, 48, 7, 7, 192, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 0, 248, 0, 0, 48, 7, 0, 62, 0, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 7, 128, 0, 48, 7, 0, 3, 128, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 62, 0, 0, 48, 7, 0, 120, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 7, 128, 0, 0, 48, 7, 15, 0, 0, 0, 48, 7, 60, 0, 0, 0, 48, 7, 240, 0, 0, 0, 48, 7, 192, 0, 0, 0, 48, 7, 128, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 124, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, 128, 0, 0, 0, 0, 55, 224, 0, 0, 0, 0, 49, 252, 0, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 15, 224, 0, 0, 0, 48, 15, 248, 0, 0, 0, 48, 15, 62, 0, 0, 0, 48, 15, 31, 128, 0, 0, 48, 15, 7, 192, 0, 0, 48, 15, 1, 240, 0, 0, 48, 15, 0, 124, 0, 0, 48, 15, 0, 31, 0, 0, 48, 15, 0, 7, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 7, 0, 0, 48, 15, 0, 31, 0, 0, 48, 15, 0, 124, 0, 0, 48, 15, 0, 240, 0, 0, 48, 15, 3, 192, 0, 0, 48, 15, 15, 0, 0, 0, 48, 15, 60, 0, 0, 0, 48, 15, 248, 0, 0, 0, 48, 15, 224, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 248, 0, 0, 0, 0, 51, 224, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 31, 192, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 24, 253, 128, 0, 0, 0, 24, 13, 224, 0, 0, 0, 24, 13, 248, 0, 0, 0, 24, 13, 254, 0, 0, 0, 24, 13, 207, 192, 0, 0, 24, 13, 195, 240, 0, 0, 24, 13, 192, 252, 0, 0, 24, 13, 192, 62, 0, 0, 24, 13, 192, 14, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 30, 0, 0, 24, 13, 192, 120, 0, 0, 24, 13, 195, 224, 0, 0, 24, 13, 207, 128, 0, 0, 24, 13, 254, 0, 0, 0, 24, 13, 248, 0, 0, 0, 24, 13, 224, 0, 0, 0, 24, 124, 0, 0, 0, 0, 27, 248, 0, 0, 0, 0, 31, 128, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 31, 252, 120, 0, 0, 0, 24, 28, 127, 128, 0, 0, 24, 28, 127, 240, 0, 0, 24, 28, 97, 252, 0, 0, 24, 28, 96, 28, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 28, 0, 0, 24, 28, 96, 252, 0, 0, 24, 28, 127, 240, 0, 0, 24, 28, 127, 0, 0, 0, 31, 252, 112, 0, 0, 0, 31, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + +static const byte PROGMEM animation_timer_start[][288] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 240, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 254, 3, 224, 15, 255, 255, 248, 0, 240, 31, 255, 255, 240, 0, 56, 63, 255, 255, 224, 0, 28, 63, 255, 255, 224, 0, 12, 127, 255, 255, 192, 0, 14, 127, 255, 255, 192, 0, 6, 255, 255, 255, 128, 0, 6, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 7, 127, 255, 255, 128, 0, 7, 127, 255, 255, 192, 0, 6, 127, 255, 255, 192, 0, 14, 63, 255, 255, 224, 0, 12, 63, 255, 255, 224, 0, 28, 31, 255, 255, 240, 0, 56, 15, 255, 255, 252, 0, 112, 7, 255, 255, 255, 1, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 232, 0, 0, 127, 255, 255, 255, 128, 1, 255, 255, 255, 255, 192, 7, 255, 255, 255, 3, 224, 15, 255, 255, 254, 0, 240, 31, 255, 255, 252, 0, 56, 63, 255, 255, 248, 0, 28, 63, 255, 255, 240, 0, 12, 127, 255, 255, 240, 0, 14, 127, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 3, 255, 255, 255, 224, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 6, 127, 255, 255, 240, 0, 14, 63, 255, 255, 240, 0, 12, 63, 255, 255, 248, 0, 28, 31, 255, 255, 252, 0, 56, 15, 255, 255, 254, 0, 112, 7, 255, 255, 255, 129, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 240, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 255, 3, 224, 15, 255, 255, 252, 0, 240, 31, 255, 255, 248, 0, 56, 63, 255, 255, 240, 0, 28, 63, 255, 255, 240, 0, 28, 127, 255, 255, 224, 0, 14, 127, 255, 255, 224, 0, 14, 255, 255, 255, 192, 0, 6, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 127, 255, 255, 192, 0, 7, 127, 255, 255, 192, 0, 14, 127, 255, 255, 224, 0, 14, 63, 255, 255, 224, 0, 28, 63, 255, 255, 240, 0, 28, 31, 255, 255, 248, 0, 56, 15, 255, 255, 252, 0, 112, 7, 255, 255, 255, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 248, 15, 224, 15, 255, 255, 224, 7, 240, 31, 255, 255, 192, 1, 184, 63, 255, 255, 128, 0, 220, 63, 255, 255, 0, 0, 204, 127, 255, 255, 0, 0, 110, 127, 255, 254, 0, 0, 102, 255, 255, 254, 0, 0, 38, 255, 255, 254, 0, 0, 51, 255, 255, 254, 0, 0, 51, 255, 255, 254, 0, 0, 51, 255, 255, 252, 0, 0, 51, 255, 255, 254, 0, 0, 51, 255, 255, 254, 0, 0, 55, 127, 255, 254, 0, 0, 103, 127, 255, 254, 0, 0, 102, 127, 255, 255, 0, 0, 110, 63, 255, 255, 0, 0, 204, 63, 255, 255, 128, 1, 220, 31, 255, 255, 192, 1, 184, 15, 255, 255, 224, 3, 240, 7, 255, 255, 248, 15, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 254, 3, 192, 3, 224, 15, 252, 0, 224, 0, 240, 31, 248, 0, 112, 0, 56, 63, 240, 0, 56, 0, 28, 63, 224, 0, 24, 0, 12, 127, 224, 0, 24, 0, 14, 127, 192, 0, 12, 0, 6, 255, 192, 0, 12, 0, 6, 255, 192, 0, 12, 0, 3, 255, 128, 0, 4, 0, 3, 255, 128, 0, 6, 0, 3, 255, 128, 0, 6, 0, 3, 255, 128, 0, 12, 0, 3, 255, 128, 0, 12, 0, 7, 127, 192, 0, 12, 0, 7, 127, 192, 0, 12, 0, 6, 127, 192, 0, 28, 0, 14, 63, 224, 0, 24, 0, 12, 63, 240, 0, 56, 0, 28, 31, 248, 0, 112, 0, 56, 15, 252, 0, 224, 0, 112, 7, 255, 1, 192, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 192, 60, 0, 3, 224, 15, 128, 30, 0, 0, 240, 31, 0, 6, 0, 0, 56, 62, 0, 3, 0, 0, 28, 60, 0, 3, 0, 0, 12, 124, 0, 1, 128, 0, 14, 120, 0, 1, 128, 0, 6, 248, 0, 0, 128, 0, 6, 248, 0, 0, 128, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 240, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 7, 120, 0, 1, 128, 0, 7, 120, 0, 1, 128, 0, 6, 124, 0, 3, 128, 0, 14, 60, 0, 3, 0, 0, 12, 62, 0, 7, 0, 0, 28, 31, 0, 6, 0, 0, 56, 15, 128, 14, 0, 0, 112, 7, 224, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 255, 255, 255, 255, 0, 3, 255, 255, 255, 255, 192, 7, 128, 248, 0, 3, 224, 14, 0, 60, 0, 0, 240, 28, 0, 12, 0, 0, 56, 56, 0, 6, 0, 0, 28, 48, 0, 6, 0, 0, 12, 112, 0, 3, 0, 0, 14, 96, 0, 3, 0, 0, 6, 224, 0, 1, 128, 0, 6, 224, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 7, 96, 0, 1, 128, 0, 7, 96, 0, 3, 128, 0, 6, 112, 0, 3, 0, 0, 14, 48, 0, 7, 0, 0, 12, 56, 0, 14, 0, 0, 28, 28, 0, 14, 0, 0, 56, 15, 0, 60, 0, 0, 112, 7, 192, 120, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 15, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 255, 255, 255, 255, 0, 3, 255, 255, 255, 255, 192, 7, 128, 248, 0, 3, 224, 14, 0, 60, 0, 0, 240, 28, 0, 12, 0, 0, 56, 56, 0, 6, 0, 0, 28, 48, 0, 6, 0, 0, 12, 112, 0, 3, 0, 0, 14, 96, 0, 3, 0, 0, 6, 224, 0, 1, 128, 0, 6, 224, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 7, 96, 0, 1, 128, 0, 7, 96, 0, 3, 128, 0, 6, 112, 0, 3, 0, 0, 14, 48, 0, 7, 0, 0, 12, 56, 0, 14, 0, 0, 28, 28, 0, 14, 0, 0, 56, 15, 0, 60, 0, 0, 112, 7, 192, 120, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 15, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 224, 60, 0, 3, 224, 15, 128, 30, 0, 0, 240, 31, 0, 6, 0, 0, 56, 62, 0, 3, 0, 0, 28, 60, 0, 3, 0, 0, 12, 124, 0, 1, 128, 0, 14, 124, 0, 1, 128, 0, 6, 248, 0, 0, 128, 0, 6, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 7, 120, 0, 1, 192, 0, 7, 120, 0, 1, 128, 0, 6, 124, 0, 1, 128, 0, 14, 60, 0, 3, 128, 0, 12, 62, 0, 7, 0, 0, 28, 31, 0, 6, 0, 0, 56, 15, 128, 14, 0, 0, 112, 7, 224, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 252, 7, 128, 3, 224, 15, 248, 1, 192, 0, 240, 31, 224, 0, 224, 0, 56, 63, 224, 0, 96, 0, 28, 63, 192, 0, 48, 0, 12, 127, 192, 0, 48, 0, 14, 127, 128, 0, 24, 0, 6, 255, 128, 0, 24, 0, 6, 255, 128, 0, 24, 0, 3, 255, 0, 0, 8, 0, 3, 255, 0, 0, 8, 0, 3, 255, 0, 0, 12, 0, 3, 255, 0, 0, 24, 0, 3, 255, 0, 0, 24, 0, 7, 127, 128, 0, 24, 0, 7, 127, 128, 0, 24, 0, 6, 127, 128, 0, 56, 0, 14, 63, 192, 0, 48, 0, 12, 63, 224, 0, 112, 0, 28, 31, 224, 0, 224, 0, 56, 15, 248, 1, 192, 0, 112, 7, 254, 3, 128, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 248, 15, 3, 224, 15, 255, 240, 3, 128, 240, 31, 255, 224, 1, 192, 56, 63, 255, 192, 0, 224, 28, 63, 255, 128, 0, 96, 12, 127, 255, 128, 0, 32, 14, 127, 255, 0, 0, 48, 6, 255, 255, 0, 0, 48, 6, 255, 255, 0, 0, 48, 3, 255, 254, 0, 0, 16, 3, 255, 254, 0, 0, 24, 3, 255, 254, 0, 0, 24, 3, 255, 254, 0, 0, 24, 3, 255, 255, 0, 0, 48, 7, 127, 255, 0, 0, 48, 7, 127, 255, 0, 0, 48, 6, 127, 255, 0, 0, 112, 14, 63, 255, 128, 0, 96, 12, 63, 255, 192, 0, 224, 28, 31, 255, 224, 1, 192, 56, 15, 255, 240, 3, 128, 112, 7, 255, 252, 7, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 7, 224, 15, 255, 255, 240, 3, 240, 31, 255, 255, 224, 0, 248, 63, 255, 255, 192, 0, 124, 63, 255, 255, 192, 0, 44, 127, 255, 255, 128, 0, 62, 127, 255, 255, 128, 0, 54, 255, 255, 255, 0, 0, 30, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 31, 127, 255, 255, 0, 0, 31, 127, 255, 255, 0, 0, 62, 127, 255, 255, 128, 0, 62, 63, 255, 255, 128, 0, 124, 63, 255, 255, 192, 0, 124, 31, 255, 255, 224, 0, 248, 15, 255, 255, 240, 1, 240, 7, 255, 255, 252, 7, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 232, 0, 0, 127, 255, 255, 255, 128, 1, 255, 255, 255, 255, 192, 7, 255, 255, 255, 3, 224, 15, 255, 255, 254, 0, 240, 31, 255, 255, 252, 0, 56, 63, 255, 255, 248, 0, 28, 63, 255, 255, 240, 0, 12, 127, 255, 255, 240, 0, 14, 127, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 3, 255, 255, 255, 224, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 6, 127, 255, 255, 240, 0, 14, 63, 255, 255, 240, 0, 12, 63, 255, 255, 248, 0, 28, 31, 255, 255, 252, 0, 56, 15, 255, 255, 254, 0, 112, 7, 255, 255, 255, 129, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 240, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 254, 3, 224, 15, 255, 255, 248, 0, 240, 31, 255, 255, 240, 0, 56, 63, 255, 255, 224, 0, 28, 63, 255, 255, 224, 0, 12, 127, 255, 255, 192, 0, 14, 127, 255, 255, 192, 0, 6, 255, 255, 255, 128, 0, 6, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 7, 127, 255, 255, 128, 0, 7, 127, 255, 255, 192, 0, 6, 127, 255, 255, 192, 0, 14, 63, 255, 255, 224, 0, 12, 63, 255, 255, 224, 0, 28, 31, 255, 255, 240, 0, 56, 15, 255, 255, 252, 0, 112, 7, 255, 255, 255, 1, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + +static const byte PROGMEM animation_wifi[][288] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 63, 254, 7, 158, 63, 129, 255, 255, 129, 252, 31, 7, 192, 7, 224, 248, 12, 31, 0, 0, 248, 112, 0, 60, 0, 0, 60, 0, 0, 112, 3, 224, 30, 0, 0, 224, 63, 252, 7, 0, 0, 112, 254, 127, 14, 0, 0, 59, 224, 7, 220, 0, 0, 31, 128, 1, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 254, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 192, 7, 252, 0, 0, 124, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 127, 255, 0, 240, 28, 1, 255, 255, 192, 56, 120, 15, 128, 3, 248, 30, 240, 62, 0, 0, 124, 15, 240, 240, 7, 192, 31, 15, 113, 224, 127, 255, 7, 142, 63, 131, 248, 63, 227, 252, 31, 15, 128, 1, 240, 248, 14, 28, 0, 0, 120, 112, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 15, 142, 0, 0, 59, 128, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 15, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 3, 255, 255, 192, 0, 0, 31, 224, 15, 248, 0, 0, 126, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 63, 254, 0, 240, 28, 1, 255, 255, 192, 56, 56, 15, 224, 15, 240, 30, 240, 62, 0, 0, 252, 15, 224, 120, 0, 0, 31, 7, 113, 224, 3, 128, 7, 142, 59, 192, 127, 255, 3, 220, 31, 3, 252, 63, 192, 248, 14, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 248, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 62, 254, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 127, 0, 1, 224, 0, 0, 15, 192, 7, 128, 0, 0, 3, 224, 14, 0, 127, 255, 0, 240, 60, 1, 255, 255, 192, 60, 120, 15, 192, 7, 248, 30, 224, 62, 0, 0, 254, 15, 224, 240, 0, 0, 31, 7, 113, 224, 0, 0, 7, 142, 59, 128, 0, 0, 1, 252, 31, 0, 0, 0, 0, 248, 14, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 224, 0, 0, 0, 0, 127, 255, 0, 0, 0, 1, 224, 15, 192, 0, 0, 7, 128, 3, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 15, 248, 56, 0, 0, 28, 127, 254, 56, 0, 0, 14, 240, 15, 112, 0, 0, 7, 192, 3, 224, 0, 0, 3, 128, 129, 192, 0, 0, 0, 15, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 240, 31, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 1, 254, 255, 192, 0, 0, 7, 128, 3, 240, 0, 0, 30, 0, 0, 124, 0, 0, 112, 15, 248, 30, 0, 0, 224, 127, 255, 7, 0, 1, 195, 224, 7, 195, 192, 3, 143, 0, 1, 241, 192, 1, 156, 0, 0, 121, 128, 0, 248, 0, 0, 31, 0, 0, 112, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 62, 124, 0, 0, 0, 0, 127, 254, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 30, 252, 0, 0, 0, 0, 97, 206, 0, 0, 0, 0, 223, 251, 128, 0, 0, 1, 179, 239, 128, 0, 0, 0, 223, 255, 0, 0, 0, 0, 60, 126, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 49, 156, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 7, 192, 0, 0, 15, 1, 193, 240, 0, 0, 28, 63, 252, 120, 0, 0, 56, 252, 127, 156, 0, 0, 115, 192, 7, 206, 0, 0, 63, 0, 0, 252, 0, 0, 30, 0, 0, 120, 0, 0, 8, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 124, 126, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 7, 255, 255, 224, 0, 0, 31, 128, 3, 248, 0, 0, 124, 0, 0, 62, 0, 1, 240, 0, 0, 15, 128, 3, 192, 63, 254, 3, 192, 7, 1, 255, 255, 192, 224, 30, 7, 192, 7, 240, 120, 28, 30, 0, 0, 252, 56, 28, 120, 0, 0, 62, 56, 14, 240, 0, 0, 15, 112, 7, 192, 0, 0, 7, 224, 3, 128, 0, 0, 1, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 0, 248, 63, 0, 0, 0, 1, 192, 7, 192, 0, 0, 7, 135, 241, 224, 0, 0, 7, 63, 252, 224, 0, 0, 3, 248, 63, 192, 0, 0, 1, 239, 255, 128, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 127, 0, 1, 224, 0, 0, 15, 192, 7, 128, 0, 0, 3, 224, 14, 0, 127, 255, 0, 240, 60, 1, 255, 255, 192, 60, 120, 15, 192, 7, 248, 30, 224, 62, 0, 0, 254, 15, 224, 240, 0, 0, 31, 7, 113, 224, 0, 0, 7, 142, 59, 128, 0, 0, 1, 252, 31, 0, 0, 0, 0, 248, 14, 0, 0, 0, 0, 112, 0, 0, 15, 224, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 240, 31, 192, 0, 0, 7, 128, 3, 240, 0, 0, 30, 0, 0, 120, 0, 0, 60, 7, 240, 60, 0, 0, 56, 63, 254, 30, 0, 0, 60, 252, 127, 60, 0, 0, 31, 224, 7, 248, 0, 0, 15, 128, 1, 240, 0, 0, 2, 0, 0, 64, 0, 0, 0, 0, 128, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 240, 31, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 3, 255, 255, 192, 0, 0, 31, 224, 15, 248, 0, 0, 126, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 63, 254, 0, 240, 28, 1, 255, 255, 192, 56, 56, 15, 224, 15, 240, 30, 240, 62, 0, 0, 252, 15, 224, 120, 0, 0, 31, 7, 113, 224, 3, 128, 7, 142, 59, 192, 127, 255, 3, 220, 31, 3, 252, 63, 192, 248, 14, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 248, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 62, 254, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 254, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 192, 7, 252, 0, 0, 124, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 127, 255, 0, 240, 28, 1, 255, 255, 192, 56, 120, 15, 128, 3, 248, 30, 240, 62, 0, 0, 124, 15, 240, 240, 7, 192, 31, 15, 113, 224, 127, 255, 7, 142, 63, 131, 248, 63, 227, 252, 31, 15, 128, 1, 240, 248, 14, 28, 0, 0, 120, 112, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 15, 142, 0, 0, 59, 128, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 15, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 63, 254, 7, 158, 63, 129, 255, 255, 129, 252, 31, 7, 192, 7, 224, 248, 12, 31, 0, 0, 248, 112, 0, 60, 0, 0, 60, 0, 0, 112, 3, 224, 30, 0, 0, 224, 63, 252, 7, 0, 0, 112, 254, 127, 14, 0, 0, 59, 224, 7, 220, 0, 0, 31, 128, 1, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; \ No newline at end of file diff --git a/firmware/include/controllers/DisplayController.h b/firmware/include/controllers/DisplayController.h new file mode 100644 index 0000000..b285cd1 --- /dev/null +++ b/firmware/include/controllers/DisplayController.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include "Animation.h" + +class DisplayController +{ +public: + DisplayController(uint8_t oledWidth, uint8_t oledHeight, uint8_t oledAddress = 0x3C); + + void begin(); + + void drawSplashScreen(); + void drawIdleScreen(int duration, bool wifi); + void drawTimerScreen(int remainingSeconds); + void drawPausedScreen(int remainingSeconds); + void drawResetScreen(bool resetSelected); + void drawDoneScreen(); + void drawAdjustScreen(int duration); + void drawProvisionScreen(); + void clear(); + + void showAnimation(const byte frames[][288], int frameCount, bool loop = false, bool reverse = false, unsigned long durationMs = 0, int width = 48, int height = 48); + void updateAnimation(); + bool isAnimationRunning(); + + void showConfirmation(); + void showCancel(); + void showReset(); + void showConnected(); + void showTimerDone(); + void showTimerStart(); + void showTimerPause(); + void showTimerResume(); + +private: + Adafruit_SSD1306 oled; + Animation animation; +}; diff --git a/firmware/include/controllers/InputController.h b/firmware/include/controllers/InputController.h new file mode 100644 index 0000000..7c9c93a --- /dev/null +++ b/firmware/include/controllers/InputController.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include + +class InputController +{ +public: + InputController(uint8_t buttonPin, uint8_t encoderPinA, uint8_t encoderPinB); + void begin(); + void update(); + + void onPressHandler(std::function handler); + void onDoublePressHandler(std::function handler); + void onLongPressHandler(std::function handler); + void onEncoderRotateHandler(std::function handler); + + void releaseHandlers(); + +private: + OneButton button; + RotaryEncoder encoder; + + uint8_t buttonPin; + uint8_t encoderPinA; + uint8_t encoderPinB; + + std::function pressHandler = nullptr; + std::function doublePressHandler = nullptr; + std::function longPressHandler = nullptr; + std::function encoderRotateHandler = nullptr; + + int lastPosition; + + void onButtonClick(); + void onButtonDoubleClick(); + void onButtonLongPress(); + void onEncoderRotate(int delta); + + static void handleEncoderInterrupt(); + static void handleButtonInterrupt(); +}; + +extern InputController inputController; diff --git a/firmware/include/controllers/LedController.h b/firmware/include/controllers/LedController.h new file mode 100644 index 0000000..29fe4a0 --- /dev/null +++ b/firmware/include/controllers/LedController.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +class LEDController +{ +public: + LEDController(uint8_t ledPin, uint16_t numLeds, uint8_t brightness = 255); + + void begin(); + void update(); + + void startFillAndDecay(uint32_t color, uint32_t totalDuration); + void setSpinner(uint32_t color, int cycles); + void setBreath(uint32_t color, int cycles, bool endFilled, uint32_t speed); + void setSolid(uint32_t color); + + void turnOff(); + void printDebugInfo(); + +private: + Adafruit_NeoPixel leds; + uint16_t numLeds; + uint8_t brightness; + int brightnessLevel; + + enum AnimationType + { + None, + FillAndDecay, + Spinner, + Breath + } currentAnimation; + unsigned long lastUpdateTime; + + uint32_t animationColor; + uint32_t animationDuration; + uint32_t animationSpeed; + + int currentStep; + int currentCycle; + int pixelIndex; + int animationCycles; + bool endFilled; + bool decayStarted; + + // Animation handling methods + void handleFillAndDecay(); + void handleSpinner(); + void handleBreath(); + + // Reset animation state + void stopCurrentAnimation(); + + // Helper to scale color by brightness + uint32_t scaleColor(uint32_t color, uint8_t brightness); +}; \ No newline at end of file diff --git a/firmware/include/controllers/NetworkController.h b/firmware/include/controllers/NetworkController.h new file mode 100644 index 0000000..9272c75 --- /dev/null +++ b/firmware/include/controllers/NetworkController.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include + +class NetworkController +{ +public: + NetworkController(); + void begin(); + void update(); + void startProvisioning(); + void stopProvisioning(); + void reset(); + bool isWiFiProvisioned(); + bool isWiFiConnected(); + bool isBluetoothPaired(); + void initializeBluetooth(); + void startBluetooth(); + void stopBluetooth(); + void sendWebhookAction(const String &action); + +private: + BluetoothA2DPSink a2dp_sink; + Preferences preferences; + WiFiProvisioner::WiFiProvisioner wifiProvisioner; // Instance of WiFiProvisioner + + String webhookURL; + bool btPaired; // Paired state loaded from NVS + bool bluetoothActive; + bool bluetoothAttempted; + bool provisioningMode; + unsigned long lastBluetoothtAttempt; + + void WiFiProvisionerSettings(); + void saveBluetoothPairedState(bool paired); + static void btConnectionStateCallback(esp_a2d_connection_state_t state, void *obj); + + // Tasks + TaskHandle_t bluetoothTaskHandle; + TaskHandle_t webhookTaskHandle; + QueueHandle_t webhookQueue; + + static void bluetoothTask(void *param); + static void webhookTask(void *param); + bool sendWebhookRequest(const String &action); + + static NetworkController *instance; + + static bool validateInputCallback(const String &input); + static void factoryResetCallback(); + + bool validateInput(const String &input); + void handleFactoryReset(); +}; diff --git a/firmware/include/fonts/Org_01.h b/firmware/include/fonts/Org_01.h new file mode 100644 index 0000000..9b80258 --- /dev/null +++ b/firmware/include/fonts/Org_01.h @@ -0,0 +1,131 @@ +#pragma once +#include + +// Org_v01 by Orgdot (www.orgdot.com/aliasfonts). A tiny, +// stylized font with all characters within a 6 pixel height. + +const uint8_t Org_01Bitmaps[] PROGMEM = { + 0xE8, 0xA0, 0x57, 0xD5, 0xF5, 0x00, 0xFD, 0x3E, 0x5F, 0x80, 0x88, 0x88, + 0x88, 0x80, 0xF4, 0xBF, 0x2E, 0x80, 0x80, 0x6A, 0x40, 0x95, 0x80, 0xAA, + 0x80, 0x5D, 0x00, 0xC0, 0xF0, 0x80, 0x08, 0x88, 0x88, 0x00, 0xFC, 0x63, + 0x1F, 0x80, 0xF8, 0xF8, 0x7F, 0x0F, 0x80, 0xF8, 0x7E, 0x1F, 0x80, 0x8C, + 0x7E, 0x10, 0x80, 0xFC, 0x3E, 0x1F, 0x80, 0xFC, 0x3F, 0x1F, 0x80, 0xF8, + 0x42, 0x10, 0x80, 0xFC, 0x7F, 0x1F, 0x80, 0xFC, 0x7E, 0x1F, 0x80, 0x90, + 0xB0, 0x2A, 0x22, 0xF0, 0xF0, 0x88, 0xA8, 0xF8, 0x4E, 0x02, 0x00, 0xFD, + 0x6F, 0x0F, 0x80, 0xFC, 0x7F, 0x18, 0x80, 0xF4, 0x7D, 0x1F, 0x00, 0xFC, + 0x21, 0x0F, 0x80, 0xF4, 0x63, 0x1F, 0x00, 0xFC, 0x3F, 0x0F, 0x80, 0xFC, + 0x3F, 0x08, 0x00, 0xFC, 0x2F, 0x1F, 0x80, 0x8C, 0x7F, 0x18, 0x80, 0xF9, + 0x08, 0x4F, 0x80, 0x78, 0x85, 0x2F, 0x80, 0x8D, 0xB1, 0x68, 0x80, 0x84, + 0x21, 0x0F, 0x80, 0xFD, 0x6B, 0x5A, 0x80, 0xFC, 0x63, 0x18, 0x80, 0xFC, + 0x63, 0x1F, 0x80, 0xFC, 0x7F, 0x08, 0x00, 0xFC, 0x63, 0x3F, 0x80, 0xFC, + 0x7F, 0x29, 0x00, 0xFC, 0x3E, 0x1F, 0x80, 0xF9, 0x08, 0x42, 0x00, 0x8C, + 0x63, 0x1F, 0x80, 0x8C, 0x62, 0xA2, 0x00, 0xAD, 0x6B, 0x5F, 0x80, 0x8A, + 0x88, 0xA8, 0x80, 0x8C, 0x54, 0x42, 0x00, 0xF8, 0x7F, 0x0F, 0x80, 0xEA, + 0xC0, 0x82, 0x08, 0x20, 0x80, 0xD5, 0xC0, 0x54, 0xF8, 0x80, 0xF1, 0xFF, + 0x8F, 0x99, 0xF0, 0xF8, 0x8F, 0x1F, 0x99, 0xF0, 0xFF, 0x8F, 0x6B, 0xA4, + 0xF9, 0x9F, 0x10, 0x8F, 0x99, 0x90, 0xF0, 0x55, 0xC0, 0x8A, 0xF9, 0x90, + 0xF8, 0xFD, 0x63, 0x10, 0xF9, 0x99, 0xF9, 0x9F, 0xF9, 0x9F, 0x80, 0xF9, + 0x9F, 0x20, 0xF8, 0x88, 0x47, 0x1F, 0x27, 0xC8, 0x42, 0x00, 0x99, 0x9F, + 0x99, 0x97, 0x8C, 0x6B, 0xF0, 0x96, 0x69, 0x99, 0x9F, 0x10, 0x2E, 0x8F, + 0x2B, 0x22, 0xF8, 0x89, 0xA8, 0x0F, 0xE0}; + +const GFXglyph Org_01Glyphs[] PROGMEM = {{0, 0, 0, 6, 0, 1}, // 0x20 ' ' + {0, 1, 5, 2, 0, -4}, // 0x21 '!' + {1, 3, 1, 4, 0, -4}, // 0x22 '"' + {2, 5, 5, 6, 0, -4}, // 0x23 '#' + {6, 5, 5, 6, 0, -4}, // 0x24 '$' + {10, 5, 5, 6, 0, -4}, // 0x25 '%' + {14, 5, 5, 6, 0, -4}, // 0x26 '&' + {18, 1, 1, 2, 0, -4}, // 0x27 ''' + {19, 2, 5, 3, 0, -4}, // 0x28 '(' + {21, 2, 5, 3, 0, -4}, // 0x29 ')' + {23, 3, 3, 4, 0, -3}, // 0x2A '*' + {25, 3, 3, 4, 0, -3}, // 0x2B '+' + {27, 1, 2, 2, 0, 0}, // 0x2C ',' + {28, 4, 1, 5, 0, -2}, // 0x2D '-' + {29, 1, 1, 2, 0, 0}, // 0x2E '.' + {30, 5, 5, 6, 0, -4}, // 0x2F '/' + {34, 5, 5, 6, 0, -4}, // 0x30 '0' + {38, 1, 5, 2, 0, -4}, // 0x31 '1' + {39, 5, 5, 6, 0, -4}, // 0x32 '2' + {43, 5, 5, 6, 0, -4}, // 0x33 '3' + {47, 5, 5, 6, 0, -4}, // 0x34 '4' + {51, 5, 5, 6, 0, -4}, // 0x35 '5' + {55, 5, 5, 6, 0, -4}, // 0x36 '6' + {59, 5, 5, 6, 0, -4}, // 0x37 '7' + {63, 5, 5, 6, 0, -4}, // 0x38 '8' + {67, 5, 5, 6, 0, -4}, // 0x39 '9' + {71, 1, 4, 2, 0, -3}, // 0x3A ':' + {72, 1, 4, 2, 0, -3}, // 0x3B ';' + {73, 3, 5, 4, 0, -4}, // 0x3C '<' + {75, 4, 3, 5, 0, -3}, // 0x3D '=' + {77, 3, 5, 4, 0, -4}, // 0x3E '>' + {79, 5, 5, 6, 0, -4}, // 0x3F '?' + {83, 5, 5, 6, 0, -4}, // 0x40 '@' + {87, 5, 5, 6, 0, -4}, // 0x41 'A' + {91, 5, 5, 6, 0, -4}, // 0x42 'B' + {95, 5, 5, 6, 0, -4}, // 0x43 'C' + {99, 5, 5, 6, 0, -4}, // 0x44 'D' + {103, 5, 5, 6, 0, -4}, // 0x45 'E' + {107, 5, 5, 6, 0, -4}, // 0x46 'F' + {111, 5, 5, 6, 0, -4}, // 0x47 'G' + {115, 5, 5, 6, 0, -4}, // 0x48 'H' + {119, 5, 5, 6, 0, -4}, // 0x49 'I' + {123, 5, 5, 6, 0, -4}, // 0x4A 'J' + {127, 5, 5, 6, 0, -4}, // 0x4B 'K' + {131, 5, 5, 6, 0, -4}, // 0x4C 'L' + {135, 5, 5, 6, 0, -4}, // 0x4D 'M' + {139, 5, 5, 6, 0, -4}, // 0x4E 'N' + {143, 5, 5, 6, 0, -4}, // 0x4F 'O' + {147, 5, 5, 6, 0, -4}, // 0x50 'P' + {151, 5, 5, 6, 0, -4}, // 0x51 'Q' + {155, 5, 5, 6, 0, -4}, // 0x52 'R' + {159, 5, 5, 6, 0, -4}, // 0x53 'S' + {163, 5, 5, 6, 0, -4}, // 0x54 'T' + {167, 5, 5, 6, 0, -4}, // 0x55 'U' + {171, 5, 5, 6, 0, -4}, // 0x56 'V' + {175, 5, 5, 6, 0, -4}, // 0x57 'W' + {179, 5, 5, 6, 0, -4}, // 0x58 'X' + {183, 5, 5, 6, 0, -4}, // 0x59 'Y' + {187, 5, 5, 6, 0, -4}, // 0x5A 'Z' + {191, 2, 5, 3, 0, -4}, // 0x5B '[' + {193, 5, 5, 6, 0, -4}, // 0x5C '\' + {197, 2, 5, 3, 0, -4}, // 0x5D ']' + {199, 3, 2, 4, 0, -4}, // 0x5E '^' + {200, 5, 1, 6, 0, 1}, // 0x5F '_' + {201, 1, 1, 2, 0, -4}, // 0x60 '`' + {202, 4, 4, 5, 0, -3}, // 0x61 'a' + {204, 4, 5, 5, 0, -4}, // 0x62 'b' + {207, 4, 4, 5, 0, -3}, // 0x63 'c' + {209, 4, 5, 5, 0, -4}, // 0x64 'd' + {212, 4, 4, 5, 0, -3}, // 0x65 'e' + {214, 3, 5, 4, 0, -4}, // 0x66 'f' + {216, 4, 5, 5, 0, -3}, // 0x67 'g' + {219, 4, 5, 5, 0, -4}, // 0x68 'h' + {222, 1, 4, 2, 0, -3}, // 0x69 'i' + {223, 2, 5, 3, 0, -3}, // 0x6A 'j' + {225, 4, 5, 5, 0, -4}, // 0x6B 'k' + {228, 1, 5, 2, 0, -4}, // 0x6C 'l' + {229, 5, 4, 6, 0, -3}, // 0x6D 'm' + {232, 4, 4, 5, 0, -3}, // 0x6E 'n' + {234, 4, 4, 5, 0, -3}, // 0x6F 'o' + {236, 4, 5, 5, 0, -3}, // 0x70 'p' + {239, 4, 5, 5, 0, -3}, // 0x71 'q' + {242, 4, 4, 5, 0, -3}, // 0x72 'r' + {244, 4, 4, 5, 0, -3}, // 0x73 's' + {246, 5, 5, 6, 0, -4}, // 0x74 't' + {250, 4, 4, 5, 0, -3}, // 0x75 'u' + {252, 4, 4, 5, 0, -3}, // 0x76 'v' + {254, 5, 4, 6, 0, -3}, // 0x77 'w' + {257, 4, 4, 5, 0, -3}, // 0x78 'x' + {259, 4, 5, 5, 0, -3}, // 0x79 'y' + {262, 4, 4, 5, 0, -3}, // 0x7A 'z' + {264, 3, 5, 4, 0, -4}, // 0x7B '{' + {266, 1, 5, 2, 0, -4}, // 0x7C '|' + {267, 3, 5, 4, 0, -4}, // 0x7D '}' + {269, 5, 3, 6, 0, -3}}; // 0x7E '~' + +const GFXfont Org_01 PROGMEM = {(uint8_t *)Org_01Bitmaps, + (GFXglyph *)Org_01Glyphs, 0x20, 0x7E, 7}; + +// Approx. 943 bytes diff --git a/firmware/include/fonts/Picopixel.h b/firmware/include/fonts/Picopixel.h new file mode 100644 index 0000000..463b1b5 --- /dev/null +++ b/firmware/include/fonts/Picopixel.h @@ -0,0 +1,123 @@ +#pragma once +#include + +// Picopixel by Sebastian Weber. A tiny font +// with all characters within a 6 pixel height. + +const uint8_t PicopixelBitmaps[] PROGMEM = { + 0xE8, 0xB4, 0x57, 0xD5, 0xF5, 0x00, 0x4E, 0x3E, 0x80, 0xA5, 0x4A, 0x4A, + 0x5A, 0x50, 0xC0, 0x6A, 0x40, 0x95, 0x80, 0xAA, 0x80, 0x5D, 0x00, 0x60, + 0xE0, 0x80, 0x25, 0x48, 0x56, 0xD4, 0x75, 0x40, 0xC5, 0x4E, 0xC5, 0x1C, + 0x97, 0x92, 0xF3, 0x1C, 0x53, 0x54, 0xE5, 0x48, 0x55, 0x54, 0x55, 0x94, + 0xA0, 0x46, 0x64, 0xE3, 0x80, 0x98, 0xC5, 0x04, 0x56, 0xC6, 0x57, 0xDA, + 0xD7, 0x5C, 0x72, 0x46, 0xD6, 0xDC, 0xF3, 0xCE, 0xF3, 0x48, 0x72, 0xD4, + 0xB7, 0xDA, 0xF8, 0x24, 0xD4, 0xBB, 0x5A, 0x92, 0x4E, 0x8E, 0xEB, 0x58, + 0x80, 0x9D, 0xB9, 0x90, 0x56, 0xD4, 0xD7, 0x48, 0x56, 0xD4, 0x40, 0xD7, + 0x5A, 0x71, 0x1C, 0xE9, 0x24, 0xB6, 0xD4, 0xB6, 0xA4, 0x8C, 0x6B, 0x55, + 0x00, 0xB5, 0x5A, 0xB5, 0x24, 0xE5, 0x4E, 0xEA, 0xC0, 0x91, 0x12, 0xD5, + 0xC0, 0x54, 0xF0, 0x90, 0xC7, 0xF0, 0x93, 0x5E, 0x71, 0x80, 0x25, 0xDE, + 0x5E, 0x30, 0x6E, 0x80, 0x77, 0x9C, 0x93, 0x5A, 0xB8, 0x45, 0x60, 0x92, + 0xEA, 0xAA, 0x40, 0xD5, 0x6A, 0xD6, 0x80, 0x55, 0x00, 0xD7, 0x40, 0x75, + 0x90, 0xE8, 0x71, 0xE0, 0xBA, 0x40, 0xB5, 0x80, 0xB5, 0x00, 0x8D, 0x54, + 0xAA, 0x80, 0xAC, 0xE0, 0xE5, 0x70, 0x6A, 0x26, 0xFC, 0xC8, 0xAC, 0x5A}; + +const GFXglyph PicopixelGlyphs[] PROGMEM = {{0, 0, 0, 2, 0, 1}, // 0x20 ' ' + {0, 1, 5, 2, 0, -4}, // 0x21 '!' + {1, 3, 2, 4, 0, -4}, // 0x22 '"' + {2, 5, 5, 6, 0, -4}, // 0x23 '#' + {6, 3, 6, 4, 0, -4}, // 0x24 '$' + {9, 3, 5, 4, 0, -4}, // 0x25 '%' + {11, 4, 5, 5, 0, -4}, // 0x26 '&' + {14, 1, 2, 2, 0, -4}, // 0x27 ''' + {15, 2, 5, 3, 0, -4}, // 0x28 '(' + {17, 2, 5, 3, 0, -4}, // 0x29 ')' + {19, 3, 3, 4, 0, -3}, // 0x2A '*' + {21, 3, 3, 4, 0, -3}, // 0x2B '+' + {23, 2, 2, 3, 0, 0}, // 0x2C ',' + {24, 3, 1, 4, 0, -2}, // 0x2D '-' + {25, 1, 1, 2, 0, 0}, // 0x2E '.' + {26, 3, 5, 4, 0, -4}, // 0x2F '/' + {28, 3, 5, 4, 0, -4}, // 0x30 '0' + {30, 2, 5, 3, 0, -4}, // 0x31 '1' + {32, 3, 5, 4, 0, -4}, // 0x32 '2' + {34, 3, 5, 4, 0, -4}, // 0x33 '3' + {36, 3, 5, 4, 0, -4}, // 0x34 '4' + {38, 3, 5, 4, 0, -4}, // 0x35 '5' + {40, 3, 5, 4, 0, -4}, // 0x36 '6' + {42, 3, 5, 4, 0, -4}, // 0x37 '7' + {44, 3, 5, 4, 0, -4}, // 0x38 '8' + {46, 3, 5, 4, 0, -4}, // 0x39 '9' + {48, 1, 3, 2, 0, -3}, // 0x3A ':' + {49, 2, 4, 3, 0, -3}, // 0x3B ';' + {50, 2, 3, 3, 0, -3}, // 0x3C '<' + {51, 3, 3, 4, 0, -3}, // 0x3D '=' + {53, 2, 3, 3, 0, -3}, // 0x3E '>' + {54, 3, 5, 4, 0, -4}, // 0x3F '?' + {56, 3, 5, 4, 0, -4}, // 0x40 '@' + {58, 3, 5, 4, 0, -4}, // 0x41 'A' + {60, 3, 5, 4, 0, -4}, // 0x42 'B' + {62, 3, 5, 4, 0, -4}, // 0x43 'C' + {64, 3, 5, 4, 0, -4}, // 0x44 'D' + {66, 3, 5, 4, 0, -4}, // 0x45 'E' + {68, 3, 5, 4, 0, -4}, // 0x46 'F' + {70, 3, 5, 4, 0, -4}, // 0x47 'G' + {72, 3, 5, 4, 0, -4}, // 0x48 'H' + {74, 1, 5, 2, 0, -4}, // 0x49 'I' + {75, 3, 5, 4, 0, -4}, // 0x4A 'J' + {77, 3, 5, 4, 0, -4}, // 0x4B 'K' + {79, 3, 5, 4, 0, -4}, // 0x4C 'L' + {81, 5, 5, 6, 0, -4}, // 0x4D 'M' + {85, 4, 5, 5, 0, -4}, // 0x4E 'N' + {88, 3, 5, 4, 0, -4}, // 0x4F 'O' + {90, 3, 5, 4, 0, -4}, // 0x50 'P' + {92, 3, 6, 4, 0, -4}, // 0x51 'Q' + {95, 3, 5, 4, 0, -4}, // 0x52 'R' + {97, 3, 5, 4, 0, -4}, // 0x53 'S' + {99, 3, 5, 4, 0, -4}, // 0x54 'T' + {101, 3, 5, 4, 0, -4}, // 0x55 'U' + {103, 3, 5, 4, 0, -4}, // 0x56 'V' + {105, 5, 5, 6, 0, -4}, // 0x57 'W' + {109, 3, 5, 4, 0, -4}, // 0x58 'X' + {111, 3, 5, 4, 0, -4}, // 0x59 'Y' + {113, 3, 5, 4, 0, -4}, // 0x5A 'Z' + {115, 2, 5, 3, 0, -4}, // 0x5B '[' + {117, 3, 5, 4, 0, -4}, // 0x5C '\' + {119, 2, 5, 3, 0, -4}, // 0x5D ']' + {121, 3, 2, 4, 0, -4}, // 0x5E '^' + {122, 4, 1, 4, 0, 1}, // 0x5F '_' + {123, 2, 2, 3, 0, -4}, // 0x60 '`' + {124, 3, 4, 4, 0, -3}, // 0x61 'a' + {126, 3, 5, 4, 0, -4}, // 0x62 'b' + {128, 3, 3, 4, 0, -2}, // 0x63 'c' + {130, 3, 5, 4, 0, -4}, // 0x64 'd' + {132, 3, 4, 4, 0, -3}, // 0x65 'e' + {134, 2, 5, 3, 0, -4}, // 0x66 'f' + {136, 3, 5, 4, 0, -3}, // 0x67 'g' + {138, 3, 5, 4, 0, -4}, // 0x68 'h' + {140, 1, 5, 2, 0, -4}, // 0x69 'i' + {141, 2, 6, 3, 0, -4}, // 0x6A 'j' + {143, 3, 5, 4, 0, -4}, // 0x6B 'k' + {145, 2, 5, 3, 0, -4}, // 0x6C 'l' + {147, 5, 3, 6, 0, -2}, // 0x6D 'm' + {149, 3, 3, 4, 0, -2}, // 0x6E 'n' + {151, 3, 3, 4, 0, -2}, // 0x6F 'o' + {153, 3, 4, 4, 0, -2}, // 0x70 'p' + {155, 3, 4, 4, 0, -2}, // 0x71 'q' + {157, 2, 3, 3, 0, -2}, // 0x72 'r' + {158, 3, 4, 4, 0, -3}, // 0x73 's' + {160, 2, 5, 3, 0, -4}, // 0x74 't' + {162, 3, 3, 4, 0, -2}, // 0x75 'u' + {164, 3, 3, 4, 0, -2}, // 0x76 'v' + {166, 5, 3, 6, 0, -2}, // 0x77 'w' + {168, 3, 3, 4, 0, -2}, // 0x78 'x' + {170, 3, 4, 4, 0, -2}, // 0x79 'y' + {172, 3, 4, 4, 0, -3}, // 0x7A 'z' + {174, 3, 5, 4, 0, -4}, // 0x7B '{' + {176, 1, 6, 2, 0, -4}, // 0x7C '|' + {177, 3, 5, 4, 0, -4}, // 0x7D '}' + {179, 4, 2, 5, 0, -3}}; // 0x7E '~' + +const GFXfont Picopixel PROGMEM = {(uint8_t *)PicopixelBitmaps, + (GFXglyph *)PicopixelGlyphs, 0x20, 0x7E, 7}; + +// Approx. 852 bytes diff --git a/firmware/include/states/AdjustState.h b/firmware/include/states/AdjustState.h new file mode 100644 index 0000000..3245c54 --- /dev/null +++ b/firmware/include/states/AdjustState.h @@ -0,0 +1,16 @@ +#pragma once + +#include "State.h" + +class AdjustState : public State +{ +public: + void enter() override; + void update() override; + void exit() override; + void adjustTimer(int duration); + +private: + int adjustDuration; + unsigned long lastActivity; +}; \ No newline at end of file diff --git a/firmware/include/states/DoneState.h b/firmware/include/states/DoneState.h new file mode 100644 index 0000000..a740bb9 --- /dev/null +++ b/firmware/include/states/DoneState.h @@ -0,0 +1,15 @@ +#pragma once + +#include "State.h" + +class DoneState : public State +{ +public: + DoneState(); + void enter() override; + void update() override; + void exit() override; + +private: + unsigned long doneEnter; +}; \ No newline at end of file diff --git a/firmware/include/states/IdleState.h b/firmware/include/states/IdleState.h new file mode 100644 index 0000000..9ceb1dc --- /dev/null +++ b/firmware/include/states/IdleState.h @@ -0,0 +1,17 @@ +#pragma once + +#include "State.h" + +class IdleState : public State +{ +public: + IdleState(); + void enter() override; + void update() override; + void exit() override; + void setTimer(int duration); + +private: + int defaultDuration; + unsigned long lastActivity; +}; diff --git a/firmware/include/states/PausedState.h b/firmware/include/states/PausedState.h new file mode 100644 index 0000000..954e332 --- /dev/null +++ b/firmware/include/states/PausedState.h @@ -0,0 +1,19 @@ +#pragma once + +#include "State.h" + +class PausedState : public State +{ +public: + PausedState(); + void enter() override; + void update() override; + void exit() override; + + void setPause(int duration, unsigned long elapsedTime); + +private: + int duration; + unsigned long pauseEnter; + unsigned long elapsedTime; +}; \ No newline at end of file diff --git a/firmware/include/states/ProvisionState.h b/firmware/include/states/ProvisionState.h new file mode 100644 index 0000000..8b79bb3 --- /dev/null +++ b/firmware/include/states/ProvisionState.h @@ -0,0 +1,11 @@ +#pragma once + +#include "State.h" + +class ProvisionState : public State +{ +public: + void enter() override; + void update() override; + void exit() override; +}; \ No newline at end of file diff --git a/firmware/include/states/ResetState.h b/firmware/include/states/ResetState.h new file mode 100644 index 0000000..3411658 --- /dev/null +++ b/firmware/include/states/ResetState.h @@ -0,0 +1,13 @@ +#pragma once + +#include "State.h" + +class ResetState : public State +{ +public: + void enter() override; + void update() override; + void exit() override; + + unsigned long resetStartTime = 0; +}; \ No newline at end of file diff --git a/firmware/include/states/SleepState.h b/firmware/include/states/SleepState.h new file mode 100644 index 0000000..547b03f --- /dev/null +++ b/firmware/include/states/SleepState.h @@ -0,0 +1,11 @@ +#pragma once + +#include "State.h" + +class SleepState : public State +{ +public: + void enter() override; + void update() override; + void exit() override; +}; \ No newline at end of file diff --git a/firmware/include/states/StartupState.h b/firmware/include/states/StartupState.h new file mode 100644 index 0000000..10fecdc --- /dev/null +++ b/firmware/include/states/StartupState.h @@ -0,0 +1,15 @@ +#pragma once + +#include "State.h" + +class StartupState : public State +{ +public: + StartupState(); + void enter() override; + void update() override; + void exit() override; + +private: + unsigned long startEnter; +}; diff --git a/firmware/include/states/TimerState.h b/firmware/include/states/TimerState.h new file mode 100644 index 0000000..69a91ac --- /dev/null +++ b/firmware/include/states/TimerState.h @@ -0,0 +1,20 @@ +#pragma once + +#include "State.h" + +class TimerState : public State +{ +public: + TimerState(); + + void enter() override; + void update() override; + void exit() override; + + void setTimer(int duration, unsigned long elapsedTime); + +private: + int duration; + unsigned long startTime; + unsigned long elapsedTime; +}; \ No newline at end of file diff --git a/firmware/lib/README b/firmware/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/firmware/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/firmware/partitions.csv b/firmware/partitions.csv new file mode 100644 index 0000000..828a596 --- /dev/null +++ b/firmware/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x7C0000, +spiffs, data, spiffs, 0x7D0000,0x30000, \ No newline at end of file diff --git a/firmware/src/Animation.cpp b/firmware/src/Animation.cpp new file mode 100644 index 0000000..25c4f67 --- /dev/null +++ b/firmware/src/Animation.cpp @@ -0,0 +1,82 @@ +#include "Animation.h" + +Animation::Animation(Adafruit_SSD1306* display) : oled(display), animationRunning(false), playInReverse(false) {} + +void Animation::start(const byte* frames, int frameCount, bool loop, bool reverse, unsigned long durationMs, int width, int height) { + animationFrames = frames; + totalFrames = frameCount; + loopAnimation = loop; + playInReverse = reverse; // Set reverse playback flag + animationRunning = true; + + // Initialize current frame correctly based on direction + currentFrame = playInReverse ? totalFrames - 1 : 0; + + frameWidth = width; + frameHeight = height; + frameDelay = DEFAULT_FRAME_DELAY; + + if (durationMs == 0) { + animationDuration = totalFrames * frameDelay; + } else { + animationDuration = durationMs; + } + + animationStartTime = millis(); + lastFrameTime = millis(); + + frameX = (oled->width() - frameWidth) / 2; + frameY = (oled->height() - frameHeight) / 2; + + oled->clearDisplay(); + oled->drawBitmap(frameX, frameY, &animationFrames[currentFrame * 288], frameWidth, frameHeight, 1); + oled->display(); +} + +void Animation::update() { + if (!animationRunning) return; + + unsigned long currentTime = millis(); + + if (currentTime - animationStartTime >= animationDuration) { + animationRunning = false; + return; + } + + // Check if it's time to advance to the next frame + if (currentTime - lastFrameTime >= frameDelay) { + lastFrameTime = currentTime; + + // Adjust current frame based on direction + if (playInReverse) { + currentFrame--; + if (currentFrame < 0) { + if (loopAnimation) { + currentFrame = totalFrames - 1; // Wrap around to last frame + } else { + animationRunning = false; + return; + } + } + } else { + currentFrame++; + if (currentFrame >= totalFrames) { + if (loopAnimation) { + currentFrame = 0; // Wrap around to first frame + } else { + animationRunning = false; + return; + } + } + } + + // Display the current frame + oled->clearDisplay(); + oled->drawBitmap(frameX, frameY, &animationFrames[currentFrame * 288], frameWidth, frameHeight, 1); + oled->display(); + } +} + +bool Animation::isRunning() { + return animationRunning; +} diff --git a/firmware/src/StateMachine.cpp b/firmware/src/StateMachine.cpp new file mode 100644 index 0000000..7ef7bcb --- /dev/null +++ b/firmware/src/StateMachine.cpp @@ -0,0 +1,47 @@ +#include "StateMachine.h" + +// Global state machine instance +StateMachine stateMachine; + +// Initialize static states +AdjustState StateMachine::adjustState; +SleepState StateMachine::sleepState; +DoneState StateMachine::doneState; +IdleState StateMachine::idleState; +PausedState StateMachine::pausedState; +ProvisionState StateMachine::provisionState; +ResetState StateMachine::resetState; +StartupState StateMachine::startupState; +TimerState StateMachine::timerState; + +StateMachine::StateMachine() { + currentState = &startupState; // Start with StartupState + stateMutex = xSemaphoreCreateMutex(); // Initialize the mutex +} + +// Clean up the state and delete the mutex +StateMachine::~StateMachine() { + if (stateMutex != NULL) { + vSemaphoreDelete(stateMutex); // Delete the mutex + } +} + +void StateMachine::changeState(State* newState) { + // Lock the mutex + if (xSemaphoreTake(stateMutex, portMAX_DELAY) == pdTRUE) { + transition = true; + if (currentState != nullptr) { + currentState->exit(); + } + currentState = newState; // Assign the new state (static state) + currentState->enter(); + transition = false; + xSemaphoreGive(stateMutex); // Release the mutex + } +} + +void StateMachine::update() { + if (!transition && currentState != nullptr) { + currentState->update(); // Call update on the current state + } +} \ No newline at end of file diff --git a/firmware/src/controllers/DisplayController.cpp b/firmware/src/controllers/DisplayController.cpp new file mode 100644 index 0000000..8dbe684 --- /dev/null +++ b/firmware/src/controllers/DisplayController.cpp @@ -0,0 +1,458 @@ +#include "controllers/DisplayController.h" + +#include "fonts/Picopixel.h" +#include "fonts/Org_01.h" +#include "bitmaps.h" + +DisplayController::DisplayController(uint8_t oledWidth, uint8_t oledHeight, uint8_t oledAddress) + : oled(oledWidth, oledHeight, &Wire, -1), animation(&oled) {} + +void DisplayController::begin() { + if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { + Serial.println(F("SSD1306 allocation failed")); + for (;;); // Loop forever if initialization fails + } + + // oled.ssd1306_command(SSD1306_SETCONTRAST); + // oled.ssd1306_command(128); + + oled.clearDisplay(); + oled.display(); + Serial.println("DisplayController initialized."); +} + +void DisplayController::drawSplashScreen() { + oled.clearDisplay(); + + oled.drawBitmap(16, 3, focusdial_logo, 99, 45, 1); + oled.setTextColor(1); + oled.setTextSize(1); + oled.setFont(&Picopixel); + oled.setCursor(21, 60); + oled.print("YOUTUBE/ @SALIMBENBOUZ"); + + oled.display(); +} + +void DisplayController::drawIdleScreen(int duration, bool wifi) { + if (isAnimationRunning()) return; + + static unsigned long lastBlinkTime = 0; + static bool blinkState = true; + + unsigned long currentTime = millis(); + + // Toggle blink state if WiFi is off + if (!wifi && (currentTime - lastBlinkTime >= 500)) { + blinkState = !blinkState; + lastBlinkTime = currentTime; + } + + oled.clearDisplay(); + + // "PRESS TO START" + oled.setFont(&Picopixel); + oled.setTextSize(1); + oled.setTextColor(1); + oled.setCursor(40, 58); + oled.print("PRESS TO START"); + oled.drawRoundRect(35, 51, 60, 11, 1, 1); + + // Display WiFi icon based on WiFi state + if (wifi) { + oled.drawBitmap(70, 3, icon_wifi_on, 5, 5, 1); + oled.setCursor(54, 7); + oled.print("WIFI"); + } else if (blinkState) { + oled.drawBitmap(70, 3, icon_wifi_off, 5, 5, 1); + oled.setCursor(54, 7); + oled.print("WIFI"); + } + + char left[3], right[3]; + int xLeft = 1; + int xRight = 73; + + if (duration < 60) { + sprintf(left, "%02d", duration); + strcpy(right, "00"); + } else { + int hours = duration / 60; + int minutes = duration % 60; + sprintf(left, "%02d", hours); + sprintf(right, "%02d", minutes); + } + + // Adjust position if the first character is '1' + if (left[0] == '1') { + xLeft += 20; + } + if (right[0] == '1') { + xRight += 20; + } + + oled.setTextSize(5); + oled.setFont(&Org_01); + oled.setCursor(xLeft, 36); + oled.print(left); + + oled.setCursor(xRight, 36); + oled.print(right); + + // Separator dots + oled.fillRect(62, 21, 5, 5, 1); + oled.fillRect(62, 31, 5, 5, 1); + + oled.display(); +} + +void DisplayController::drawTimerScreen(int remainingSeconds) { + if (isAnimationRunning()) return; + + oled.clearDisplay(); + + if (remainingSeconds < 0) { + remainingSeconds = 0; + } + + int hours = remainingSeconds / 3600; + int minutes = (remainingSeconds % 3600) / 60; + int seconds = remainingSeconds % 60; + + char left[3], right[3], secondsStr[3]; + int xLeft = 1; + int xRight = 73; + + // Format left and right + if (hours > 0) { + sprintf(left, "%02d", hours); + sprintf(right, "%02d", minutes); + } else { + sprintf(left, "%02d", minutes); + sprintf(right, "%02d", seconds); + } + + // Adjust position if the first character is '1' + if (left[0] == '1') { + xLeft += 20; + } + if (right[0] == '1') { + xRight += 20; + } + + // Draw the left value (hours or minutes) + oled.setTextColor(1); + oled.setTextSize(5); + oled.setFont(&Org_01); + oled.setCursor(xLeft, 36); + oled.print(left); + + // Draw the right value (minutes or seconds) + oled.setCursor(xRight, 36); + oled.print(right); + + // Separator dots + oled.fillRect(62, 31, 5, 5, 1); + oled.fillRect(62, 21, 5, 5, 1); + + sprintf(secondsStr, "%02d", seconds); + + int xSeconds = 54; + if (secondsStr[0] == '1') { + xSeconds += 8; // Offset by 8 if the first char is '1' + } + + oled.setTextSize(2); + oled.setCursor(xSeconds, 58); + oled.print(secondsStr); + + // Draw icons and labels + oled.drawBitmap(61, 3, icon_star, 7, 7, 1); + oled.setTextSize(1); + oled.setCursor(27, 54); + oled.print(hours > 0 ? "H" : "M"); + oled.setCursor(98, 54); + oled.print(hours > 0 ? "M" : "S"); + + oled.display(); +} + +void DisplayController::drawPausedScreen(int remainingSeconds) { + if (isAnimationRunning()) return; + + oled.clearDisplay(); + + if (remainingSeconds < 0) { + remainingSeconds = 0; + } + + int hours = remainingSeconds / 3600; + int minutes = (remainingSeconds % 3600) / 60; + int seconds = remainingSeconds % 60; + + char left[3], right[3]; + int xLeft = 1; + int xRight = 73; + + // Format left and right + if (hours > 0) { + sprintf(left, "%02d", hours); + sprintf(right, "%02d", minutes); + } else { + sprintf(left, "%02d", minutes); + sprintf(right, "%02d", seconds); + } + + // Adjust position if the first character is '1' + if (left[0] == '1') { + xLeft += 20; + } + if (right[0] == '1') { + xRight += 20; + } + + if ((millis() / 400) % 2 == 0) { + oled.setTextColor(1); + oled.setTextSize(5); + oled.setFont(&Org_01); + oled.setCursor(xLeft, 36); + oled.print(left); + oled.setCursor(xRight, 36); + oled.print(right); + + oled.fillRect(62, 31, 5, 5, 1); + oled.fillRect(62, 22, 5, 5, 1); + + oled.setFont(&Org_01); + oled.setTextSize(1); + oled.setCursor(27, 54); + oled.print(hours > 0 ? "H" : "M"); + oled.setCursor(98, 54); + oled.print(hours > 0 ? "M" : "S"); + } + + // Draw label and icon + oled.drawRoundRect(47, 51, 35, 11, 1, 1); + oled.setTextColor(1); + oled.setTextSize(1); + oled.setFont(&Picopixel); + oled.setCursor(53, 58); + oled.print("PAUSED"); + oled.drawBitmap(60, 2, icon_pause, 9, 9, 1); + + oled.display(); +} + +void DisplayController::drawResetScreen(bool resetSelected) { + if (isAnimationRunning()) return; + oled.clearDisplay(); + + // Static UI elements + oled.setTextColor(1); + oled.setTextSize(2); + oled.setFont(&Picopixel); + oled.setCursor(54, 15); + oled.print("RESET"); + oled.setTextSize(1); + oled.setCursor(20, 30); + oled.print("ALL STORED SETTINGS WILL "); + oled.setCursor(21, 40); + oled.print("BE PERMANENTLY ERASED."); + oled.drawBitmap(35, 4, icon_reset, 13, 16, 1); + + // Change only the rectangle fill and text color based on selection + if (resetSelected) { + // "RESET" filled, "CANCEL" outlined + oled.fillRoundRect(67, 49, 37, 11, 1, 1); + oled.setTextColor(0); + oled.setCursor(76, 56); + oled.print("RESET"); + + oled.drawRoundRect(24, 49, 37, 11, 1, 1); + oled.setTextColor(1); + oled.setCursor(31, 56); + oled.print("CANCEL"); + } else { + // "CANCEL" filled, "RESET" outlined + oled.fillRoundRect(24, 49, 37, 11, 1, 1); + oled.setTextColor(0); + oled.setCursor(31, 56); + oled.print("CANCEL"); + + oled.drawRoundRect(67, 49, 37, 11, 1, 1); + oled.setTextColor(1); + oled.setCursor(76, 56); + oled.print("RESET"); + } + + oled.display(); +} + +void DisplayController::drawDoneScreen() { + if (isAnimationRunning()) return; + + static unsigned long lastBlinkTime = 0; + static bool blinkState = true; + + unsigned long currentTime = millis(); + + // Toggle blink every 500 ms + if (currentTime - lastBlinkTime >= 500) { + blinkState = !blinkState; + lastBlinkTime = currentTime; + } + + oled.clearDisplay(); + + if (blinkState) { + oled.setTextColor(1); + oled.setTextSize(5); + oled.setFont(&Org_01); + oled.setCursor(1, 36); + oled.print("00"); + oled.setCursor(73, 36); + oled.print("00"); + oled.fillRect(62, 31, 5, 5, 1); + oled.fillRect(62, 21, 5, 5, 1); + } + + // Draw label and icon + oled.fillRoundRect(46, 51, 35, 11, 1, 1); + oled.setTextColor(0); + oled.setTextSize(1); + oled.setFont(&Picopixel); + oled.setCursor(56, 58); + oled.print("DONE"); + oled.drawBitmap(61, 3, icon_star, 7, 7, 1); + + oled.display(); +} + + +void DisplayController::drawAdjustScreen(int duration) { + if (isAnimationRunning()) return; + + oled.clearDisplay(); + + oled.setTextColor(1); + oled.setTextSize(4); + oled.setFont(&Org_01); + + int hours = duration / 60; + int minutes = duration % 60; + + char hourStr[3]; + char minuteStr[3]; + + // Format hour and minute strings with leading zeros + sprintf(hourStr, "%02d", hours); + sprintf(minuteStr, "%02d", minutes); + + // Default positions for hours and minutes + int xHour = 13; + int xMinute = 72; + + // Check the first character and adjust position if '1' + if (hourStr[0] == '1') { + xHour += 15; + } + if (minuteStr[0] == '1') { + xMinute += 15; + } + + // Display hours + oled.setCursor(xHour, 37); + oled.print(hourStr); + + // Display minutes + oled.setCursor(xMinute, 37); + oled.print(minuteStr); + + // Display labels + oled.setTextSize(1); + oled.setCursor(26, 55); + oled.print("HRS"); + oled.setCursor(86, 55); + oled.print("MIN"); + + // Additional UI elements + oled.drawBitmap(0, 12, image_change_left, 7, 40, 1); + oled.drawRoundRect(36, 1, 57, 11, 1, 1); + oled.drawBitmap(121, 12, image_change_right, 7, 40, 1); + oled.setFont(&Picopixel); + oled.setCursor(41, 8); + oled.print("PRESS TO SAVE"); + oled.drawBitmap(103, 3, icon_arrow_down, 5, 7, 1); + oled.drawBitmap(21, 3, icon_arrow_down, 5, 7, 1); + + oled.display(); +} + + +void DisplayController::drawProvisionScreen() { + if (isAnimationRunning()) return; + + oled.clearDisplay(); + + oled.setTextColor(1); + oled.setTextSize(1); + oled.setFont(&Picopixel); + oled.setCursor(12, 38); + oled.print("PLEASE CONNECT TO BLUETOOTH"); + oled.setCursor(14, 48); + oled.print("AND THIS FOCUSDIAL NETWORK"); + oled.setCursor(35, 58); + oled.print("TO PROVISION WIFI"); + oled.drawBitmap(39, 4, provision_logo, 51, 23, 1); + + oled.display(); +} + +void DisplayController::clear() { + oled.clearDisplay(); + oled.display(); +} + +void DisplayController::showAnimation(const byte frames[][288], int frameCount, bool loop, bool reverse, unsigned long durationMs, int width, int height) { + animation.start(&frames[0][0], frameCount, loop, reverse, durationMs, width, height); // Pass array as pointer +} + +void DisplayController::updateAnimation() { + animation.update(); +} + +bool DisplayController::isAnimationRunning() { + return animation.isRunning(); +} + +void DisplayController::showConfirmation() { + showAnimation(animation_tick, 20); +} + +void DisplayController::showCancel() { + showAnimation(animation_cancel, 18, false, true); +} + +void DisplayController::showReset() { + showAnimation(animation_reset, 28, true, false); +} + +void DisplayController::showConnected() { + showAnimation(animation_wifi, 28); +} + +void DisplayController::showTimerStart() { + showAnimation(animation_timer_start, 20, false, true); +} + +void DisplayController::showTimerDone() { + showAnimation(animation_timer_start, 20); +} + +void DisplayController::showTimerPause() { + showAnimation(animation_resume, 18, false, true); +} + +void DisplayController::showTimerResume() { + showAnimation(animation_resume, 18); +} diff --git a/firmware/src/controllers/InputController.cpp b/firmware/src/controllers/InputController.cpp new file mode 100644 index 0000000..98841a6 --- /dev/null +++ b/firmware/src/controllers/InputController.cpp @@ -0,0 +1,141 @@ +#include "controllers/InputController.h" +#include + +static InputController *instancePtr = nullptr; // Global pointer for the ISR + +void InputController::handleEncoderInterrupt() +{ + if (instancePtr) + { + instancePtr->encoder.tick(); + } +} + +void InputController::handleButtonInterrupt() +{ + if (instancePtr) + { + instancePtr->button.tick(); + } +} + +InputController::InputController(uint8_t buttonPin, uint8_t encoderPinA, uint8_t encoderPinB) + : button(buttonPin, true), + encoder(encoderPinA, encoderPinB, RotaryEncoder::LatchMode::TWO03), + lastPosition(0), + buttonPin(buttonPin), + encoderPinA(encoderPinA), + encoderPinB(encoderPinB) +{ + + // Attach click, double-click, and long-press handlers using OneButton library + button.attachClick([](void *scope) + { static_cast(scope)->onButtonClick(); }, this); + button.attachDoubleClick([](void *scope) + { static_cast(scope)->onButtonDoubleClick(); }, this); + button.attachLongPressStart([](void *scope) + { static_cast(scope)->onButtonLongPress(); }, this); + + instancePtr = this; // Set the global instance pointer to this instance +} + +void InputController::begin() +{ + button.setDebounceMs(20); + button.setClickMs(150); + button.setPressMs(400); + lastPosition = encoder.getPosition(); + + pinMode(buttonPin, INPUT_PULLUP); + pinMode(encoderPinA, INPUT_PULLUP); + pinMode(encoderPinB, INPUT_PULLUP); + + // Set up interrupts for encoder handling + attachInterrupt(digitalPinToInterrupt(encoderPinA), handleEncoderInterrupt, CHANGE); + attachInterrupt(digitalPinToInterrupt(encoderPinB), handleEncoderInterrupt, CHANGE); + + // Set up interrupt for button handling + attachInterrupt(digitalPinToInterrupt(buttonPin), handleButtonInterrupt, CHANGE); // Interrupt on button state change +} + +void InputController::update() +{ + button.tick(); + encoder.tick(); + + // Check encoder position and calculate delta + int currentPosition = encoder.getPosition(); + int delta = currentPosition - lastPosition; + + if (delta != 0) + { + onEncoderRotate(delta); + lastPosition = currentPosition; + } +} + +// Register state-specific handlers +void InputController::onPressHandler(std::function handler) +{ + pressHandler = handler; +} + +void InputController::onDoublePressHandler(std::function handler) +{ + doublePressHandler = handler; +} + +void InputController::onLongPressHandler(std::function handler) +{ + longPressHandler = handler; +} + +void InputController::onEncoderRotateHandler(std::function handler) +{ + encoderRotateHandler = handler; +} + +// Method to release all handlers +void InputController::releaseHandlers() +{ + pressHandler = nullptr; + doublePressHandler = nullptr; + longPressHandler = nullptr; + encoderRotateHandler = nullptr; + + button.reset(); // Reset button state machine + lastPosition = encoder.getPosition(); // Reset encoder position tracking +} + +// Internal event handlers that call the registered state handlers +void InputController::onButtonClick() +{ + if (pressHandler != nullptr) + { + pressHandler(); + } +} + +void InputController::onButtonDoubleClick() +{ + if (doublePressHandler != nullptr) + { + doublePressHandler(); + } +} + +void InputController::onButtonLongPress() +{ + if (longPressHandler != nullptr) + { + longPressHandler(); + } +} + +void InputController::onEncoderRotate(int delta) +{ + if (encoderRotateHandler != nullptr) + { + encoderRotateHandler(delta); // Pass delta to the handler + } +} diff --git a/firmware/src/controllers/LedController.cpp b/firmware/src/controllers/LedController.cpp new file mode 100644 index 0000000..ce49d01 --- /dev/null +++ b/firmware/src/controllers/LedController.cpp @@ -0,0 +1,241 @@ +#include "controllers/LedController.h" + +LEDController::LEDController(uint8_t ledPin, uint16_t numLeds, uint8_t brightness) + : leds(numLeds, ledPin), + numLeds(numLeds), + brightness(brightness), + currentAnimation(None), + lastUpdateTime(0), + currentStep(0), + currentCycle(0), + decayStarted(false) {} + +void LEDController::begin() +{ + leds.begin(); + leds.setBrightness(brightness); + leds.show(); +} + +void LEDController::update() +{ + switch (currentAnimation) + { + case FillAndDecay: + handleFillAndDecay(); + break; + case Spinner: + handleSpinner(); + break; + case Breath: + handleBreath(); + break; + default: + break; + } +} + +void LEDController::startFillAndDecay(uint32_t color, uint32_t totalDuration) +{ + stopCurrentAnimation(); + currentAnimation = FillAndDecay; + animationColor = color; + animationDuration = totalDuration; + currentStep = 0; + pixelIndex = 0; + brightnessLevel = brightness; + lastUpdateTime = millis(); +} + +void LEDController::setSpinner(uint32_t color, int cycles) +{ + stopCurrentAnimation(); + currentAnimation = Spinner; + animationColor = color; + animationCycles = cycles; + currentCycle = 0; + currentStep = 0; + lastUpdateTime = millis(); +} + +void LEDController::setBreath(uint32_t color, int cycles, bool endFilled, uint32_t speed) +{ + stopCurrentAnimation(); + currentAnimation = Breath; + animationColor = color; + animationCycles = cycles; + this->endFilled = endFilled; + animationSpeed = speed; + currentCycle = 0; + currentStep = 0; + lastUpdateTime = millis(); +} + +void LEDController::setSolid(uint32_t color) +{ + stopCurrentAnimation(); + leds.fill(color); + leds.show(); +} + +void LEDController::turnOff() +{ + stopCurrentAnimation(); + leds.clear(); + leds.show(); +} + +uint32_t LEDController::scaleColor(uint32_t color, uint8_t brightnessLevel) +{ + uint8_t r = (color >> 16 & 0xFF) * brightnessLevel / 255; + uint8_t g = (color >> 8 & 0xFF) * brightnessLevel / 255; + uint8_t b = (color & 0xFF) * brightnessLevel / 255; + return leds.Color(r, g, b); +} + +void LEDController::handleFillAndDecay() +{ + uint32_t fillDuration = 300; // Initial fill duration + uint32_t decayDuration = animationDuration - fillDuration; + uint32_t totalSteps = (numLeds + 1) * brightness; + uint32_t stepDuration = decayDuration / totalSteps; + + if (currentStep < numLeds) + { + // Quick fill phase + uint32_t stepDurationFill = fillDuration / numLeds; + if (millis() - lastUpdateTime >= stepDurationFill) + { + leds.setPixelColor(currentStep, scaleColor(animationColor, brightness)); + leds.show(); + currentStep++; + lastUpdateTime = millis(); + } + } + else + { + // Initialize decay phase + if (!decayStarted) + { + decayStarted = true; + pixelIndex = 1; + brightnessLevel = brightness; + lastUpdateTime = millis(); + } + + // Decay phase + if (millis() - lastUpdateTime >= stepDuration) + { + lastUpdateTime = millis(); + + if (brightnessLevel > 0) + { + brightnessLevel--; + leds.setPixelColor(pixelIndex, scaleColor(animationColor, brightnessLevel)); + leds.show(); + } + else + { + leds.setPixelColor(pixelIndex, 0); + leds.show(); + pixelIndex++; + brightnessLevel = brightness; + } + + if (pixelIndex > numLeds) + { + stopCurrentAnimation(); + } + } + } +} + +void LEDController::handleSpinner() +{ + uint32_t stepDuration = 100; + if (millis() - lastUpdateTime >= stepDuration) + { + leds.clear(); + for (int i = 0; i < numLeds; i++) + { + leds.setPixelColor((i + currentStep) % numLeds, scaleColor(animationColor, i * 255 / numLeds)); + } + leds.show(); + currentStep++; + lastUpdateTime = millis(); + + if (currentStep >= numLeds) + { + currentStep = 0; + currentCycle++; + if (animationCycles != -1 && currentCycle >= animationCycles) + { + stopCurrentAnimation(); + } + } + } +} + +void LEDController::handleBreath() +{ + if (millis() - lastUpdateTime >= animationSpeed) + { + uint8_t fadeBrightness = (currentStep <= 127) ? currentStep * 2 : (255 - currentStep) * 2; + + for (int i = 0; i < numLeds; i++) + { + leds.setPixelColor(i, scaleColor(animationColor, fadeBrightness)); + } + leds.show(); + currentStep++; + + if (currentStep >= 255) + { + currentStep = 0; + currentCycle++; + + // Adjust the number of cycles if `endFilled` is true + int effectiveCycles = animationCycles; + if (endFilled && effectiveCycles > 0) + { + effectiveCycles--; + } + + if (effectiveCycles != -1 && currentCycle >= effectiveCycles) + { + if (endFilled) + { + // Additional half cycle to fill the LEDs + for (int i = 0; i < numLeds; i++) + { + leds.setPixelColor(i, animationColor); + } + leds.show(); + } + else + { + turnOff(); + } + stopCurrentAnimation(); + } + } + lastUpdateTime = millis(); + } +} + +void LEDController::stopCurrentAnimation() +{ + currentAnimation = None; + currentStep = 0; + currentCycle = 0; + pixelIndex = 0; + brightnessLevel = brightness; + decayStarted = false; + lastUpdateTime = millis(); +} + +void LEDController::printDebugInfo() +{ + Serial.printf("Anim: %d, Step: %d, Cycle: %d, PixelIdx: %d, Leds numb: %d, Brightness: %d, Color: 0x%06X, Dur: %lu, Speed: %lu, Cycles: %d, EndFilled: %d\n", + currentAnimation, currentStep, currentCycle, pixelIndex, numLeds, brightness, animationColor, animationDuration, animationSpeed, animationCycles, endFilled); +} \ No newline at end of file diff --git a/firmware/src/controllers/NetworkController.cpp b/firmware/src/controllers/NetworkController.cpp new file mode 100644 index 0000000..d5c3f37 --- /dev/null +++ b/firmware/src/controllers/NetworkController.cpp @@ -0,0 +1,511 @@ +#include "Config.h" +#include "controllers/NetworkController.h" + +#include +#include +#include +#include +#include + +NetworkController *NetworkController::instance = nullptr; + +NetworkController::NetworkController() + : a2dp_sink(), + btPaired(false), + bluetoothActive(false), + bluetoothAttempted(false), + lastBluetoothtAttempt(0), + bluetoothTaskHandle(nullptr), + webhookQueue(nullptr), + webhookTaskHandle(nullptr), + provisioningMode(false) +{ + + instance = this; +} + +void NetworkController::begin() +{ + WiFiProvisionerSettings(); + + if (isWiFiProvisioned()) + { + Serial.println("Stored WiFi credentials found. Connecting..."); + wifiProvisioner.connectToWiFi(); + } + + // Load bluetooth paired state from nvs + preferences.begin("network", true); + btPaired = preferences.getBool("bt_paired", false); + preferences.end(); + + if (btPaired) + { + Serial.println("Previously paired with a device. Initializing Bluetooth."); + initializeBluetooth(); // Initialize Bluetooth if previously paired + } + else + { + Serial.println("No previous Bluetooth pairing found. Skipping Bluetooth initialization."); + } + + // Load Webhook URL from NVS under the "focusdial" namespace + preferences.begin("focusdial", true); + webhookURL = preferences.getString("webhook_url", ""); + preferences.end(); + + if (!webhookURL.isEmpty()) + { + Serial.println("Loaded Webhook URL: " + webhookURL); + } + + if (webhookQueue == nullptr) + { + webhookQueue = xQueueCreate(5, sizeof(char *)); + } + + if (webhookTaskHandle == nullptr) + { + xTaskCreatePinnedToCore(webhookTask, "Webhook Task", 4096, this, 0, &webhookTaskHandle, 1); + Serial.println("Persistent webhook task started."); + } +} + +void NetworkController::update() +{ + if (WiFi.status() != WL_CONNECTED) + { + WiFi.reconnect(); + } +} + +bool NetworkController::isWiFiProvisioned() +{ + // Check for stored WiFi credentials + preferences.begin("network", true); + String storedSSID = preferences.getString("ssid", ""); + preferences.end(); + + return !storedSSID.isEmpty(); // Return true if credentials are found +} + +bool NetworkController::isWiFiConnected() +{ + return (WiFi.status() == WL_CONNECTED); +} + +bool NetworkController::isBluetoothPaired() +{ + return btPaired; +} + +void NetworkController::startProvisioning() +{ + Serial.println("Starting provisioning mode..."); + btPaired = false; // Reset paired state for new provisioning + bluetoothActive = true; // Enable Bluetooth for pairing + provisioningMode = true; // Indicate we are in provisioning mode + initializeBluetooth(); + wifiProvisioner.setupAccessPointAndServer(); +} + +void NetworkController::stopProvisioning() +{ + Serial.println("Stopping provisioning mode..."); + bluetoothActive = false; // Disable Bluetooth after provisioning + provisioningMode = false; // Exit provisioning mode + stopBluetooth(); +} + +void NetworkController::reset() +{ + wifiProvisioner.resetCredentials(); + if (btPaired) + { + a2dp_sink.clean_last_connection(); + saveBluetoothPairedState(false); + } + Serial.println("Reset complete. WiFi credentials and paired state cleared."); +} + +void NetworkController::initializeBluetooth() +{ + if (bluetoothTaskHandle == nullptr) + { + + // Configure the A2DP sink with empty callbacks to use it for the trigger only + a2dp_sink.set_stream_reader(nullptr, false); + a2dp_sink.set_raw_stream_reader(nullptr); + a2dp_sink.set_on_volumechange(nullptr); + a2dp_sink.set_avrc_connection_state_callback(nullptr); + a2dp_sink.set_avrc_metadata_callback(nullptr); + a2dp_sink.set_avrc_rn_playstatus_callback(nullptr); + a2dp_sink.set_avrc_rn_track_change_callback(nullptr); + a2dp_sink.set_avrc_rn_play_pos_callback(nullptr); + a2dp_sink.set_spp_active(false); + a2dp_sink.set_output_active(false); + a2dp_sink.set_rssi_active(false); + + a2dp_sink.set_on_connection_state_changed(btConnectionStateCallback, this); + + Serial.println("Bluetooth A2DP Sink configured."); + + // Create task for handling Bluetooth + xTaskCreate(bluetoothTask, "Bluetooth Task", 4096, this, 0, &bluetoothTaskHandle); + } +} + +void NetworkController::startBluetooth() +{ + if (btPaired) + { // Only start if paired + bluetoothActive = true; + } +} + +void NetworkController::stopBluetooth() +{ + bluetoothActive = false; // Stop Bluetooth activity +} + +void NetworkController::btConnectionStateCallback(esp_a2d_connection_state_t state, void *obj) +{ + auto *self = static_cast(obj); + + if (state == ESP_A2D_CONNECTION_STATE_CONNECTED) + { + Serial.println("Bluetooth device connected."); + + // Save paired state only in provisioning mode + if (self->provisioningMode) + { + self->saveBluetoothPairedState(true); + self->btPaired = true; + Serial.println("Paired state saved during provisioning."); + } + } + else if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) + { + Serial.println("Bluetooth device disconnected."); + // No need to set flags; task loop will handle reconnection logic based on is_connected() + } +} + +void NetworkController::saveBluetoothPairedState(bool paired) +{ + preferences.begin("network", false); + preferences.putBool("bt_paired", paired); + preferences.end(); + btPaired = paired; + Serial.println("Bluetooth pairing state saved in NVS."); +} + +void NetworkController::bluetoothTask(void *param) +{ + NetworkController *self = static_cast(param); + + while (true) + { + // If in provisioning mode, start Bluetooth only once + if (self->provisioningMode) + { + if (!self->bluetoothAttempted) + { + Serial.println("Starting Bluetooth for provisioning..."); + self->a2dp_sink.start("Focus Dial", true); + self->bluetoothAttempted = true; // Mark as attempted to prevent repeated starts + } + } + else + { + // Normal operation mode + if (self->bluetoothActive && !self->bluetoothAttempted) + { + Serial.println("Starting Bluetooth..."); + self->a2dp_sink.start("Focus Dial", true); // Auto-reconnect enabled + self->bluetoothAttempted = true; + self->lastBluetoothtAttempt = millis(); // Record the time of the start attempt + } + + // If Bluetooth is active but not connected, attempt reconnect every 2 seconds + if (self->bluetoothActive && !self->a2dp_sink.is_connected() && (millis() - self->lastBluetoothtAttempt >= 2000)) + { + Serial.println("Attempting Bluetooth reconnect..."); + self->a2dp_sink.start("Focus Dial", true); + self->lastBluetoothtAttempt = millis(); // Update last attempt time + } + + // If Bluetooth is not supposed to be active but is connected, disconnect + if (!self->bluetoothActive && self->a2dp_sink.is_connected()) + { + Serial.println("Stopping Bluetooth..."); + self->a2dp_sink.disconnect(); + self->bluetoothAttempted = false; // Allow re-attempt later + } + } + + vTaskDelay(100 / portTICK_PERIOD_MS); + } +} + +void NetworkController::sendWebhookAction(const String &action) +{ + if (webhookQueue == nullptr) + { + webhookQueue = xQueueCreate(5, sizeof(char *)); + } + + char *actionCopy = strdup(action.c_str()); + if (actionCopy == nullptr) + { + Serial.println("Failed to allocate memory for webhook action."); + return; + } + + if (xQueueSend(webhookQueue, &actionCopy, 0) == pdPASS) + { + Serial.println("Webhook action enqueued: " + String(actionCopy)); + } + else + { + Serial.println("Failed to enqueue webhook action: Queue is full."); + free(actionCopy); // Free the memory if not enqueued + } +} + +void NetworkController::webhookTask(void *param) +{ + NetworkController *self = static_cast(param); + char *action; + + while (true) + { + // Wait for a webhook action to arrive in the queue + if (xQueueReceive(self->webhookQueue, &action, portMAX_DELAY) == pdPASS) + { + Serial.println("Processing webhook action: " + String(action)); + + // Send the webhook request and check the response + bool success = self->sendWebhookRequest(String(action)); + if (success) + { + Serial.println("Webhook action sent successfully."); + } + else + { + Serial.println("Failed to send webhook action."); + } + + free(action); // Free the allocated memory for action + + Serial.println("Finished processing webhook action."); + } + + // Small delay to yield + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} + +bool NetworkController::sendWebhookRequest(const String &action) +{ + if (webhookURL.isEmpty()) + { + Serial.println("Webhook URL is not set. Cannot send action."); + return false; + } + + std::unique_ptr client; + if (webhookURL.startsWith("https://")) + { + client.reset(new WiFiClientSecure()); + if (!client) + { + Serial.println("Memory allocation for WiFiClientSecure failed."); + return false; + } + static_cast(client.get())->setInsecure(); // Not verifying server certificate + } + else + { + client.reset(new WiFiClient()); + if (!client) + { + Serial.println("Memory allocation for WiFiClient failed."); + return false; + } + } + + HTTPClient http; + bool result = false; + + if (http.begin(*client, webhookURL)) + { + http.addHeader("Content-Type", "application/json"); + + String jsonPayload = "{\"action\":\"" + action + "\"}"; + + // Send the POST request + int httpResponseCode = http.POST(jsonPayload); + + if (httpResponseCode > 0) + { + String response = http.getString(); + Serial.println("HTTP Response code: " + String(httpResponseCode)); + Serial.println("Response: " + response); + result = true; + } + else + { + Serial.println("Error in sending POST: " + String(httpResponseCode)); + } + + http.end(); // Close the connection + } + else + { + Serial.println("Unable to connect to server."); + } + + return result; +} + +void NetworkController::WiFiProvisionerSettings() +{ + wifiProvisioner.enableSerialDebug(true); + wifiProvisioner.AP_NAME = "Focus Dial"; + wifiProvisioner.SVG_LOGO = + R"rawliteral( + + + + + + + + + + + + + + + + )rawliteral"; + + wifiProvisioner.HTML_TITLE = "Focus Dial - Provisioning"; + wifiProvisioner.PROJECT_TITLE = " Focus Dial — Setup"; + wifiProvisioner.PROJECT_INFO = R"rawliteral( + 1. Connect to Bluetooth if you want to use the phone automation trigger. + 2. Select a WiFi network to save and allow Focus Dial to trigger webhook automations. + 3. Enter the webhook URL below to trigger it when a focus session starts.)rawliteral"; + + wifiProvisioner.FOOTER_INFO = R"rawliteral( + Focus Dial - Made by Salim Benbouziyane)rawliteral"; + + wifiProvisioner.CONNECTION_SUCCESSFUL = + "Provision Complete. Focus Dial will now start and status led will turn to blue."; + + wifiProvisioner.RESET_CONFIRMATION_TEXT = + "This will erase all settings and require re-provisioning. Confirm on the device."; + + wifiProvisioner.setShowInputField(true); + wifiProvisioner.INPUT_TEXT = "Webhook URL to Trigger Automation:"; + wifiProvisioner.INPUT_PLACEHOLDER = "e.g., https://example.com/webhook"; + wifiProvisioner.INPUT_INVALID_LENGTH = "The URL appears incomplete. Please enter the valid URL to trigger the automation."; + wifiProvisioner.INPUT_NOT_VALID = "The URL entered is not valid. Please verify it and try again."; + + // Set the static methods as callbacks + wifiProvisioner.setInputCheckCallback(validateInputCallback); + wifiProvisioner.setFactoryResetCallback(factoryResetCallback); +} + +// Static method for input validation callback +bool NetworkController::validateInputCallback(const String &input) +{ + if (instance) + { + return instance->validateInput(input); + } + return false; +} + +// Static method for factory reset callback +void NetworkController::factoryResetCallback() +{ + if (instance) + { + instance->handleFactoryReset(); + } +} + +bool NetworkController::validateInput(const String &input) +{ + String modifiedInput = input; + + // Check if URL starts with "http://" or "https://" + if (!(modifiedInput.startsWith("http://") || modifiedInput.startsWith("https://"))) + { + // If none supplied assume "http://" + modifiedInput = "http://" + modifiedInput; + Serial.println("Protocol missing, defaulting to http://"); + } + + // Basic validation + int protocolEnd = modifiedInput.indexOf("://") + 3; + int dotPosition = modifiedInput.indexOf('.', protocolEnd); + + bool isValid = (dotPosition != -1); + + Serial.print("Validating input: "); + Serial.println(modifiedInput); + + // Save URL to NVS here if valid + if (isValid) + { + Serial.println("URL is valid. Saving to NVS..."); + + if (preferences.begin("focusdial", false)) + { // false means open for writing + preferences.putString("webhook_url", modifiedInput); + preferences.end(); + webhookURL = modifiedInput; + Serial.println("Webhook URL saved: " + webhookURL); + } + else + { + Serial.println("Failed to open NVS for writing."); + } + } + else + { + Serial.println("Invalid URL. Not saving to NVS."); + } + + return isValid; +} + +void NetworkController::handleFactoryReset() +{ + Serial.println("Factory reset initiated."); + reset(); +} \ No newline at end of file diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp new file mode 100644 index 0000000..4da8621 --- /dev/null +++ b/firmware/src/main.cpp @@ -0,0 +1,31 @@ +#include +#include "Config.h" +#include "StateMachine.h" +#include "Controllers.h" + +// Global instances of controllers +DisplayController displayController(OLED_WIDTH, OLED_HEIGHT, OLED_ADDR); +LEDController ledController(LED_PIN, NUM_LEDS, LED_BRIGHTNESS); +InputController inputController(BUTTON_PIN, ENCODER_A_PIN, ENCODER_B_PIN); +NetworkController networkController; +Preferences preferences; + +void setup() { + Serial.begin(115200); + + // Initialize controllers + inputController.begin(); + displayController.begin(); + ledController.begin(); + networkController.begin(); + + // Startup state + stateMachine.changeState(&StateMachine::startupState); +} + +void loop() { + // Update state machine + stateMachine.update(); + // If any animation needs to run + displayController.updateAnimation(); +} diff --git a/firmware/src/states/AdjustState.cpp b/firmware/src/states/AdjustState.cpp new file mode 100644 index 0000000..b656628 --- /dev/null +++ b/firmware/src/states/AdjustState.cpp @@ -0,0 +1,57 @@ +#include "StateMachine.h" +#include "Controllers.h" + +void AdjustState::enter() +{ + Serial.println("Entering Adjust State"); + + lastActivity = millis(); + ledController.setSolid(AMBER); + + // Register state-specific handlers + inputController.onPressHandler([this]() + { + Serial.println("Adjust State: Button pressed"); + + StateMachine::idleState.setTimer(this->adjustDuration); + displayController.showConfirmation(); + stateMachine.changeState(&StateMachine::idleState); }); + + inputController.onEncoderRotateHandler([this](int delta) + { + Serial.println("Adjust State: Encoder turned"); + Serial.println(delta); + + // Update duration with delta and enforce bounds + this->adjustDuration += (delta * 5); + if (this->adjustDuration < MIN_TIMER) { + this->adjustDuration = MIN_TIMER; + } else if (this->adjustDuration > MAX_TIMER) { + this->adjustDuration = MAX_TIMER; + } + + this->lastActivity = millis(); }); +} + +void AdjustState::update() +{ + inputController.update(); + displayController.drawAdjustScreen(adjustDuration); + + if (millis() - lastActivity >= (CHANGE_TIMEOUT * 1000)) + { + // Transition to Idle + stateMachine.changeState(&StateMachine::idleState); + } +} + +void AdjustState::exit() +{ + Serial.println("Exiting Adjust State"); + inputController.releaseHandlers(); +} + +void AdjustState::adjustTimer(int duration) +{ + adjustDuration = duration; +} diff --git a/firmware/src/states/DoneState.cpp b/firmware/src/states/DoneState.cpp new file mode 100644 index 0000000..9d76922 --- /dev/null +++ b/firmware/src/states/DoneState.cpp @@ -0,0 +1,41 @@ +#include "StateMachine.h" +#include "Controllers.h" + +DoneState::DoneState() : doneEnter(0) {} + +void DoneState::enter() +{ + Serial.println("Entering Done State"); + + doneEnter = millis(); + ledController.setBreath(GREEN, -1, true, 2); + + // Register state-specific handlers + inputController.onPressHandler([]() + { + Serial.println("Done State: Button pressed"); + stateMachine.changeState(&StateMachine::idleState); }); + + // Send 'Stop' webhook + networkController.sendWebhookAction("stop"); +} + +void DoneState::update() +{ + inputController.update(); + ledController.update(); + + displayController.drawDoneScreen(); + + if (millis() - doneEnter >= (CHANGE_TIMEOUT * 1000)) + { + // Transition to Idle after timeout + stateMachine.changeState(&StateMachine::idleState); + } +} + +void DoneState::exit() +{ + Serial.println("Exiting Done State"); + inputController.releaseHandlers(); +} diff --git a/firmware/src/states/IdleState.cpp b/firmware/src/states/IdleState.cpp new file mode 100644 index 0000000..c36f087 --- /dev/null +++ b/firmware/src/states/IdleState.cpp @@ -0,0 +1,87 @@ +#include "StateMachine.h" +#include "Controllers.h" + +IdleState::IdleState() : defaultDuration(0), lastActivity(0) +{ + + if (nvs_flash_init() != ESP_OK) + { + Serial.println("NVS Flash Init Failed"); + } + else + { + Serial.println("NVS initialized successfully."); + } + + // Load the default duration + if (preferences.begin("focusdial", true)) + { + defaultDuration = preferences.getInt("timer", DEFAULT_TIMER); + preferences.end(); + } +} + +void IdleState::enter() +{ + Serial.println("Entering Idle State"); + ledController.setBreath(BLUE, -1, false, 5); + + // Register state-specific handlers + inputController.onPressHandler([this]() + { + Serial.println("Idle State: Button pressed"); + StateMachine::timerState.setTimer(this->defaultDuration, 0); + displayController.showTimerStart(); + stateMachine.changeState(&StateMachine::timerState); // Start timer + }); + + inputController.onLongPressHandler([this]() + { + Serial.println("Idle State: Button long pressed"); + stateMachine.changeState(&StateMachine::resetState); // Transition to Reset State + }); + + inputController.onEncoderRotateHandler([this](int delta) + { + Serial.println("Idle State: Encoder turned"); + StateMachine::adjustState.adjustTimer(this->defaultDuration); + stateMachine.changeState(&StateMachine::adjustState); // Transition to Adjust State + }); + + lastActivity = millis(); // Activity timer +} + +void IdleState::update() +{ + static unsigned long lastUpdateTime = 0; + + // Controllers updates + inputController.update(); + ledController.update(); + networkController.update(); + + displayController.drawIdleScreen(defaultDuration, networkController.isWiFiConnected()); + + // Check if sleep timeout is reached + if (millis() - lastActivity >= (SLEEP_TIMOUT * 60 * 1000)) + { + Serial.println("Idle State: Activity timeout"); + stateMachine.changeState(&StateMachine::sleepState); // Transition to Sleep State + } +} + +void IdleState::exit() +{ + Serial.println("Exiting Idle State"); + inputController.releaseHandlers(); + ledController.turnOff(); +} + +void IdleState::setTimer(int duration) +{ + defaultDuration = duration; + + preferences.begin("focusdial", true); + preferences.putInt("timer", defaultDuration); + preferences.end(); +} \ No newline at end of file diff --git a/firmware/src/states/PausedState.cpp b/firmware/src/states/PausedState.cpp new file mode 100644 index 0000000..e9d4e86 --- /dev/null +++ b/firmware/src/states/PausedState.cpp @@ -0,0 +1,71 @@ +#include "StateMachine.h" +#include "Controllers.h" + +PausedState::PausedState() : duration(0), elapsedTime(0), pauseEnter(0) {} + +void PausedState::enter() +{ + Serial.println("Entering Paused State"); + pauseEnter = millis(); // Record the time when the pause started + ledController.setBreath(YELLOW, -1, false, 20); + + // Register state-specific handlers + inputController.onPressHandler([this]() + { + Serial.println("Paused State: Button Pressed"); + + // Send 'Start' webhook (resume) + networkController.sendWebhookAction("start"); + + // Transition back to TimerState with the stored duration and elapsed time + StateMachine::timerState.setTimer(duration, elapsedTime); + displayController.showTimerResume(); + stateMachine.changeState(&StateMachine::timerState); // Transition back to Timer State + }); + + inputController.onDoublePressHandler([]() + { + Serial.println("Paused State: Button Double Pressed"); + + // Send 'Stop' webhook (canceled) + networkController.sendWebhookAction("stop"); + displayController.showCancel(); + stateMachine.changeState(&StateMachine::idleState); // Transition back to Idle State + }); +} + +void PausedState::update() +{ + inputController.update(); + ledController.update(); + + // Redraw the paused screen with remaining time + int remainingTime = (duration * 60) - elapsedTime; + displayController.drawPausedScreen(remainingTime); + + unsigned long currentTime = millis(); + + // Check if the pause timeout has been reached + if (currentTime - pauseEnter >= (PAUSE_TIMEOUT * 60 * 1000)) + { + // Timeout reached, transition to Idle State + Serial.println("Paused State: Timout"); + + // Send 'Stop' webhook (timeout) + networkController.sendWebhookAction("stop"); + displayController.showCancel(); + stateMachine.changeState(&StateMachine::idleState); // Transition back to Idle State + } +} + +void PausedState::exit() +{ + Serial.println("Exiting Paused State"); + inputController.releaseHandlers(); +} + +void PausedState::setPause(int duration, unsigned long elapsedTime) +{ + this->duration = duration; + this->elapsedTime = elapsedTime; +} \ No newline at end of file diff --git a/firmware/src/states/ProvisionState.cpp b/firmware/src/states/ProvisionState.cpp new file mode 100644 index 0000000..2d6b7ad --- /dev/null +++ b/firmware/src/states/ProvisionState.cpp @@ -0,0 +1,29 @@ +#include "StateMachine.h" +#include "Controllers.h" + +void ProvisionState::enter() +{ + Serial.println("Entering Provision State"); + inputController.releaseHandlers(); + displayController.drawProvisionScreen(); + ledController.setSolid(AMBER); + networkController.startProvisioning(); +} + +void ProvisionState::update() +{ + ledController.update(); + if (networkController.isWiFiProvisioned() && networkController.isWiFiConnected()) + { + Serial.println("Provisioning Complete, WiFi Connected"); + displayController.showConnected(); + networkController.stopProvisioning(); + stateMachine.changeState(&StateMachine::idleState); + } +} + +void ProvisionState::exit() +{ + Serial.println("Exiting Provision State"); + networkController.stopProvisioning(); +} diff --git a/firmware/src/states/ResetState.cpp b/firmware/src/states/ResetState.cpp new file mode 100644 index 0000000..6132494 --- /dev/null +++ b/firmware/src/states/ResetState.cpp @@ -0,0 +1,54 @@ +#include "StateMachine.h" +#include "Controllers.h" + +bool resetSelected = false; // button selection + +void ResetState::enter() +{ + Serial.println("Entering Reset State"); + + ledController.setBreath(MAGENTA, -1, false, 10); + + // Register state-specific handlers + inputController.onEncoderRotateHandler([this](int delta) + { + if (delta > 0) { + resetSelected = true; // Select "RESET" + } else if (delta < 0) { + resetSelected = false; // Select "CANCEL" + } }); + + inputController.onPressHandler([this]() + { + if (resetSelected) { + Serial.println("Reset State: RESET button pressed, rebooting."); + displayController.showReset(); + networkController.reset(); + resetStartTime = millis(); + } else { + Serial.println("Reset State: CANCEL button pressed, returning to Idle."); + displayController.showCancel(); + stateMachine.changeState(&StateMachine::idleState); + } }); +} + +void ResetState::update() +{ + + inputController.update(); + ledController.update(); + displayController.drawResetScreen(resetSelected); + + if (resetStartTime > 0 && (millis() - resetStartTime >= 1000)) + { + Serial.println("Restarting ..."); + ESP.restart(); // Restart after 1 second + } +} + +void ResetState::exit() +{ + Serial.println("Exiting Reset State"); + inputController.releaseHandlers(); + ledController.turnOff(); +} diff --git a/firmware/src/states/SleepState.cpp b/firmware/src/states/SleepState.cpp new file mode 100644 index 0000000..c0c643d --- /dev/null +++ b/firmware/src/states/SleepState.cpp @@ -0,0 +1,37 @@ +#include "StateMachine.h" +#include "Controllers.h" + +void SleepState::enter() +{ + Serial.println("Entering Sleep State"); + + ledController.turnOff(); + displayController.clear(); + + // Register state-specific handlers + inputController.onPressHandler([]() + { + Serial.println("Sleep State: Button pressed"); + stateMachine.changeState(&StateMachine::idleState); }); + + inputController.onLongPressHandler([]() + { + Serial.println("Sleep State: long pressed"); + stateMachine.changeState(&StateMachine::idleState); }); + + inputController.onEncoderRotateHandler([this](int delta) + { + Serial.println("Sleep State: Encoder turned"); + stateMachine.changeState(&StateMachine::idleState); }); +} + +void SleepState::update() +{ + inputController.update(); +} + +void SleepState::exit() +{ + Serial.println("Exiting Sleep State"); + inputController.releaseHandlers(); +} diff --git a/firmware/src/states/StartupState.cpp b/firmware/src/states/StartupState.cpp new file mode 100644 index 0000000..a0459cc --- /dev/null +++ b/firmware/src/states/StartupState.cpp @@ -0,0 +1,37 @@ +#include "StateMachine.h" +#include "Controllers.h" + +StartupState::StartupState() : startEnter(0) {} + +void StartupState::enter() +{ + Serial.println("Entering Splash State"); + + displayController.drawSplashScreen(); + ledController.setSpinner(TEAL, -1); + + startEnter = millis(); +} + +void StartupState::update() +{ + ledController.update(); + + if (millis() - startEnter >= (SPLASH_DURATION * 1000)) + { + if (networkController.isWiFiProvisioned()) + { + stateMachine.changeState(&StateMachine::idleState); // Transition to Idle + } + else + { + stateMachine.changeState(&StateMachine::provisionState); // Trigger Provision + } + } +} + +void StartupState::exit() +{ + ledController.turnOff(); + Serial.println("Exiting Splash State"); +} diff --git a/firmware/src/states/TimerState.cpp b/firmware/src/states/TimerState.cpp new file mode 100644 index 0000000..0d5a695 --- /dev/null +++ b/firmware/src/states/TimerState.cpp @@ -0,0 +1,77 @@ +#include "StateMachine.h" +#include "Controllers.h" + +TimerState::TimerState() : duration(0), elapsedTime(0), startTime(0) {} + +void TimerState::enter() +{ + Serial.println("Entering Timer State"); + + // Start time based on the elapsed time + startTime = millis() - (elapsedTime * 1000); + + displayController.drawTimerScreen(duration * 60); + ledController.startFillAndDecay(RED, ((duration * 60) - elapsedTime) * 1000); + + // Register state-specific handlers + inputController.onPressHandler([this]() + { + Serial.println("Timer State: Button Pressed"); + + // Send 'Stop' webhook (pause) + networkController.sendWebhookAction("stop"); + displayController.showTimerPause(); + + // Transition to PausedState and set elapsed time + StateMachine::pausedState.setPause(this->duration, this->elapsedTime); // Save current elapsed time + stateMachine.changeState(&StateMachine::pausedState); // Transition to Paused State + }); + + inputController.onDoublePressHandler([this]() + { + Serial.println("Timer State: Button Double Pressed"); + + // Send 'Stop' webhook (canceled) + networkController.sendWebhookAction("stop"); + displayController.showCancel(); + stateMachine.changeState(&StateMachine::idleState); // Transition to IdleState + }); + + networkController.startBluetooth(); + networkController.sendWebhookAction("start"); +} + +void TimerState::update() +{ + inputController.update(); + ledController.update(); + + unsigned long currentTime = millis(); + elapsedTime = (currentTime - startTime) / 1000; + + int remainingSeconds = duration * 60 - elapsedTime; + + displayController.drawTimerScreen(remainingSeconds); + + // Check if the timer is done + if (remainingSeconds <= 0) + { + Serial.println("Timer State: Done"); + displayController.showTimerDone(); + stateMachine.changeState(&StateMachine::doneState); // Transition to Done State + } +} + +void TimerState::exit() +{ + inputController.releaseHandlers(); + networkController.stopBluetooth(); + ledController.turnOff(); + Serial.println("Exiting Timer State"); +} + +void TimerState::setTimer(int duration, unsigned long elapsedTime) +{ + this->duration = duration; + this->elapsedTime = elapsedTime; +} \ No newline at end of file diff --git a/firmware/test/README b/firmware/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/firmware/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html diff --git a/images/Focus-Dial_Logo.svg b/images/Focus-Dial_Logo.svg new file mode 100644 index 0000000..e61f576 --- /dev/null +++ b/images/Focus-Dial_Logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Focus-Dial_Thumbnail.jpg b/images/Focus-Dial_Thumbnail.jpg new file mode 100644 index 0000000..75a76bb Binary files /dev/null and b/images/Focus-Dial_Thumbnail.jpg differ diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..df85ed2 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,36 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = adafruit_qtpy_esp32 +src_dir = firmware/src +include_dir = firmware/include +lib_dir = firmware/lib +data_dir = firmware/data +test_dir = firmware/test + +[env:adafruit_qtpy_esp32] +build_flags = -Os +platform = espressif32 +board = adafruit_qtpy_esp32 +framework = arduino +lib_deps = + mathertel/OneButton@^2.6.1 + mathertel/RotaryEncoder@^1.5.3 + adafruit/Adafruit GFX Library@^1.11.10 + adafruit/Adafruit NeoPixel@^1.12.3 + adafruit/Adafruit SSD1306@^2.5.11 + santerilindfors/WiFiProvisioner@^1.0.0 + https://github.com/pschatzmann/ESP32-A2DP + https://github.com/pschatzmann/arduino-audio-tools.git + +board_build.flash_size = 8MB +board_build.partitions = firmware/partitions.csv +monitor_speed = 115200 diff --git a/resources/ref/Adafruit QT Py ESP32-Pico Pinout.pdf b/resources/ref/Adafruit QT Py ESP32-Pico Pinout.pdf new file mode 100644 index 0000000..328c300 Binary files /dev/null and b/resources/ref/Adafruit QT Py ESP32-Pico Pinout.pdf differ diff --git a/resources/ref/Encoder_per56.pdf b/resources/ref/Encoder_per56.pdf new file mode 100644 index 0000000..4fae908 Binary files /dev/null and b/resources/ref/Encoder_per56.pdf differ diff --git a/resources/unifi_script.sh b/resources/unifi_script.sh new file mode 100644 index 0000000..ba86196 --- /dev/null +++ b/resources/unifi_script.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# Enable or disable logging based on an input argument (0 = no debug, 1 = debug) +debug=$7 # Pass 1 for debugging, 0 for no debugging + +if [[ $debug -eq 1 ]]; then + # Enable logging + exec > /config/scripts/unifi_traffic_rules.log 2>&1 +else + exec > /dev/null 2>&1 # Disable logging if debug is not enabled +fi + +unifi_username=$2 +unifi_password=$3 +unifi_controller=$4 +target_rule_id=$5 # The rule ID you're targeting +action=$6 # 'enable' or 'disable' +cookie=$(mktemp) +headers=$(mktemp) + +curl_cmd="curl -s -S --cookie ${cookie} --cookie-jar ${cookie} --insecure " + +unifi_login() { + # Log in to the UniFi controller and capture CSRF token from headers + if [[ $debug -eq 1 ]]; then echo "Logging in to UniFi Controller..."; fi + login_response=$(${curl_cmd} -H "Content-Type: application/json" -D ${headers} -d "{\"password\":\"$unifi_password\",\"username\":\"$unifi_username\"}" $unifi_controller/api/auth/login) + if [[ $debug -eq 1 ]]; then echo "Login Response: $login_response"; fi + csrf_token=$(awk -v IGNORECASE=1 -v FS=': ' '/^X-CSRF-Token/ {print $2}' "${headers}" | tr -d '\r') + if [[ $debug -eq 1 ]]; then echo "CSRF Token: $csrf_token"; fi +} + +unifi_logout() { + # Log out from the UniFi controller + if [[ $debug -eq 1 ]]; then echo "Logging out of UniFi Controller..."; fi + logout_response=$(${curl_cmd} $unifi_controller/api/auth/logout) + if [[ $debug -eq 1 ]]; then echo "Logout Response: $logout_response"; fi +} + +get_traffic_rules() { + # Fetch traffic rules + if [[ $debug -eq 1 ]]; then echo "Fetching traffic rules..."; fi + traffic_rules_response=$(${curl_cmd} "$unifi_controller/proxy/network/v2/api/site/default/trafficrules" -H "Content-Type: application/json" --compressed) + if [[ $debug -eq 1 ]]; then echo "Traffic Rules Response: $traffic_rules_response"; fi +} + +find_and_modify_rule() { + # Extract the rule that matches the target rule ID + if [[ $debug -eq 1 ]]; then echo "Searching for rule with ID: $target_rule_id"; fi + rule=$(echo "$traffic_rules_response" | jq --arg rule_id "$target_rule_id" '.[] | select(._id == $rule_id)') + + if [ -z "$rule" ]; then + echo "No matching rule found with ID: $target_rule_id" + exit 1 + else + # Set the action based on 'enable' or 'disable' + if [ "$action" == "enable" ]; then + new_enabled_value=true + elif [ "$action" == "disable" ]; then + new_enabled_value=false + else + echo "Error: Action must be 'enable' or 'disable'." + exit 1 + fi + + # Modify the rule by setting 'enabled' to true or false + if [[ $debug -eq 1 ]]; then echo "Found rule: $rule"; fi + updated_rule=$(echo "$rule" | jq --argjson action "$new_enabled_value" '.enabled = $action') + + # Send PUT request to modify the rule, including CSRF token in the headers + if [[ $debug -eq 1 ]]; then echo "Modifying rule with ID: $target_rule_id"; fi + + modify_response=$(${curl_cmd} "$unifi_controller/proxy/network/v2/api/site/default/trafficrules/$target_rule_id" -X PUT \ + -H "Content-Type: application/json" \ + -H "X-CSRF-Token: $csrf_token" \ + -d "$updated_rule" --compressed) + + if [[ $debug -eq 1 ]]; then echo "Modify Response: $modify_response"; fi + fi +} + +# Ensure all required parameters are provided +if [[ $# < 7 ]]; then + echo "Error: Must include parameters [fwrule] [username] [password] [UDM address] [rule_id] [enable or disable] [0=debug off, 1=debug on]." + exit -1 +fi + +# Log in, get traffic rules, find the rule by ID, modify it, and log out +unifi_login +get_traffic_rules +find_and_modify_rule +unifi_logout \ No newline at end of file