From f200c195902670d6a9f8ec5f8267bb3d128344d7 Mon Sep 17 00:00:00 2001 From: kennedn Date: Sat, 27 Jan 2024 01:41:00 +0000 Subject: [PATCH 1/7] Add initial badger2040w library and sleep example --- examples/CMakeLists.txt | 1 + examples/badger2040w/CMakeLists.txt | 1 + examples/badger2040w/badger2040w_sleep.cmake | 12 ++ examples/badger2040w/badger2040w_sleep.cpp | 68 ++++++++++ libraries/CMakeLists.txt | 1 + libraries/badger2040w/CMakeLists.txt | 1 + libraries/badger2040w/badger2040w.cmake | 19 +++ libraries/badger2040w/badger2040w.cpp | 132 +++++++++++++++++++ libraries/badger2040w/badger2040w.hpp | 65 +++++++++ 9 files changed, 300 insertions(+) create mode 100644 examples/badger2040w/CMakeLists.txt create mode 100644 examples/badger2040w/badger2040w_sleep.cmake create mode 100644 examples/badger2040w/badger2040w_sleep.cpp create mode 100644 libraries/badger2040w/CMakeLists.txt create mode 100644 libraries/badger2040w/badger2040w.cmake create mode 100644 libraries/badger2040w/badger2040w.cpp create mode 100644 libraries/badger2040w/badger2040w.hpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d32cc949..66ef25d1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -52,6 +52,7 @@ add_subdirectory(automation2040w) add_subdirectory(plasma_stick) add_subdirectory(plasma2040) add_subdirectory(badger2040) +add_subdirectory(badger2040w) add_subdirectory(tufty2040) add_subdirectory(interstate75) add_subdirectory(servo2040) diff --git a/examples/badger2040w/CMakeLists.txt b/examples/badger2040w/CMakeLists.txt new file mode 100644 index 00000000..f29ada38 --- /dev/null +++ b/examples/badger2040w/CMakeLists.txt @@ -0,0 +1 @@ +include(badger2040w_sleep.cmake) diff --git a/examples/badger2040w/badger2040w_sleep.cmake b/examples/badger2040w/badger2040w_sleep.cmake new file mode 100644 index 00000000..616354d9 --- /dev/null +++ b/examples/badger2040w/badger2040w_sleep.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME badger2040w_sleep) +add_executable(${OUTPUT_NAME} badger2040w_sleep.cpp) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi +) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/badger2040w/badger2040w_sleep.cpp b/examples/badger2040w/badger2040w_sleep.cpp new file mode 100644 index 00000000..f3f97cd8 --- /dev/null +++ b/examples/badger2040w/badger2040w_sleep.cpp @@ -0,0 +1,68 @@ +#include "pico/stdlib.h" +#include +#include +#include +#include +#include "pico/time.h" +#include "pico/platform.h" + +#include "common/pimoroni_common.hpp" +#include "badger2040w.hpp" + +using namespace pimoroni; + +// this simple example tells you which button was used to wake up +// Badger2040W and then immediately halts again on another button press + +Badger2040W badger; + +int main() { + + badger.init(); + badger.update_speed(2); + + // find which button was used to wake up + std::string button = ""; + std::string message = "started up."; + if(badger.pressed_to_wake(badger.A)) { button += "A"; } + if(badger.pressed_to_wake(badger.B)) { button += "B"; } + if(badger.pressed_to_wake(badger.C)) { button += "C"; } + if(badger.pressed_to_wake(badger.D)) { button += "D"; } + if(badger.pressed_to_wake(badger.E)) { button += "E"; } + + if(button != "") { + message = "woken up by button " + button + "."; + } + + badger.graphics.set_thickness(2); + + badger.graphics.set_pen(15); + badger.graphics.clear(); + badger.graphics.set_pen(0); + badger.graphics.text(message, Point(10, 20), 286, 2); + badger.graphics.text("(press any button to go to sleep.)", Point(10, 100), 200, 2); + badger.update(); + + badger.led(255); + badger.wait_for_press(); + + badger.graphics.set_pen(15); + badger.graphics.clear(); + badger.graphics.set_pen(0); + badger.graphics.text("going back to sleep...", Point(10, 20), 200, 3); + badger.graphics.text("z", Point(220, 50), 200, 3); + badger.graphics.text("z", Point(235, 30), 200, 4); + badger.graphics.text("z", Point(255, 5), 200, 5); + badger.graphics.text("(press any button to wake up.)", Point(10, 100), 200, 2); + badger.update(); + + while (badger.is_busy()) { + sleep_ms(10); + } + badger.led(0); + + badger.halt(); + + // proof we halted, the LED will not turn on + badger.led(255); +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index e6d140ad..4192a120 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(automation2040w) add_subdirectory(plasma_stick) add_subdirectory(plasma2040) add_subdirectory(badger2040) +add_subdirectory(badger2040w) add_subdirectory(tufty2040) add_subdirectory(servo2040) add_subdirectory(motor2040) diff --git a/libraries/badger2040w/CMakeLists.txt b/libraries/badger2040w/CMakeLists.txt new file mode 100644 index 00000000..8a638056 --- /dev/null +++ b/libraries/badger2040w/CMakeLists.txt @@ -0,0 +1 @@ +include(badger2040w.cmake) \ No newline at end of file diff --git a/libraries/badger2040w/badger2040w.cmake b/libraries/badger2040w/badger2040w.cmake new file mode 100644 index 00000000..78bd290b --- /dev/null +++ b/libraries/badger2040w/badger2040w.cmake @@ -0,0 +1,19 @@ +if(NOT TARGET uc8151) + include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/uc8151/uc8151.cmake) +endif() + +if(NOT TARGET pico_graphics) + include(${CMAKE_CURRENT_LIST_DIR}/../../libraries/pico_graphics/pico_graphics.cmake) +endif() + +set(LIB_NAME badger2040w) +add_library(${LIB_NAME} INTERFACE) + +target_sources(${LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp +) + +target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(${LIB_NAME} INTERFACE uc8151 pico_graphics pico_stdlib hardware_pwm) diff --git a/libraries/badger2040w/badger2040w.cpp b/libraries/badger2040w/badger2040w.cpp new file mode 100644 index 00000000..b8f81bba --- /dev/null +++ b/libraries/badger2040w/badger2040w.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include "hardware/pwm.h" +#include "hardware/watchdog.h" + +#include "badger2040w.hpp" + +namespace pimoroni { + + void Badger2040W::init() { + // set clock speed to 12MHz to reduce the maximum current draw on the + // battery. when updating a small, monochrome, display only every few + // seconds or so then you don't need much processing power anyway... + //set_sys_clock_khz(48000, true); + + gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO); + gpio_set_dir(ENABLE_3V3, GPIO_OUT); + gpio_put(ENABLE_3V3, 1); + + gpio_set_function(A, GPIO_FUNC_SIO); + gpio_set_dir(A, GPIO_IN); + gpio_set_pulls(A, false, true); + + gpio_set_function(B, GPIO_FUNC_SIO); + gpio_set_dir(B, GPIO_IN); + gpio_set_pulls(B, false, true); + + gpio_set_function(C, GPIO_FUNC_SIO); + gpio_set_dir(C, GPIO_IN); + gpio_set_pulls(C, false, true); + + gpio_set_function(D, GPIO_FUNC_SIO); + gpio_set_dir(D, GPIO_IN); + gpio_set_pulls(D, false, true); + + gpio_set_function(E, GPIO_FUNC_SIO); + gpio_set_dir(E, GPIO_IN); + gpio_set_pulls(E, false, true); + + // read initial button states + uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); + _wake_button_states |= gpio_get_all() & mask; + + // led control pin + pwm_config cfg = pwm_get_default_config(); + pwm_set_wrap(pwm_gpio_to_slice_num(LED), 65535); + pwm_init(pwm_gpio_to_slice_num(LED), &cfg, true); + gpio_set_function(LED, GPIO_FUNC_PWM); + led(0); + } + + void Badger2040W::halt() { + gpio_put(ENABLE_3V3, 0); + + // If running on USB we will not actually power down, so emulate the behaviour + // of battery powered badge by listening for a button press and then resetting + // Note: Don't use wait_for_press as that waits for the button to be release and + // we want the reboot to complete before the button is released. + update_button_states(); + while(_button_states == 0) { + update_button_states(); + } + watchdog_reboot(0, 0, 0); + } + + void Badger2040W::update_button_states() { + uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); + _button_states = gpio_get_all() & mask; + } + + uint32_t Badger2040W::button_states() { + return _button_states; + } + + bool Badger2040W::is_busy() { + return uc8151.is_busy(); + } + + void Badger2040W::power_off() { + uc8151.power_off(); + } + + void Badger2040W::invert(bool invert) { + // Not implemented by uc8151 driver + } + + void Badger2040W::update_speed(uint8_t speed) { + uc8151.set_update_speed(speed); + } + + uint32_t Badger2040W::update_time() { + return uc8151.update_time(); + } + + void Badger2040W::partial_update(Rect region) { + uc8151.partial_update(&graphics, region); + } + + void Badger2040W::update() { + uc8151.update(&graphics); + } + + + void Badger2040W::led(uint8_t brightness) { + // set the led brightness from 1 to 256 with gamma correction + float gamma = 2.8; + uint16_t v = (uint16_t)(pow((float)(brightness) / 256.0f, gamma) * 65535.0f + 0.5f); + pwm_set_gpio_level(LED, v); + } + + bool Badger2040W::pressed(uint8_t button) { + return (_button_states & (1UL << button)) != 0; + } + + bool Badger2040W::pressed_to_wake(uint8_t button) { + return (_wake_button_states & (1UL << button)) != 0; + } + + void Badger2040W::wait_for_press() { + update_button_states(); + while(_button_states == 0) { + update_button_states(); + tight_loop_contents(); + } + + uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); + while(gpio_get_all() & mask) { + tight_loop_contents(); + } + } +} diff --git a/libraries/badger2040w/badger2040w.hpp b/libraries/badger2040w/badger2040w.hpp new file mode 100644 index 00000000..099a3aff --- /dev/null +++ b/libraries/badger2040w/badger2040w.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include + +#include "drivers/uc8151/uc8151.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" + +namespace pimoroni { + + class Badger2040W { + protected: + UC8151 uc8151; + uint32_t _button_states = 0; + uint32_t _wake_button_states = 0; + private: + + public: + PicoGraphics_Pen1BitY graphics; + Badger2040W() + : uc8151(296, 128, ROTATE_0, SPIPins{spi0, CS, CLK, MOSI, PIN_UNUSED, DC, PIN_UNUSED}), graphics(296, 128, nullptr) { + }; + void init(); + void update(); + void partial_update(Rect region); + void update_speed(uint8_t speed); + uint32_t update_time(); + void halt(); + bool is_busy(); + void power_off(); + void invert(bool invert); + + // state + void led(uint8_t brightness); + + // inputs (buttons: A, B, C, D, E, USER) + bool pressed(uint8_t button); + bool pressed_to_wake(uint8_t button); + void wait_for_press(); + void update_button_states(); + uint32_t button_states(); + + public: + enum pin { + A = 12, + B = 13, + C = 14, + D = 15, + E = 11, + UP = 15, // alias for D + DOWN = 11, // alias for E + CS = 17, + CLK = 18, + MOSI = 19, + DC = 20, + RESET = 21, + BUSY = 26, + VBUS_DETECT = 24, + LED = 22, + BATTERY = 29, + ENABLE_3V3 = 10 + }; + + }; + +} From 02ffbf513622cd2ab00c5ac17c2ed5e09f9e8c81 Mon Sep 17 00:00:00 2001 From: kennedn Date: Sat, 27 Jan 2024 15:28:18 +0000 Subject: [PATCH 2/7] Speed improvements / refactor - Allow direct access to graphics and display driver - Run init function before initialising graphics and display drivers --- examples/badger2040w/badger2040w_sleep.cpp | 32 +++++++++++----------- libraries/badger2040w/badger2040w.cpp | 31 ++++----------------- libraries/badger2040w/badger2040w.hpp | 13 ++------- 3 files changed, 24 insertions(+), 52 deletions(-) diff --git a/examples/badger2040w/badger2040w_sleep.cpp b/examples/badger2040w/badger2040w_sleep.cpp index f3f97cd8..4605e398 100644 --- a/examples/badger2040w/badger2040w_sleep.cpp +++ b/examples/badger2040w/badger2040w_sleep.cpp @@ -19,7 +19,7 @@ Badger2040W badger; int main() { badger.init(); - badger.update_speed(2); + badger.uc8151->set_update_speed(2); // find which button was used to wake up std::string button = ""; @@ -34,29 +34,29 @@ int main() { message = "woken up by button " + button + "."; } - badger.graphics.set_thickness(2); + badger.graphics->set_thickness(2); - badger.graphics.set_pen(15); - badger.graphics.clear(); - badger.graphics.set_pen(0); - badger.graphics.text(message, Point(10, 20), 286, 2); - badger.graphics.text("(press any button to go to sleep.)", Point(10, 100), 200, 2); + badger.graphics->set_pen(15); + badger.graphics->clear(); + badger.graphics->set_pen(0); + badger.graphics->text(message, Point(10, 20), 286, 2); + badger.graphics->text("(press any button to go to sleep.)", Point(10, 100), 200, 2); badger.update(); badger.led(255); badger.wait_for_press(); - badger.graphics.set_pen(15); - badger.graphics.clear(); - badger.graphics.set_pen(0); - badger.graphics.text("going back to sleep...", Point(10, 20), 200, 3); - badger.graphics.text("z", Point(220, 50), 200, 3); - badger.graphics.text("z", Point(235, 30), 200, 4); - badger.graphics.text("z", Point(255, 5), 200, 5); - badger.graphics.text("(press any button to wake up.)", Point(10, 100), 200, 2); + badger.graphics->set_pen(15); + badger.graphics->clear(); + badger.graphics->set_pen(0); + badger.graphics->text("going back to sleep...", Point(10, 20), 200, 3); + badger.graphics->text("z", Point(220, 50), 200, 3); + badger.graphics->text("z", Point(235, 30), 200, 4); + badger.graphics->text("z", Point(255, 5), 200, 5); + badger.graphics->text("(press any button to wake up.)", Point(10, 100), 200, 2); badger.update(); - while (badger.is_busy()) { + while (badger.uc8151->is_busy()) { sleep_ms(10); } badger.led(0); diff --git a/libraries/badger2040w/badger2040w.cpp b/libraries/badger2040w/badger2040w.cpp index b8f81bba..935d050a 100644 --- a/libraries/badger2040w/badger2040w.cpp +++ b/libraries/badger2040w/badger2040w.cpp @@ -9,10 +9,6 @@ namespace pimoroni { void Badger2040W::init() { - // set clock speed to 12MHz to reduce the maximum current draw on the - // battery. when updating a small, monochrome, display only every few - // seconds or so then you don't need much processing power anyway... - //set_sys_clock_khz(48000, true); gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO); gpio_set_dir(ENABLE_3V3, GPIO_OUT); @@ -48,6 +44,9 @@ namespace pimoroni { pwm_init(pwm_gpio_to_slice_num(LED), &cfg, true); gpio_set_function(LED, GPIO_FUNC_PWM); led(0); + + uc8151 = new UC8151(296, 128, ROTATE_0); + graphics = new PicoGraphics_Pen1BitY(296, 128, nullptr); } void Badger2040W::halt() { @@ -73,32 +72,12 @@ namespace pimoroni { return _button_states; } - bool Badger2040W::is_busy() { - return uc8151.is_busy(); - } - - void Badger2040W::power_off() { - uc8151.power_off(); - } - - void Badger2040W::invert(bool invert) { - // Not implemented by uc8151 driver - } - - void Badger2040W::update_speed(uint8_t speed) { - uc8151.set_update_speed(speed); - } - - uint32_t Badger2040W::update_time() { - return uc8151.update_time(); - } - void Badger2040W::partial_update(Rect region) { - uc8151.partial_update(&graphics, region); + uc8151->partial_update(graphics, region); } void Badger2040W::update() { - uc8151.update(&graphics); + uc8151->update(graphics); } diff --git a/libraries/badger2040w/badger2040w.hpp b/libraries/badger2040w/badger2040w.hpp index 099a3aff..eaa385e8 100644 --- a/libraries/badger2040w/badger2040w.hpp +++ b/libraries/badger2040w/badger2040w.hpp @@ -9,25 +9,18 @@ namespace pimoroni { class Badger2040W { protected: - UC8151 uc8151; uint32_t _button_states = 0; uint32_t _wake_button_states = 0; private: public: - PicoGraphics_Pen1BitY graphics; - Badger2040W() - : uc8151(296, 128, ROTATE_0, SPIPins{spi0, CS, CLK, MOSI, PIN_UNUSED, DC, PIN_UNUSED}), graphics(296, 128, nullptr) { - }; + UC8151* uc8151 = nullptr; + PicoGraphics_Pen1BitY* graphics = nullptr; + Badger2040W(){}; void init(); void update(); void partial_update(Rect region); - void update_speed(uint8_t speed); - uint32_t update_time(); void halt(); - bool is_busy(); - void power_off(); - void invert(bool invert); // state void led(uint8_t brightness); From 729b8596e42907cea91c630f4132e5535ec2aba9 Mon Sep 17 00:00:00 2001 From: kennedn Date: Tue, 6 Feb 2024 16:07:41 +0000 Subject: [PATCH 3/7] Use Unique for external libraries and add image functionality back --- libraries/badger2040w/badger2040w.cpp | 35 ++++++++++++++++++++++++--- libraries/badger2040w/badger2040w.hpp | 9 +++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/libraries/badger2040w/badger2040w.cpp b/libraries/badger2040w/badger2040w.cpp index 935d050a..4c06dd79 100644 --- a/libraries/badger2040w/badger2040w.cpp +++ b/libraries/badger2040w/badger2040w.cpp @@ -45,8 +45,8 @@ namespace pimoroni { gpio_set_function(LED, GPIO_FUNC_PWM); led(0); - uc8151 = new UC8151(296, 128, ROTATE_0); - graphics = new PicoGraphics_Pen1BitY(296, 128, nullptr); + uc8151 = std::make_unique(296, 128, ROTATE_0); + graphics = std::make_unique(296, 128, nullptr); } void Badger2040W::halt() { @@ -72,12 +72,39 @@ namespace pimoroni { return _button_states; } + // // Display a portion of an image (icon sheet) at dx, dy + // void Badger2040W::icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy) { + // image(data, sheet_width, icon_size * index, 0, icon_size, icon_size, dx, dy); + // } + + void Badger2040W::imageRow(const uint8_t *data, Rect rect) { + for(auto x = 0; x < rect.w; x++) { + // work out byte offset in source data + uint32_t o = (x >> 3); + + // extract bitmask for this pixel + uint32_t bm = 0b10000000 >> (x & 0b111); + + // set pixel color + graphics->set_pen(data[o] & bm ? 15 : 0); + // draw the pixel + graphics->set_pixel(Point(x + rect.x, rect.y)); + } + } + // Display an image smaller than the screen (sw*sh) at dx, dy + void Badger2040W::image(const uint8_t *data, Rect rect) { + for(auto y = 0; y < rect.h; y++) { + const uint8_t *scanline = data + ((y * rect.w) >> 3); + Badger2040W::imageRow(scanline, Rect(rect.x, y + rect.y, rect.w, 0)); + } + } + void Badger2040W::partial_update(Rect region) { - uc8151->partial_update(graphics, region); + uc8151->partial_update(graphics.get(), region); } void Badger2040W::update() { - uc8151->update(graphics); + uc8151->update(graphics.get()); } diff --git a/libraries/badger2040w/badger2040w.hpp b/libraries/badger2040w/badger2040w.hpp index eaa385e8..e2a618e0 100644 --- a/libraries/badger2040w/badger2040w.hpp +++ b/libraries/badger2040w/badger2040w.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "drivers/uc8151/uc8151.hpp" #include "libraries/pico_graphics/pico_graphics.hpp" @@ -12,10 +13,11 @@ namespace pimoroni { uint32_t _button_states = 0; uint32_t _wake_button_states = 0; private: + void imageRow(const uint8_t *data, Rect rect); public: - UC8151* uc8151 = nullptr; - PicoGraphics_Pen1BitY* graphics = nullptr; + std::unique_ptr uc8151; + std::unique_ptr graphics; Badger2040W(){}; void init(); void update(); @@ -32,6 +34,9 @@ namespace pimoroni { void update_button_states(); uint32_t button_states(); + // void icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy); + void image(const uint8_t *data, Rect rect); + public: enum pin { A = 12, From bca8333e6d8713812949a719de21be2676c170c9 Mon Sep 17 00:00:00 2001 From: kennedn Date: Tue, 6 Feb 2024 21:06:16 +0000 Subject: [PATCH 4/7] Add pcf85063a driver --- libraries/badger2040w/badger2040w.cmake | 15 ++++++++++++++- libraries/badger2040w/badger2040w.cpp | 2 ++ libraries/badger2040w/badger2040w.hpp | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/badger2040w/badger2040w.cmake b/libraries/badger2040w/badger2040w.cmake index 78bd290b..a7c4d31e 100644 --- a/libraries/badger2040w/badger2040w.cmake +++ b/libraries/badger2040w/badger2040w.cmake @@ -6,6 +6,13 @@ if(NOT TARGET pico_graphics) include(${CMAKE_CURRENT_LIST_DIR}/../../libraries/pico_graphics/pico_graphics.cmake) endif() +if(NOT TARGET pcf85063a) + include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/pcf85063a/pcf85063a.cmake) +endif() + +if(NOT TARGET pimoroni_i2c) + include(${CMAKE_CURRENT_LIST_DIR}/../../common/pimoroni_i2c.cmake) +endif() set(LIB_NAME badger2040w) add_library(${LIB_NAME} INTERFACE) @@ -16,4 +23,10 @@ target_sources(${LIB_NAME} INTERFACE target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(${LIB_NAME} INTERFACE uc8151 pico_graphics pico_stdlib hardware_pwm) +target_link_libraries(${LIB_NAME} INTERFACE + uc8151 + pcf85063a + pico_graphics + pico_stdlib + hardware_pwm + pimoroni_i2c) diff --git a/libraries/badger2040w/badger2040w.cpp b/libraries/badger2040w/badger2040w.cpp index 4c06dd79..526b20e8 100644 --- a/libraries/badger2040w/badger2040w.cpp +++ b/libraries/badger2040w/badger2040w.cpp @@ -4,6 +4,7 @@ #include "hardware/pwm.h" #include "hardware/watchdog.h" +#include "pimoroni_i2c.hpp" #include "badger2040w.hpp" namespace pimoroni { @@ -47,6 +48,7 @@ namespace pimoroni { uc8151 = std::make_unique(296, 128, ROTATE_0); graphics = std::make_unique(296, 128, nullptr); + pcf85063a = std::make_unique(new I2C(I2C_BG_SDA, I2C_BG_SCL), (uint)RTC); } void Badger2040W::halt() { diff --git a/libraries/badger2040w/badger2040w.hpp b/libraries/badger2040w/badger2040w.hpp index e2a618e0..0550a5fd 100644 --- a/libraries/badger2040w/badger2040w.hpp +++ b/libraries/badger2040w/badger2040w.hpp @@ -4,6 +4,7 @@ #include #include "drivers/uc8151/uc8151.hpp" +#include "drivers/pcf85063a/pcf85063a.hpp" #include "libraries/pico_graphics/pico_graphics.hpp" namespace pimoroni { @@ -18,6 +19,7 @@ namespace pimoroni { public: std::unique_ptr uc8151; std::unique_ptr graphics; + std::unique_ptr pcf85063a; Badger2040W(){}; void init(); void update(); @@ -39,6 +41,7 @@ namespace pimoroni { public: enum pin { + RTC = 8, A = 12, B = 13, C = 14, From 8d3611548ca7756abf68f02f0d924b1a6034e5ff Mon Sep 17 00:00:00 2001 From: kennedn Date: Mon, 19 Feb 2024 11:45:46 +0000 Subject: [PATCH 5/7] Port and add examples using badger2040w library - Add icon functionality to badger2040w library - Add external RTC functionality to badger2040w library - Port badger2040 examples and add new icon and rtc examples --- examples/badger2040w/CMakeLists.txt | 5 + .../badger2040w/badger2040w_drawing.cmake | 12 + examples/badger2040w/badger2040w_drawing.cpp | 45 ++ examples/badger2040w/badger2040w_fonts.cmake | 12 + examples/badger2040w/badger2040w_fonts.cpp | 103 ++++ examples/badger2040w/badger2040w_icon.cmake | 12 + examples/badger2040w/badger2040w_icon.cpp | 36 ++ .../badger2040w_icon_demo_icons.hpp | 3 + examples/badger2040w/badger2040w_image.cmake | 12 + examples/badger2040w/badger2040w_image.cpp | 51 ++ .../badger2040w_image_demo_images.hpp | 12 + examples/badger2040w/badger2040w_rtc.cmake | 31 ++ examples/badger2040w/badger2040w_rtc.cpp | 242 +++++++++ examples/badger2040w/lwipopts.h | 89 +++ libraries/badger2040/badger2040.cpp | 508 +++++++++--------- libraries/badger2040w/badger2040w.cpp | 40 +- libraries/badger2040w/badger2040w.hpp | 6 +- 17 files changed, 963 insertions(+), 256 deletions(-) create mode 100644 examples/badger2040w/badger2040w_drawing.cmake create mode 100644 examples/badger2040w/badger2040w_drawing.cpp create mode 100644 examples/badger2040w/badger2040w_fonts.cmake create mode 100644 examples/badger2040w/badger2040w_fonts.cpp create mode 100644 examples/badger2040w/badger2040w_icon.cmake create mode 100644 examples/badger2040w/badger2040w_icon.cpp create mode 100644 examples/badger2040w/badger2040w_icon_demo_icons.hpp create mode 100644 examples/badger2040w/badger2040w_image.cmake create mode 100644 examples/badger2040w/badger2040w_image.cpp create mode 100644 examples/badger2040w/badger2040w_image_demo_images.hpp create mode 100644 examples/badger2040w/badger2040w_rtc.cmake create mode 100644 examples/badger2040w/badger2040w_rtc.cpp create mode 100644 examples/badger2040w/lwipopts.h diff --git a/examples/badger2040w/CMakeLists.txt b/examples/badger2040w/CMakeLists.txt index f29ada38..840cd3e6 100644 --- a/examples/badger2040w/CMakeLists.txt +++ b/examples/badger2040w/CMakeLists.txt @@ -1 +1,6 @@ include(badger2040w_sleep.cmake) +include(badger2040w_drawing.cmake) +include(badger2040w_fonts.cmake) +include(badger2040w_image.cmake) +include(badger2040w_icon.cmake) +include(badger2040w_rtc.cmake) \ No newline at end of file diff --git a/examples/badger2040w/badger2040w_drawing.cmake b/examples/badger2040w/badger2040w_drawing.cmake new file mode 100644 index 00000000..8b812a8b --- /dev/null +++ b/examples/badger2040w/badger2040w_drawing.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME badger2040w_drawing) +add_executable(${OUTPUT_NAME} badger2040w_drawing.cpp) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi +) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/badger2040w/badger2040w_drawing.cpp b/examples/badger2040w/badger2040w_drawing.cpp new file mode 100644 index 00000000..c2063330 --- /dev/null +++ b/examples/badger2040w/badger2040w_drawing.cpp @@ -0,0 +1,45 @@ +#include "pico/stdlib.h" +#include + +#include "common/pimoroni_common.hpp" +#include "badger2040w.hpp" + +using namespace pimoroni; + +Badger2040W badger; + +uint32_t time() { + absolute_time_t t = get_absolute_time(); + return to_ms_since_boot(t); +} + +int main() { + + badger.init(); + stdio_init_all(); + printf("\n\n=======\nbadger2040 starting up\n\n"); + + badger.uc8151->set_update_speed(2); + badger.graphics->set_font("bitmap8"); + badger.graphics->set_thickness(2); + char time_str[11]; + while(true) { + + badger.graphics->set_pen(15); + badger.graphics->clear(); + + badger.graphics->set_pen(0); + badger.graphics->rectangle(Rect(0,badger.DISPLAY_HEIGHT / 4,badger.DISPLAY_WIDTH,badger.DISPLAY_HEIGHT / 2)); + badger.graphics->set_pen(15); + badger.graphics->rectangle(Rect(5,badger.DISPLAY_HEIGHT / 4 + 5,badger.DISPLAY_WIDTH - 10,badger.DISPLAY_HEIGHT / 2 - 10)); + + badger.graphics->set_pen(0); + sprintf(time_str, "%ld", time()); + int32_t time_x_centered = (badger.DISPLAY_WIDTH - badger.graphics->measure_text(time_str, 2.0f)) / 2; + badger.graphics->text("Time since boot (ms)", Point(5, 10), badger.DISPLAY_WIDTH, 2.0f); + badger.graphics->text(time_str, Point(time_x_centered, badger.DISPLAY_HEIGHT / 2 - 8), badger.DISPLAY_WIDTH, 2.0f); + + badger.update(); + sleep_ms(5000); + } +} diff --git a/examples/badger2040w/badger2040w_fonts.cmake b/examples/badger2040w/badger2040w_fonts.cmake new file mode 100644 index 00000000..f54f0b14 --- /dev/null +++ b/examples/badger2040w/badger2040w_fonts.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME badger2040w_fonts) +add_executable(${OUTPUT_NAME} badger2040w_fonts.cpp) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi +) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/badger2040w/badger2040w_fonts.cpp b/examples/badger2040w/badger2040w_fonts.cpp new file mode 100644 index 00000000..db4cc28d --- /dev/null +++ b/examples/badger2040w/badger2040w_fonts.cpp @@ -0,0 +1,103 @@ +#include "pico/stdlib.h" +#include +#include +#include +#include +#include "pico/time.h" +#include "pico/platform.h" + +#include "common/pimoroni_common.hpp" +#include "badger2040w.hpp" + +using namespace pimoroni; + +Badger2040W badger; + +uint32_t time() { + absolute_time_t t = get_absolute_time(); + return to_ms_since_boot(t); +} + +std::array font_names = { + "sans", "sans_bold", "gothic", "cursive", + "cursive_bold", "serif", "serif_bold", "serif_italic" +}; +int8_t selected_font = 0; + +void draw() { + badger.graphics->set_pen(15); + badger.graphics->clear(); + + badger.graphics->set_font("sans"); + for(int i = 0; i < int(font_names.size()); i++) { + std::string name = font_names[i]; + + if(selected_font == i) { + badger.graphics->set_pen(0); + badger.graphics->rectangle(Rect(0, i * 16, 80, 16)); + badger.graphics->set_pen(15); + }else{ + badger.graphics->set_pen(0); + } + + badger.graphics->text(name, Point(2, i * 16 + 7), badger.DISPLAY_WIDTH, 0.4f); + } + + badger.graphics->set_font(font_names[selected_font]); + badger.graphics->set_thickness(2); + badger.graphics->text("The quick", Point(90, 10), badger.DISPLAY_WIDTH, 0.80f); + badger.graphics->text("brown fox", Point(90, 32), badger.DISPLAY_WIDTH, 0.80f); + badger.graphics->text("jumped over", Point(90, 54), badger.DISPLAY_WIDTH, 0.80f); + badger.graphics->text("the lazy dog.", Point(90, 76), badger.DISPLAY_WIDTH, 0.80f); + badger.graphics->text("0123456789", Point(90, 98), badger.DISPLAY_WIDTH, 0.80f); + badger.graphics->text("!\"£$%^&*()", Point(90, 120), badger.DISPLAY_WIDTH, 0.80f); + badger.graphics->set_thickness(1); + + badger.update(); +} + +int main() { + + badger.init(); + stdio_init_all(); + + printf("\n\n=======\nbadger2040 starting up\n\n"); + + badger.uc8151->set_update_speed(2); + + uint32_t i = 0; + + while(true) { + printf("> drawing.."); + + draw(); + + printf("done!\n"); + + printf("> waiting for a button press.."); + badger.wait_for_press(); + printf("done!\n"); + + if(badger.pressed(badger.DOWN)) { + printf("> down pressed\n"); + selected_font++; + } + + if(badger.pressed(badger.UP)) { + printf("> up pressed\n"); + selected_font--; + } + + if(badger.pressed(badger.C)) { + printf("> C pressed\n"); + badger.halt(); + } + + selected_font = selected_font < 0 ? int(font_names.size()) - 1 : selected_font; + selected_font = selected_font >= int(font_names.size()) ? 0 : selected_font; + + printf("> newly selected font is %s (%d)\n", font_names[selected_font].c_str(), selected_font); + + i++; + } +} diff --git a/examples/badger2040w/badger2040w_icon.cmake b/examples/badger2040w/badger2040w_icon.cmake new file mode 100644 index 00000000..88e7af97 --- /dev/null +++ b/examples/badger2040w/badger2040w_icon.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME badger2040w_icon) +add_executable(${OUTPUT_NAME} badger2040w_icon.cpp) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi +) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/badger2040w/badger2040w_icon.cpp b/examples/badger2040w/badger2040w_icon.cpp new file mode 100644 index 00000000..5deaa135 --- /dev/null +++ b/examples/badger2040w/badger2040w_icon.cpp @@ -0,0 +1,36 @@ +#include "pico/stdlib.h" +#include + +#include "common/pimoroni_common.hpp" +#include "badger2040w.hpp" + +#include "badger2040w_icon_demo_icons.hpp" + +using namespace pimoroni; + +Badger2040W badger; + +int main() { + + badger.init(); + stdio_init_all(); + + printf("\n\n=======\nbadger2040 starting up\n\n"); + + badger.uc8151->set_update_speed(1); + + badger.graphics->set_pen(15); + badger.graphics->clear(); + auto iconsize = 40; + auto x_offset = 10; + for (auto x=0; x < (int)badger.DISPLAY_WIDTH / iconsize; x++) { + for (auto i=0; i < 3; i++) { + auto idx = (i + x) % 3; + badger.icon(iconsheet, idx, iconsize * 3, Rect(x_offset + x * iconsize, iconsize * i, iconsize, iconsize)); + } + } + + badger.update(); + badger.halt(); + +} diff --git a/examples/badger2040w/badger2040w_icon_demo_icons.hpp b/examples/badger2040w/badger2040w_icon_demo_icons.hpp new file mode 100644 index 00000000..a9e8ebfb --- /dev/null +++ b/examples/badger2040w/badger2040w_icon_demo_icons.hpp @@ -0,0 +1,3 @@ +static const uint8_t iconsheet[600] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x58, 0x00, 0x15, 0xff, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc1, 0x81, 0x87, 0x80, 0x1f, 0xff, 0xe9, 0x7f, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x40, 0x0f, 0xff, 0xe5, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x40, 0x17, 0xff, 0xd4, 0xff, 0xfc, 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x00, 0x18, 0x00, 0x40, 0x1f, 0xff, 0xea, 0xff, 0xfc, 0x00, 0x01, 0xff, 0x80, 0x00, 0x02, 0x00, 0x18, 0x00, 0x40, 0x0f, 0xff, 0xd2, 0x7f, 0xfc, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x02, 0x01, 0x18, 0x00, 0x40, 0x17, 0xff, 0xa9, 0xff, 0xfc, 0x00, 0xff, 0xc7, 0xe0, 0x00, 0x01, 0x00, 0x99, 0x00, 0x80, 0x1f, 0xff, 0xca, 0x7f, 0xfc, 0x01, 0xff, 0x81, 0xf0, 0x00, 0x01, 0x00, 0x7e, 0x01, 0x00, 0x0f, 0xff, 0xa5, 0x7f, 0xfc, 0x03, 0xff, 0x80, 0xf8, 0x00, 0x00, 0xc0, 0x7e, 0x01, 0x00, 0x13, 0xff, 0xd2, 0xff, 0xfc, 0x07, 0xff, 0xb4, 0xf8, 0x00, 0x00, 0x20, 0xff, 0x06, 0x00, 0x0f, 0xff, 0xd4, 0xff, 0xfc, 0x07, 0xff, 0x84, 0xff, 0x80, 0x00, 0x3f, 0xc3, 0xfc, 0x00, 0x15, 0xff, 0x85, 0x7f, 0xfc, 0x07, 0xff, 0x81, 0xff, 0xc0, 0x00, 0x61, 0x00, 0x86, 0x00, 0x0a, 0xff, 0xe9, 0xff, 0xfc, 0x07, 0xff, 0xa3, 0xff, 0xe0, 0x00, 0xc1, 0x00, 0x82, 0x00, 0x15, 0x7f, 0x94, 0x7f, 0xfc, 0x07, 0xff, 0xf7, 0xff, 0xf0, 0x00, 0x83, 0x00, 0xc1, 0x00, 0x0a, 0xbf, 0x49, 0xff, 0xcc, 0x07, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x87, 0x81, 0xe1, 0x00, 0x1a, 0x7f, 0xa4, 0x7f, 0xa4, 0x03, 0xe0, 0x7f, 0xff, 0xf0, 0x01, 0x9c, 0x7e, 0x18, 0x80, 0x05, 0x7f, 0x22, 0xff, 0x54, 0x03, 0xe0, 0x1b, 0xff, 0xf0, 0x01, 0x30, 0x3c, 0x0c, 0x80, 0x15, 0x3f, 0x94, 0xdf, 0x14, 0x01, 0xe0, 0x00, 0x7f, 0xf0, 0x01, 0xe0, 0x18, 0x07, 0x80, 0x0a, 0xaf, 0xa2, 0x77, 0x4c, 0x00, 0x62, 0x00, 0x3f, 0xf0, 0x02, 0x60, 0x18, 0x02, 0x60, 0x0d, 0x3e, 0x95, 0xfe, 0x54, 0x00, 0x63, 0x00, 0x1f, 0xf0, 0x04, 0x40, 0x18, 0x02, 0x20, 0x16, 0xbf, 0xc8, 0xef, 0x2c, 0x00, 0xc0, 0x0c, 0x1f, 0xe0, 0x0c, 0x40, 0x18, 0x02, 0x20, 0x0b, 0x5f, 0xa2, 0x7e, 0x9c, 0x00, 0xc0, 0x0c, 0x1f, 0xc0, 0x08, 0x40, 0x18, 0x02, 0x10, 0x16, 0x9f, 0x95, 0x7c, 0x7c, 0x01, 0xde, 0x00, 0x3f, 0x00, 0x08, 0x60, 0x3c, 0x02, 0x10, 0x0f, 0x4f, 0x48, 0xfd, 0x5c, 0x01, 0xff, 0x80, 0x3e, 0x00, 0x08, 0x60, 0x76, 0x06, 0x30, 0x17, 0xd7, 0x92, 0xfa, 0xbc, 0x01, 0xf3, 0xf8, 0x3e, 0x00, 0x04, 0xf8, 0x81, 0xbf, 0x20, 0x07, 0xd7, 0x49, 0x79, 0xfc, 0x01, 0xf2, 0x3c, 0x7c, 0x00, 0x06, 0xff, 0x00, 0xf9, 0x60, 0x15, 0xf7, 0x52, 0xf7, 0xfc, 0x03, 0xf8, 0x0f, 0xfc, 0x00, 0x03, 0x0f, 0x00, 0x70, 0xc0, 0x0b, 0xfe, 0xad, 0x37, 0xfc, 0x01, 0xfc, 0x0f, 0xfc, 0x00, 0x03, 0x06, 0x00, 0x60, 0xc0, 0x07, 0xfa, 0xff, 0x57, 0xfc, 0x01, 0xfe, 0x7f, 0xf8, 0x00, 0x01, 0x02, 0x00, 0x40, 0x80, 0x13, 0xfa, 0xff, 0xaf, 0xfc, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x03, 0x00, 0x00, 0x80, 0x0a, 0xfd, 0xfb, 0xdf, 0xfc, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x01, 0x00, 0x80, 0x80, 0x0b, 0xfd, 0xff, 0xff, 0xfc, 0x00, 0xcf, 0xff, 0xe0, 0x00, 0x00, 0x81, 0x81, 0x81, 0x00, 0x07, 0xff, 0xff, 0xdf, 0xfc, 0x00, 0x4f, 0xff, 0xc0, 0x00, 0x00, 0xc1, 0xff, 0x83, 0x00, 0x10, 0xfe, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x63, 0xc3, 0x86, 0x00, 0x0b, 0xff, 0x7f, 0x7f, 0xfc, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x78, 0x00, 0x05, 0x7f, 0xde, 0xff, 0xfc, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x14, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x03, 0xbf, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x15, 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfb, 0xfc +}; diff --git a/examples/badger2040w/badger2040w_image.cmake b/examples/badger2040w/badger2040w_image.cmake new file mode 100644 index 00000000..6d2ba9e1 --- /dev/null +++ b/examples/badger2040w/badger2040w_image.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME badger2040w_image) +add_executable(${OUTPUT_NAME} badger2040w_image.cpp) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi +) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/badger2040w/badger2040w_image.cpp b/examples/badger2040w/badger2040w_image.cpp new file mode 100644 index 00000000..1d23db6f --- /dev/null +++ b/examples/badger2040w/badger2040w_image.cpp @@ -0,0 +1,51 @@ +#include "pico/stdlib.h" +#include + +#include "common/pimoroni_common.hpp" +#include "badger2040w.hpp" + +#include "badger2040w_image_demo_images.hpp" + +using namespace pimoroni; + +Badger2040W badger; + +int main() { + + badger.init(); + stdio_init_all(); + + printf("\n\n=======\nbadger2040 starting up\n\n"); + + badger.uc8151->set_update_speed(2); + + + if(badger.pressed_to_wake(badger.A)) { + printf("> A pressed\n"); + badger.image(shaun, Rect(0, 0, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT)); + } + + else if(badger.pressed_to_wake(badger.B)) { + printf("> B pressed\n"); + badger.image(paul, Rect(0, 0, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT)); + } + + else if(badger.pressed_to_wake(badger.C)) { + printf("> C pressed\n"); + badger.image(adam, Rect(0, 0, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT)); + } + + else { + printf("> No A/B/C key pressed\n"); + badger.graphics->set_pen(15); + badger.graphics->clear(); + + badger.graphics->set_pen(0); + badger.graphics->set_font("sans"); + badger.graphics->text("Press A, B, or C", Point(15, 65), badger.DISPLAY_WIDTH, 1.0f); + } + + badger.update(); + badger.halt(); + +} diff --git a/examples/badger2040w/badger2040w_image_demo_images.hpp b/examples/badger2040w/badger2040w_image_demo_images.hpp new file mode 100644 index 00000000..0178613b --- /dev/null +++ b/examples/badger2040w/badger2040w_image_demo_images.hpp @@ -0,0 +1,12 @@ +static const uint8_t adam[4736] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 48, 0, 0, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 48, 0, 1, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 255, 255, 255, 255, 255, 255, 191, 255, 255, 255, 255, 255, 240, 48, 0, 1, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 224, 255, 255, 255, 255, 255, 182, 251, 127, 255, 255, 255, 255, 240, 48, 0, 1, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 255, 255, 255, 237, 219, 255, 255, 255, 255, 255, 255, 240, 48, 0, 3, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 255, 255, 255, 255, 254, 182, 175, 239, 255, 255, 255, 255, 240, 48, 0, 3, 255, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 171, 90, 187, 255, 255, 255, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 234, 165, 86, 253, 255, 255, 255, 255, 240, 48, 0, 7, 255, 207, 255, 193, 255, 191, 255, 255, 191, 254, 0, 63, 252, 255, 255, 253, 255, 240, 255, 248, 0, 255, 255, 255, 254, 168, 149, 85, 87, 191, 255, 255, 255, 240, 48, 0, 7, 255, 223, 255, 227, 255, 63, 255, 255, 191, 252, 0, 127, 253, 255, 255, 253, 255, 241, 255, 240, 0, 255, 255, 255, 251, 82, 74, 171, 127, 255, 255, 255, 255, 240, 48, 0, 7, 255, 223, 255, 227, 255, 63, 255, 255, 127, 252, 0, 127, 253, 255, 255, 253, 255, 227, 255, 224, 0, 255, 255, 255, 253, 73, 33, 42, 213, 111, 255, 255, 255, 240, 48, 0, 15, 255, 159, 255, 227, 255, 127, 255, 255, 127, 252, 0, 127, 249, 255, 255, 251, 255, 231, 255, 192, 0, 255, 255, 255, 246, 164, 148, 69, 95, 255, 255, 255, 255, 240, 48, 0, 15, 255, 159, 255, 231, 254, 127, 255, 255, 127, 248, 0, 255, 251, 255, 255, 251, 255, 239, 255, 128, 0, 255, 255, 223, 234, 16, 1, 17, 82, 239, 255, 255, 255, 240, 48, 0, 15, 255, 191, 255, 247, 254, 127, 255, 254, 255, 248, 0, 255, 251, 255, 255, 251, 255, 223, 255, 0, 0, 255, 255, 255, 245, 69, 72, 4, 155, 59, 255, 255, 255, 240, 48, 0, 31, 255, 63, 255, 247, 254, 255, 248, 64, 255, 248, 0, 255, 243, 255, 225, 3, 255, 255, 254, 0, 0, 255, 255, 255, 169, 0, 0, 64, 74, 221, 255, 255, 255, 240, 48, 0, 31, 255, 63, 255, 255, 254, 255, 255, 252, 255, 248, 1, 255, 247, 255, 255, 247, 255, 255, 252, 0, 0, 255, 255, 239, 170, 32, 1, 1, 37, 174, 255, 255, 255, 240, 48, 0, 31, 255, 127, 255, 255, 252, 255, 255, 253, 255, 240, 1, 255, 247, 255, 255, 247, 255, 255, 248, 0, 0, 255, 255, 254, 164, 0, 0, 0, 20, 183, 127, 255, 255, 240, 48, 0, 63, 254, 127, 255, 255, 253, 255, 255, 253, 255, 240, 1, 255, 247, 255, 255, 231, 255, 255, 240, 0, 0, 255, 255, 223, 80, 2, 0, 0, 133, 85, 255, 255, 255, 240, 48, 0, 63, 254, 127, 255, 255, 253, 255, 255, 249, 255, 240, 3, 255, 231, 255, 255, 239, 255, 255, 248, 0, 0, 255, 255, 253, 1, 0, 0, 2, 34, 170, 191, 255, 255, 240, 48, 0, 63, 254, 255, 255, 255, 249, 255, 255, 251, 255, 224, 3, 255, 239, 255, 255, 239, 255, 255, 248, 0, 0, 255, 255, 221, 84, 0, 0, 0, 8, 174, 239, 255, 255, 240, 48, 0, 127, 252, 255, 223, 255, 251, 255, 255, 243, 255, 224, 3, 255, 239, 255, 255, 143, 255, 127, 252, 0, 0, 255, 255, 250, 0, 0, 0, 0, 5, 43, 95, 255, 255, 240, 48, 0, 127, 252, 255, 223, 255, 251, 255, 224, 3, 255, 234, 167, 255, 207, 255, 0, 95, 255, 63, 252, 0, 0, 255, 255, 189, 64, 0, 0, 0, 16, 172, 223, 255, 255, 240, 48, 0, 127, 253, 255, 159, 255, 243, 255, 255, 247, 255, 255, 247, 255, 223, 255, 255, 223, 255, 63, 252, 0, 0, 255, 255, 248, 16, 0, 0, 0, 2, 70, 183, 255, 255, 240, 48, 0, 255, 249, 255, 143, 255, 247, 255, 255, 247, 255, 255, 247, 255, 223, 255, 255, 223, 254, 63, 254, 0, 0, 255, 255, 245, 64, 0, 0, 0, 72, 82, 191, 255, 255, 240, 48, 0, 255, 249, 255, 143, 255, 247, 255, 255, 247, 255, 255, 247, 255, 159, 255, 255, 191, 254, 63, 254, 0, 0, 255, 255, 245, 1, 0, 0, 34, 1, 42, 215, 255, 255, 240, 48, 0, 255, 251, 255, 15, 255, 231, 255, 255, 247, 255, 255, 239, 255, 191, 255, 255, 191, 254, 31, 255, 0, 0, 255, 255, 244, 32, 0, 0, 0, 4, 9, 59, 255, 255, 240, 48, 0, 255, 251, 255, 15, 255, 231, 255, 255, 239, 255, 255, 239, 255, 191, 255, 255, 191, 252, 31, 255, 0, 0, 255, 255, 234, 136, 64, 2, 0, 16, 165, 87, 255, 255, 240, 48, 0, 170, 161, 182, 3, 109, 133, 91, 109, 166, 219, 109, 75, 109, 22, 219, 109, 45, 180, 10, 173, 0, 0, 255, 255, 233, 33, 0, 8, 64, 128, 9, 91, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 181, 64, 0, 32, 0, 0, 68, 151, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 213, 8, 0, 128, 0, 2, 21, 85, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 234, 161, 68, 0, 0, 0, 72, 171, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 181, 16, 0, 128, 0, 0, 37, 21, 127, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 218, 164, 64, 0, 0, 2, 9, 85, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 234, 129, 0, 0, 0, 0, 162, 85, 127, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 180, 0, 0, 0, 0, 0, 9, 85, 219, 255, 240, 48, 0, 0, 96, 0, 9, 128, 0, 24, 0, 0, 0, 32, 48, 0, 0, 1, 25, 128, 0, 0, 0, 0, 0, 255, 255, 210, 160, 0, 0, 0, 64, 165, 42, 255, 255, 240, 48, 0, 252, 96, 16, 25, 128, 1, 24, 0, 0, 0, 50, 48, 0, 7, 243, 59, 128, 0, 0, 0, 0, 0, 255, 255, 212, 0, 0, 0, 0, 20, 18, 170, 111, 255, 240, 48, 0, 206, 0, 56, 1, 128, 3, 128, 0, 0, 0, 7, 48, 0, 7, 48, 51, 0, 0, 0, 0, 0, 0, 255, 255, 170, 128, 0, 0, 160, 129, 9, 43, 191, 255, 240, 48, 0, 199, 103, 189, 221, 249, 155, 217, 227, 224, 217, 183, 190, 15, 134, 27, 127, 158, 123, 207, 199, 60, 0, 255, 255, 208, 32, 0, 0, 90, 10, 69, 85, 127, 255, 240, 48, 0, 195, 110, 59, 217, 249, 155, 155, 179, 240, 217, 183, 63, 1, 134, 27, 55, 54, 115, 111, 206, 102, 0, 255, 255, 170, 72, 0, 1, 85, 64, 176, 170, 239, 255, 240, 48, 0, 195, 103, 49, 153, 141, 155, 27, 51, 48, 223, 54, 51, 7, 134, 27, 179, 63, 103, 108, 220, 126, 0, 255, 255, 197, 160, 0, 0, 32, 10, 86, 75, 95, 255, 240, 48, 0, 199, 99, 179, 157, 141, 153, 27, 59, 48, 255, 54, 51, 13, 135, 59, 51, 126, 103, 236, 216, 126, 0, 255, 255, 181, 84, 0, 4, 0, 0, 137, 42, 255, 255, 240, 48, 0, 206, 97, 153, 153, 217, 251, 155, 179, 48, 119, 55, 51, 13, 134, 115, 51, 48, 103, 12, 205, 112, 0, 255, 255, 223, 104, 0, 8, 32, 0, 34, 149, 183, 255, 240, 48, 0, 252, 111, 31, 153, 249, 249, 217, 227, 48, 102, 51, 179, 15, 135, 227, 51, 30, 99, 236, 207, 62, 0, 255, 255, 238, 182, 160, 16, 149, 64, 8, 75, 127, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 250, 1, 64, 0, 23, 244, 145, 43, 234, 191, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 208, 1, 104, 64, 71, 254, 64, 149, 125, 191, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 240, 40, 16, 32, 3, 207, 132, 85, 181, 95, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 225, 254, 32, 64, 64, 65, 81, 42, 242, 143, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 215, 126, 80, 36, 0, 0, 0, 75, 244, 15, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 214, 60, 36, 128, 0, 0, 10, 37, 115, 143, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 215, 32, 96, 40, 32, 0, 1, 21, 232, 207, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 204, 128, 168, 146, 0, 0, 0, 171, 180, 15, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 220, 2, 80, 32, 1, 0, 0, 85, 112, 79, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 196, 18, 96, 69, 0, 0, 34, 149, 224, 31, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 210, 136, 168, 16, 0, 0, 0, 86, 176, 31, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 208, 36, 224, 4, 64, 0, 9, 43, 112, 63, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 201, 17, 32, 80, 0, 0, 0, 85, 224, 31, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 232, 160, 232, 17, 0, 0, 36, 174, 177, 95, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 210, 10, 32, 72, 0, 0, 0, 53, 100, 191, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 233, 64, 96, 21, 0, 0, 2, 154, 241, 31, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 208, 16, 64, 0, 64, 0, 0, 61, 80, 191, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 234, 64, 80, 84, 128, 0, 16, 86, 224, 127, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 240, 0, 160, 0, 65, 0, 2, 27, 81, 63, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 234, 128, 192, 4, 0, 0, 8, 45, 100, 127, 240, 48, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 224, 2, 0, 21, 0, 64, 64, 29, 194, 127, 240, 48, 0, 30, 0, 28, 0, 0, 0, 0, 60, 30, 56, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 244, 0, 192, 20, 64, 16, 10, 86, 196, 255, 240, 48, 0, 62, 0, 28, 0, 0, 0, 0, 60, 30, 60, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 233, 0, 80, 65, 0, 0, 0, 27, 97, 255, 240, 48, 0, 63, 0, 28, 0, 0, 0, 0, 126, 62, 24, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 240, 21, 42, 136, 32, 8, 40, 13, 127, 255, 240, 48, 0, 63, 0, 28, 0, 0, 0, 0, 62, 63, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 244, 0, 91, 68, 136, 0, 0, 46, 191, 255, 240, 48, 0, 119, 3, 252, 126, 29, 231, 128, 126, 62, 56, 231, 7, 199, 112, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 242, 42, 164, 32, 1, 2, 8, 21, 255, 255, 240, 48, 0, 119, 135, 252, 127, 31, 255, 192, 119, 119, 56, 231, 31, 227, 240, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 249, 2, 146, 128, 68, 0, 0, 78, 255, 255, 240, 48, 0, 115, 143, 60, 7, 158, 251, 192, 119, 119, 56, 231, 28, 231, 224, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 244, 41, 84, 64, 16, 2, 0, 21, 127, 255, 240, 48, 0, 227, 142, 28, 31, 156, 113, 192, 119, 103, 56, 231, 56, 119, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 250, 4, 161, 16, 0, 0, 8, 47, 255, 255, 240, 48, 0, 255, 142, 28, 127, 156, 113, 192, 115, 231, 60, 231, 63, 243, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 245, 18, 148, 0, 64, 168, 0, 42, 191, 255, 240, 48, 0, 255, 206, 28, 243, 156, 113, 192, 115, 231, 56, 231, 63, 247, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 249, 10, 170, 2, 20, 160, 0, 155, 127, 255, 240, 48, 0, 247, 207, 28, 231, 156, 113, 192, 115, 199, 56, 231, 60, 3, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 248, 33, 113, 80, 0, 64, 8, 45, 239, 255, 240, 48, 1, 225, 207, 252, 247, 156, 113, 192, 115, 199, 56, 231, 30, 199, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 249, 8, 184, 0, 11, 0, 32, 170, 255, 255, 240, 48, 1, 193, 231, 252, 255, 156, 113, 192, 113, 199, 56, 231, 15, 231, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 252, 128, 88, 1, 108, 0, 0, 55, 127, 255, 240, 48, 1, 192, 225, 204, 59, 156, 113, 192, 113, 135, 56, 231, 7, 195, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 252, 128, 62, 133, 116, 0, 2, 170, 251, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 254, 66, 149, 82, 128, 0, 64, 85, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 254, 64, 74, 136, 64, 1, 9, 90, 253, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 32, 148, 0, 8, 0, 33, 85, 247, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 144, 80, 0, 0, 0, 129, 43, 125, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 160, 73, 32, 0, 8, 4, 169, 215, 127, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 217, 36, 0, 0, 33, 2, 83, 125, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 228, 81, 0, 1, 0, 21, 75, 87, 223, 240, 48, 2, 8, 32, 130, 8, 16, 129, 4, 16, 65, 2, 16, 32, 130, 8, 32, 65, 4, 16, 65, 4, 16, 128, 255, 255, 255, 250, 168, 64, 0, 2, 130, 166, 251, 127, 240, 48, 2, 56, 113, 199, 28, 113, 231, 28, 56, 227, 142, 56, 227, 143, 28, 113, 199, 30, 113, 195, 142, 56, 192, 255, 255, 255, 252, 20, 16, 8, 64, 9, 77, 87, 239, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 66, 64, 1, 5, 18, 149, 125, 127, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 254, 168, 4, 0, 16, 10, 21, 171, 171, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 85, 80, 4, 132, 77, 85, 126, 255, 112, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 164, 0, 64, 18, 40, 85, 171, 223, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 170, 160, 9, 68, 180, 170, 246, 239, 208, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 200, 0, 0, 8, 161, 42, 173, 187, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 229, 0, 0, 42, 233, 85, 182, 247, 160, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 244, 0, 9, 43, 132, 170, 219, 175, 176, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 254, 178, 128, 0, 191, 18, 171, 110, 234, 160, 48, 0, 0, 0, 3, 0, 192, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 253, 184, 32, 5, 106, 65, 74, 181, 89, 80, 48, 1, 252, 192, 3, 0, 224, 62, 0, 56, 0, 0, 31, 192, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 246, 222, 128, 37, 252, 22, 170, 175, 244, 32, 48, 1, 254, 224, 3, 128, 224, 126, 0, 56, 0, 0, 31, 192, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 219, 109, 20, 151, 162, 4, 85, 90, 168, 160, 48, 1, 200, 0, 3, 0, 224, 228, 0, 24, 0, 0, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 109, 175, 66, 127, 116, 85, 85, 109, 97, 80, 48, 1, 192, 225, 195, 142, 224, 224, 62, 56, 120, 56, 28, 14, 224, 238, 230, 112, 120, 60, 100, 0, 0, 0, 255, 255, 255, 181, 111, 253, 218, 128, 21, 42, 171, 132, 96, 48, 1, 192, 231, 243, 31, 224, 240, 127, 56, 252, 252, 28, 7, 241, 254, 231, 248, 252, 126, 126, 0, 0, 0, 255, 255, 249, 86, 181, 247, 237, 209, 50, 170, 174, 192, 176, 48, 1, 252, 230, 115, 185, 224, 124, 3, 57, 206, 224, 31, 207, 113, 220, 231, 185, 206, 231, 124, 0, 0, 0, 255, 255, 238, 219, 221, 93, 85, 0, 84, 85, 106, 145, 32, 48, 1, 252, 238, 179, 56, 224, 62, 31, 153, 222, 240, 31, 198, 59, 142, 231, 57, 222, 239, 112, 0, 0, 0, 255, 255, 171, 106, 175, 171, 90, 0, 162, 149, 86, 128, 144, 48, 1, 192, 239, 243, 184, 224, 15, 127, 185, 254, 124, 28, 14, 51, 142, 231, 57, 254, 255, 112, 0, 0, 0, 255, 254, 181, 91, 116, 234, 168, 65, 82, 85, 91, 68, 32, 48, 1, 192, 238, 67, 56, 224, 7, 115, 185, 192, 28, 28, 6, 59, 142, 231, 25, 192, 224, 112, 0, 0, 0, 255, 251, 90, 237, 175, 106, 164, 2, 146, 165, 85, 17, 16, 48, 1, 192, 231, 3, 189, 224, 238, 119, 57, 196, 156, 29, 78, 49, 220, 231, 57, 196, 226, 112, 0, 0, 0, 255, 246, 237, 85, 90, 180, 145, 2, 164, 148, 170, 130, 208, 48, 1, 192, 231, 243, 31, 224, 254, 127, 152, 252, 252, 31, 230, 57, 254, 231, 56, 252, 126, 112, 0, 0, 0, 255, 237, 86, 181, 107, 90, 160, 5, 18, 213, 90, 137, 64, 48, 0, 192, 193, 227, 14, 192, 120, 59, 56, 124, 112, 31, 206, 48, 108, 231, 24, 124, 62, 112, 0, 0, 0, 255, 212, 219, 85, 86, 173, 72, 8, 164, 82, 171, 64, 16, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 255, 219, 173, 213, 191, 42, 144, 31, 133, 84, 170, 4, 160, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 252, 0, 0, 0, 0, 0, 0, 0, 0, 255, 173, 245, 55, 251, 74, 68, 159, 242, 170, 85, 16, 64, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 248, 0, 0, 0, 0, 0, 0, 0, 0, 255, 214, 150, 255, 253, 133, 80, 55, 249, 82, 170, 2, 144, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 213, 111, 255, 86, 160, 148, 87, 182, 169, 41, 18, 64, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 238, 255, 212, 170, 138, 34, 111, 170, 84, 148, 9, 0, 48, 2, 56, 113, 199, 28, 113, 199, 28, 56, 227, 142, 56, 243, 143, 28, 113, 199, 30, 121, 227, 142, 56, 192, 255, 251, 253, 85, 125, 96, 152, 191, 75, 42, 74, 68, 64, 48, 2, 16, 65, 5, 8, 32, 130, 8, 32, 130, 132, 16, 33, 4, 16, 64, 130, 8, 16, 66, 8, 40, 0, 255, 215, 229, 85, 106, 194, 36, 254, 165, 145, 81, 41, 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, 255, 255, 170, 170, 213, 80, 73, 250, 188, 108, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 173, 85, 213, 65, 43, 249, 145, 66, 165, 66, 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, 255, 255, 182, 171, 106, 232, 35, 230, 114, 58, 81, 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, 255, 236, 64, 68, 136, 0, 2, 8, 64, 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 +}; + +static const uint8_t paul[4736] = { + 41, 95, 253, 0, 0, 22, 168, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 255, 255, 64, 0, 47, 254, 165, 127, 84, 128, 0, 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, 173, 127, 255, 168, 0, 31, 242, 146, 170, 162, 32, 1, 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, 219, 255, 255, 210, 0, 5, 250, 82, 173, 84, 136, 0, 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, 238, 255, 255, 232, 34, 23, 105, 73, 118, 168, 34, 7, 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, 187, 255, 255, 241, 0, 3, 245, 85, 85, 82, 136, 2, 176, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 255, 255, 248, 0, 10, 186, 82, 173, 72, 32, 155, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 255, 255, 250, 0, 7, 233, 73, 107, 101, 4, 47, 112, 48, 0, 0, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 245, 255, 255, 253, 8, 5, 125, 37, 93, 80, 161, 93, 240, 48, 0, 1, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 255, 255, 255, 254, 128, 11, 208, 170, 170, 170, 8, 126, 240, 48, 0, 1, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 224, 239, 255, 255, 254, 0, 5, 0, 2, 182, 145, 66, 191, 112, 48, 0, 1, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 255, 255, 255, 160, 0, 0, 0, 85, 72, 17, 123, 240, 48, 0, 3, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 255, 255, 191, 255, 128, 0, 0, 0, 42, 165, 69, 255, 240, 48, 0, 3, 255, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 173, 247, 255, 192, 0, 0, 0, 13, 16, 18, 254, 240, 48, 0, 0, 66, 0, 0, 1, 85, 85, 85, 85, 85, 85, 85, 127, 254, 170, 170, 170, 170, 170, 85, 80, 0, 255, 223, 255, 255, 208, 8, 2, 128, 1, 69, 69, 254, 240, 48, 0, 7, 255, 207, 255, 193, 255, 31, 255, 255, 63, 252, 0, 63, 252, 255, 255, 252, 255, 240, 255, 248, 0, 254, 182, 255, 255, 226, 1, 32, 0, 0, 72, 23, 255, 240, 48, 0, 7, 255, 223, 255, 227, 255, 191, 255, 255, 191, 254, 0, 127, 253, 255, 255, 253, 255, 241, 255, 248, 0, 255, 255, 223, 255, 232, 4, 72, 146, 64, 34, 143, 254, 240, 48, 0, 7, 255, 223, 255, 227, 255, 63, 255, 255, 127, 252, 0, 127, 253, 255, 255, 253, 255, 227, 255, 224, 0, 250, 175, 111, 255, 192, 66, 132, 68, 16, 16, 87, 255, 112, 48, 0, 15, 255, 159, 255, 227, 255, 127, 255, 255, 127, 252, 0, 127, 253, 255, 255, 253, 255, 231, 255, 224, 0, 255, 251, 183, 255, 128, 56, 82, 169, 68, 10, 63, 254, 240, 48, 0, 15, 255, 159, 255, 231, 255, 127, 255, 255, 127, 252, 0, 255, 249, 255, 255, 251, 255, 231, 255, 128, 0, 255, 254, 223, 254, 0, 171, 74, 86, 136, 1, 95, 255, 240, 48, 0, 15, 255, 191, 255, 247, 254, 127, 255, 254, 255, 248, 0, 255, 251, 255, 255, 251, 255, 239, 255, 0, 0, 255, 255, 175, 248, 0, 84, 181, 106, 98, 0, 191, 255, 240, 48, 0, 31, 255, 63, 255, 247, 254, 255, 248, 0, 255, 248, 0, 255, 251, 255, 192, 3, 255, 223, 254, 0, 0, 255, 253, 255, 248, 3, 73, 75, 45, 96, 146, 255, 254, 240, 48, 0, 31, 255, 63, 255, 255, 254, 255, 255, 252, 255, 248, 1, 255, 243, 255, 255, 247, 255, 255, 252, 0, 0, 255, 254, 175, 208, 4, 160, 42, 182, 180, 32, 255, 223, 240, 48, 0, 31, 255, 127, 255, 255, 252, 255, 255, 253, 255, 240, 1, 255, 247, 255, 255, 247, 255, 255, 248, 0, 0, 255, 251, 191, 224, 2, 4, 170, 213, 170, 40, 127, 191, 240, 48, 0, 63, 254, 127, 255, 255, 253, 255, 255, 253, 255, 240, 1, 255, 247, 255, 255, 231, 255, 255, 240, 0, 0, 255, 254, 255, 192, 17, 64, 21, 110, 218, 149, 127, 254, 240, 48, 0, 63, 254, 127, 255, 255, 253, 255, 255, 249, 255, 240, 3, 255, 231, 255, 255, 239, 255, 255, 248, 0, 0, 255, 245, 127, 224, 20, 0, 21, 186, 110, 90, 127, 221, 240, 48, 0, 63, 254, 255, 255, 255, 249, 255, 255, 251, 255, 224, 3, 255, 239, 255, 255, 239, 255, 255, 248, 0, 0, 255, 254, 255, 192, 10, 0, 10, 87, 171, 77, 59, 251, 176, 48, 0, 127, 254, 255, 223, 255, 251, 255, 255, 251, 255, 224, 3, 255, 239, 255, 255, 207, 255, 127, 252, 0, 0, 255, 235, 255, 192, 65, 0, 1, 90, 169, 70, 31, 191, 240, 48, 0, 127, 252, 255, 223, 255, 251, 255, 224, 3, 255, 224, 7, 255, 207, 255, 0, 31, 255, 63, 252, 0, 0, 255, 251, 255, 192, 36, 0, 9, 37, 74, 105, 159, 250, 176, 48, 0, 127, 253, 255, 159, 255, 243, 255, 255, 247, 255, 255, 247, 255, 223, 255, 255, 223, 255, 63, 252, 0, 0, 255, 255, 255, 128, 0, 0, 0, 40, 16, 18, 15, 219, 240, 48, 0, 127, 253, 255, 143, 255, 247, 255, 255, 247, 255, 255, 247, 255, 223, 255, 255, 223, 254, 63, 254, 0, 0, 255, 251, 255, 128, 32, 0, 0, 5, 0, 5, 15, 255, 240, 48, 0, 255, 249, 255, 143, 255, 247, 255, 255, 247, 255, 255, 247, 255, 159, 255, 255, 191, 254, 63, 254, 0, 0, 255, 255, 255, 128, 0, 0, 0, 144, 0, 2, 15, 255, 240, 48, 0, 255, 251, 255, 15, 255, 231, 255, 255, 247, 255, 255, 255, 255, 191, 255, 255, 191, 254, 31, 255, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 9, 7, 255, 240, 48, 0, 255, 251, 255, 15, 255, 231, 255, 255, 239, 255, 255, 239, 255, 191, 255, 255, 191, 252, 31, 255, 0, 0, 255, 255, 255, 0, 128, 0, 0, 0, 0, 2, 135, 239, 112, 48, 0, 255, 243, 255, 7, 255, 231, 255, 255, 239, 255, 255, 239, 255, 63, 255, 255, 63, 252, 31, 255, 0, 0, 255, 255, 255, 34, 0, 0, 0, 0, 0, 0, 3, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 16, 0, 0, 0, 0, 0, 0, 131, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 37, 32, 0, 0, 0, 0, 0, 7, 223, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 254, 64, 0, 0, 0, 0, 0, 0, 3, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 34, 0, 0, 0, 0, 0, 0, 7, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 254, 168, 72, 0, 0, 0, 0, 0, 3, 127, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 254, 162, 0, 0, 0, 0, 0, 0, 83, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 254, 168, 146, 5, 34, 0, 0, 0, 3, 255, 240, 48, 0, 16, 96, 0, 9, 128, 0, 24, 0, 0, 0, 32, 48, 0, 0, 129, 25, 128, 0, 0, 0, 0, 0, 255, 255, 254, 106, 64, 0, 4, 65, 8, 0, 83, 255, 240, 48, 0, 252, 96, 16, 25, 128, 1, 24, 0, 0, 0, 50, 48, 0, 7, 243, 59, 128, 0, 0, 0, 0, 0, 255, 255, 252, 212, 40, 0, 0, 20, 1, 0, 43, 223, 240, 48, 0, 206, 0, 56, 1, 128, 3, 128, 0, 0, 0, 7, 48, 0, 7, 56, 51, 0, 0, 0, 0, 0, 0, 255, 255, 252, 233, 68, 0, 0, 64, 16, 0, 19, 255, 240, 48, 0, 199, 103, 189, 221, 249, 155, 217, 227, 224, 217, 183, 190, 15, 134, 27, 255, 158, 123, 207, 199, 60, 0, 255, 255, 248, 164, 17, 0, 0, 0, 0, 1, 43, 255, 224, 48, 0, 195, 110, 59, 217, 249, 155, 155, 179, 240, 217, 183, 63, 1, 134, 27, 55, 54, 115, 111, 206, 102, 0, 255, 255, 192, 242, 136, 0, 0, 0, 0, 4, 25, 255, 240, 48, 0, 195, 103, 49, 157, 141, 155, 27, 51, 48, 223, 54, 51, 7, 135, 27, 51, 63, 103, 108, 220, 126, 0, 255, 255, 129, 200, 80, 0, 0, 0, 0, 17, 43, 255, 240, 48, 0, 199, 99, 179, 153, 157, 185, 155, 59, 48, 255, 54, 51, 13, 134, 59, 179, 126, 103, 236, 216, 126, 0, 255, 255, 128, 229, 2, 0, 0, 0, 0, 2, 27, 255, 240, 48, 0, 222, 97, 153, 157, 217, 187, 155, 179, 48, 119, 55, 51, 13, 135, 115, 51, 48, 231, 12, 206, 112, 0, 255, 255, 240, 232, 72, 0, 0, 0, 0, 4, 175, 255, 240, 48, 0, 252, 111, 31, 153, 249, 249, 217, 227, 48, 102, 51, 179, 15, 135, 227, 51, 30, 99, 236, 207, 62, 0, 255, 255, 181, 82, 32, 0, 64, 0, 0, 17, 27, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 108, 228, 128, 0, 0, 0, 0, 132, 175, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 245, 165, 72, 0, 84, 8, 0, 34, 2, 89, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 219, 74, 66, 2, 10, 130, 132, 128, 33, 43, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 107, 64, 160, 85, 181, 232, 80, 0, 8, 185, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 171, 145, 4, 21, 127, 247, 42, 0, 2, 51, 255, 224, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 213, 22, 0, 170, 255, 253, 169, 84, 1, 89, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 171, 174, 128, 87, 255, 254, 94, 169, 65, 112, 123, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 223, 27, 8, 23, 255, 253, 95, 245, 32, 176, 61, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 171, 172, 0, 175, 255, 252, 95, 254, 180, 82, 127, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 151, 154, 0, 88, 57, 248, 63, 255, 73, 47, 189, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 95, 136, 18, 160, 5, 252, 63, 255, 212, 87, 254, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 95, 8, 64, 13, 82, 72, 63, 255, 232, 27, 189, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 63, 128, 0, 2, 43, 244, 27, 127, 240, 10, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 0, 34, 5, 173, 80, 30, 148, 120, 75, 123, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 255, 130, 72, 0, 214, 136, 19, 64, 52, 41, 125, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 255, 128, 36, 128, 40, 32, 13, 85, 136, 60, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 255, 128, 137, 0, 2, 148, 18, 168, 165, 26, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 255, 130, 18, 0, 16, 0, 9, 127, 3, 45, 254, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 192, 36, 0, 4, 84, 42, 74, 0, 148, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 255, 224, 138, 64, 64, 0, 9, 0, 18, 145, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 255, 240, 40, 4, 0, 32, 20, 64, 1, 11, 255, 240, 48, 0, 120, 0, 0, 0, 120, 7, 128, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 248, 2, 144, 1, 8, 8, 16, 12, 145, 255, 240, 48, 0, 255, 0, 0, 0, 120, 31, 248, 0, 0, 3, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 255, 252, 42, 65, 10, 0, 4, 0, 37, 5, 255, 240, 48, 1, 255, 128, 0, 0, 120, 31, 252, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 255, 254, 5, 168, 42, 0, 3, 4, 5, 73, 255, 240, 48, 0, 227, 128, 0, 0, 112, 30, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 252, 43, 69, 40, 0, 0, 128, 134, 129, 255, 240, 48, 0, 227, 207, 131, 142, 120, 28, 30, 31, 28, 59, 131, 224, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 252, 10, 180, 170, 137, 34, 80, 18, 131, 255, 240, 48, 1, 227, 159, 195, 142, 120, 30, 14, 63, 158, 123, 199, 241, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 248, 37, 234, 177, 208, 132, 132, 165, 67, 255, 240, 48, 0, 231, 137, 227, 142, 112, 30, 15, 51, 142, 115, 143, 115, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 252, 69, 125, 226, 245, 125, 105, 18, 15, 255, 176, 48, 0, 255, 129, 227, 142, 120, 28, 14, 7, 206, 115, 206, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 255, 252, 18, 213, 164, 255, 188, 228, 181, 23, 255, 240, 48, 1, 254, 15, 227, 142, 120, 30, 14, 63, 206, 115, 143, 249, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 248, 9, 85, 193, 127, 253, 123, 88, 175, 255, 48, 48, 0, 224, 31, 227, 142, 120, 30, 14, 127, 199, 227, 223, 248, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 248, 160, 171, 42, 191, 245, 61, 250, 135, 255, 240, 48, 0, 224, 28, 227, 142, 112, 28, 30, 113, 199, 227, 142, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 255, 252, 21, 7, 193, 111, 244, 190, 244, 75, 255, 176, 48, 1, 224, 60, 227, 222, 120, 30, 124, 115, 199, 227, 207, 1, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 248, 128, 174, 90, 95, 213, 95, 122, 151, 255, 208, 48, 0, 224, 31, 227, 254, 120, 31, 248, 127, 195, 195, 143, 243, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 255, 252, 85, 11, 105, 95, 100, 174, 168, 67, 255, 112, 48, 0, 224, 15, 225, 247, 120, 31, 240, 63, 195, 195, 195, 243, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 255, 252, 136, 141, 245, 74, 219, 119, 101, 42, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 255, 254, 4, 70, 255, 181, 109, 173, 116, 147, 255, 112, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 254, 82, 11, 255, 255, 255, 245, 74, 72, 251, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 255, 247, 36, 165, 151, 255, 255, 234, 164, 165, 119, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 255, 222, 66, 6, 64, 63, 255, 213, 82, 16, 189, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 255, 182, 137, 170, 0, 0, 0, 80, 73, 74, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 254, 126, 164, 165, 0, 0, 10, 42, 40, 144, 63, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 254, 238, 165, 90, 5, 0, 32, 36, 149, 37, 187, 240, 48, 0, 16, 64, 130, 8, 32, 129, 4, 16, 65, 4, 16, 32, 130, 8, 32, 130, 8, 16, 65, 4, 16, 0, 139, 249, 254, 101, 168, 1, 117, 84, 146, 72, 66, 87, 240, 48, 3, 60, 113, 199, 28, 113, 231, 28, 56, 227, 142, 56, 227, 143, 28, 113, 199, 30, 121, 227, 142, 56, 192, 165, 251, 222, 178, 234, 36, 223, 192, 85, 41, 16, 175, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 235, 254, 82, 212, 66, 118, 169, 41, 160, 69, 31, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 235, 255, 42, 224, 41, 21, 66, 22, 82, 16, 79, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 159, 255, 91, 113, 64, 189, 42, 156, 128, 133, 19, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 171, 255, 81, 64, 20, 2, 136, 70, 168, 32, 143, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 127, 255, 153, 88, 128, 0, 37, 50, 162, 10, 87, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 175, 255, 205, 82, 1, 72, 8, 26, 232, 161, 11, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 191, 255, 181, 160, 32, 0, 128, 174, 208, 10, 71, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 127, 255, 235, 250, 132, 132, 34, 91, 116, 144, 47, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 219, 255, 237, 248, 16, 82, 136, 118, 168, 37, 23, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 255, 255, 245, 254, 138, 148, 66, 222, 146, 136, 175, 240, 48, 0, 160, 160, 0, 0, 0, 0, 12, 0, 0, 0, 40, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 111, 255, 245, 251, 74, 171, 35, 255, 73, 38, 191, 240, 48, 0, 241, 224, 0, 0, 0, 0, 14, 0, 0, 0, 255, 14, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 157, 191, 255, 251, 127, 171, 117, 151, 255, 42, 169, 95, 240, 48, 1, 241, 224, 0, 0, 0, 0, 12, 0, 0, 0, 255, 132, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 166, 255, 255, 253, 255, 239, 190, 175, 255, 181, 86, 127, 240, 48, 0, 241, 224, 193, 16, 20, 4, 132, 68, 4, 64, 225, 202, 68, 32, 8, 248, 32, 68, 0, 0, 0, 0, 191, 191, 255, 254, 127, 253, 253, 191, 255, 222, 253, 191, 240, 48, 1, 243, 227, 241, 252, 126, 31, 206, 255, 15, 224, 225, 206, 124, 252, 126, 249, 252, 124, 0, 0, 0, 0, 213, 255, 255, 253, 191, 255, 255, 255, 255, 213, 87, 255, 224, 48, 1, 251, 115, 57, 254, 103, 63, 206, 127, 31, 224, 224, 238, 125, 220, 124, 249, 220, 124, 0, 0, 0, 0, 127, 255, 255, 255, 95, 255, 255, 254, 255, 234, 170, 191, 240, 48, 1, 219, 96, 121, 206, 15, 57, 206, 243, 184, 224, 224, 238, 113, 206, 224, 115, 142, 112, 0, 0, 0, 0, 191, 255, 255, 255, 191, 255, 255, 255, 255, 250, 85, 127, 240, 48, 1, 223, 115, 249, 206, 127, 49, 206, 99, 184, 224, 225, 206, 113, 254, 224, 99, 142, 96, 0, 0, 0, 0, 187, 191, 255, 255, 111, 255, 255, 255, 255, 255, 173, 127, 240, 48, 1, 222, 119, 185, 206, 119, 49, 206, 227, 56, 224, 225, 206, 113, 254, 224, 115, 142, 96, 0, 0, 0, 0, 255, 255, 255, 255, 215, 255, 255, 253, 255, 247, 85, 127, 240, 48, 1, 222, 119, 57, 206, 231, 57, 206, 99, 156, 224, 227, 206, 113, 192, 240, 115, 142, 112, 0, 0, 0, 0, 126, 255, 255, 255, 255, 255, 251, 191, 255, 255, 229, 127, 240, 48, 1, 142, 119, 249, 206, 255, 63, 206, 227, 159, 224, 255, 142, 113, 252, 126, 121, 252, 96, 0, 0, 0, 0, 239, 255, 255, 255, 219, 239, 238, 247, 255, 247, 250, 63, 240, 48, 1, 204, 115, 249, 206, 127, 31, 206, 99, 15, 224, 254, 14, 112, 124, 62, 56, 248, 96, 0, 0, 0, 0, 63, 255, 255, 255, 255, 251, 191, 223, 255, 255, 221, 159, 240, 48, 0, 0, 0, 0, 0, 0, 1, 192, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 251, 127, 251, 123, 255, 255, 254, 223, 240, 48, 0, 0, 0, 0, 0, 0, 31, 128, 0, 31, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 127, 255, 255, 239, 255, 255, 255, 255, 255, 255, 99, 240, 48, 0, 0, 0, 0, 0, 0, 63, 128, 0, 31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 217, 240, 48, 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 127, 255, 239, 255, 255, 247, 234, 112, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 251, 223, 255, 255, 255, 255, 255, 186, 176, 48, 2, 56, 113, 199, 28, 113, 231, 28, 56, 227, 142, 56, 243, 207, 28, 113, 199, 30, 121, 227, 142, 56, 192, 255, 255, 255, 255, 253, 239, 253, 223, 255, 254, 255, 255, 80, 48, 2, 16, 65, 5, 8, 32, 130, 8, 32, 130, 132, 16, 65, 4, 16, 64, 130, 8, 32, 130, 8, 40, 128, 255, 127, 255, 255, 246, 187, 255, 255, 255, 255, 255, 251, 160, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 250, 253, 94, 189, 255, 255, 255, 254, 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, 255, 247, 255, 255, 255, 87, 251, 123, 255, 255, 191, 255, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 253, 92, 170, 255, 255, 255, 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, 255, 255, 255, 255, 255, 119, 235, 119, 255, 255, 251, 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 +}; + +static const uint8_t shaun[4736] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 254, 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, 127, 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, 1, 255, 255, 252, 0, 0, 0, 0, 0, 32, 0, 0, 0, 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, 175, 255, 128, 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, 31, 250, 170, 127, 224, 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, 63, 218, 170, 175, 240, 0, 0, 0, 0, 48, 0, 0, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 0, 0, 0, 0, 255, 86, 235, 87, 248, 0, 0, 0, 0, 48, 0, 1, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 0, 0, 0, 1, 255, 107, 85, 105, 126, 0, 0, 0, 0, 48, 0, 1, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 224, 0, 0, 0, 3, 253, 189, 181, 173, 127, 0, 0, 0, 0, 48, 0, 3, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 0, 0, 0, 7, 245, 75, 122, 181, 95, 128, 0, 0, 0, 48, 0, 3, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 15, 234, 191, 215, 213, 47, 192, 0, 0, 0, 48, 0, 3, 255, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 15, 213, 118, 253, 84, 167, 224, 0, 0, 0, 48, 0, 0, 0, 128, 0, 128, 1, 0, 0, 1, 0, 8, 0, 63, 254, 0, 0, 8, 0, 32, 0, 16, 0, 0, 0, 0, 31, 170, 219, 182, 170, 145, 240, 0, 0, 0, 48, 0, 7, 255, 207, 255, 193, 255, 191, 255, 255, 191, 254, 0, 63, 252, 255, 255, 253, 255, 240, 255, 248, 0, 0, 0, 0, 63, 17, 42, 217, 84, 69, 240, 0, 0, 0, 48, 0, 7, 255, 223, 255, 227, 255, 63, 255, 255, 191, 252, 0, 127, 253, 255, 255, 253, 255, 241, 255, 240, 0, 0, 0, 0, 127, 74, 149, 100, 2, 144, 248, 0, 0, 0, 48, 0, 7, 255, 223, 255, 227, 255, 63, 255, 255, 127, 252, 0, 127, 253, 255, 255, 253, 255, 227, 255, 224, 0, 0, 0, 0, 253, 32, 68, 146, 32, 4, 124, 0, 0, 0, 48, 0, 15, 255, 159, 255, 227, 255, 127, 255, 255, 127, 252, 0, 127, 249, 255, 255, 253, 255, 231, 255, 192, 0, 0, 0, 0, 252, 149, 16, 0, 0, 17, 60, 0, 0, 0, 48, 0, 15, 255, 191, 255, 231, 255, 127, 255, 255, 127, 248, 0, 255, 251, 255, 255, 251, 255, 239, 255, 128, 0, 0, 0, 0, 250, 72, 64, 0, 0, 0, 126, 0, 0, 0, 48, 0, 15, 255, 191, 255, 247, 254, 127, 255, 254, 255, 248, 0, 255, 251, 255, 255, 251, 255, 223, 255, 0, 0, 0, 0, 1, 249, 82, 0, 64, 0, 74, 30, 0, 0, 0, 48, 0, 31, 255, 63, 255, 247, 254, 255, 248, 0, 255, 248, 0, 255, 243, 255, 224, 7, 255, 255, 254, 0, 0, 0, 0, 1, 245, 33, 1, 0, 0, 1, 94, 0, 0, 0, 48, 0, 31, 255, 127, 255, 255, 254, 255, 255, 253, 255, 248, 1, 255, 247, 255, 255, 247, 255, 255, 252, 0, 0, 0, 0, 1, 244, 148, 32, 0, 0, 40, 159, 0, 0, 0, 48, 0, 31, 255, 127, 255, 255, 252, 255, 255, 253, 255, 240, 1, 255, 247, 255, 255, 247, 255, 255, 248, 0, 0, 0, 0, 3, 242, 165, 4, 18, 0, 133, 15, 0, 0, 0, 48, 0, 63, 254, 127, 255, 255, 253, 255, 255, 253, 255, 240, 1, 255, 247, 255, 255, 231, 255, 255, 248, 0, 0, 0, 0, 3, 237, 82, 65, 64, 132, 34, 175, 128, 0, 0, 48, 0, 63, 254, 127, 255, 255, 253, 255, 255, 249, 255, 240, 3, 255, 231, 255, 255, 239, 255, 255, 248, 0, 0, 0, 0, 3, 244, 169, 16, 8, 33, 20, 175, 128, 0, 0, 48, 0, 63, 254, 255, 255, 255, 249, 255, 255, 251, 255, 224, 3, 255, 239, 255, 255, 239, 255, 255, 248, 0, 0, 0, 0, 3, 234, 170, 68, 130, 20, 162, 175, 128, 0, 0, 48, 0, 127, 252, 255, 223, 255, 251, 255, 246, 211, 255, 224, 3, 255, 239, 255, 219, 79, 255, 127, 252, 0, 0, 0, 0, 3, 245, 85, 18, 32, 128, 74, 87, 128, 0, 0, 48, 0, 127, 253, 255, 223, 255, 251, 255, 233, 35, 255, 234, 167, 255, 207, 255, 73, 31, 255, 63, 252, 0, 0, 0, 0, 3, 245, 82, 160, 136, 73, 21, 79, 128, 0, 0, 48, 0, 127, 253, 255, 159, 255, 243, 255, 255, 255, 255, 255, 247, 255, 223, 255, 255, 223, 255, 63, 254, 0, 0, 0, 0, 7, 237, 168, 8, 1, 0, 66, 175, 192, 0, 0, 48, 0, 255, 249, 255, 143, 255, 247, 255, 255, 247, 255, 255, 247, 255, 223, 255, 255, 223, 254, 63, 254, 0, 0, 0, 0, 3, 246, 170, 161, 16, 0, 20, 175, 128, 0, 0, 48, 0, 255, 249, 255, 143, 255, 247, 255, 255, 247, 255, 255, 255, 255, 159, 255, 255, 191, 254, 63, 254, 0, 0, 0, 0, 7, 245, 84, 128, 0, 0, 66, 151, 192, 0, 0, 48, 0, 255, 251, 255, 15, 255, 231, 255, 255, 255, 255, 255, 239, 255, 191, 255, 255, 191, 254, 31, 255, 0, 0, 0, 0, 7, 245, 169, 16, 68, 1, 8, 171, 192, 0, 0, 48, 0, 255, 251, 255, 15, 255, 239, 255, 255, 239, 255, 255, 239, 255, 191, 255, 255, 191, 252, 31, 255, 0, 0, 0, 0, 7, 246, 210, 2, 0, 68, 2, 87, 192, 0, 0, 48, 0, 170, 161, 84, 2, 170, 130, 170, 170, 165, 85, 85, 69, 85, 21, 85, 85, 42, 168, 10, 170, 0, 0, 0, 0, 7, 245, 72, 168, 17, 0, 72, 171, 192, 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, 7, 246, 165, 2, 64, 41, 0, 19, 224, 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, 7, 245, 82, 84, 138, 130, 82, 171, 192, 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, 7, 235, 73, 42, 36, 169, 84, 5, 224, 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, 7, 250, 146, 85, 170, 175, 254, 171, 224, 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, 7, 237, 74, 218, 170, 191, 255, 169, 224, 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, 7, 246, 191, 255, 181, 255, 255, 213, 192, 0, 0, 48, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 8, 128, 0, 0, 0, 0, 0, 0, 0, 7, 235, 255, 255, 213, 127, 255, 233, 224, 0, 0, 48, 0, 248, 96, 0, 25, 128, 0, 24, 0, 0, 0, 48, 48, 0, 3, 195, 59, 128, 0, 0, 0, 0, 0, 0, 0, 7, 245, 255, 255, 161, 255, 255, 233, 192, 0, 0, 48, 0, 254, 96, 48, 9, 128, 3, 24, 0, 0, 0, 54, 48, 0, 7, 241, 51, 0, 0, 0, 0, 0, 0, 0, 0, 7, 223, 255, 255, 200, 255, 255, 244, 200, 0, 0, 48, 0, 198, 66, 57, 9, 161, 19, 208, 66, 64, 137, 39, 52, 2, 6, 57, 127, 136, 64, 132, 130, 16, 0, 0, 0, 7, 234, 255, 255, 192, 255, 255, 245, 206, 0, 0, 48, 0, 199, 103, 191, 253, 249, 155, 217, 243, 224, 217, 183, 191, 15, 135, 27, 127, 190, 123, 239, 207, 60, 0, 0, 0, 7, 215, 255, 255, 160, 127, 255, 232, 222, 0, 0, 48, 0, 195, 110, 49, 153, 221, 187, 27, 51, 112, 221, 118, 55, 1, 134, 27, 51, 51, 118, 110, 204, 102, 0, 0, 0, 3, 237, 255, 255, 192, 254, 255, 244, 254, 0, 0, 48, 0, 199, 103, 51, 157, 141, 155, 155, 59, 48, 255, 54, 51, 15, 135, 27, 179, 63, 103, 236, 216, 126, 0, 0, 0, 31, 215, 255, 255, 192, 127, 235, 233, 126, 0, 0, 48, 0, 198, 99, 187, 153, 157, 185, 27, 51, 48, 119, 55, 51, 13, 134, 59, 51, 122, 103, 76, 220, 116, 0, 0, 0, 59, 237, 251, 239, 192, 187, 94, 160, 254, 2, 32, 48, 0, 254, 101, 155, 157, 249, 251, 219, 243, 48, 119, 51, 51, 15, 135, 243, 51, 62, 99, 236, 207, 124, 0, 0, 0, 127, 219, 239, 253, 80, 29, 253, 20, 254, 0, 0, 48, 0, 248, 111, 29, 25, 240, 217, 216, 227, 48, 102, 51, 179, 15, 135, 195, 51, 30, 97, 236, 199, 30, 0, 0, 0, 63, 214, 222, 191, 193, 70, 149, 130, 110, 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, 127, 223, 255, 245, 96, 151, 85, 36, 244, 9, 32, 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, 61, 234, 173, 171, 193, 33, 170, 2, 252, 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, 63, 221, 255, 106, 160, 137, 248, 21, 116, 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, 31, 246, 183, 165, 193, 36, 0, 10, 120, 36, 160, 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, 31, 173, 221, 74, 160, 80, 2, 170, 136, 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, 15, 223, 106, 3, 64, 40, 0, 85, 84, 72, 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, 13, 181, 168, 23, 65, 24, 1, 42, 168, 2, 160, 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, 7, 110, 210, 132, 160, 70, 144, 74, 148, 32, 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, 7, 183, 80, 44, 0, 6, 5, 43, 72, 4, 16, 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, 2, 218, 202, 26, 64, 7, 80, 74, 208, 144, 128, 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, 3, 125, 169, 93, 5, 83, 69, 43, 64, 2, 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, 3, 171, 84, 191, 171, 253, 169, 85, 168, 8, 80, 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, 1, 253, 171, 123, 255, 248, 165, 42, 128, 161, 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, 1, 86, 237, 215, 255, 250, 85, 171, 248, 4, 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, 1, 253, 182, 239, 255, 240, 90, 173, 113, 0, 160, 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, 3, 223, 109, 171, 255, 249, 38, 219, 160, 36, 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, 250, 255, 85, 255, 244, 149, 109, 4, 1, 32, 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, 255, 181, 190, 191, 234, 139, 183, 128, 144, 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, 58, 255, 87, 255, 246, 237, 250, 130, 5, 64, 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, 31, 221, 173, 127, 191, 245, 87, 8, 80, 16, 48, 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, 15, 126, 255, 251, 255, 253, 109, 128, 2, 64, 48, 0, 63, 56, 0, 0, 0, 0, 0, 0, 252, 14, 127, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 247, 127, 255, 255, 245, 187, 2, 144, 0, 48, 0, 255, 60, 0, 0, 0, 0, 0, 1, 254, 14, 127, 192, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 221, 255, 255, 75, 244, 239, 8, 5, 32, 48, 0, 255, 56, 0, 0, 0, 0, 0, 3, 255, 12, 119, 192, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 254, 189, 170, 0, 170, 186, 0, 160, 0, 48, 1, 224, 56, 0, 0, 0, 0, 0, 7, 135, 156, 113, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 117, 118, 218, 218, 43, 239, 36, 9, 80, 48, 1, 224, 63, 193, 248, 113, 239, 248, 7, 3, 152, 113, 199, 103, 15, 135, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 237, 111, 84, 186, 190, 1, 32, 0, 48, 1, 248, 63, 225, 252, 113, 231, 252, 15, 3, 152, 119, 199, 231, 31, 199, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 250, 183, 186, 234, 31, 252, 8, 10, 64, 48, 0, 254, 61, 240, 28, 113, 231, 188, 15, 3, 192, 127, 135, 231, 56, 231, 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 255, 122, 239, 181, 111, 110, 1, 64, 144, 48, 0, 63, 60, 240, 254, 113, 207, 28, 15, 3, 192, 127, 199, 135, 56, 231, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 253, 239, 126, 245, 127, 252, 36, 18, 0, 48, 0, 15, 56, 113, 252, 113, 231, 28, 15, 3, 128, 113, 231, 7, 63, 231, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 251, 171, 170, 175, 190, 0, 128, 64, 48, 0, 7, 184, 243, 222, 113, 231, 28, 7, 3, 128, 112, 231, 7, 127, 231, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 182, 232, 42, 189, 252, 8, 42, 16, 48, 0, 7, 188, 115, 156, 121, 239, 28, 7, 135, 128, 113, 231, 7, 56, 7, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 253, 164, 9, 87, 254, 34, 0, 128, 48, 1, 255, 56, 243, 222, 127, 199, 28, 3, 255, 0, 123, 231, 7, 62, 199, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 214, 160, 133, 95, 252, 0, 164, 64, 48, 1, 254, 56, 115, 254, 63, 239, 28, 1, 254, 0, 127, 199, 7, 31, 199, 28, 0, 0, 0, 0, 0, 0, 0, 0, 8, 128, 127, 123, 170, 20, 175, 126, 8, 1, 16, 48, 0, 252, 56, 241, 236, 28, 231, 28, 0, 248, 0, 127, 7, 7, 15, 199, 28, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 127, 237, 96, 146, 87, 250, 34, 148, 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, 1, 0, 0, 255, 251, 173, 74, 191, 254, 128, 0, 160, 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, 8, 2, 64, 127, 182, 214, 213, 95, 250, 4, 164, 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, 32, 8, 8, 127, 255, 123, 234, 255, 254, 64, 1, 32, 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, 64, 0, 127, 251, 223, 189, 255, 250, 96, 36, 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, 1, 1, 1, 32, 127, 254, 247, 247, 255, 252, 98, 0, 160, 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, 4, 8, 1, 63, 255, 255, 255, 255, 244, 112, 72, 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, 4, 32, 32, 129, 191, 255, 255, 255, 255, 216, 120, 2, 80, 48, 2, 8, 32, 130, 8, 32, 129, 4, 16, 65, 4, 16, 32, 130, 8, 32, 130, 8, 16, 65, 4, 16, 128, 0, 0, 130, 3, 55, 255, 255, 255, 253, 248, 124, 0, 0, 48, 2, 56, 113, 199, 28, 113, 231, 28, 56, 227, 142, 56, 243, 207, 28, 113, 199, 30, 121, 227, 142, 56, 192, 16, 8, 8, 7, 31, 255, 255, 255, 255, 240, 126, 1, 16, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 33, 0, 7, 143, 255, 255, 255, 255, 224, 63, 128, 64, 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, 32, 143, 7, 255, 255, 255, 239, 192, 127, 240, 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, 16, 68, 132, 15, 131, 255, 255, 255, 255, 128, 63, 248, 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, 2, 0, 0, 31, 1, 255, 255, 255, 255, 16, 127, 254, 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, 16, 0, 127, 128, 255, 255, 255, 254, 0, 127, 255, 192, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 66, 65, 255, 16, 63, 255, 255, 252, 64, 127, 255, 224, 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, 7, 255, 129, 31, 255, 255, 248, 0, 127, 255, 240, 48, 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, 31, 255, 132, 79, 255, 255, 241, 16, 127, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 127, 255, 128, 35, 255, 255, 177, 32, 127, 255, 240, 48, 0, 0, 0, 0, 192, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 255, 194, 1, 255, 255, 100, 0, 255, 255, 240, 48, 1, 254, 0, 0, 224, 0, 14, 0, 0, 112, 63, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 255, 255, 192, 144, 127, 253, 68, 64, 255, 255, 240, 48, 3, 255, 0, 0, 224, 0, 14, 0, 0, 48, 63, 195, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 63, 255, 255, 196, 72, 15, 252, 136, 128, 255, 255, 240, 48, 0, 248, 0, 0, 224, 0, 4, 0, 0, 112, 57, 225, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 224, 68, 15, 241, 17, 4, 255, 255, 240, 48, 0, 48, 120, 60, 238, 55, 142, 30, 124, 48, 56, 115, 27, 30, 15, 62, 60, 59, 0, 0, 0, 0, 0, 3, 255, 255, 255, 226, 18, 14, 248, 32, 0, 255, 255, 240, 48, 0, 113, 252, 126, 254, 63, 206, 126, 126, 112, 48, 115, 191, 127, 31, 126, 127, 63, 0, 0, 0, 0, 0, 15, 255, 255, 255, 240, 144, 159, 252, 0, 16, 255, 255, 240, 48, 0, 49, 204, 240, 247, 61, 206, 112, 7, 48, 56, 115, 31, 99, 56, 56, 231, 62, 0, 0, 0, 0, 0, 63, 255, 255, 255, 240, 64, 63, 252, 0, 129, 255, 255, 240, 48, 0, 113, 222, 224, 231, 57, 206, 224, 63, 112, 56, 115, 156, 247, 184, 24, 227, 56, 0, 0, 0, 0, 0, 255, 255, 255, 255, 240, 36, 127, 254, 0, 1, 255, 255, 240, 48, 0, 51, 254, 224, 231, 57, 206, 224, 255, 48, 48, 115, 56, 255, 176, 56, 227, 184, 0, 0, 0, 0, 0, 255, 255, 255, 255, 241, 16, 127, 255, 2, 33, 255, 255, 240, 48, 0, 113, 196, 224, 231, 57, 206, 224, 231, 112, 56, 243, 152, 232, 56, 24, 231, 56, 0, 0, 0, 0, 0, 255, 255, 255, 255, 240, 128, 247, 255, 0, 3, 255, 255, 240, 48, 0, 49, 192, 244, 231, 57, 206, 122, 239, 48, 59, 227, 56, 114, 61, 30, 231, 56, 0, 0, 0, 0, 0, 255, 255, 255, 255, 248, 8, 252, 255, 132, 3, 255, 255, 240, 48, 0, 113, 252, 126, 231, 57, 206, 126, 255, 112, 63, 195, 156, 127, 31, 30, 126, 56, 0, 0, 0, 0, 0, 255, 255, 255, 255, 248, 65, 254, 127, 128, 3, 255, 255, 240, 48, 0, 48, 124, 60, 231, 56, 206, 30, 119, 48, 62, 3, 24, 30, 15, 14, 60, 56, 0, 0, 0, 0, 0, 255, 255, 255, 255, 248, 33, 255, 31, 193, 39, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 248, 137, 252, 143, 224, 3, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 252, 3, 255, 7, 224, 7, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 254, 35, 255, 7, 224, 3, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 254, 3, 255, 199, 240, 39, 255, 255, 240, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 7, 239, 199, 240, 39, 255, 255, 240, 48, 3, 56, 113, 199, 28, 113, 231, 28, 56, 227, 142, 56, 243, 207, 28, 113, 199, 30, 121, 227, 142, 56, 192, 255, 255, 255, 255, 255, 7, 195, 227, 208, 39, 255, 255, 240, 48, 0, 16, 65, 5, 8, 32, 130, 12, 40, 130, 132, 40, 65, 5, 20, 80, 130, 8, 32, 130, 138, 40, 0, 255, 255, 255, 255, 255, 7, 195, 251, 180, 71, 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, 255, 255, 255, 255, 255, 135, 129, 254, 40, 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, 255, 255, 255, 255, 255, 143, 137, 206, 20, 71, 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, 255, 255, 255, 255, 255, 198, 97, 190, 6, 135, 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, 255, 255, 255, 255, 255, 132, 1, 220, 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 +}; + diff --git a/examples/badger2040w/badger2040w_rtc.cmake b/examples/badger2040w/badger2040w_rtc.cmake new file mode 100644 index 00000000..8162adf0 --- /dev/null +++ b/examples/badger2040w/badger2040w_rtc.cmake @@ -0,0 +1,31 @@ +set(OUTPUT_NAME badger2040w_rtc) +add_executable(${OUTPUT_NAME} badger2040w_rtc.cpp) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi + pico_cyw43_arch_lwip_threadsafe_background +) + +target_include_directories(badger2040w_rtc PRIVATE + ${CMAKE_CURRENT_LIST_DIR} +) + +set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID") +set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password") + +if ("${WIFI_SSID}" STREQUAL "") + error("WIFI_SSID is not defined") +elseif ("${WIFI_PASSWORD}" STREQUAL "") + error("WIFI_PASSWORD is not defined") +else() + target_compile_definitions(badger2040w_rtc PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" + ) +endif() + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/badger2040w/badger2040w_rtc.cpp b/examples/badger2040w/badger2040w_rtc.cpp new file mode 100644 index 00000000..662355e6 --- /dev/null +++ b/examples/badger2040w/badger2040w_rtc.cpp @@ -0,0 +1,242 @@ +#include +#include +#include + +#include "badger2040w.hpp" +#include "common/pimoroni_common.hpp" +#include "lwip/dns.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "pico/cyw43_arch.h" +#include "pico/stdlib.h" + +#define NTP_SERVER "pool.ntp.org" + +using namespace pimoroni; + +Badger2040W badger; + +typedef void (*ntp_callback_t)(datetime_t *datetime, void *arg); +static volatile bool ntp_time_set = false; + +typedef struct NTP_T_ { + ip_addr_t ntp_server_address; + struct udp_pcb *ntp_pcb; + alarm_id_t ntp_failure_alarm; + ntp_callback_t ntp_callback; + void *ntp_callback_arg; +} NTP_T; + +#define NTP_MSG_LEN 48 +#define NTP_PORT 123 +#define NTP_DELTA 2208988800 // seconds between 1 Jan 1900 and 1 Jan 1970 +#define NTP_FAILURE_TIME (5 * 1000) + +static void ntp_convert_epoch(const time_t *epoch, datetime_t *datetime) { + struct tm *timeinfo = localtime(epoch); + datetime->year = timeinfo->tm_year + 1900; + datetime->month = timeinfo->tm_mon + 1; + datetime->day = timeinfo->tm_mday; + datetime->dotw = timeinfo->tm_wday; + datetime->hour = timeinfo->tm_hour; + datetime->min = timeinfo->tm_min; + datetime->sec = timeinfo->tm_sec; +} + +// Called with results of operation +static void ntp_result(NTP_T *state, int status, time_t *result) { + if (state->ntp_failure_alarm > 0) { + cancel_alarm(state->ntp_failure_alarm); + state->ntp_failure_alarm = 0; + } + + if (status == 0 && result) { + datetime_t datetime; + ntp_convert_epoch(result, &datetime); + if (state->ntp_callback) { + state->ntp_callback(&datetime, state->ntp_callback_arg); + } + } else { + if (state->ntp_callback) { + state->ntp_callback(NULL, state->ntp_callback_arg); + } + } + free(state); +} + +// Make an NTP request +static void ntp_request(NTP_T *state) { + cyw43_arch_lwip_begin(); + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, NTP_MSG_LEN, PBUF_RAM); + uint8_t *req = (uint8_t *)p->payload; + memset(req, 0, NTP_MSG_LEN); + req[0] = 0x1b; + udp_sendto(state->ntp_pcb, p, &state->ntp_server_address, NTP_PORT); + pbuf_free(p); + cyw43_arch_lwip_end(); +} + +static int64_t ntp_failed_handler(alarm_id_t id, void *user_data) { + NTP_T *state = (NTP_T *)user_data; + printf("ntp request failed\n"); + ntp_result(state, -1, NULL); + return 0; +} + +// Call back with a DNS result +static void ntp_dns_found(const char *hostname, const ip_addr_t *ipaddr, void *arg) { + NTP_T *state = (NTP_T *)arg; + if (ipaddr) { + state->ntp_server_address = *ipaddr; + printf("ntp address %s\n", ipaddr_ntoa(ipaddr)); + ntp_request(state); + } else { + printf("ntp dns request failed\n"); + ntp_result(state, -1, NULL); + } +} + +// NTP data received +static void ntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { + NTP_T *state = (NTP_T *)arg; + uint8_t mode = pbuf_get_at(p, 0) & 0x7; + uint8_t stratum = pbuf_get_at(p, 1); + + // Check the result + if (ip_addr_cmp(addr, &state->ntp_server_address) && port == NTP_PORT && p->tot_len == NTP_MSG_LEN && + mode == 0x4 && stratum != 0) { + uint8_t seconds_buf[4] = {0}; + pbuf_copy_partial(p, seconds_buf, sizeof(seconds_buf), 40); + uint32_t seconds_since_1900 = seconds_buf[0] << 24 | seconds_buf[1] << 16 | seconds_buf[2] << 8 | seconds_buf[3]; + uint32_t seconds_since_1970 = seconds_since_1900 - NTP_DELTA; + time_t epoch = seconds_since_1970; + ntp_result(state, 0, &epoch); + } else { + printf("invalid ntp response\n"); + ntp_result(state, -1, NULL); + } + pbuf_free(p); +} + +// Perform initialisation +static NTP_T *ntp_init(ntp_callback_t callback, void *arg) { + NTP_T *state = (NTP_T *)calloc(1, sizeof(NTP_T)); + if (!state) { + printf("failed to allocate state\n"); + return NULL; + } + state->ntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (!state->ntp_pcb) { + printf("failed to create pcb\n"); + free(state); + return NULL; + } + state->ntp_callback = callback; + state->ntp_callback_arg = arg; + udp_recv(state->ntp_pcb, ntp_recv, state); + return state; +} + +void ntp_get_time(ntp_callback_t callback, void *arg) { + NTP_T *state = ntp_init(callback, arg); + if (!state) + return; + + // Set alarm in case udp request is lost + state->ntp_failure_alarm = add_alarm_in_ms(NTP_FAILURE_TIME, ntp_failed_handler, state, true); + + cyw43_arch_lwip_begin(); + int err = dns_gethostbyname(NTP_SERVER, &state->ntp_server_address, ntp_dns_found, state); + cyw43_arch_lwip_end(); + + if (err == ERR_OK) { // dns record retrieved from cache + ntp_request(state); + } else if (err != ERR_INPROGRESS) { // ERR_INPROGRESS means the dns callback is pending + printf("dns request failed\n"); + ntp_result(state, -1, NULL); + } +} + +void ntp_callback(datetime_t *datetime, void *arg) { + if (datetime == NULL) { + ntp_time_set = true; + return; + } + printf("Got datetime from NTP\n"); + badger.pcf85063a->set_datetime(datetime); + rtc_set_datetime(datetime); + + // Flag that NTP callback has concluded + ntp_time_set = true; +} + +void retrieve_time(bool from_ntp) { + ntp_time_set = false; + // Check if RTC has been initialised previously, if not or if the RTC int is high get the internet time via NTP + if (from_ntp) { + printf("Retrieving time from NTP\n"); + ntp_get_time(ntp_callback, NULL); + // Block until the callback sets datetime + while (!ntp_time_set) { + tight_loop_contents(); + } + } else { + printf("Retrieving time from RTC\n"); + // Retrieve stored time from external RTC + datetime_t datetime = badger.pcf85063a->get_datetime(); + // Store time in internal RTC + rtc_set_datetime(&datetime); + } +} + +int main() { + badger.init(); + rtc_init(); + stdio_init_all(); + printf("\n\n=======\nbadger2040 starting up\n\n"); + + badger.graphics->set_font("bitmap8"); + badger.graphics->set_thickness(2); + + cyw43_arch_init(); + cyw43_arch_enable_sta_mode(); + if (cyw43_arch_wifi_connect_blocking(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK)) { + printf("Failed to connect to wifi, halting\n"); + badger.halt(); + } + + // External RTC has 1 free byte, we can use this to determine whether the time has been set previously + if (!badger.pcf85063a->get_byte()) { + retrieve_time(true); + + // Set the external RTC free byte so we can later determine if it has been initalized + badger.pcf85063a->set_byte(1); + } else { + retrieve_time(false); + } + + char time_str[32]; + datetime_t datetime; + while (true) { + badger.graphics->set_pen(15); + badger.graphics->clear(); + + badger.graphics->set_pen(0); + badger.graphics->rectangle(Rect(0, badger.DISPLAY_HEIGHT / 4, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT / 2)); + badger.graphics->set_pen(15); + badger.graphics->rectangle(Rect(5, badger.DISPLAY_HEIGHT / 4 + 5, badger.DISPLAY_WIDTH - 10, badger.DISPLAY_HEIGHT / 2 - 10)); + + badger.graphics->set_pen(0); + rtc_get_datetime(&datetime); + sprintf(time_str, "%02d/%02d/%02d %02d:%02d\n", datetime.day, datetime.month, datetime.year, datetime.hour, datetime.min); + int32_t time_x_centered = (badger.DISPLAY_WIDTH - badger.graphics->measure_text(time_str, 2.0f)) / 2; + badger.graphics->text("Time (GMT+0)", Point(5, 10), badger.DISPLAY_WIDTH, 2.0f); + badger.graphics->text(time_str, Point(time_x_centered, badger.DISPLAY_HEIGHT / 2 - 8), badger.DISPLAY_WIDTH, 2.0f); + + badger.update(); + + do { + rtc_get_datetime(&datetime); + } while(datetime.sec != 0); + } +} diff --git a/examples/badger2040w/lwipopts.h b/examples/badger2040w/lwipopts.h new file mode 100644 index 00000000..ea9daf0c --- /dev/null +++ b/examples/badger2040w/lwipopts.h @@ -0,0 +1,89 @@ +#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H +#define _LWIPOPTS_EXAMPLE_COMMONH_H + +// Common settings used in most of the pico_w examples +// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) + +// allow override in some examples +#ifndef NO_SYS +#define NO_SYS 1 +#endif +// allow override in some examples +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif +#if PICO_CYW43_ARCH_POLL +#define MEM_LIBC_MALLOC 1 +#else +// MEM_LIBC_MALLOC is incompatible with non polling versions +#define MEM_LIBC_MALLOC 0 +#endif +#define MEM_ALIGNMENT 4 +#define MEM_SIZE 1600 +#define MEMP_NUM_TCP_SEG 16 +#define MEMP_NUM_ARP_QUEUE 30 +#define PBUF_POOL_SIZE 16 +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_ICMP 1 +#define LWIP_RAW 1 +#define TCP_WND (4 * TCP_MSS) +#define TCP_MSS 536 +#define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETCONN 0 +#define MEM_STATS 1 +#define SYS_STATS 1 +#define MEMP_STATS 1 +#define LINK_STATS 1 +// #define ETH_PAD_SIZE 2 +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_DHCP 1 +#define LWIP_IPV4 1 +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_DNS 1 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#define DHCP_DOES_ARP_CHECK 0 +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#ifndef NDEBUG +#define LWIP_DEBUG 1 +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#endif + +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define PPP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF + +#endif /* __LWIPOPTS_H__ */ diff --git a/libraries/badger2040/badger2040.cpp b/libraries/badger2040/badger2040.cpp index 6be32b91..d74635d7 100644 --- a/libraries/badger2040/badger2040.cpp +++ b/libraries/badger2040/badger2040.cpp @@ -1,18 +1,18 @@ -#include +#include "badger2040.hpp" + #include +#include #include "hardware/pwm.h" #include "hardware/watchdog.h" -#include "badger2040.hpp" - namespace pimoroni { - void Badger2040::init() { +void Badger2040::init() { // set clock speed to 12MHz to reduce the maximum current draw on the // battery. when updating a small, monochrome, display only every few // seconds or so then you don't need much processing power anyway... - //set_sys_clock_khz(48000, true); + // set_sys_clock_khz(48000, true); gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO); gpio_set_dir(ENABLE_3V3, GPIO_OUT); @@ -50,12 +50,12 @@ namespace pimoroni { uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); _wake_button_states |= gpio_get_all() & mask; -/* - // wait for button to be released before continuing - while(gpio_get_all() & mask) { - tight_loop_contents(); - } -*/ + /* + // wait for button to be released before continuing + while(gpio_get_all() & mask) { + tight_loop_contents(); + } + */ // led control pin pwm_config cfg = pwm_get_default_config(); @@ -67,9 +67,9 @@ namespace pimoroni { uc8151_legacy.init(); // TODO: set default image? - } +} - void Badger2040::halt() { +void Badger2040::halt() { gpio_put(ENABLE_3V3, 0); // If running on USB we will not actually power down, so emulate the behaviour @@ -77,356 +77,382 @@ namespace pimoroni { // Note: Don't use wait_for_press as that waits for the button to be release and // we want the reboot to complete before the button is released. update_button_states(); - while(_button_states == 0) { - update_button_states(); + while (_button_states == 0) { + update_button_states(); } watchdog_reboot(0, 0, 0); - } +} - uint8_t _dither_value(int32_t x, int32_t y, uint8_t p) { +uint8_t _dither_value(int32_t x, int32_t y, uint8_t p) { // ordered dither matrix used in 4-bit mode static uint8_t _odm[16] = { - 0, 8, 2, 10, - 12, 4, 14, 6, - 3, 11, 1, 9, - 15, 7, 13, 5 - }; + 0, 8, 2, 10, + 12, 4, 14, 6, + 3, 11, 1, 9, + 15, 7, 13, 5}; if (p == 0) { - return 1; + return 1; } if (p == 15) { - return 0; + return 0; } // calculate dither matrix offset uint32_t dmo = (x & 0b11) | ((y & 0b11) << 2); return p <= _odm[dmo] ? 1 : 0; - } +} - // Return dither values for an entire byte in the column - uint8_t _dither_column_value(int32_t x, uint8_t p) { +// Return dither values for an entire byte in the column +uint8_t _dither_column_value(int32_t x, uint8_t p) { if (p == 0) { - return 0xff; + return 0xff; } if (p == 15) { - return 0; + return 0; } uint8_t val = 0; for (int32_t y = 0; y < 4; ++y) { - val |= _dither_value(x, y, p) << (7 - y); + val |= _dither_value(x, y, p) << (7 - y); } val |= val >> 4; return val; - } +} - - void Badger2040::clear() { +void Badger2040::clear() { const uint32_t column_len = 128 / 8; const uint32_t buf_len = column_len * 296; uint8_t* buf = uc8151_legacy.get_frame_buffer(); - + if (_pen == 0) { - memset(buf, 0xff, buf_len); - } - else if (_pen == 15) { - memset(buf, 0, buf_len); - } - else { - for(uint32_t x = 0; x < 296; x++) { - uint8_t val = _dither_column_value(x, _pen); - memset(buf, val, column_len); - buf += column_len; - } - } - } - - void Badger2040::pixel(int32_t x, int32_t y) { - if(_thickness == 1) { - uc8151_legacy.pixel(x, y, _dither_value(x, y, _pen)); - }else{ - uint8_t ht = _thickness / 2; - for(int sy = 0; sy < _thickness; sy++) { - for(int sx = 0; sx < _thickness; sx++) { - uc8151_legacy.pixel(x + sx - ht, y + sy - ht, _dither_value(x + sx - ht, y + sy - ht, _pen)); + memset(buf, 0xff, buf_len); + } else if (_pen == 15) { + memset(buf, 0, buf_len); + } else { + for (uint32_t x = 0; x < 296; x++) { + uint8_t val = _dither_column_value(x, _pen); + memset(buf, val, column_len); + buf += column_len; } - } } - } +} - // Display a portion of an image (icon sheet) at dx, dy - void Badger2040::icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy) { +void Badger2040::pixel(int32_t x, int32_t y) { + if (_thickness == 1) { + uc8151_legacy.pixel(x, y, _dither_value(x, y, _pen)); + } else { + uint8_t ht = _thickness / 2; + for (int sy = 0; sy < _thickness; sy++) { + for (int sx = 0; sx < _thickness; sx++) { + uc8151_legacy.pixel(x + sx - ht, y + sy - ht, _dither_value(x + sx - ht, y + sy - ht, _pen)); + } + } + } +} + +// Display a portion of an image (icon sheet) at dx, dy +void Badger2040::icon(const uint8_t* data, int sheet_width, int icon_size, int index, int dx, int dy) { image(data, sheet_width, icon_size * index, 0, icon_size, icon_size, dx, dy); - } +} - // Display an image that fills the screen (296*128) - void Badger2040::image(const uint8_t* data) { +// Display an image that fills the screen (296*128) +void Badger2040::image(const uint8_t* data) { uint8_t* ptr = uc8151_legacy.get_frame_buffer(); - + for (uint32_t x = 0; x < 296; ++x) { - // extract bitmask for this pixel - uint32_t bm = 0b10000000 >> (x & 0b111); - - for (uint32_t y = 0; y < 128; y += 8) { - uint8_t val = 0; - for (uint32_t cy = 0; cy < 8; ++cy) { - // work out byte offset in source data - uint32_t o = ((y + cy) * (296 >> 3)) + (x >> 3); - - // Set bit in val if set in source data - if (data[o] & bm) { - val |= 0b10000000 >> cy; - } - } - *ptr++ = val; - } - } - } - - // Display an image smaller than the screen (sw*sh) at dx, dy - void Badger2040::image(const uint8_t *data, int w, int h, int x, int y) { - if (x == 0 && y == 0 && w == 296 && h == 128) { - image(data); - } - else { - image(data, w, 0, 0, w, h, x, y); - } - } - - void Badger2040::image(const uint8_t *data, int stride, int sx, int sy, int dw, int dh, int dx, int dy) { - for(auto y = 0; y < dh; y++) { - for(auto x = 0; x < dw; x++) { - // work out byte offset in source data - uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3); - // extract bitmask for this pixel - uint32_t bm = 0b10000000 >> ((x + sx) & 0b111); + uint32_t bm = 0b10000000 >> (x & 0b111); - // draw the pixel - uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm); - } + for (uint32_t y = 0; y < 128; y += 8) { + uint8_t val = 0; + for (uint32_t cy = 0; cy < 8; ++cy) { + // work out byte offset in source data + uint32_t o = ((y + cy) * (296 >> 3)) + (x >> 3); + + // Set bit in val if set in source data + if (data[o] & bm) { + val |= 0b10000000 >> cy; + } + } + *ptr++ = val; + } } - } +} - void Badger2040::rectangle(int32_t x, int32_t y, int32_t w, int32_t h) { +// Display an image smaller than the screen (sw*sh) at dx, dy +void Badger2040::image(const uint8_t* data, int w, int h, int x, int y) { + if (x == 0 && y == 0 && w == 296 && h == 128) { + image(data); + } else { + image(data, w, 0, 0, w, h, x, y); + } +} + +void Badger2040::image(const uint8_t* data, int stride, int sx, int sy, int dw, int dh, int dx, int dy) { + for (auto y = 0; y < dh; y++) { + for (auto x = 0; x < dw; x++) { + // work out byte offset in source data + uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3); + + // extract bitmask for this pixel + uint32_t bm = 0b10000000 >> ((x + sx) & 0b111); + + // draw the pixel + uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm); + } + } +} + +void Badger2040::rectangle(int32_t x, int32_t y, int32_t w, int32_t h) { // Adjust for thickness uint32_t ht = _thickness / 2; x -= ht; if (x < 0) { - w += x; - x = 0; + w += x; + x = 0; } y -= ht; if (y < 0) { - h += y; - y = 0; + h += y; + y = 0; } w += _thickness - 1; h += _thickness - 1; if (x + w > 296) { - w = 296 - x; + w = 296 - x; } if (y + h > 128) { - h = 128 - y; + h = 128 - y; } if (h >= 8) { - // Directly write to the frame buffer when clearing a large area - uint8_t* buf = uc8151_legacy.get_frame_buffer(); - - for(int cx = x; cx < x + w; cx++) { - uint8_t* buf_ptr = &buf[cx * 16 + y / 8]; - uint8_t first_mask = 0xff >> (y & 7); - uint8_t last_mask = 0xff >> ((y + h) & 7); - uint32_t val = _dither_column_value(cx, _pen); - *buf_ptr &= ~first_mask; - *buf_ptr++ |= (val & first_mask); - for (int32_t c = h - (8 - (y & 7)); c >= 8; c -= 8) { - *buf_ptr++ = val; + // Directly write to the frame buffer when clearing a large area + uint8_t* buf = uc8151_legacy.get_frame_buffer(); + + for (int cx = x; cx < x + w; cx++) { + uint8_t* buf_ptr = &buf[cx * 16 + y / 8]; + uint8_t first_mask = 0xff >> (y & 7); + uint8_t last_mask = 0xff >> ((y + h) & 7); + uint32_t val = _dither_column_value(cx, _pen); + *buf_ptr &= ~first_mask; + *buf_ptr++ |= (val & first_mask); + for (int32_t c = h - (8 - (y & 7)); c >= 8; c -= 8) { + *buf_ptr++ = val; + } + *buf_ptr &= last_mask; + *buf_ptr |= (val & (~last_mask)); } - *buf_ptr &= last_mask; - *buf_ptr |= (val & (~last_mask)); - } - } - else { - for(int cx = x; cx < x + w; cx++) { - for(int cy = y; cy < y + h; cy++) { - uc8151_legacy.pixel(cx, cy, _dither_value(cx, cy, _pen)); - } - } - } - } - - void Badger2040::line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - int32_t x = x1, y = y1, dx, dy, incx, incy, balance; - - if(x2 >= x1) {dx = x2 - x1; incx = 1;} else {dx = x1 - x2; incx = -1;} - if(y2 >= y1) {dy = y2 - y1; incy = 1;} else {dy = y1 - y2; incy = -1;} - - if(dx >= dy) { - dy <<= 1; balance = dy - dx; dx <<= 1; - while(x != x2) { - pixel(x, y); - if (balance >= 0) {y += incy; balance -= dx;} - balance += dy; x += incx; - } } else { - dx <<= 1; balance = dx - dy; dy <<= 1; - while(y != y2) { - pixel(x, y); - if(balance >= 0) {x += incx; balance -= dy;} - balance += dx; y += incy; - } + for (int cx = x; cx < x + w; cx++) { + for (int cy = y; cy < y + h; cy++) { + uc8151_legacy.pixel(cx, cy, _dither_value(cx, cy, _pen)); + } + } } - } +} - void Badger2040::debug_command(uint8_t reg, size_t len, const uint8_t *data) { +void Badger2040::line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + int32_t x = x1, y = y1, dx, dy, incx, incy, balance; + + if (x2 >= x1) { + dx = x2 - x1; + incx = 1; + } else { + dx = x1 - x2; + incx = -1; + } + if (y2 >= y1) { + dy = y2 - y1; + incy = 1; + } else { + dy = y1 - y2; + incy = -1; + } + + if (dx >= dy) { + dy <<= 1; + balance = dy - dx; + dx <<= 1; + while (x != x2) { + pixel(x, y); + if (balance >= 0) { + y += incy; + balance -= dx; + } + balance += dy; + x += incx; + } + } else { + dx <<= 1; + balance = dx - dy; + dy <<= 1; + while (y != y2) { + pixel(x, y); + if (balance >= 0) { + x += incx; + balance -= dy; + } + balance += dx; + y += incy; + } + } +} + +void Badger2040::debug_command(uint8_t reg, size_t len, const uint8_t* data) { uc8151_legacy.command(reg, len, data); - } +} - void Badger2040::dump_otp(uint8_t *data) { - uc8151_legacy.read(0xa2, 0xFFF, data); - } +void Badger2040::dump_otp(uint8_t* data) { + uc8151_legacy.read(0xa2, 0xFFF, data); +} - void Badger2040::update_button_states() { +void Badger2040::update_button_states() { uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << USER); _button_states = gpio_get_all() & mask; - _button_states ^= (1UL << USER); // USER button state is inverted - } + _button_states ^= (1UL << USER); // USER button state is inverted +} - uint32_t Badger2040::button_states() { +uint32_t Badger2040::button_states() { return _button_states; - } +} - bool Badger2040::is_busy() { +bool Badger2040::is_busy() { return uc8151_legacy.is_busy(); - } +} - void Badger2040::power_off() { +void Badger2040::power_off() { uc8151_legacy.power_off(); - } +} - void Badger2040::invert(bool invert) { +void Badger2040::invert(bool invert) { uc8151_legacy.invert(invert); - } +} - void Badger2040::update_speed(uint8_t speed) { +void Badger2040::update_speed(uint8_t speed) { uc8151_legacy.update_speed(speed); - } +} - uint32_t Badger2040::update_time() { +uint32_t Badger2040::update_time() { return uc8151_legacy.update_time(); - } +} - void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) { +void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) { uc8151_legacy.partial_update(x, y, w, h, blocking); - } +} - void Badger2040::update(bool blocking) { +void Badger2040::update(bool blocking) { uc8151_legacy.update(blocking); - } +} - const hershey::font_glyph_t* Badger2040::glyph_data(unsigned char c) { +const hershey::font_glyph_t* Badger2040::glyph_data(unsigned char c) { return hershey::glyph_data(_font, c); - } +} - int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) { +int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) { if (_bitmap_font) { - bitmap::character(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { - for(auto px = 0; px < w; px++) { - for(auto py = 0; py < h; py++) { - pixel(x + px, y + py); - } - } - }, c, x, y, std::max(1.0f, s)); - return 0; + bitmap::character( + _bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { + for (auto px = 0; px < w; px++) { + for (auto py = 0; py < h; py++) { + pixel(x + px, y + py); + } + } + }, + c, x, y, std::max(1.0f, s)); + return 0; } else { - return hershey::glyph(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - line(x1, y1, x2, y2); - }, c, x, y, s, a); + return hershey::glyph( + _font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + line(x1, y1, x2, y2); + }, + c, x, y, s, a); } - } +} - void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a, uint8_t letter_spacing) { +void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a, uint8_t letter_spacing) { if (_bitmap_font) { - bitmap::text(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { - for(auto px = 0; px < w; px++) { - for(auto py = 0; py < h; py++) { - pixel(x + px, y + py); - } - } - }, message, x, y, 296 - x, std::max(1.0f, s), letter_spacing); + bitmap::text( + _bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { + for (auto px = 0; px < w; px++) { + for (auto py = 0; py < h; py++) { + pixel(x + px, y + py); + } + } + }, + message, x, y, 296 - x, std::max(1.0f, s), letter_spacing); } else { - hershey::text(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - line(x1, y1, x2, y2); - }, message, x, y, s, a); + hershey::text( + _font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + line(x1, y1, x2, y2); + }, + message, x, y, s, a); } - } +} - int32_t Badger2040::measure_text(std::string message, float s, uint8_t letter_spacing) { +int32_t Badger2040::measure_text(std::string message, float s, uint8_t letter_spacing) { if (_bitmap_font) return bitmap::measure_text(_bitmap_font, message, std::max(1.0f, s), letter_spacing); return hershey::measure_text(_font, message, s); - } +} - int32_t Badger2040::measure_glyph(unsigned char c, float s) { +int32_t Badger2040::measure_glyph(unsigned char c, float s) { if (_bitmap_font) return bitmap::measure_character(_bitmap_font, c, std::max(1.0f, s)); return hershey::measure_glyph(_font, c, s); - } +} - void Badger2040::font(std::string name) { +void Badger2040::font(std::string name) { if (name == "bitmap6") { - _bitmap_font = &font6; - _font = nullptr; + _bitmap_font = &font6; + _font = nullptr; } else if (name == "bitmap8") { - _bitmap_font = &font8; - _font = nullptr; + _bitmap_font = &font8; + _font = nullptr; } else if (name == "bitmap14_outline") { - _bitmap_font = &font14_outline; - _font = nullptr; + _bitmap_font = &font14_outline; + _font = nullptr; } else { - // check that font exists and assign it - if(hershey::fonts.find(name) != hershey::fonts.end()) { - _bitmap_font = nullptr; - _font = hershey::fonts[name]; - } + // check that font exists and assign it + if (hershey::fonts.find(name) != hershey::fonts.end()) { + _bitmap_font = nullptr; + _font = hershey::fonts[name]; + } } - } +} - void Badger2040::pen(uint8_t pen) { +void Badger2040::pen(uint8_t pen) { _pen = pen; - } +} - void Badger2040::thickness(uint8_t thickness) { +void Badger2040::thickness(uint8_t thickness) { _thickness = thickness; - } +} - void Badger2040::led(uint8_t brightness) { +void Badger2040::led(uint8_t brightness) { // set the led brightness from 1 to 256 with gamma correction float gamma = 2.8; uint16_t v = (uint16_t)(pow((float)(brightness) / 256.0f, gamma) * 65535.0f + 0.5f); pwm_set_gpio_level(LED, v); - } +} - bool Badger2040::pressed(uint8_t button) { +bool Badger2040::pressed(uint8_t button) { return (_button_states & (1UL << button)) != 0; - } +} - bool Badger2040::pressed_to_wake(uint8_t button) { +bool Badger2040::pressed_to_wake(uint8_t button) { return (_wake_button_states & (1UL << button)) != 0; - } +} - void Badger2040::wait_for_press() { +void Badger2040::wait_for_press() { update_button_states(); - while(_button_states == 0) { - update_button_states(); - tight_loop_contents(); + while (_button_states == 0) { + update_button_states(); + tight_loop_contents(); } uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); - while(gpio_get_all() & mask) { - tight_loop_contents(); + while (gpio_get_all() & mask) { + tight_loop_contents(); } - } } +} // namespace pimoroni diff --git a/libraries/badger2040w/badger2040w.cpp b/libraries/badger2040w/badger2040w.cpp index 526b20e8..66f24d84 100644 --- a/libraries/badger2040w/badger2040w.cpp +++ b/libraries/badger2040w/badger2040w.cpp @@ -35,8 +35,11 @@ namespace pimoroni { gpio_set_dir(E, GPIO_IN); gpio_set_pulls(E, false, true); + // PCF85063a handles the initialisation of the RTC GPIO pin + pcf85063a = std::make_unique(new I2C(I2C_BG_SDA, I2C_BG_SCL), (uint)RTC); + // read initial button states - uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); + uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << RTC); _wake_button_states |= gpio_get_all() & mask; // led control pin @@ -46,9 +49,9 @@ namespace pimoroni { gpio_set_function(LED, GPIO_FUNC_PWM); led(0); - uc8151 = std::make_unique(296, 128, ROTATE_0); - graphics = std::make_unique(296, 128, nullptr); - pcf85063a = std::make_unique(new I2C(I2C_BG_SDA, I2C_BG_SCL), (uint)RTC); + // Initialise display driver and pico graphics library + uc8151 = std::make_unique(DISPLAY_WIDTH, DISPLAY_HEIGHT, ROTATE_0); + graphics = std::make_unique(DISPLAY_WIDTH, DISPLAY_HEIGHT, nullptr); } void Badger2040W::halt() { @@ -66,7 +69,7 @@ namespace pimoroni { } void Badger2040W::update_button_states() { - uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); + uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << RTC); _button_states = gpio_get_all() & mask; } @@ -74,11 +77,6 @@ namespace pimoroni { return _button_states; } - // // Display a portion of an image (icon sheet) at dx, dy - // void Badger2040W::icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy) { - // image(data, sheet_width, icon_size * index, 0, icon_size, icon_size, dx, dy); - // } - void Badger2040W::imageRow(const uint8_t *data, Rect rect) { for(auto x = 0; x < rect.w; x++) { // work out byte offset in source data @@ -88,19 +86,33 @@ namespace pimoroni { uint32_t bm = 0b10000000 >> (x & 0b111); // set pixel color - graphics->set_pen(data[o] & bm ? 15 : 0); + graphics->set_pen(data[o] & bm ? 0 : 15); // draw the pixel graphics->set_pixel(Point(x + rect.x, rect.y)); } } - // Display an image smaller than the screen (sw*sh) at dx, dy + + // Display a portion of an image (icon sheet) at rect + void Badger2040W::icon(const uint8_t *data, int index, int sheet_width, Rect rect) { + for(auto y = 0; y < rect.h; y++) { + const uint8_t *scanline = data + ((y * sheet_width) >> 3) + ((rect.w * index) >> 3); + imageRow(scanline, Rect(rect.x, y + rect.y, rect.w, 0)); + } + } + + // Display an image at rect void Badger2040W::image(const uint8_t *data, Rect rect) { for(auto y = 0; y < rect.h; y++) { const uint8_t *scanline = data + ((y * rect.w) >> 3); - Badger2040W::imageRow(scanline, Rect(rect.x, y + rect.y, rect.w, 0)); + imageRow(scanline, Rect(rect.x, y + rect.y, rect.w, 0)); } } + // Display an image that covers the entire screen + void Badger2040W::image(const uint8_t *data) { + image(data, Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)); + } + void Badger2040W::partial_update(Rect region) { uc8151->partial_update(graphics.get(), region); } @@ -132,7 +144,7 @@ namespace pimoroni { tight_loop_contents(); } - uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); + uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << RTC); while(gpio_get_all() & mask) { tight_loop_contents(); } diff --git a/libraries/badger2040w/badger2040w.hpp b/libraries/badger2040w/badger2040w.hpp index 0550a5fd..f4684651 100644 --- a/libraries/badger2040w/badger2040w.hpp +++ b/libraries/badger2040w/badger2040w.hpp @@ -20,6 +20,9 @@ namespace pimoroni { std::unique_ptr uc8151; std::unique_ptr graphics; std::unique_ptr pcf85063a; + uint DISPLAY_WIDTH = 296; + uint DISPLAY_HEIGHT = 128; + Badger2040W(){}; void init(); void update(); @@ -36,8 +39,9 @@ namespace pimoroni { void update_button_states(); uint32_t button_states(); - // void icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy); + void icon(const uint8_t *data, int index, int sheet_width, Rect rect); void image(const uint8_t *data, Rect rect); + void image(const uint8_t *data); public: enum pin { From c5a7c5951091a19eb5b483b267c337661d6d9210 Mon Sep 17 00:00:00 2001 From: kennedn Date: Mon, 19 Feb 2024 16:24:45 +0000 Subject: [PATCH 6/7] Minor tweaks --- examples/badger2040w/badger2040w_rtc.cmake | 24 +-- examples/badger2040w/badger2040w_rtc.cpp | 8 +- .../badger2040w/image_converter/convert.py | 136 ++++++++++++++++ .../badger2040w/image_converter/data_to_py.py | 154 ++++++++++++++++++ .../image_converter/test-images/adam.png | Bin 0 -> 45400 bytes .../image_converter/test-images/iconsheet.png | Bin 0 -> 8325 bytes .../image_converter/test-images/paul.png | Bin 0 -> 49990 bytes .../image_converter/test-images/shaun.png | Bin 0 -> 47431 bytes 8 files changed, 304 insertions(+), 18 deletions(-) create mode 100755 examples/badger2040w/image_converter/convert.py create mode 100644 examples/badger2040w/image_converter/data_to_py.py create mode 100644 examples/badger2040w/image_converter/test-images/adam.png create mode 100644 examples/badger2040w/image_converter/test-images/iconsheet.png create mode 100644 examples/badger2040w/image_converter/test-images/paul.png create mode 100644 examples/badger2040w/image_converter/test-images/shaun.png diff --git a/examples/badger2040w/badger2040w_rtc.cmake b/examples/badger2040w/badger2040w_rtc.cmake index 8162adf0..9dc62702 100644 --- a/examples/badger2040w/badger2040w_rtc.cmake +++ b/examples/badger2040w/badger2040w_rtc.cmake @@ -1,3 +1,11 @@ +set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID") +set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password") + +if ("${WIFI_SSID}" STREQUAL "" OR "${WIFI_PASSWORD}" STREQUAL "") + message(WARNING "WIFI_SSID or WIFI_PASSWORD is not defined. Skipping rtc example.") + return() +endif() + set(OUTPUT_NAME badger2040w_rtc) add_executable(${OUTPUT_NAME} badger2040w_rtc.cpp) @@ -11,19 +19,11 @@ target_include_directories(badger2040w_rtc PRIVATE ${CMAKE_CURRENT_LIST_DIR} ) -set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID") -set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password") -if ("${WIFI_SSID}" STREQUAL "") - error("WIFI_SSID is not defined") -elseif ("${WIFI_PASSWORD}" STREQUAL "") - error("WIFI_PASSWORD is not defined") -else() - target_compile_definitions(badger2040w_rtc PRIVATE - WIFI_SSID=\"${WIFI_SSID}\" - WIFI_PASSWORD=\"${WIFI_PASSWORD}\" - ) -endif() +target_compile_definitions(badger2040w_rtc PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" +) # enable usb output pico_enable_stdio_usb(${OUTPUT_NAME} 1) diff --git a/examples/badger2040w/badger2040w_rtc.cpp b/examples/badger2040w/badger2040w_rtc.cpp index 662355e6..d718656f 100644 --- a/examples/badger2040w/badger2040w_rtc.cpp +++ b/examples/badger2040w/badger2040w_rtc.cpp @@ -172,7 +172,7 @@ void ntp_callback(datetime_t *datetime, void *arg) { void retrieve_time(bool from_ntp) { ntp_time_set = false; - // Check if RTC has been initialised previously, if not or if the RTC int is high get the internet time via NTP + // Check if RTC has been initialised previously, if not get the internet time via NTP if (from_ntp) { printf("Retrieving time from NTP\n"); ntp_get_time(ntp_callback, NULL); @@ -221,11 +221,6 @@ int main() { badger.graphics->set_pen(15); badger.graphics->clear(); - badger.graphics->set_pen(0); - badger.graphics->rectangle(Rect(0, badger.DISPLAY_HEIGHT / 4, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT / 2)); - badger.graphics->set_pen(15); - badger.graphics->rectangle(Rect(5, badger.DISPLAY_HEIGHT / 4 + 5, badger.DISPLAY_WIDTH - 10, badger.DISPLAY_HEIGHT / 2 - 10)); - badger.graphics->set_pen(0); rtc_get_datetime(&datetime); sprintf(time_str, "%02d/%02d/%02d %02d:%02d\n", datetime.day, datetime.month, datetime.year, datetime.hour, datetime.min); @@ -235,6 +230,7 @@ int main() { badger.update(); + // Wait for next minute before redrawing do { rtc_get_datetime(&datetime); } while(datetime.sec != 0); diff --git a/examples/badger2040w/image_converter/convert.py b/examples/badger2040w/image_converter/convert.py new file mode 100755 index 00000000..fac68898 --- /dev/null +++ b/examples/badger2040w/image_converter/convert.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +""" +Converts images into a format suitable for display on Badger 2040. + +Optionally resizes images to 296x128 to fit the display. + +Crunches images down to dithered, 1bit colour depth. + +Outputs either in raw binary format or as a .py file for embedding into MicroPython. + +Output to py functionality is borrwed from data_to_py.py, Copyright (c) 2016 Peter Hinch +""" + +import io +import argparse +from PIL import Image, ImageEnhance +from pathlib import Path + + +PY_HEADER = """# Code generated by convert.py. +""" + +PY_FOOTER = """_mvdata = memoryview(_data) + +def data(): + return _mvdata + +""" + + +parser = argparse.ArgumentParser(description='Converts images into the format used by Badger2040.') +parser.add_argument('file', nargs="+", help='input files to convert') +parser.add_argument('--out_dir', type=Path, default=None, help='output directory') +parser.add_argument('--binary', action="store_true", help='output binary file for MicroPython') +parser.add_argument('--py', action="store_true", help='output .py file for MicroPython embedding') +parser.add_argument('--resize', action="store_true", help='force images to 296x128 pixels') + +options = parser.parse_args() + + +class ByteWriter(object): + bytes_per_line = 16 + + def __init__(self, stream, varname): + self.stream = stream + self.stream.write('{} =\\\n'.format(varname)) + self.bytecount = 0 # For line breaks + + def _eol(self): + self.stream.write("'\\\n") + + def _eot(self): + self.stream.write("'\n") + + def _bol(self): + self.stream.write("b'") + + # Output a single byte + def obyte(self, data): + if not self.bytecount: + self._bol() + self.stream.write('\\x{:02x}'.format(data)) + self.bytecount += 1 + self.bytecount %= self.bytes_per_line + if not self.bytecount: + self._eol() + + # Output from a sequence + def odata(self, bytelist): + for byt in bytelist: + self.obyte(byt) + + # ensure a correct final line + def eot(self): # User force EOL if one hasn't occurred + if self.bytecount: + self._eot() + self.stream.write('\n') + + +def convert_image(img): + if options.resize: + img = img.resize((296, 128)) # resize + try: + enhancer = ImageEnhance.Contrast(img) + img = enhancer.enhance(2.0) + except ValueError: + pass + img = img.convert("1") # convert to black and white + return img + + +def write_stream(header, footer, ip_stream, op_stream): + op_stream.write(header) + op_stream.write('\n') + data = ip_stream.read() + bw_data = ByteWriter(op_stream, '_data') + bw_data.odata(data) + bw_data.eot() + op_stream.write(footer) + + +# create map of images based on input filenames +for input_filename in options.file: + with Image.open(input_filename) as img: + img = convert_image(img) + + image_name = Path(input_filename).stem + + w, h = img.size + + output_data = [~b & 0xff for b in list(img.tobytes())] + + if options.binary: + if options.out_dir is not None: + output_filename = (options.out_dir / image_name).with_suffix(".bin") + else: + output_filename = Path(input_filename).with_suffix(".bin") + print(f"Saving to {output_filename}, {w}x{h}") + with open(output_filename, "wb") as out: + out.write(bytearray(output_data)) + elif options.py: + if options.out_dir is not None: + output_filename = (options.out_dir / image_name).with_suffix(".py") + else: + output_filename = Path(input_filename).with_suffix(".py") + print(f"Saving to {output_filename}, {w}x{h}") + with open(output_filename, "w") as out: + write_stream(PY_HEADER, PY_FOOTER, io.BytesIO(bytes(output_data)), out) + else: + image_code = '''\ +static const uint8_t {image_name}[{count}] = {{ + {byte_data} +}}; + '''.format(image_name=image_name, count=len(output_data), byte_data=", ".join(str(b) for b in output_data)) + + print(image_code) diff --git a/examples/badger2040w/image_converter/data_to_py.py b/examples/badger2040w/image_converter/data_to_py.py new file mode 100644 index 00000000..e5515f13 --- /dev/null +++ b/examples/badger2040w/image_converter/data_to_py.py @@ -0,0 +1,154 @@ +#! /usr/bin/python3 +# -*- coding: utf-8 -*- + +# The MIT License (MIT) +# +# Copyright (c) 2016 Peter Hinch +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import argparse +import sys +import os + +# UTILITIES FOR WRITING PYTHON SOURCECODE TO A FILE + +# ByteWriter takes as input a variable name and data values and writes +# Python source to an output stream of the form +# my_variable = b'\x01\x02\x03\x04\x05\x06\x07\x08'\ + +# Lines are broken with \ for readability. + + +class ByteWriter(object): + bytes_per_line = 16 + + def __init__(self, stream, varname): + self.stream = stream + self.stream.write('{} =\\\n'.format(varname)) + self.bytecount = 0 # For line breaks + + def _eol(self): + self.stream.write("'\\\n") + + def _eot(self): + self.stream.write("'\n") + + def _bol(self): + self.stream.write("b'") + + # Output a single byte + def obyte(self, data): + if not self.bytecount: + self._bol() + self.stream.write('\\x{:02x}'.format(data)) + self.bytecount += 1 + self.bytecount %= self.bytes_per_line + if not self.bytecount: + self._eol() + + # Output from a sequence + def odata(self, bytelist): + for byt in bytelist: + self.obyte(byt) + + # ensure a correct final line + def eot(self): # User force EOL if one hasn't occurred + if self.bytecount: + self._eot() + self.stream.write('\n') + + +# PYTHON FILE WRITING + +STR01 = """# Code generated by data_to_py.py. +version = '0.1' +""" + +STR02 = """_mvdata = memoryview(_data) + +def data(): + return _mvdata + +""" + + +def write_func(stream, name, arg): + stream.write('def {}():\n return {}\n\n'.format(name, arg)) + + +def write_data(op_path, ip_path): + try: + with open(ip_path, 'rb') as ip_stream: + try: + with open(op_path, 'w') as op_stream: + write_stream(ip_stream, op_stream) + except OSError: + print("Can't open", op_path, 'for writing') + return False + except OSError: + print("Can't open", ip_path) + return False + return True + + +def write_stream(ip_stream, op_stream): + op_stream.write(STR01) + op_stream.write('\n') + data = ip_stream.read() + bw_data = ByteWriter(op_stream, '_data') + bw_data.odata(data) + bw_data.eot() + op_stream.write(STR02) + + +# PARSE COMMAND LINE ARGUMENTS + +def quit(msg): + print(msg) + sys.exit(1) + + +DESC = """data_to_py.py +Utility to convert an arbitrary binary file to Python source. +Sample usage: +data_to_py.py image.jpg image.py + +""" + +if __name__ == "__main__": + parser = argparse.ArgumentParser(__file__, description=DESC, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('infile', type=str, help='Input file path') + parser.add_argument('outfile', type=str, + help='Path and name of output file. Must have .py extension.') + + args = parser.parse_args() + + if not os.path.isfile(args.infile): + quit("Data filename does not exist") + + if not os.path.splitext(args.outfile)[1].upper() == '.PY': + quit('Output filename must have a .py extension.') + + print('Writing Python file.') + if not write_data(args.outfile, args.infile): + sys.exit(1) + + print(args.outfile, 'written successfully.') diff --git a/examples/badger2040w/image_converter/test-images/adam.png b/examples/badger2040w/image_converter/test-images/adam.png new file mode 100644 index 0000000000000000000000000000000000000000..0ab424480bae61c7466a3fca3e79bc496448283b GIT binary patch literal 45400 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 BsYw6; literal 0 HcmV?d00001 diff --git a/examples/badger2040w/image_converter/test-images/iconsheet.png b/examples/badger2040w/image_converter/test-images/iconsheet.png new file mode 100644 index 0000000000000000000000000000000000000000..cba08d38f639178de5a80ec2def28215d2f8f0ef GIT binary patch literal 8325 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 QaAXaUlTwx}moN_gALNoqWdHyG literal 0 HcmV?d00001 diff --git a/examples/badger2040w/image_converter/test-images/paul.png b/examples/badger2040w/image_converter/test-images/paul.png new file mode 100644 index 0000000000000000000000000000000000000000..4015b41924b4aa691b907f38ab4a2bc379f9a430 GIT binary patch literal 49990 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
  • =&#!R%FB5@!LyH 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

    (hW?PZ=c*u^hKCVMn(E7w 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 Kc%`VJ|NjL>|Gv5a literal 0 HcmV?d00001 diff --git a/examples/badger2040w/image_converter/test-images/shaun.png b/examples/badger2040w/image_converter/test-images/shaun.png new file mode 100644 index 0000000000000000000000000000000000000000..1d80751a89a234357fa778aaed884939c48fbfeb GIT binary patch literal 47431 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 literal 0 HcmV?d00001 From b5f67b0426de3f2f894b4d53100d7464de6e125d Mon Sep 17 00:00:00 2001 From: kennedn Date: Mon, 19 Feb 2024 16:40:13 +0000 Subject: [PATCH 7/7] Revert changes to badger2040 library --- libraries/badger2040/badger2040.cpp | 494 +++++++++++++--------------- 1 file changed, 234 insertions(+), 260 deletions(-) diff --git a/libraries/badger2040/badger2040.cpp b/libraries/badger2040/badger2040.cpp index d74635d7..6be32b91 100644 --- a/libraries/badger2040/badger2040.cpp +++ b/libraries/badger2040/badger2040.cpp @@ -1,18 +1,18 @@ -#include "badger2040.hpp" - -#include #include +#include #include "hardware/pwm.h" #include "hardware/watchdog.h" +#include "badger2040.hpp" + namespace pimoroni { -void Badger2040::init() { + void Badger2040::init() { // set clock speed to 12MHz to reduce the maximum current draw on the // battery. when updating a small, monochrome, display only every few // seconds or so then you don't need much processing power anyway... - // set_sys_clock_khz(48000, true); + //set_sys_clock_khz(48000, true); gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO); gpio_set_dir(ENABLE_3V3, GPIO_OUT); @@ -50,12 +50,12 @@ void Badger2040::init() { uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); _wake_button_states |= gpio_get_all() & mask; - /* - // wait for button to be released before continuing - while(gpio_get_all() & mask) { - tight_loop_contents(); - } - */ +/* + // wait for button to be released before continuing + while(gpio_get_all() & mask) { + tight_loop_contents(); + } +*/ // led control pin pwm_config cfg = pwm_get_default_config(); @@ -67,9 +67,9 @@ void Badger2040::init() { uc8151_legacy.init(); // TODO: set default image? -} + } -void Badger2040::halt() { + void Badger2040::halt() { gpio_put(ENABLE_3V3, 0); // If running on USB we will not actually power down, so emulate the behaviour @@ -77,382 +77,356 @@ void Badger2040::halt() { // Note: Don't use wait_for_press as that waits for the button to be release and // we want the reboot to complete before the button is released. update_button_states(); - while (_button_states == 0) { - update_button_states(); + while(_button_states == 0) { + update_button_states(); } watchdog_reboot(0, 0, 0); -} + } -uint8_t _dither_value(int32_t x, int32_t y, uint8_t p) { + uint8_t _dither_value(int32_t x, int32_t y, uint8_t p) { // ordered dither matrix used in 4-bit mode static uint8_t _odm[16] = { - 0, 8, 2, 10, - 12, 4, 14, 6, - 3, 11, 1, 9, - 15, 7, 13, 5}; + 0, 8, 2, 10, + 12, 4, 14, 6, + 3, 11, 1, 9, + 15, 7, 13, 5 + }; if (p == 0) { - return 1; + return 1; } if (p == 15) { - return 0; + return 0; } // calculate dither matrix offset uint32_t dmo = (x & 0b11) | ((y & 0b11) << 2); return p <= _odm[dmo] ? 1 : 0; -} + } -// Return dither values for an entire byte in the column -uint8_t _dither_column_value(int32_t x, uint8_t p) { + // Return dither values for an entire byte in the column + uint8_t _dither_column_value(int32_t x, uint8_t p) { if (p == 0) { - return 0xff; + return 0xff; } if (p == 15) { - return 0; + return 0; } uint8_t val = 0; for (int32_t y = 0; y < 4; ++y) { - val |= _dither_value(x, y, p) << (7 - y); + val |= _dither_value(x, y, p) << (7 - y); } val |= val >> 4; return val; -} + } -void Badger2040::clear() { + + void Badger2040::clear() { const uint32_t column_len = 128 / 8; const uint32_t buf_len = column_len * 296; uint8_t* buf = uc8151_legacy.get_frame_buffer(); - + if (_pen == 0) { - memset(buf, 0xff, buf_len); - } else if (_pen == 15) { - memset(buf, 0, buf_len); - } else { - for (uint32_t x = 0; x < 296; x++) { - uint8_t val = _dither_column_value(x, _pen); - memset(buf, val, column_len); - buf += column_len; - } + memset(buf, 0xff, buf_len); } -} - -void Badger2040::pixel(int32_t x, int32_t y) { - if (_thickness == 1) { - uc8151_legacy.pixel(x, y, _dither_value(x, y, _pen)); - } else { - uint8_t ht = _thickness / 2; - for (int sy = 0; sy < _thickness; sy++) { - for (int sx = 0; sx < _thickness; sx++) { - uc8151_legacy.pixel(x + sx - ht, y + sy - ht, _dither_value(x + sx - ht, y + sy - ht, _pen)); - } - } + else if (_pen == 15) { + memset(buf, 0, buf_len); } -} + else { + for(uint32_t x = 0; x < 296; x++) { + uint8_t val = _dither_column_value(x, _pen); + memset(buf, val, column_len); + buf += column_len; + } + } + } -// Display a portion of an image (icon sheet) at dx, dy -void Badger2040::icon(const uint8_t* data, int sheet_width, int icon_size, int index, int dx, int dy) { + void Badger2040::pixel(int32_t x, int32_t y) { + if(_thickness == 1) { + uc8151_legacy.pixel(x, y, _dither_value(x, y, _pen)); + }else{ + uint8_t ht = _thickness / 2; + for(int sy = 0; sy < _thickness; sy++) { + for(int sx = 0; sx < _thickness; sx++) { + uc8151_legacy.pixel(x + sx - ht, y + sy - ht, _dither_value(x + sx - ht, y + sy - ht, _pen)); + } + } + } + } + + // Display a portion of an image (icon sheet) at dx, dy + void Badger2040::icon(const uint8_t *data, int sheet_width, int icon_size, int index, int dx, int dy) { image(data, sheet_width, icon_size * index, 0, icon_size, icon_size, dx, dy); -} + } -// Display an image that fills the screen (296*128) -void Badger2040::image(const uint8_t* data) { + // Display an image that fills the screen (296*128) + void Badger2040::image(const uint8_t* data) { uint8_t* ptr = uc8151_legacy.get_frame_buffer(); - + for (uint32_t x = 0; x < 296; ++x) { - // extract bitmask for this pixel - uint32_t bm = 0b10000000 >> (x & 0b111); - - for (uint32_t y = 0; y < 128; y += 8) { - uint8_t val = 0; - for (uint32_t cy = 0; cy < 8; ++cy) { - // work out byte offset in source data - uint32_t o = ((y + cy) * (296 >> 3)) + (x >> 3); - - // Set bit in val if set in source data - if (data[o] & bm) { - val |= 0b10000000 >> cy; - } - } - *ptr++ = val; + // extract bitmask for this pixel + uint32_t bm = 0b10000000 >> (x & 0b111); + + for (uint32_t y = 0; y < 128; y += 8) { + uint8_t val = 0; + for (uint32_t cy = 0; cy < 8; ++cy) { + // work out byte offset in source data + uint32_t o = ((y + cy) * (296 >> 3)) + (x >> 3); + + // Set bit in val if set in source data + if (data[o] & bm) { + val |= 0b10000000 >> cy; + } } + *ptr++ = val; + } } -} + } -// Display an image smaller than the screen (sw*sh) at dx, dy -void Badger2040::image(const uint8_t* data, int w, int h, int x, int y) { + // Display an image smaller than the screen (sw*sh) at dx, dy + void Badger2040::image(const uint8_t *data, int w, int h, int x, int y) { if (x == 0 && y == 0 && w == 296 && h == 128) { - image(data); - } else { - image(data, w, 0, 0, w, h, x, y); + image(data); } -} - -void Badger2040::image(const uint8_t* data, int stride, int sx, int sy, int dw, int dh, int dx, int dy) { - for (auto y = 0; y < dh; y++) { - for (auto x = 0; x < dw; x++) { - // work out byte offset in source data - uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3); - - // extract bitmask for this pixel - uint32_t bm = 0b10000000 >> ((x + sx) & 0b111); - - // draw the pixel - uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm); - } + else { + image(data, w, 0, 0, w, h, x, y); } -} + } -void Badger2040::rectangle(int32_t x, int32_t y, int32_t w, int32_t h) { + void Badger2040::image(const uint8_t *data, int stride, int sx, int sy, int dw, int dh, int dx, int dy) { + for(auto y = 0; y < dh; y++) { + for(auto x = 0; x < dw; x++) { + // work out byte offset in source data + uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3); + + // extract bitmask for this pixel + uint32_t bm = 0b10000000 >> ((x + sx) & 0b111); + + // draw the pixel + uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm); + } + } + } + + void Badger2040::rectangle(int32_t x, int32_t y, int32_t w, int32_t h) { // Adjust for thickness uint32_t ht = _thickness / 2; x -= ht; if (x < 0) { - w += x; - x = 0; + w += x; + x = 0; } y -= ht; if (y < 0) { - h += y; - y = 0; + h += y; + y = 0; } w += _thickness - 1; h += _thickness - 1; if (x + w > 296) { - w = 296 - x; + w = 296 - x; } if (y + h > 128) { - h = 128 - y; + h = 128 - y; } if (h >= 8) { - // Directly write to the frame buffer when clearing a large area - uint8_t* buf = uc8151_legacy.get_frame_buffer(); - - for (int cx = x; cx < x + w; cx++) { - uint8_t* buf_ptr = &buf[cx * 16 + y / 8]; - uint8_t first_mask = 0xff >> (y & 7); - uint8_t last_mask = 0xff >> ((y + h) & 7); - uint32_t val = _dither_column_value(cx, _pen); - *buf_ptr &= ~first_mask; - *buf_ptr++ |= (val & first_mask); - for (int32_t c = h - (8 - (y & 7)); c >= 8; c -= 8) { - *buf_ptr++ = val; - } - *buf_ptr &= last_mask; - *buf_ptr |= (val & (~last_mask)); + // Directly write to the frame buffer when clearing a large area + uint8_t* buf = uc8151_legacy.get_frame_buffer(); + + for(int cx = x; cx < x + w; cx++) { + uint8_t* buf_ptr = &buf[cx * 16 + y / 8]; + uint8_t first_mask = 0xff >> (y & 7); + uint8_t last_mask = 0xff >> ((y + h) & 7); + uint32_t val = _dither_column_value(cx, _pen); + *buf_ptr &= ~first_mask; + *buf_ptr++ |= (val & first_mask); + for (int32_t c = h - (8 - (y & 7)); c >= 8; c -= 8) { + *buf_ptr++ = val; } - } else { - for (int cx = x; cx < x + w; cx++) { - for (int cy = y; cy < y + h; cy++) { - uc8151_legacy.pixel(cx, cy, _dither_value(cx, cy, _pen)); - } + *buf_ptr &= last_mask; + *buf_ptr |= (val & (~last_mask)); + } + } + else { + for(int cx = x; cx < x + w; cx++) { + for(int cy = y; cy < y + h; cy++) { + uc8151_legacy.pixel(cx, cy, _dither_value(cx, cy, _pen)); } + } } -} + } -void Badger2040::line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - int32_t x = x1, y = y1, dx, dy, incx, incy, balance; + void Badger2040::line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + int32_t x = x1, y = y1, dx, dy, incx, incy, balance; - if (x2 >= x1) { - dx = x2 - x1; - incx = 1; + if(x2 >= x1) {dx = x2 - x1; incx = 1;} else {dx = x1 - x2; incx = -1;} + if(y2 >= y1) {dy = y2 - y1; incy = 1;} else {dy = y1 - y2; incy = -1;} + + if(dx >= dy) { + dy <<= 1; balance = dy - dx; dx <<= 1; + while(x != x2) { + pixel(x, y); + if (balance >= 0) {y += incy; balance -= dx;} + balance += dy; x += incx; + } } else { - dx = x1 - x2; - incx = -1; - } - if (y2 >= y1) { - dy = y2 - y1; - incy = 1; - } else { - dy = y1 - y2; - incy = -1; + dx <<= 1; balance = dx - dy; dy <<= 1; + while(y != y2) { + pixel(x, y); + if(balance >= 0) {x += incx; balance -= dy;} + balance += dx; y += incy; + } } + } - if (dx >= dy) { - dy <<= 1; - balance = dy - dx; - dx <<= 1; - while (x != x2) { - pixel(x, y); - if (balance >= 0) { - y += incy; - balance -= dx; - } - balance += dy; - x += incx; - } - } else { - dx <<= 1; - balance = dx - dy; - dy <<= 1; - while (y != y2) { - pixel(x, y); - if (balance >= 0) { - x += incx; - balance -= dy; - } - balance += dx; - y += incy; - } - } -} - -void Badger2040::debug_command(uint8_t reg, size_t len, const uint8_t* data) { + void Badger2040::debug_command(uint8_t reg, size_t len, const uint8_t *data) { uc8151_legacy.command(reg, len, data); -} + } -void Badger2040::dump_otp(uint8_t* data) { - uc8151_legacy.read(0xa2, 0xFFF, data); -} + void Badger2040::dump_otp(uint8_t *data) { + uc8151_legacy.read(0xa2, 0xFFF, data); + } -void Badger2040::update_button_states() { + void Badger2040::update_button_states() { uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << USER); _button_states = gpio_get_all() & mask; - _button_states ^= (1UL << USER); // USER button state is inverted -} + _button_states ^= (1UL << USER); // USER button state is inverted + } -uint32_t Badger2040::button_states() { + uint32_t Badger2040::button_states() { return _button_states; -} + } -bool Badger2040::is_busy() { + bool Badger2040::is_busy() { return uc8151_legacy.is_busy(); -} + } -void Badger2040::power_off() { + void Badger2040::power_off() { uc8151_legacy.power_off(); -} + } -void Badger2040::invert(bool invert) { + void Badger2040::invert(bool invert) { uc8151_legacy.invert(invert); -} + } -void Badger2040::update_speed(uint8_t speed) { + void Badger2040::update_speed(uint8_t speed) { uc8151_legacy.update_speed(speed); -} + } -uint32_t Badger2040::update_time() { + uint32_t Badger2040::update_time() { return uc8151_legacy.update_time(); -} + } -void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) { + void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) { uc8151_legacy.partial_update(x, y, w, h, blocking); -} + } -void Badger2040::update(bool blocking) { + void Badger2040::update(bool blocking) { uc8151_legacy.update(blocking); -} + } -const hershey::font_glyph_t* Badger2040::glyph_data(unsigned char c) { + const hershey::font_glyph_t* Badger2040::glyph_data(unsigned char c) { return hershey::glyph_data(_font, c); -} + } -int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) { + int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) { if (_bitmap_font) { - bitmap::character( - _bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { - for (auto px = 0; px < w; px++) { - for (auto py = 0; py < h; py++) { - pixel(x + px, y + py); - } - } - }, - c, x, y, std::max(1.0f, s)); - return 0; + bitmap::character(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { + for(auto px = 0; px < w; px++) { + for(auto py = 0; py < h; py++) { + pixel(x + px, y + py); + } + } + }, c, x, y, std::max(1.0f, s)); + return 0; } else { - return hershey::glyph( - _font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - line(x1, y1, x2, y2); - }, - c, x, y, s, a); + return hershey::glyph(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + line(x1, y1, x2, y2); + }, c, x, y, s, a); } -} + } -void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a, uint8_t letter_spacing) { + void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a, uint8_t letter_spacing) { if (_bitmap_font) { - bitmap::text( - _bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { - for (auto px = 0; px < w; px++) { - for (auto py = 0; py < h; py++) { - pixel(x + px, y + py); - } - } - }, - message, x, y, 296 - x, std::max(1.0f, s), letter_spacing); + bitmap::text(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) { + for(auto px = 0; px < w; px++) { + for(auto py = 0; py < h; py++) { + pixel(x + px, y + py); + } + } + }, message, x, y, 296 - x, std::max(1.0f, s), letter_spacing); } else { - hershey::text( - _font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - line(x1, y1, x2, y2); - }, - message, x, y, s, a); + hershey::text(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + line(x1, y1, x2, y2); + }, message, x, y, s, a); } -} + } -int32_t Badger2040::measure_text(std::string message, float s, uint8_t letter_spacing) { + int32_t Badger2040::measure_text(std::string message, float s, uint8_t letter_spacing) { if (_bitmap_font) return bitmap::measure_text(_bitmap_font, message, std::max(1.0f, s), letter_spacing); return hershey::measure_text(_font, message, s); -} + } -int32_t Badger2040::measure_glyph(unsigned char c, float s) { + int32_t Badger2040::measure_glyph(unsigned char c, float s) { if (_bitmap_font) return bitmap::measure_character(_bitmap_font, c, std::max(1.0f, s)); return hershey::measure_glyph(_font, c, s); -} + } -void Badger2040::font(std::string name) { + void Badger2040::font(std::string name) { if (name == "bitmap6") { - _bitmap_font = &font6; - _font = nullptr; + _bitmap_font = &font6; + _font = nullptr; } else if (name == "bitmap8") { - _bitmap_font = &font8; - _font = nullptr; + _bitmap_font = &font8; + _font = nullptr; } else if (name == "bitmap14_outline") { - _bitmap_font = &font14_outline; - _font = nullptr; + _bitmap_font = &font14_outline; + _font = nullptr; } else { - // check that font exists and assign it - if (hershey::fonts.find(name) != hershey::fonts.end()) { - _bitmap_font = nullptr; - _font = hershey::fonts[name]; - } + // check that font exists and assign it + if(hershey::fonts.find(name) != hershey::fonts.end()) { + _bitmap_font = nullptr; + _font = hershey::fonts[name]; + } } -} + } -void Badger2040::pen(uint8_t pen) { + void Badger2040::pen(uint8_t pen) { _pen = pen; -} + } -void Badger2040::thickness(uint8_t thickness) { + void Badger2040::thickness(uint8_t thickness) { _thickness = thickness; -} + } -void Badger2040::led(uint8_t brightness) { + void Badger2040::led(uint8_t brightness) { // set the led brightness from 1 to 256 with gamma correction float gamma = 2.8; uint16_t v = (uint16_t)(pow((float)(brightness) / 256.0f, gamma) * 65535.0f + 0.5f); pwm_set_gpio_level(LED, v); -} + } -bool Badger2040::pressed(uint8_t button) { + bool Badger2040::pressed(uint8_t button) { return (_button_states & (1UL << button)) != 0; -} + } -bool Badger2040::pressed_to_wake(uint8_t button) { + bool Badger2040::pressed_to_wake(uint8_t button) { return (_wake_button_states & (1UL << button)) != 0; -} + } -void Badger2040::wait_for_press() { + void Badger2040::wait_for_press() { update_button_states(); - while (_button_states == 0) { - update_button_states(); - tight_loop_contents(); + while(_button_states == 0) { + update_button_states(); + tight_loop_contents(); } uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E); - while (gpio_get_all() & mask) { - tight_loop_contents(); + while(gpio_get_all() & mask) { + tight_loop_contents(); } + } } -} // namespace pimoroni