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..840cd3e6 --- /dev/null +++ b/examples/badger2040w/CMakeLists.txt @@ -0,0 +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..9dc62702 --- /dev/null +++ b/examples/badger2040w/badger2040w_rtc.cmake @@ -0,0 +1,31 @@ +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) + +target_link_libraries(${OUTPUT_NAME} + badger2040w + hardware_spi + pico_cyw43_arch_lwip_threadsafe_background +) + +target_include_directories(badger2040w_rtc PRIVATE + ${CMAKE_CURRENT_LIST_DIR} +) + + +target_compile_definitions(badger2040w_rtc PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" +) + +# 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..d718656f --- /dev/null +++ b/examples/badger2040w/badger2040w_rtc.cpp @@ -0,0 +1,238 @@ +#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 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); + 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(); + + // Wait for next minute before redrawing + do { + rtc_get_datetime(&datetime); + } while(datetime.sec != 0); + } +} 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..4605e398 --- /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.uc8151->set_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.uc8151->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/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 00000000..0ab42448 Binary files /dev/null and b/examples/badger2040w/image_converter/test-images/adam.png differ 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 00000000..cba08d38 Binary files /dev/null and b/examples/badger2040w/image_converter/test-images/iconsheet.png differ 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 00000000..4015b419 Binary files /dev/null and b/examples/badger2040w/image_converter/test-images/paul.png differ 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 00000000..1d80751a Binary files /dev/null and b/examples/badger2040w/image_converter/test-images/shaun.png differ 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/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..a7c4d31e --- /dev/null +++ b/libraries/badger2040w/badger2040w.cmake @@ -0,0 +1,32 @@ +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() + +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) + +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 + pcf85063a + pico_graphics + pico_stdlib + hardware_pwm + pimoroni_i2c) diff --git a/libraries/badger2040w/badger2040w.cpp b/libraries/badger2040w/badger2040w.cpp new file mode 100644 index 00000000..66f24d84 --- /dev/null +++ b/libraries/badger2040w/badger2040w.cpp @@ -0,0 +1,152 @@ +#include +#include + +#include "hardware/pwm.h" +#include "hardware/watchdog.h" + +#include "pimoroni_i2c.hpp" +#include "badger2040w.hpp" + +namespace pimoroni { + + void Badger2040W::init() { + + 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); + + // 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) | (1UL << RTC); + _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); + + // 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() { + 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) | (1UL << RTC); + _button_states = gpio_get_all() & mask; + } + + uint32_t Badger2040W::button_states() { + return _button_states; + } + + 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 ? 0 : 15); + // draw the pixel + graphics->set_pixel(Point(x + rect.x, rect.y)); + } + } + + // 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); + 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); + } + + void Badger2040W::update() { + uc8151->update(graphics.get()); + } + + + 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) | (1UL << RTC); + 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..f4684651 --- /dev/null +++ b/libraries/badger2040w/badger2040w.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include + +#include "drivers/uc8151/uc8151.hpp" +#include "drivers/pcf85063a/pcf85063a.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" + +namespace pimoroni { + + class Badger2040W { + protected: + uint32_t _button_states = 0; + uint32_t _wake_button_states = 0; + private: + void imageRow(const uint8_t *data, Rect rect); + + public: + 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(); + void partial_update(Rect region); + void halt(); + + // 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(); + + 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 { + RTC = 8, + 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 + }; + + }; + +}