From 54ad59c77a164391bd76080fe5b61b862d36e2c2 Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 29 Jun 2022 08:54:30 +0100 Subject: [PATCH 01/42] Rebasing Galactic Unicorn branch to main --- examples/CMakeLists.txt | 1 + examples/galactic_unicorn/CMakeLists.txt | 10 + examples/galactic_unicorn/demo.cpp | 164 +++++++ libraries/CMakeLists.txt | 1 + libraries/galactic_unicorn/CMakeLists.txt | 12 + libraries/galactic_unicorn/README.md | 101 ++++ .../galactic_unicorn/galactic_unicorn.cmake | 12 + .../galactic_unicorn/galactic_unicorn.cpp | 434 ++++++++++++++++++ .../galactic_unicorn/galactic_unicorn.hpp | 37 ++ .../galactic_unicorn/galactic_unicorn.pio | 66 +++ 10 files changed, 838 insertions(+) create mode 100644 examples/galactic_unicorn/CMakeLists.txt create mode 100644 examples/galactic_unicorn/demo.cpp create mode 100644 libraries/galactic_unicorn/CMakeLists.txt create mode 100644 libraries/galactic_unicorn/README.md create mode 100644 libraries/galactic_unicorn/galactic_unicorn.cmake create mode 100644 libraries/galactic_unicorn/galactic_unicorn.cpp create mode 100644 libraries/galactic_unicorn/galactic_unicorn.hpp create mode 100644 libraries/galactic_unicorn/galactic_unicorn.pio diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c7de23d1..a02e6f2c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -55,3 +55,4 @@ add_subdirectory(servo2040) add_subdirectory(motor2040) add_subdirectory(inventor2040w) add_subdirectory(encoder) +add_subdirectory(galactic_unicorn) diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt new file mode 100644 index 00000000..c5d9167b --- /dev/null +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable( + galactic_unicorn_demo + demo.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) + +# create map/bin/hex file etc. +pico_add_extra_outputs(galactic_unicorn_demo) diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp new file mode 100644 index 00000000..c491e490 --- /dev/null +++ b/examples/galactic_unicorn/demo.cpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { + int w = graphics.measure_text(t, s); + p.x += (53 / 2) - (w / 2); + p.y += (11 / 2); + graphics.text(t, Point(p.x, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); + graphics.text(t, Point(p.x, p.y + 1), -1, s, a); +} + +struct star_t { + float dx, dy, x, y, a; + + uint8_t brightness() { + int b = a / 5; + return b > 15 ? 15 : b; + } +}; + +void init_star(star_t &s) { + s.x = ((rand() % 100) / 5.0f) - 10.0f; + s.y = ((rand() % 100) / 10.0f) - 5.0f; + + s.dx = s.x / 10.0f; + s.dy = s.y / 10.0f; + s.a = 0; +} + +void step_star(star_t &s) { + s.x += s.dx; + s.y += s.dy; + s.a++; + + if(s.a > 100) { + init_star(s); + } +} + + +int main() { + + uint8_t hue_map[53][3]; + for(int i = 0; i < 53; i++) { + from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); + } + + star_t stars[100]; + for(int i = 0; i < 100; i++) { + init_star(stars[i]); + stars[i].a = i; + } + +gpio_set_function(28, GPIO_FUNC_SIO); + gpio_set_dir(28, GPIO_OUT); + + for(int i = 0; i < 10; i++) { + gpio_put(28, !gpio_get(28)); + sleep_ms(100); + } + sleep_ms(1000); + + gpio_put(28,true); + + galactic_unicorn.init(); + +/* + bool a_pressed = false; + bool b_pressed = false; + bool x_pressed = false; + bool y_pressed = false; +*/ + graphics.set_font("sans"); + + + + uint i = 0; + int v = 255; + while(true) { + i++; + + graphics.set_pen(0, 0, 0); + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} + graphics.clear(); + + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} + + + for(int i = 0; i < 100; i++) { + star_t &star = stars[i]; + step_star(star); + + uint b = star.brightness(); + graphics.set_pen(b, b, b); + graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2))); + } + +graphics.set_pen(255, 255, 255); + float s = 1.0f;//0.65f + (sin(i / 25.0f) * 0.15f); + float a = 1.0f;// (sin(i / 25.0f) * 100.0f); + float x = (sin(i / 25.0f) * 40.0f) * s; + float y = (cos(i / 15.0f) * 10.0f) * s; + text("Galactic", Point(x, y), s, a); + + uint16_t *p = (uint16_t *)graphics.frame_buffer; + for(size_t i = 0; i < 53 * 11; i++) { + int x = i % 53; + int y = i / 53; + uint r = ((*p & 0b1111100000000000) >> 11) << 3; + uint g = ((*p & 0b0000011111100000) >> 5) << 2; + uint b = ((*p & 0b0000000000011111) >> 0) << 3; + p++; + + if(r > 200 && g > 200 && b > 200) { + r = hue_map[x][0]; + g = hue_map[x][1]; + b = hue_map[x][2]; + } + galactic_unicorn.set_pixel(x, y, r, g, b); + } + + + sleep_ms(10); + } + + + + printf("done\n"); + + return 0; +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index b7fa264f..ab4a1473 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -35,3 +35,4 @@ add_subdirectory(inventor2040w) add_subdirectory(adcfft) add_subdirectory(jpegdec) add_subdirectory(inky_frame) +add_subdirectory(galactic_unicorn) diff --git a/libraries/galactic_unicorn/CMakeLists.txt b/libraries/galactic_unicorn/CMakeLists.txt new file mode 100644 index 00000000..1322707e --- /dev/null +++ b/libraries/galactic_unicorn/CMakeLists.txt @@ -0,0 +1,12 @@ +add_library(galactic_unicorn INTERFACE) + +pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) + +target_sources(galactic_unicorn INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp +) + +target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(galactic_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) diff --git a/libraries/galactic_unicorn/README.md b/libraries/galactic_unicorn/README.md new file mode 100644 index 00000000..c568977e --- /dev/null +++ b/libraries/galactic_unicorn/README.md @@ -0,0 +1,101 @@ +# Galactic Unicorn + +Galactic Unicorn offers 53x11 7x17 bright RGB LEDs driven by Pico W's PIO in addition to a 1W amplifier and speaker. + +Galactic Unicorn uses SM0 of PIO0. + +TODO: Update documentation + +We've included helper functions to handle every aspect of drawing to the display and interfacing with the buttons. See the [function reference](#function-reference) for details. + +- [Example Program](#example-program) +- [Reference](#reference) + - [Constants](#constants) + - [Buttons](#buttons) + - [WIDTH / HEIGHT](#width--height) + - [Functions](#functions) + - [init](#init) + - [set_pixel](#set_pixel) + - [is_pressed](#is_pressed) + +## Example Program + +The following example sets up Pico Unicorn, displays some basic demo text and graphics and will illuminate the RGB LED green if the A button is presse + +```c++ + +``` + +## Reference + +### Constants + +#### Buttons + +The four buttons, A, B, X and Y have correponding constants set to their respective GPIO pins. For example: + +```c++ +bool a_is_pressed = pico_unicorn.is_pressed(pico_unicorn.A); +``` + +#### WIDTH / HEIGHT + +The width and height of Pico Unicorn are available in constants `WIDTH` and `HEIGHT`. + +For example: + +```c++ +int num_pixels = pico_unicorn.WIDTH * pico_unicorn.HEIGHT; +``` + +### Functions + +#### init + +Sets up Pico Unicorn. `init` must be called before any other functions since it configures the PIO and require GPIO inputs. Just call `init()` like so: + +```c++ +PicoUnicorn pico_unicorn; +pico_unicorn.init(); +``` + +#### set_pixel + +```c++ +void set_pixel(uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b); +void set_pixel(uint8_t x, uint8_t y, uint8_t v); +``` + +Sets an RGB LED on Pico Unicorn with an RGB triplet: + +```c++ +pico_unicorn.set_pixel(x, y, r, g, b); +``` + +Uses hardware PWM to drive the LED. Values are automatically gamma-corrected to provide smooth brightness transitions and low values may map as "off." + +Alternatively you can use: + +```c++ +pico_unicorn.set_pixel(x, y, v); +``` + +Which sets the R, G and B elements of the pixel to the same value- lighting it up white at your chosen intensity. + +#### is_pressed + +```c++ +bool is_pressed(uint8_t button); +``` + +Reads the GPIO pin connected to one of Pico Unicorn's buttons, returning a `bool` - `true` if it's pressed and `false` if it is released. + +```c++ +pico_unicorn.is_pressed(button); +``` + +The button vaule should be a `uint8_t` denoting a pin, and constants `A`, `B`, `X` and `Y` are supplied to make it easier. e: + +```c++ +bool is_a_button_pressed = pico_unicorn.is_pressed(PicoUnicorn::A) +``` \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.cmake b/libraries/galactic_unicorn/galactic_unicorn.cmake new file mode 100644 index 00000000..fd2a3c5c --- /dev/null +++ b/libraries/galactic_unicorn/galactic_unicorn.cmake @@ -0,0 +1,12 @@ +add_library(pico_unicorn INTERFACE) + +pico_generate_pio_header(pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.pio) + +target_sources(pico_unicorn INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.cpp +) + +target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp new file mode 100644 index 00000000..37b6ef7a --- /dev/null +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -0,0 +1,434 @@ +#include + +#include "hardware/dma.h" +#include "hardware/irq.h" + +#include "galactic_unicorn.pio.h" +#include "galactic_unicorn.hpp" + +// pixel data is stored as a stream of bits delivered in the +// order the PIO needs to manage the shift registers, row +// selects, delays, and latching/blanking +// +// the data consists of 11 rows each of which has 14 frames of +// bcd timing data +// +// bits are output in order: +// +// ROW_CLEAR, ROW_DATA1, ROW_DATA0, LED_BLANK, LED_LATCH, LED_CLOCK, LED_DATA0, LED_DATA1 +// +// the data is structured like this: +// +// loop through the eleven rows of the display... +// +// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) +// 00000000 00000000 00000000 // dummy bytes to align to dwords +// +// within this row we loop through the 14 bcd frames for this row... +// +// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high +// 162: 10011000 // LATCH pixel data +// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) +// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) +// 166: 10010000 // turn BLANK back on +// 167: 00000000 // dummy byte to ensure dword aligned +// +// .. and back to the start + +/* +enum pin { + LED_DATA = 8, + LED_CLOCK = 9, + LED_LATCH = 10, + LED_BLANK = 11, + ROW_0 = 22, + ROW_1 = 21, + ROW_2 = 20, + ROW_3 = 19, + ROW_4 = 18, + ROW_5 = 17, + ROW_6 = 16, + A = 12, + B = 13, + X = 14, + Y = 15, +};*/ + +enum pin { + LED_DATA1 = 12, + LED_DATA0 = 13, + LED_CLOCK = 14, + LED_LATCH = 15, + LED_BLANK = 16, + + ROW_DATA0 = 17, + ROW_DATA1 = 18, + ROW_CLEAR = 19, + ROW_CLOCK = 20, + + SWITCH_A = 0, + SWITCH_B = 1, + SWITCH_C = 3, + SWITCH_D = 6, + SWITCH_E = 2, + SWITCH_VOLUME_UP = 21, + SWITCH_VOLUME_DOWN = 26, + SWITCH_BRIGHTNESS_UP = 7, + SWITCH_BRIGHTNESS_DOWN = 8 +}; + + + +constexpr uint32_t ROW_COUNT = 11; +constexpr uint32_t ROW_BYTES = 4; +constexpr uint32_t ROW_FRAME_BYTES = 168; +constexpr uint32_t BCD_FRAMES = 15; // includes fet discharge frame +constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES + ROW_COUNT * ROW_FRAME_BYTES * BCD_FRAMES); + +// must be aligned for 32bit dma transfer +alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0}; + +static uint16_t r_gamma_lut[256] = {0}; +static uint16_t g_gamma_lut[256] = {0}; +static uint16_t b_gamma_lut[256] = {0}; + +static uint32_t dma_channel; + +static inline void unicorn_jetpack_program_init(PIO pio, uint sm, uint offset) { + pio_gpio_init(pio, pin::LED_DATA1); + pio_gpio_init(pio, pin::LED_DATA0); + pio_gpio_init(pio, pin::LED_CLOCK); + pio_gpio_init(pio, pin::LED_LATCH); + pio_gpio_init(pio, pin::LED_BLANK); + + pio_gpio_init(pio, pin::ROW_DATA0); + pio_gpio_init(pio, pin::ROW_DATA1); + pio_gpio_init(pio, pin::ROW_CLEAR); + pio_gpio_init(pio, pin::ROW_CLOCK); + + pio_sm_set_consecutive_pindirs(pio, sm, pin::LED_DATA1, 5, true); + pio_sm_set_consecutive_pindirs(pio, sm, pin::ROW_DATA0, 4, true); + + pio_sm_config c = galactic_unicorn_program_get_default_config(offset); + + // osr shifts right, autopull on, autopull threshold 8 + sm_config_set_out_shift(&c, true, false, 32); + + // configure out, set, and sideset pins + sm_config_set_out_pins(&c, pin::LED_DATA1, 8); + sm_config_set_sideset_pins(&c, pin::ROW_CLOCK); + + // join fifos as only tx needed (gives 8 deep fifo instead of 4) + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); + ///pio_sm_set_clkdiv(pio, sm, 4.0f); +} + +namespace pimoroni { + + // once the dma transfer of the scanline is complete we move to the + // next scanline (or quit if we're finished) + void __isr dma_complete() { + if (dma_hw->ints0 & (1u << dma_channel)) { + dma_hw->ints0 = (1u << dma_channel); // clear irq flag + dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); + dma_channel_set_read_addr(dma_channel, bitstream, true); + } + } + + GalacticUnicorn::~GalacticUnicorn() { + // stop and release the dma channel + irq_set_enabled(DMA_IRQ_0, false); + dma_channel_set_irq0_enabled(dma_channel, false); + irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); + irq_remove_handler(DMA_IRQ_0, dma_complete); + + dma_channel_wait_for_finish_blocking(dma_channel); + dma_channel_unclaim(dma_channel); + + // release the pio and sm + pio_sm_unclaim(bitstream_pio, bitstream_sm); + pio_clear_instruction_memory(bitstream_pio); + pio_sm_restart(bitstream_pio, bitstream_sm); + } + + void GalacticUnicorn::init() { + // todo: shouldn't need to do this if things were cleaned up properly but without + // this any attempt to run a micropython script twice will fail + static bool already_init = false; + + // setup pins + gpio_init(pin::LED_DATA0); gpio_set_dir(pin::LED_DATA0, GPIO_OUT); + gpio_init(pin::LED_DATA1); gpio_set_dir(pin::LED_DATA1, GPIO_OUT); + gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT); + gpio_init(pin::LED_LATCH); gpio_set_dir(pin::LED_LATCH, GPIO_OUT); + gpio_init(pin::LED_BLANK); gpio_set_dir(pin::LED_BLANK, GPIO_OUT); + + gpio_init(pin::ROW_DATA0); gpio_set_dir(pin::ROW_DATA0, GPIO_OUT); + gpio_init(pin::ROW_DATA1); gpio_set_dir(pin::ROW_DATA1, GPIO_OUT); + gpio_init(pin::ROW_CLEAR); gpio_set_dir(pin::ROW_CLEAR, GPIO_OUT); + gpio_init(pin::ROW_CLOCK); gpio_set_dir(pin::ROW_CLOCK, GPIO_OUT); + + // create 14-bit gamma luts + for(uint16_t v = 0; v < 256; v++) { + // gamma correct the provided 0-255 brightness value onto a + // 0-65535 range for the pwm counter + float r_gamma = 2.8f; + r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * 16383.0f + 0.5f); + + float g_gamma = 2.8f; + g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * 16383.0f + 0.5f); + + float b_gamma = 2.8f; + b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * 16383.0f + 0.5f); + } + +// the data is structured like this: +// +// loop through the eleven rows of the display... +// +// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) +// 00000000 00000000 00000000 // dummy bytes to align to dwords +// +// within this row we loop through the 14 bcd frames for this row... +// +// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high +// 162: 10011000 // LATCH pixel data +// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) +// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) +// 166: 10010000 // turn BLANK back on +// 167: 00000000 // dummy byte to ensure dword aligned +// +// .. and back to the start + + // initialise the bcd timing values and row selects in the bitstream + for(uint8_t row = 0; row < HEIGHT; row++) { + uint16_t row_offset = row * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); + + // setup row select on rows 0 and 8 + uint8_t row_select = row == 0 ? 0b10111000 : (row == 8 ? 0b11011000 : 0b10011000); + bitstream[row_offset + 0] = row_select; + + for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { + uint16_t frame_offset = row_offset + ROW_BYTES + (ROW_FRAME_BYTES * frame); + + bitstream[frame_offset + 162] = 0b10011000; // LATCH pixel data + bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs + + // set the number of bcd ticks for this frame + uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 65535 : 1 << frame; + bitstream[frame_offset + 164] = (bcd_ticks & 0xff); + bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8; + + bitstream[frame_offset + 166] = 0b10010000; // BLANK high again to disable outputs + + // setup empty pixels with BLANK high and a clock pulse + for(uint8_t col = 0; col < 162; col += 2) { + bitstream[frame_offset + col + 0] = 0b10010000; + bitstream[frame_offset + col + 1] = 0b10010100; + } + +/* + uint16_t row_select_offset = offset + 164; + uint16_t bcd_offset = offset + 165; + + // the last bcd frame is used to allow the fets to discharge to avoid ghosting + if(frame == BCD_FRAMES - 1) { + uint16_t bcd_ticks = 65535; + bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; + bitstream[bcd_offset] = (bcd_ticks & 0xff); + }else{ + uint8_t row_select = row == 0 ? 0b01000000 : (row == 8 ? 0b00100000 : 0b00000000); + bitstream[row_select_offset] = row_select; + + uint16_t bcd_ticks = 1 << frame; + bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; + bitstream[bcd_offset] = (bcd_ticks & 0xff); + }*/ + } +/* + for(size_t i = 0; i < sizeof(bitstream); i++) { + bitstream[i] = 0b11100000; + }*/ + } + + // setup button inputs + gpio_set_function(pin::SWITCH_A, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_A, GPIO_IN); gpio_pull_up(pin::SWITCH_A); + gpio_set_function(pin::SWITCH_B, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_B, GPIO_IN); gpio_pull_up(pin::SWITCH_B); + gpio_set_function(pin::SWITCH_C, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_C, GPIO_IN); gpio_pull_up(pin::SWITCH_C); + gpio_set_function(pin::SWITCH_D, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_D, GPIO_IN); gpio_pull_up(pin::SWITCH_D); + gpio_set_function(pin::SWITCH_E, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_E, GPIO_IN); gpio_pull_up(pin::SWITCH_E); + + gpio_set_function(pin::SWITCH_BRIGHTNESS_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_UP); + gpio_set_function(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_DOWN); + + gpio_set_function(pin::SWITCH_VOLUME_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_UP); + gpio_set_function(pin::SWITCH_VOLUME_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_DOWN); + + if(already_init) { + // stop and release the dma channel + irq_set_enabled(DMA_IRQ_0, false); + dma_channel_abort(dma_channel); + dma_channel_wait_for_finish_blocking(dma_channel); + + dma_channel_set_irq0_enabled(dma_channel, false); + irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); + irq_remove_handler(DMA_IRQ_0, dma_complete); + + dma_channel_unclaim(dma_channel); + + // release the pio and sm + pio_sm_unclaim(bitstream_pio, bitstream_sm); + pio_clear_instruction_memory(bitstream_pio); + pio_sm_restart(bitstream_pio, bitstream_sm); + //return; + } + + // setup the pio + bitstream_pio = pio0; + bitstream_sm = pio_claim_unused_sm(pio0, true); + sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); + unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset); + + // setup dma transfer for pixel data to the pio + dma_channel = dma_claim_unused_channel(true); + dma_channel_config config = dma_channel_get_default_config(dma_channel); + channel_config_set_transfer_data_size(&config, DMA_SIZE_32); + channel_config_set_bswap(&config, false); // byte swap to reverse little endian + channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true)); + dma_channel_configure(dma_channel, &config, &bitstream_pio->txf[bitstream_sm], NULL, 0, false); + dma_channel_set_irq0_enabled(dma_channel, true); + irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), true); + irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); + irq_set_enabled(DMA_IRQ_0, true); + + dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); + dma_channel_set_read_addr(dma_channel, bitstream, true); + + already_init = true; + } + + void GalacticUnicorn::clear() { + for(uint8_t y = 0; y < HEIGHT; y++) { + for(uint8_t x = 0; x < WIDTH; x++) { + set_pixel(x, y, 0); + } + } + } + + void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { + + + if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; + + // make those coordinates sane + x = (WIDTH - 1) - x; + y = (HEIGHT - 1) - y; + + // determine offset in the buffer for this row + uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); + + uint16_t bits[3] = {r_gamma_lut[r], g_gamma_lut[g], b_gamma_lut[b]}; + //uint16_t gr = r_gamma_lut[r]; + //uint16_t gg = g_gamma_lut[g]; + //uint16_t gb = b_gamma_lut[b]; + + // set the appropriate bits in the separate bcd frames + for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { + uint16_t frame_offset = (ROW_FRAME_BYTES * frame) + 4; + uint16_t offset = row_offset + frame_offset;// + byte_offset; + +// loop through the eleven rows of the display... +// +// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) +// 00000000 00000000 00000000 // dummy bytes to align to dwords +// +// within this row we loop through the 14 bcd frames for this row... +// +// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high +// 162: 10011000 // LATCH pixel data +// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) +// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) +// 166: 10010000 // turn BLANK back on +// 167: 00000000 // dummy byte to ensure dword aligned +// +// .. and back to the start + + // work out the byte offset of this pixel + /*if(bit_offset >= 160) { + bit_offset -= 160; + }*/ + + for(int bit = 0; bit < 3; bit++) { + int16_t bit_offset = x * 6 + 4 + (bit * 2); + + + uint8_t bit_position = bit_offset >= 160 ? 1 : 0; + uint8_t mask = 0b1 << bit_position; + uint8_t value = (bits[bit] & 0b1) << bit_position; + + bitstream[offset + (bit_offset % 160) + 0] &= ~mask; + bitstream[offset + (bit_offset % 160) + 0] |= value; + bitstream[offset + (bit_offset % 160) + 1] &= ~mask; + bitstream[offset + (bit_offset % 160) + 1] |= value; + + //bit_offset += 2; + bits[bit] >>= 1; + } + /* // setup pixel data and matching mask + uint8_t bit_position = x >= 26 ? 1 : 0; + uint8_t mask = 0b1 << bit_position; + uint8_t red = (gr & 0b1) << bit_position; + uint8_t green = (gg & 0b1) << bit_position; + uint8_t blue = (gb & 0b1) << bit_position; + + // clear existing data and set new data + bitstream[offset + 0] &= ~mask; + bitstream[offset + 0] |= red; + bitstream[offset + 1] &= ~mask; + bitstream[offset + 1] |= red; + bitstream[offset + 2] &= ~mask; + bitstream[offset + 2] |= green; + bitstream[offset + 3] &= ~mask; + bitstream[offset + 3] |= green; + bitstream[offset + 4] &= ~mask; + bitstream[offset + 4] |= blue; + bitstream[offset + 5] &= ~mask; + bitstream[offset + 5] |= blue;*/ +/* + + uint8_t mask = 0b11; + uint8_t red = ((gr & 0b1) << 1) | (gr & 0b1) ; + uint8_t green = ((gg & 0b1) << 1) | (gg & 0b1) ; + uint8_t blue = ((gb & 0b1) << 1) | (gb & 0b1) ; + + bitstream[offset + 0] &= ~mask; + bitstream[offset + 0] |= red; + bitstream[offset + 1] &= ~mask; + bitstream[offset + 1] |= red; + bitstream[offset + 2] &= ~mask; + bitstream[offset + 2] |= green; + bitstream[offset + 3] &= ~mask; + bitstream[offset + 3] |= green; + bitstream[offset + 4] &= ~mask; + bitstream[offset + 4] |= blue; + bitstream[offset + 5] &= ~mask; + bitstream[offset + 5] |= blue; +*/ + /* gr >>= 1; + gg >>= 1; + gb >>= 1;*/ + } + } + + void GalacticUnicorn::set_pixel(int x, int y, uint8_t v) { + set_pixel(x, y, v, v, v); + } + + bool GalacticUnicorn::is_pressed(uint8_t button) { + return !gpio_get(button); + } + +} diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp new file mode 100644 index 00000000..768977f9 --- /dev/null +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "hardware/pio.h" + +namespace pimoroni { + + class GalacticUnicorn { + public: + static const int WIDTH = 53; + static const int HEIGHT = 11; + static const uint8_t SWITCH_A = 0; + static const uint8_t SWITCH_B = 1; + static const uint8_t SWITCH_C = 3; + static const uint8_t SWITCH_D = 6; + static const uint8_t SWITCH_E = 2; + static const uint8_t SWITCH_VOLUME_UP = 21; + static const uint8_t SWITCH_VOLUME_DOWN = 26; + static const uint8_t SWITCH_BRIGHTNESS_UP = 7; + static const uint8_t SWITCH_BRIGHTNESS_DOWN = 8; + + private: + PIO bitstream_pio = pio0; + uint bitstream_sm = 0; + uint sm_offset = 0; + public: + ~GalacticUnicorn(); + + void init(); + + void clear(); + void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b); + void set_pixel(int x, int y, uint8_t v); + + bool is_pressed(uint8_t button); + }; + +} \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.pio b/libraries/galactic_unicorn/galactic_unicorn.pio new file mode 100644 index 00000000..a843cc58 --- /dev/null +++ b/libraries/galactic_unicorn/galactic_unicorn.pio @@ -0,0 +1,66 @@ +.program galactic_unicorn +.side_set 1 opt + +; out pins: +; 0: data1 (base) +; 1: data0 +; 2: clock +; 3: latch +; 4: blank +; 5: row1 +; 6: row2 +; 7: row_clear + + +; sideset pin: row_clock + +.wrap_target + + +; set row select pins + pull + out pins, 8 side 0 [4] + nop side 1 [4] ; pulse row select clock + out null, 24 ; discard dummy data + +; loop for bcd frames + set x, 14 +bcd_frame: + +; clock out 53 pixels worth of data - two pixels at a time, so 27 (actually 26.5) bits of data + set y, 26 ; 26 because `jmp` test is pre decrement + +pixels: + + pull ifempty + out pins, 8 [1] ; two red bits.. + out pins, 8 [1] ; ..with clock pulse + + pull ifempty + out pins, 8 [1] ; two green bits.. + out pins, 8 [1] ; ..with green pulse + + pull ifempty + out pins, 8 [1] ; two blue bits.. + out pins, 8 [1] ; ..with blue pulse + + jmp y-- pixels + + out pins, 8 ; LATCH pixel data + out pins, 8 ; turn off BLANK signal + + pull + +; pull bcd tick count into x register + out y, 16 + +bcd_count: + jmp y-- bcd_count ; loop until bcd delay complete + +; disable led output (blank) and clear latch pin + out pins, 8 ; turn off BLANK signal and clear row output + out null, 8 ; discard dummy data + + jmp x-- bcd_frame ; loop to next bcd frame + +.wrap \ No newline at end of file From 210b334fff106d8d0cb7ca200119358e37bcf0a3 Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 29 Jun 2022 21:45:25 +0100 Subject: [PATCH 02/42] more stuff --- examples/galactic_unicorn/CMakeLists.txt | 13 + examples/galactic_unicorn/demo.cpp | 70 +- examples/galactic_unicorn/demo2.cpp | 178 +++++ examples/galactic_unicorn/okcolor.hpp | 684 ++++++++++++++++++ .../galactic_unicorn/galactic_unicorn.cpp | 4 +- 5 files changed, 943 insertions(+), 6 deletions(-) create mode 100644 examples/galactic_unicorn/demo2.cpp create mode 100644 examples/galactic_unicorn/okcolor.hpp diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index c5d9167b..60165650 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -8,3 +8,16 @@ target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dm # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo) + + + +add_executable( + galactic_unicorn_demo2 + demo2.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) + +# create map/bin/hex file etc. +pico_add_extra_outputs(galactic_unicorn_demo2) diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index c491e490..517c2d68 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -5,6 +5,7 @@ #include "libraries/pico_graphics/pico_graphics.hpp" #include "galactic_unicorn.hpp" +#include "okcolor.hpp" using namespace pimoroni; @@ -106,10 +107,71 @@ gpio_set_function(28, GPIO_FUNC_SIO); - uint i = 0; - int v = 255; + //uint i = 0; + //int v = 255; + + float hue_offset = 0.0f; + float brightness = 0.5f; + float curve = 4.0f; + while(true) { - i++; + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { + hue_offset += 0.05; + if(hue_offset > 1.0f) hue_offset = 1.0f; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { + hue_offset -= 0.05; + if(hue_offset < 0.0f) hue_offset = 0.0f; + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + brightness += 0.05; + if(brightness > 1.0f) brightness = 1.0f; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + brightness -= 0.05; + if(brightness < 0.0f) brightness = 0.0f; + } + + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + curve += 0.5; + if(curve > 100.0f) curve = 100.0f; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + curve -= 0.5; + if(curve < 0.5) curve = 0.5; + } + + for(int y = 0; y < 11; y++) { + for(int x = 0; x < 53; x++) { + float fx = x / 53.0f; + float fy = (y / 11.0f) - 0.5f; + float twopi = M_PI * 2; + float hue = fy + (sin(fx * twopi / curve)); + float fade = 1.0f; + /* if(hue < 0.0f) { + fade += (hue * 10.0f); + if(fade < 0.0f) fade = 0.0f; + } + if(hue > 1.0f) { + fade -= ((hue - 1.0f) * 10.0f); + if(fade < 0.0f) fade = 0.0f; + }*/ + + hue += hue_offset; + while(hue < 0.0f) {hue += 1.0f;} + while(hue > 1.0f) {hue -= 1.0f;} + hue = 1.0f - hue; +/* + uint8_t r = 0, g = 0, b = 0; + from_hsv(hue, 1.0f, brightness * fade, r, g, b);*/ + ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade}; + ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); + galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f); + } + } + /*i++; graphics.set_pen(0, 0, 0); if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} @@ -151,7 +213,7 @@ graphics.set_pen(255, 255, 255); } galactic_unicorn.set_pixel(x, y, r, g, b); } - +*/ sleep_ms(10); } diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp new file mode 100644 index 00000000..ce06cec1 --- /dev/null +++ b/examples/galactic_unicorn/demo2.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { + int w = graphics.measure_text(t, s); + p.x += (53 / 2) - (w / 2); + p.y += (11 / 2); + graphics.text(t, Point(p.x, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); + graphics.text(t, Point(p.x, p.y + 1), -1, s, a); +} + +struct star_t { + float dx, dy, x, y, a; + + uint8_t brightness() { + int b = a / 5; + return b > 15 ? 15 : b; + } +}; + +void init_star(star_t &s) { + s.x = ((rand() % 100) / 5.0f) - 10.0f; + s.y = ((rand() % 100) / 10.0f) - 5.0f; + + s.dx = s.x / 10.0f; + s.dy = s.y / 10.0f; + s.a = 0; +} + +void step_star(star_t &s) { + s.x += s.dx; + s.y += s.dy; + s.a++; + + if(s.a > 100) { + init_star(s); + } +} + +void number(int n, int x, int y) { + switch(n) { + case 6: { + graphics.rectangle(Rect(x, y, 6, 2)); + graphics.rectangle(Rect(x, y + 4, 6, 2)); + graphics.rectangle(Rect(x, y + 9, 6, 2)); + graphics.rectangle(Rect(x, y, 2, 11)); + graphics.rectangle(Rect(x + 4, y + 4, 2, 5)); + }break; + + case 9: { + graphics.rectangle(Rect(x, y, 6, 2)); + graphics.rectangle(Rect(x, y + 4, 6, 2)); + graphics.rectangle(Rect(x, y + 9, 6, 2)); + graphics.rectangle(Rect(x + 4, y, 2, 11)); + graphics.rectangle(Rect(x, y, 2, 5)); + }break; + + case 4: { + graphics.rectangle(Rect(x, y + 4, 6, 2)); + graphics.rectangle(Rect(x + 4, y, 2, 11)); + graphics.rectangle(Rect(x, y, 2, 5)); + }break; + + case 0: { + graphics.rectangle(Rect(x, y, 6, 2)); + graphics.rectangle(Rect(x + 4, y, 2, 11)); + graphics.rectangle(Rect(x, y, 2, 11)); + graphics.rectangle(Rect(x, y + 9, 6, 2)); + }break; + } +} + +int main() { + + galactic_unicorn.init(); + + // graphics.set_font("sans"); + + + while(true) { + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + } + + graphics.set_pen(0, 0, 0); + graphics.clear(); + graphics.set_pen(200, 200, 0); + number(6, 23, 0); + number(9, 31, 0); + number(4, 39, 0); + number(0, 47, 0); + + graphics.set_pen(200, 0, 0); + graphics.circle(Point(8, 5), 6); + + graphics.set_pen(255, 255, 255); + std::vector triangle = {Point(5, 2), Point(10, 5), Point(5, 7)}; + graphics.polygon(triangle); + + + graphics.set_pen(255, 0, 0); + graphics.rectangle(Rect(0, 0, 10, 11)); + graphics.set_pen(0, 255, 0); + graphics.rectangle(Rect(10, 0, 10, 11)); + graphics.set_pen(0, 0, 255); + graphics.rectangle(Rect(20, 0, 10, 11)); + + uint16_t *p = (uint16_t *)graphics.frame_buffer; + for(size_t i = 0; i < 53 * 11; i++) { + int x = i % 53; + int y = i / 53; + /* uint r = ((*p & 0b0111110000000000) >> 10) << 3; + uint g = ((*p & 0b0000001111100000) >> 5) << 3; + uint b = ((*p & 0b0000000000011111) >> 0) << 3;*/ + p++; + +/* if(r > 200 && g > 200 && b > 200) { + r = hue_map[x][0]; + g = hue_map[x][1]; + b = hue_map[x][2]; + }*/ + galactic_unicorn.set_pixel(x, y, 0, 0, 255); + } + + + sleep_ms(10); + } + + + + printf("done\n"); + + return 0; +} diff --git a/examples/galactic_unicorn/okcolor.hpp b/examples/galactic_unicorn/okcolor.hpp new file mode 100644 index 00000000..2ea021d6 --- /dev/null +++ b/examples/galactic_unicorn/okcolor.hpp @@ -0,0 +1,684 @@ +#pragma once +// Copyright(c) 2021 Björn Ottosson +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this softwareand 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 noticeand 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. + +#include +#include + +namespace ok_color +{ + +struct Lab { float L; float a; float b; }; +struct RGB { float r; float g; float b; }; +struct HSV { float h; float s; float v; }; +struct HSL { float h; float s; float l; }; +struct LC { float L; float C; }; + +// Alternative representation of (L_cusp, C_cusp) +// Encoded so S = C_cusp/L_cusp and T = C_cusp/(1-L_cusp) +// The maximum value for C in the triangle is then found as fmin(S*L, T*(1-L)), for a given L +struct ST { float S; float T; }; + +constexpr float pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062f; + +float clamp(float x, float min, float max) +{ + if (x < min) + return min; + if (x > max) + return max; + + return x; +} + +float sgn(float x) +{ + return (float)(0.f < x) - (float)(x < 0.f); +} + +float srgb_transfer_function(float a) +{ + return .0031308f >= a ? 12.92f * a : 1.055f * powf(a, .4166666666666667f) - .055f; +} + +float srgb_transfer_function_inv(float a) +{ + return .04045f < a ? powf((a + .055f) / 1.055f, 2.4f) : a / 12.92f; +} + +Lab linear_srgb_to_oklab(RGB c) +{ + float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b; + float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b; + float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b; + + float l_ = cbrtf(l); + float m_ = cbrtf(m); + float s_ = cbrtf(s); + + return { + 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_, + 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_, + 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_, + }; +} + +RGB oklab_to_linear_srgb(Lab c) +{ + float l_ = c.L + 0.3963377774f * c.a + 0.2158037573f * c.b; + float m_ = c.L - 0.1055613458f * c.a - 0.0638541728f * c.b; + float s_ = c.L - 0.0894841775f * c.a - 1.2914855480f * c.b; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + return { + +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s, + -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s, + -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s, + }; +} + +// Finds the maximum saturation possible for a given hue that fits in sRGB +// Saturation here is defined as S = C/L +// a and b must be normalized so a^2 + b^2 == 1 +float compute_max_saturation(float a, float b) +{ + // Max saturation will be when one of r, g or b goes below zero. + + // Select different coefficients depending on which component goes below zero first + float k0, k1, k2, k3, k4, wl, wm, ws; + + if (-1.88170328f * a - 0.80936493f * b > 1) + { + // Red component + k0 = +1.19086277f; k1 = +1.76576728f; k2 = +0.59662641f; k3 = +0.75515197f; k4 = +0.56771245f; + wl = +4.0767416621f; wm = -3.3077115913f; ws = +0.2309699292f; + } + else if (1.81444104f * a - 1.19445276f * b > 1) + { + // Green component + k0 = +0.73956515f; k1 = -0.45954404f; k2 = +0.08285427f; k3 = +0.12541070f; k4 = +0.14503204f; + wl = -1.2684380046f; wm = +2.6097574011f; ws = -0.3413193965f; + } + else + { + // Blue component + k0 = +1.35733652f; k1 = -0.00915799f; k2 = -1.15130210f; k3 = -0.50559606f; k4 = +0.00692167f; + wl = -0.0041960863f; wm = -0.7034186147f; ws = +1.7076147010f; + } + + // Approximate max saturation using a polynomial: + float S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b; + + // Do one step Halley's method to get closer + // this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite + // this should be sufficient for most applications, otherwise do two/three steps + + float k_l = +0.3963377774f * a + 0.2158037573f * b; + float k_m = -0.1055613458f * a - 0.0638541728f * b; + float k_s = -0.0894841775f * a - 1.2914855480f * b; + + { + float l_ = 1.f + S * k_l; + float m_ = 1.f + S * k_m; + float s_ = 1.f + S * k_s; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + float l_dS = 3.f * k_l * l_ * l_; + float m_dS = 3.f * k_m * m_ * m_; + float s_dS = 3.f * k_s * s_ * s_; + + float l_dS2 = 6.f * k_l * k_l * l_; + float m_dS2 = 6.f * k_m * k_m * m_; + float s_dS2 = 6.f * k_s * k_s * s_; + + float f = wl * l + wm * m + ws * s; + float f1 = wl * l_dS + wm * m_dS + ws * s_dS; + float f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2; + + S = S - f * f1 / (f1 * f1 - 0.5f * f * f2); + } + + return S; +} + +// finds L_cusp and C_cusp for a given hue +// a and b must be normalized so a^2 + b^2 == 1 +LC find_cusp(float a, float b) +{ + // First, find the maximum saturation (saturation S = C/L) + float S_cusp = compute_max_saturation(a, b); + + // Convert to linear sRGB to find the first point where at least one of r,g or b >= 1: + RGB rgb_at_max = oklab_to_linear_srgb({ 1, S_cusp * a, S_cusp * b }); + float L_cusp = cbrtf(1.f / fmax(fmax(rgb_at_max.r, rgb_at_max.g), rgb_at_max.b)); + float C_cusp = L_cusp * S_cusp; + + return { L_cusp , C_cusp }; +} + +// Finds intersection of the line defined by +// L = L0 * (1 - t) + t * L1; +// C = t * C1; +// a and b must be normalized so a^2 + b^2 == 1 +float find_gamut_intersection(float a, float b, float L1, float C1, float L0, LC cusp) +{ + // Find the intersection for upper and lower half seprately + float t; + if (((L1 - L0) * cusp.C - (cusp.L - L0) * C1) <= 0.f) + { + // Lower half + + t = cusp.C * L0 / (C1 * cusp.L + cusp.C * (L0 - L1)); + } + else + { + // Upper half + + // First intersect with triangle + t = cusp.C * (L0 - 1.f) / (C1 * (cusp.L - 1.f) + cusp.C * (L0 - L1)); + + // Then one step Halley's method + { + float dL = L1 - L0; + float dC = C1; + + float k_l = +0.3963377774f * a + 0.2158037573f * b; + float k_m = -0.1055613458f * a - 0.0638541728f * b; + float k_s = -0.0894841775f * a - 1.2914855480f * b; + + float l_dt = dL + dC * k_l; + float m_dt = dL + dC * k_m; + float s_dt = dL + dC * k_s; + + + // If higher accuracy is required, 2 or 3 iterations of the following block can be used: + { + float L = L0 * (1.f - t) + t * L1; + float C = t * C1; + + float l_ = L + C * k_l; + float m_ = L + C * k_m; + float s_ = L + C * k_s; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + float ldt = 3 * l_dt * l_ * l_; + float mdt = 3 * m_dt * m_ * m_; + float sdt = 3 * s_dt * s_ * s_; + + float ldt2 = 6 * l_dt * l_dt * l_; + float mdt2 = 6 * m_dt * m_dt * m_; + float sdt2 = 6 * s_dt * s_dt * s_; + + float r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1; + float r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt; + float r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2; + + float u_r = r1 / (r1 * r1 - 0.5f * r * r2); + float t_r = -r * u_r; + + float g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1; + float g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt; + float g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2; + + float u_g = g1 / (g1 * g1 - 0.5f * g * g2); + float t_g = -g * u_g; + + float b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1; + float b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt; + float b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2; + + float u_b = b1 / (b1 * b1 - 0.5f * b * b2); + float t_b = -b * u_b; + + t_r = u_r >= 0.f ? t_r : FLT_MAX; + t_g = u_g >= 0.f ? t_g : FLT_MAX; + t_b = u_b >= 0.f ? t_b : FLT_MAX; + + t += fmin(t_r, fmin(t_g, t_b)); + } + } + } + + return t; +} + +float find_gamut_intersection(float a, float b, float L1, float C1, float L0) +{ + // Find the cusp of the gamut triangle + LC cusp = find_cusp(a, b); + + return find_gamut_intersection(a, b, L1, C1, L0, cusp); +} + +RGB gamut_clip_preserve_chroma(RGB rgb) +{ + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L0 = clamp(L, 0, 1); + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1 - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); +} + +RGB gamut_clip_project_to_0_5(RGB rgb) +{ + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L0 = 0.5; + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1 - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); +} + +RGB gamut_clip_project_to_L_cusp(RGB rgb) +{ + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once. + LC cusp = find_cusp(a_, b_); + + float L0 = cusp.L; + + float t = find_gamut_intersection(a_, b_, L, C, L0); + + float L_clipped = L0 * (1 - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); +} + +RGB gamut_clip_adaptive_L0_0_5(RGB rgb, float alpha = 0.05f) +{ + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float Ld = L - 0.5f; + float e1 = 0.5f + fabs(Ld) + alpha * C; + float L0 = 0.5f * (1.f + sgn(Ld) * (e1 - sqrtf(e1 * e1 - 2.f * fabs(Ld)))); + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1.f - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); +} + +RGB gamut_clip_adaptive_L0_L_cusp(RGB rgb, float alpha = 0.05f) +{ + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once. + LC cusp = find_cusp(a_, b_); + + float Ld = L - cusp.L; + float k = 2.f * (Ld > 0 ? 1.f - cusp.L : cusp.L); + + float e1 = 0.5f * k + fabs(Ld) + alpha * C / k; + float L0 = cusp.L + 0.5f * (sgn(Ld) * (e1 - sqrtf(e1 * e1 - 2.f * k * fabs(Ld)))); + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1.f - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); +} + +float toe(float x) +{ + constexpr float k_1 = 0.206f; + constexpr float k_2 = 0.03f; + constexpr float k_3 = (1.f + k_1) / (1.f + k_2); + return 0.5f * (k_3 * x - k_1 + sqrtf((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x)); +} + +float toe_inv(float x) +{ + constexpr float k_1 = 0.206f; + constexpr float k_2 = 0.03f; + constexpr float k_3 = (1.f + k_1) / (1.f + k_2); + return (x * x + k_1 * x) / (k_3 * (x + k_2)); +} + +ST to_ST(LC cusp) +{ + float L = cusp.L; + float C = cusp.C; + return { C / L, C / (1 - L) }; +} + +// Returns a smooth approximation of the location of the cusp +// This polynomial was created by an optimization process +// It has been designed so that S_mid < S_max and T_mid < T_max +ST get_ST_mid(float a_, float b_) +{ + float S = 0.11516993f + 1.f / ( + +7.44778970f + 4.15901240f * b_ + + a_ * (-2.19557347f + 1.75198401f * b_ + + a_ * (-2.13704948f - 10.02301043f * b_ + + a_ * (-4.24894561f + 5.38770819f * b_ + 4.69891013f * a_ + ))) + ); + + float T = 0.11239642f + 1.f / ( + +1.61320320f - 0.68124379f * b_ + + a_ * (+0.40370612f + 0.90148123f * b_ + + a_ * (-0.27087943f + 0.61223990f * b_ + + a_ * (+0.00299215f - 0.45399568f * b_ - 0.14661872f * a_ + ))) + ); + + return { S, T }; +} + +struct Cs { float C_0; float C_mid; float C_max; }; +Cs get_Cs(float L, float a_, float b_) +{ + LC cusp = find_cusp(a_, b_); + + float C_max = find_gamut_intersection(a_, b_, L, 1, L, cusp); + ST ST_max = to_ST(cusp); + + // Scale factor to compensate for the curved part of gamut shape: + float k = C_max / fmin((L * ST_max.S), (1 - L) * ST_max.T); + + float C_mid; + { + ST ST_mid = get_ST_mid(a_, b_); + + // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma. + float C_a = L * ST_mid.S; + float C_b = (1.f - L) * ST_mid.T; + C_mid = 0.9f * k * sqrtf(sqrtf(1.f / (1.f / (C_a * C_a * C_a * C_a) + 1.f / (C_b * C_b * C_b * C_b)))); + } + + float C_0; + { + // for C_0, the shape is independent of hue, so ST are constant. Values picked to roughly be the average values of ST. + float C_a = L * 0.4f; + float C_b = (1.f - L) * 0.8f; + + // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma. + C_0 = sqrtf(1.f / (1.f / (C_a * C_a) + 1.f / (C_b * C_b))); + } + + return { C_0, C_mid, C_max }; +} + +RGB okhsl_to_srgb(HSL hsl) +{ + float h = hsl.h; + float s = hsl.s; + float l = hsl.l; + + if (l == 1.0f) + { + return { 1.f, 1.f, 1.f }; + } + + else if (l == 0.f) + { + return { 0.f, 0.f, 0.f }; + } + + float a_ = cosf(2.f * pi * h); + float b_ = sinf(2.f * pi * h); + float L = toe_inv(l); + + Cs cs = get_Cs(L, a_, b_); + float C_0 = cs.C_0; + float C_mid = cs.C_mid; + float C_max = cs.C_max; + + float mid = 0.8f; + float mid_inv = 1.25f; + + float C, t, k_0, k_1, k_2; + + if (s < mid) + { + t = mid_inv * s; + + k_1 = mid * C_0; + k_2 = (1.f - k_1 / C_mid); + + C = t * k_1 / (1.f - k_2 * t); + } + else + { + t = (s - mid)/ (1 - mid); + + k_0 = C_mid; + k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0; + k_2 = (1.f - (k_1) / (C_max - C_mid)); + + C = k_0 + t * k_1 / (1.f - k_2 * t); + } + + RGB rgb = oklab_to_linear_srgb({ L, C * a_, C * b_ }); + return { + srgb_transfer_function(rgb.r), + srgb_transfer_function(rgb.g), + srgb_transfer_function(rgb.b), + }; +} + +HSL srgb_to_okhsl(RGB rgb) +{ + Lab lab = linear_srgb_to_oklab({ + srgb_transfer_function_inv(rgb.r), + srgb_transfer_function_inv(rgb.g), + srgb_transfer_function_inv(rgb.b) + }); + + float C = sqrtf(lab.a * lab.a + lab.b * lab.b); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L = lab.L; + float h = 0.5f + 0.5f * atan2f(-lab.b, -lab.a) / pi; + + Cs cs = get_Cs(L, a_, b_); + float C_0 = cs.C_0; + float C_mid = cs.C_mid; + float C_max = cs.C_max; + + // Inverse of the interpolation in okhsl_to_srgb: + + float mid = 0.8f; + float mid_inv = 1.25f; + + float s; + if (C < C_mid) + { + float k_1 = mid * C_0; + float k_2 = (1.f - k_1 / C_mid); + + float t = C / (k_1 + k_2 * C); + s = t * mid; + } + else + { + float k_0 = C_mid; + float k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0; + float k_2 = (1.f - (k_1) / (C_max - C_mid)); + + float t = (C - k_0) / (k_1 + k_2 * (C - k_0)); + s = mid + (1.f - mid) * t; + } + + float l = toe(L); + return { h, s, l }; +} + + +RGB okhsv_to_srgb(HSV hsv) +{ + float h = hsv.h; + float s = hsv.s; + float v = hsv.v; + + float a_ = cosf(2.f * pi * h); + float b_ = sinf(2.f * pi * h); + + LC cusp = find_cusp(a_, b_); + ST ST_max = to_ST(cusp); + float S_max = ST_max.S; + float T_max = ST_max.T; + float S_0 = 0.5f; + float k = 1 - S_0 / S_max; + + // first we compute L and V as if the gamut is a perfect triangle: + + // L, C when v==1: + float L_v = 1 - s * S_0 / (S_0 + T_max - T_max * k * s); + float C_v = s * T_max * S_0 / (S_0 + T_max - T_max * k * s); + + float L = v * L_v; + float C = v * C_v; + + // then we compensate for both toe and the curved top part of the triangle: + float L_vt = toe_inv(L_v); + float C_vt = C_v * L_vt / L_v; + + float L_new = toe_inv(L); + C = C * L_new / L; + L = L_new; + + RGB rgb_scale = oklab_to_linear_srgb({ L_vt, a_ * C_vt, b_ * C_vt }); + float scale_L = cbrtf(1.f / fmax(fmax(rgb_scale.r, rgb_scale.g), fmax(rgb_scale.b, 0.f))); + + L = L * scale_L; + C = C * scale_L; + + RGB rgb = oklab_to_linear_srgb({ L, C * a_, C * b_ }); + return { + srgb_transfer_function(rgb.r), + srgb_transfer_function(rgb.g), + srgb_transfer_function(rgb.b), + }; +} + +HSV srgb_to_okhsv(RGB rgb) +{ + Lab lab = linear_srgb_to_oklab({ + srgb_transfer_function_inv(rgb.r), + srgb_transfer_function_inv(rgb.g), + srgb_transfer_function_inv(rgb.b) + }); + + float C = sqrtf(lab.a * lab.a + lab.b * lab.b); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L = lab.L; + float h = 0.5f + 0.5f * atan2f(-lab.b, -lab.a) / pi; + + LC cusp = find_cusp(a_, b_); + ST ST_max = to_ST(cusp); + float S_max = ST_max.S; + float T_max = ST_max.T; + float S_0 = 0.5f; + float k = 1 - S_0 / S_max; + + // first we find L_v, C_v, L_vt and C_vt + + float t = T_max / (C + L * T_max); + float L_v = t * L; + float C_v = t * C; + + float L_vt = toe_inv(L_v); + float C_vt = C_v * L_vt / L_v; + + // we can then use these to invert the step that compensates for the toe and the curved top part of the triangle: + RGB rgb_scale = oklab_to_linear_srgb({ L_vt, a_ * C_vt, b_ * C_vt }); + float scale_L = cbrtf(1.f / fmax(fmax(rgb_scale.r, rgb_scale.g), fmax(rgb_scale.b, 0.f))); + + L = L / scale_L; + C = C / scale_L; + + C = C * toe(L) / L; + L = toe(L); + + // we can now compute v and s: + + float v = L / L_v; + float s = (S_0 + T_max) * C_v / ((T_max * S_0) + T_max * k * C_v); + + return { h, s, v }; +} + +} // namespace ok_color \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 37b6ef7a..ace3b5bd 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -218,7 +218,7 @@ namespace pimoroni { bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs // set the number of bcd ticks for this frame - uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 65535 : 1 << frame; + uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 1 : 1 << frame; bitstream[frame_offset + 164] = (bcd_ticks & 0xff); bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8; @@ -330,7 +330,7 @@ namespace pimoroni { // determine offset in the buffer for this row uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); - uint16_t bits[3] = {r_gamma_lut[r], g_gamma_lut[g], b_gamma_lut[b]}; + uint16_t bits[3] = {r_gamma_lut[b], g_gamma_lut[g], b_gamma_lut[r]}; //uint16_t gr = r_gamma_lut[r]; //uint16_t gg = g_gamma_lut[g]; //uint16_t gb = b_gamma_lut[b]; From e50827c4128d3e64b950fbf9553613e10e5f2472 Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 30 Jun 2022 14:17:41 +0100 Subject: [PATCH 03/42] stuff --- examples/galactic_unicorn/demo2.cpp | 132 ++++++++++-------- .../galactic_unicorn/galactic_unicorn.cpp | 43 ------ 2 files changed, 76 insertions(+), 99 deletions(-) diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp index ce06cec1..7bf5d2f4 100644 --- a/examples/galactic_unicorn/demo2.cpp +++ b/examples/galactic_unicorn/demo2.cpp @@ -70,100 +70,120 @@ void step_star(star_t &s) { } } -void number(int n, int x, int y) { - switch(n) { - case 6: { - graphics.rectangle(Rect(x, y, 6, 2)); - graphics.rectangle(Rect(x, y + 4, 6, 2)); - graphics.rectangle(Rect(x, y + 9, 6, 2)); - graphics.rectangle(Rect(x, y, 2, 11)); - graphics.rectangle(Rect(x + 4, y + 4, 2, 5)); - }break; - - case 9: { - graphics.rectangle(Rect(x, y, 6, 2)); - graphics.rectangle(Rect(x, y + 4, 6, 2)); - graphics.rectangle(Rect(x, y + 9, 6, 2)); - graphics.rectangle(Rect(x + 4, y, 2, 11)); - graphics.rectangle(Rect(x, y, 2, 5)); - }break; - - case 4: { - graphics.rectangle(Rect(x, y + 4, 6, 2)); - graphics.rectangle(Rect(x + 4, y, 2, 11)); - graphics.rectangle(Rect(x, y, 2, 5)); - }break; - - case 0: { - graphics.rectangle(Rect(x, y, 6, 2)); - graphics.rectangle(Rect(x + 4, y, 2, 11)); - graphics.rectangle(Rect(x, y, 2, 11)); - graphics.rectangle(Rect(x, y + 9, 6, 2)); - }break; - } -} int main() { + uint8_t hue_map[53][3]; + for(int i = 0; i < 53; i++) { + from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); + } + + star_t stars[100]; + for(int i = 0; i < 100; i++) { + init_star(stars[i]); + stars[i].a = i; + } + +gpio_set_function(28, GPIO_FUNC_SIO); + gpio_set_dir(28, GPIO_OUT); + + for(int i = 0; i < 10; i++) { + gpio_put(28, !gpio_get(28)); + sleep_ms(100); + } + sleep_ms(1000); + + gpio_put(28,true); + galactic_unicorn.init(); - // graphics.set_font("sans"); +/* + bool a_pressed = false; + bool b_pressed = false; + bool x_pressed = false; + bool y_pressed = false; +*/ + graphics.set_font("sans"); + + uint i = 0; + int v = 255; + + float hue_offset = 0.0f; + float brightness = 0.5f; + float curve = 4.0f; + while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { + hue_offset += 0.05; + if(hue_offset > 1.0f) hue_offset = 1.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { + hue_offset -= 0.05; + if(hue_offset < 0.0f) hue_offset = 0.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + brightness += 0.05; + if(brightness > 1.0f) brightness = 1.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + brightness -= 0.05; + if(brightness < 0.0f) brightness = 0.0f; } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + curve += 0.5; + if(curve > 100.0f) curve = 100.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + curve -= 0.5; + if(curve < 0.5) curve = 0.5; } +i++; graphics.set_pen(0, 0, 0); + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} graphics.clear(); - graphics.set_pen(200, 200, 0); - number(6, 23, 0); - number(9, 31, 0); - number(4, 39, 0); - number(0, 47, 0); - graphics.set_pen(200, 0, 0); - graphics.circle(Point(8, 5), 6); - - graphics.set_pen(255, 255, 255); - std::vector triangle = {Point(5, 2), Point(10, 5), Point(5, 7)}; - graphics.polygon(triangle); + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} - graphics.set_pen(255, 0, 0); - graphics.rectangle(Rect(0, 0, 10, 11)); - graphics.set_pen(0, 255, 0); - graphics.rectangle(Rect(10, 0, 10, 11)); - graphics.set_pen(0, 0, 255); - graphics.rectangle(Rect(20, 0, 10, 11)); + for(int i = 0; i < 100; i++) { + star_t &star = stars[i]; + step_star(star); + uint b = star.brightness(); + graphics.set_pen(b, b, b); + //graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2))); + } + +graphics.set_pen(255, 255, 255); + float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f); + float a = 1.0f;// (sin(i / 25.0f) * 100.0f); + float x = (sin(i / 25.0f) * 40.0f) * s; + float y = (cos(i / 15.0f) * 10.0f) * s; + text("Galactic", Point(x, y), s, a); + uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t i = 0; i < 53 * 11; i++) { int x = i % 53; int y = i / 53; - /* uint r = ((*p & 0b0111110000000000) >> 10) << 3; - uint g = ((*p & 0b0000001111100000) >> 5) << 3; - uint b = ((*p & 0b0000000000011111) >> 0) << 3;*/ + uint r = ((*p & 0b1111100000000000) >> 11) << 3; + uint g = ((*p & 0b0000011111100000) >> 5) << 2; + uint b = ((*p & 0b0000000000011111) >> 0) << 3; p++; -/* if(r > 200 && g > 200 && b > 200) { + if(r > 200 && g > 200 && b > 200) { r = hue_map[x][0]; g = hue_map[x][1]; b = hue_map[x][2]; - }*/ - galactic_unicorn.set_pixel(x, y, 0, 0, 255); + } + + galactic_unicorn.set_pixel(x, y, r, g, b); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index ace3b5bd..c1b32c38 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -377,49 +377,6 @@ namespace pimoroni { //bit_offset += 2; bits[bit] >>= 1; } - /* // setup pixel data and matching mask - uint8_t bit_position = x >= 26 ? 1 : 0; - uint8_t mask = 0b1 << bit_position; - uint8_t red = (gr & 0b1) << bit_position; - uint8_t green = (gg & 0b1) << bit_position; - uint8_t blue = (gb & 0b1) << bit_position; - - // clear existing data and set new data - bitstream[offset + 0] &= ~mask; - bitstream[offset + 0] |= red; - bitstream[offset + 1] &= ~mask; - bitstream[offset + 1] |= red; - bitstream[offset + 2] &= ~mask; - bitstream[offset + 2] |= green; - bitstream[offset + 3] &= ~mask; - bitstream[offset + 3] |= green; - bitstream[offset + 4] &= ~mask; - bitstream[offset + 4] |= blue; - bitstream[offset + 5] &= ~mask; - bitstream[offset + 5] |= blue;*/ -/* - - uint8_t mask = 0b11; - uint8_t red = ((gr & 0b1) << 1) | (gr & 0b1) ; - uint8_t green = ((gg & 0b1) << 1) | (gg & 0b1) ; - uint8_t blue = ((gb & 0b1) << 1) | (gb & 0b1) ; - - bitstream[offset + 0] &= ~mask; - bitstream[offset + 0] |= red; - bitstream[offset + 1] &= ~mask; - bitstream[offset + 1] |= red; - bitstream[offset + 2] &= ~mask; - bitstream[offset + 2] |= green; - bitstream[offset + 3] &= ~mask; - bitstream[offset + 3] |= green; - bitstream[offset + 4] &= ~mask; - bitstream[offset + 4] |= blue; - bitstream[offset + 5] &= ~mask; - bitstream[offset + 5] |= blue; -*/ - /* gr >>= 1; - gg >>= 1; - gb >>= 1;*/ } } From 63183d28bef4328bdde98b3eb595dc85a854d1f2 Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 25 Jul 2022 11:24:00 +0100 Subject: [PATCH 04/42] Lots of features added --- examples/galactic_unicorn/CMakeLists.txt | 106 +- examples/galactic_unicorn/audio_samples.cpp | 7847 +++++++++++++++++ examples/galactic_unicorn/balls.cpp | 88 + examples/galactic_unicorn/demo.cpp | 39 +- examples/galactic_unicorn/demo2.cpp | 87 +- .../eighties_super_computer.cpp | 69 + examples/galactic_unicorn/feature_test.cpp | 155 + examples/galactic_unicorn/fire_effect.cpp | 88 + examples/galactic_unicorn/lava_lamp.cpp | 148 + .../galactic_unicorn/nostalgia_prompt.cpp | 122 + examples/galactic_unicorn/scroll_text.cpp | 68 + libraries/galactic_unicorn/CMakeLists.txt | 13 +- libraries/galactic_unicorn/README.md | 15 +- libraries/galactic_unicorn/audio_i2s.pio | 63 + .../galactic_unicorn/galactic_unicorn.cmake | 14 +- .../galactic_unicorn/galactic_unicorn.cpp | 511 +- .../galactic_unicorn/galactic_unicorn.hpp | 72 +- .../galactic_unicorn/galactic_unicorn.pio | 110 +- libraries/pico_graphics/pico_graphics.cpp | 10 +- 19 files changed, 9231 insertions(+), 394 deletions(-) create mode 100644 examples/galactic_unicorn/audio_samples.cpp create mode 100644 examples/galactic_unicorn/balls.cpp create mode 100644 examples/galactic_unicorn/eighties_super_computer.cpp create mode 100644 examples/galactic_unicorn/feature_test.cpp create mode 100644 examples/galactic_unicorn/fire_effect.cpp create mode 100644 examples/galactic_unicorn/lava_lamp.cpp create mode 100644 examples/galactic_unicorn/nostalgia_prompt.cpp create mode 100644 examples/galactic_unicorn/scroll_text.cpp create mode 100644 libraries/galactic_unicorn/audio_i2s.pio diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index 60165650..86b25380 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -4,7 +4,8 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) +target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(galactic_unicorn_demo 1) # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo) @@ -17,7 +18,108 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) +target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(galactic_unicorn_demo2 1) # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo2) + + + +add_executable( + nostalgia_prompt + nostalgia_prompt.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(nostalgia_prompt pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(nostalgia_prompt 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(nostalgia_prompt) + + + +add_executable( + eighties_super_computer + eighties_super_computer.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(eighties_super_computer pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(eighties_super_computer 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(eighties_super_computer) + + + + +add_executable( + fire_effect + fire_effect.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(fire_effect pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(fire_effect 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(fire_effect) + + + + +add_executable( + scroll_text + scroll_text.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(scroll_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(scroll_text 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(scroll_text) + + +add_executable( + balls + balls.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(balls pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(balls 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(balls) + + + +add_executable( + lava_lamp + lava_lamp.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(lava_lamp pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(lava_lamp 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(lava_lamp) + + + +add_executable( + feature_test + feature_test.cpp + audio_samples.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(feature_test pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(feature_test 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(feature_test) \ No newline at end of file diff --git a/examples/galactic_unicorn/audio_samples.cpp b/examples/galactic_unicorn/audio_samples.cpp new file mode 100644 index 00000000..1ecf5dce --- /dev/null +++ b/examples/galactic_unicorn/audio_samples.cpp @@ -0,0 +1,7847 @@ +#include + +uint8_t right_channel_bin[] = { + 0x52, 0x49, 0x46, 0x46, 0x2e, 0xb5, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, + 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0xc0, 0x5d, 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, + 0x64, 0x61, 0x74, 0x61, 0x0a, 0xb5, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xf8, 0xff, 0xfd, 0xff, 0x00, 0x00, 0xfe, 0xff, 0xfd, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0xfd, 0xff, 0xfe, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfc, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0xff, 0xff, 0xfc, 0xff, 0xfe, 0xff, + 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x05, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff, + 0xfd, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, + 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf7, 0xff, + 0xf7, 0xff, 0xf8, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, + 0xd8, 0xff, 0xb8, 0xff, 0xae, 0xff, 0xa4, 0xff, 0x90, 0xff, 0xb1, 0xff, + 0xc8, 0xff, 0xe0, 0xff, 0x06, 0x00, 0x36, 0x00, 0x5a, 0x00, 0x80, 0x00, + 0xc5, 0x00, 0xdc, 0x00, 0xca, 0x00, 0x13, 0x01, 0x3c, 0x01, 0x28, 0x01, + 0x5d, 0x01, 0x8e, 0x01, 0xd0, 0x01, 0x13, 0x02, 0x69, 0x02, 0x90, 0x02, + 0xcb, 0x02, 0x10, 0x03, 0x1c, 0x03, 0x24, 0x03, 0x4d, 0x03, 0x86, 0x03, + 0x69, 0x03, 0x8c, 0x03, 0x9d, 0x03, 0xb4, 0x03, 0xe6, 0x03, 0xfb, 0x03, + 0xf6, 0x03, 0xf6, 0x03, 0x0c, 0x04, 0x1d, 0x04, 0x5e, 0x04, 0x57, 0x04, + 0x3f, 0x04, 0x3b, 0x04, 0x29, 0x04, 0xba, 0x03, 0x99, 0x03, 0x5f, 0x03, + 0x08, 0x03, 0x95, 0x02, 0x68, 0x02, 0x66, 0x02, 0x6a, 0x02, 0xb4, 0x02, + 0x72, 0x02, 0x98, 0x02, 0x92, 0x02, 0x34, 0x02, 0x13, 0x02, 0x05, 0x02, + 0x82, 0x01, 0x13, 0x01, 0x69, 0x00, 0x01, 0x00, 0xd6, 0xff, 0x09, 0xff, + 0x78, 0xfe, 0xfd, 0xfd, 0x74, 0xfd, 0xfa, 0xfc, 0x94, 0xfc, 0x39, 0xfc, + 0xa1, 0xfb, 0x19, 0xfb, 0x17, 0xfb, 0xd0, 0xfa, 0xad, 0xfa, 0xc1, 0xfa, + 0xb8, 0xfa, 0xb6, 0xfa, 0x27, 0xfb, 0xef, 0xfa, 0xa2, 0xfa, 0xfc, 0xfa, + 0xe0, 0xfa, 0x87, 0xfa, 0x80, 0xfa, 0x4f, 0xfa, 0x32, 0xfa, 0x82, 0xfa, + 0x6b, 0xfa, 0x5b, 0xfa, 0x50, 0xfa, 0x79, 0xfa, 0xa1, 0xfa, 0xfa, 0xfa, + 0x6f, 0xfb, 0xae, 0xfb, 0x1b, 0xfc, 0x7b, 0xfc, 0x18, 0xfd, 0x71, 0xfd, + 0xd4, 0xfd, 0x0b, 0xfe, 0x85, 0xfe, 0x16, 0xff, 0x8b, 0xff, 0x01, 0x00, + 0x39, 0x00, 0xa9, 0x00, 0xfc, 0x00, 0x61, 0x01, 0x7d, 0x01, 0xb1, 0x01, + 0xee, 0x01, 0x1b, 0x02, 0x52, 0x02, 0x96, 0x02, 0xf7, 0x02, 0x2b, 0x03, + 0xbf, 0x03, 0x11, 0x04, 0x57, 0x04, 0x0e, 0x05, 0x6d, 0x05, 0xb3, 0x05, + 0x06, 0x06, 0xff, 0x05, 0x49, 0x06, 0x59, 0x06, 0x7a, 0x06, 0x73, 0x06, + 0x4c, 0x06, 0x58, 0x06, 0xdf, 0x05, 0xaf, 0x05, 0xa0, 0x05, 0x7e, 0x05, + 0x64, 0x05, 0x66, 0x05, 0x5b, 0x05, 0x4b, 0x05, 0x39, 0x05, 0xd5, 0x05, + 0xa0, 0x05, 0xe5, 0x04, 0x33, 0x05, 0xa6, 0x04, 0x72, 0x04, 0x5c, 0x04, + 0xa8, 0x03, 0x3f, 0x03, 0x4c, 0x02, 0xae, 0x01, 0xf8, 0x00, 0xfe, 0xff, + 0x61, 0xff, 0xb0, 0xfe, 0xcb, 0xfd, 0x88, 0xfd, 0x18, 0xfd, 0x60, 0xfc, + 0xdb, 0xfb, 0x2e, 0xfb, 0x94, 0xfa, 0x7b, 0xfa, 0x47, 0xfa, 0x05, 0xfa, + 0xe5, 0xf9, 0xf4, 0xf9, 0x9d, 0xf9, 0x48, 0xf9, 0x27, 0xf9, 0xef, 0xf8, + 0xb8, 0xf8, 0xbb, 0xf8, 0x71, 0xf8, 0x2d, 0xf8, 0x4d, 0xf8, 0x4b, 0xf8, + 0x34, 0xf8, 0x27, 0xf8, 0x42, 0xf8, 0x88, 0xf8, 0xbb, 0xf8, 0xda, 0xf8, + 0x50, 0xf9, 0x93, 0xf9, 0x0e, 0xfa, 0xac, 0xfa, 0x24, 0xfb, 0xbf, 0xfb, + 0x4a, 0xfc, 0xbf, 0xfc, 0x75, 0xfd, 0xf9, 0xfd, 0x63, 0xfe, 0x0e, 0xff, + 0x90, 0xff, 0xf8, 0xff, 0x7a, 0x00, 0xd5, 0x00, 0x0a, 0x01, 0xa0, 0x01, + 0x00, 0x02, 0x6f, 0x02, 0x9e, 0x02, 0xe9, 0x02, 0x6b, 0x03, 0x80, 0x03, + 0xe9, 0x03, 0x54, 0x04, 0xb8, 0x04, 0x53, 0x05, 0xde, 0x05, 0x3c, 0x06, + 0xa1, 0x06, 0x01, 0x07, 0x56, 0x07, 0x81, 0x07, 0xc4, 0x07, 0x15, 0x08, + 0x95, 0x08, 0xc2, 0x08, 0xeb, 0x08, 0x28, 0x09, 0x59, 0x09, 0x86, 0x09, + 0x59, 0x09, 0xcb, 0x08, 0x5d, 0x08, 0xd1, 0x07, 0x3d, 0x07, 0x2b, 0x07, + 0xeb, 0x06, 0xb3, 0x06, 0xc0, 0x06, 0x55, 0x06, 0x0a, 0x06, 0x09, 0x06, + 0x48, 0x05, 0xe8, 0x03, 0x2e, 0x03, 0x59, 0x02, 0x1b, 0x01, 0xfa, 0xff, + 0xfe, 0xfe, 0x1f, 0xfe, 0x81, 0xfd, 0x32, 0xfd, 0x77, 0xfc, 0xf3, 0xfa, + 0x9d, 0xfa, 0x98, 0xfa, 0x37, 0xfa, 0xfc, 0xf9, 0x65, 0xf9, 0x7d, 0xf9, + 0xb8, 0xf9, 0x6c, 0xf9, 0x56, 0xf9, 0xef, 0xf8, 0x2f, 0xf8, 0xcb, 0xf7, + 0x42, 0xf7, 0x98, 0xf6, 0x18, 0xf6, 0xc2, 0xf5, 0x69, 0xf5, 0x2b, 0xf5, + 0x5f, 0xf5, 0xc6, 0xf5, 0xe1, 0xf5, 0x22, 0xf6, 0x98, 0xf6, 0x12, 0xf7, + 0xb7, 0xf7, 0x77, 0xf8, 0x24, 0xf9, 0xcf, 0xf9, 0x9e, 0xfa, 0x9d, 0xfb, + 0x90, 0xfc, 0x1b, 0xfd, 0xa7, 0xfd, 0x32, 0xfe, 0x9d, 0xfe, 0x27, 0xff, + 0xa2, 0xff, 0x27, 0x00, 0x73, 0x00, 0xea, 0x00, 0x9a, 0x01, 0x0a, 0x02, + 0x7e, 0x02, 0xe7, 0x02, 0x8f, 0x03, 0x1e, 0x04, 0xa8, 0x04, 0x76, 0x05, + 0xf1, 0x05, 0x6c, 0x06, 0x34, 0x07, 0x83, 0x07, 0xb0, 0x07, 0x22, 0x08, + 0x74, 0x08, 0xbc, 0x08, 0xc6, 0x08, 0x23, 0x09, 0x4e, 0x09, 0x6c, 0x09, + 0x82, 0x09, 0x6c, 0x09, 0x71, 0x09, 0x43, 0x09, 0x79, 0x09, 0xa7, 0x09, + 0x7f, 0x09, 0x01, 0x0a, 0x23, 0x0a, 0xe5, 0x09, 0xf8, 0x09, 0xb4, 0x09, + 0x2b, 0x09, 0x5f, 0x08, 0xd3, 0x07, 0x2d, 0x07, 0xea, 0x05, 0x18, 0x05, + 0x20, 0x04, 0x88, 0x03, 0xc1, 0x02, 0x52, 0x02, 0xfe, 0x01, 0xc5, 0x00, + 0x46, 0xff, 0x8c, 0xfe, 0x41, 0xfd, 0xa7, 0xfb, 0xee, 0xfa, 0x8e, 0xf9, + 0xa1, 0xf8, 0x61, 0xf8, 0xe4, 0xf7, 0xd0, 0xf7, 0xb1, 0xf7, 0x47, 0xf7, + 0x54, 0xf7, 0x0d, 0xf7, 0xd5, 0xf6, 0xad, 0xf6, 0x26, 0xf6, 0xcf, 0xf5, + 0xe9, 0xf5, 0x08, 0xf6, 0xbd, 0xf5, 0x5e, 0xf5, 0xbd, 0xf5, 0x92, 0xf5, + 0xff, 0xf4, 0x22, 0xf5, 0x28, 0xf5, 0x54, 0xf5, 0xf6, 0xf5, 0x91, 0xf6, + 0x33, 0xf7, 0x38, 0xf8, 0x2b, 0xf9, 0x38, 0xfa, 0x68, 0xfb, 0x2c, 0xfc, + 0x30, 0xfd, 0x04, 0xfe, 0xc4, 0xfe, 0xa6, 0xff, 0x76, 0x00, 0x31, 0x01, + 0xae, 0x01, 0x60, 0x02, 0xe8, 0x02, 0x3e, 0x03, 0xbd, 0x03, 0xf2, 0x03, + 0x4a, 0x04, 0xda, 0x04, 0x60, 0x05, 0x00, 0x06, 0xc8, 0x06, 0x82, 0x07, + 0xff, 0x07, 0xad, 0x08, 0x0a, 0x09, 0xd6, 0x08, 0xee, 0x08, 0xda, 0x08, + 0xa8, 0x08, 0x8c, 0x08, 0xb9, 0x08, 0xc6, 0x08, 0x00, 0x09, 0x60, 0x09, + 0x9d, 0x09, 0x70, 0x09, 0x88, 0x09, 0x6f, 0x09, 0x78, 0x09, 0x7b, 0x09, + 0x49, 0x09, 0x2e, 0x09, 0xb1, 0x08, 0x13, 0x08, 0x17, 0x07, 0x36, 0x06, + 0xca, 0x05, 0x4e, 0x05, 0xb4, 0x04, 0x49, 0x04, 0x15, 0x04, 0x99, 0x03, + 0x5a, 0x03, 0xb0, 0x02, 0xa0, 0x00, 0x6a, 0xff, 0x87, 0xfe, 0xc3, 0xfc, + 0x40, 0xfb, 0x48, 0xfa, 0xe6, 0xf8, 0xf5, 0xf7, 0x69, 0xf7, 0x98, 0xf6, + 0xfd, 0xf5, 0xfe, 0xf5, 0x6e, 0xf5, 0xbd, 0xf5, 0x1f, 0xf6, 0x82, 0xf5, + 0x3e, 0xf6, 0x2e, 0xf6, 0x14, 0xf6, 0xac, 0xf6, 0xa4, 0xf6, 0x44, 0xf6, + 0x66, 0xf6, 0x3f, 0xf6, 0xbd, 0xf5, 0xc9, 0xf5, 0x5a, 0xf5, 0x09, 0xf5, + 0x25, 0xf5, 0x74, 0xf5, 0x8e, 0xf5, 0x24, 0xf6, 0x23, 0xf7, 0x03, 0xf8, + 0x61, 0xf9, 0xd3, 0xfa, 0x41, 0xfc, 0xc9, 0xfd, 0x26, 0xff, 0x7a, 0x00, + 0xb5, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x0a, 0x04, 0x66, 0x04, 0xc9, 0x04, + 0x00, 0x05, 0x3b, 0x05, 0x3a, 0x05, 0x96, 0x05, 0xa4, 0x05, 0xd7, 0x05, + 0x38, 0x06, 0x38, 0x06, 0xcf, 0x06, 0x17, 0x07, 0x25, 0x07, 0x6f, 0x07, + 0xac, 0x07, 0x3f, 0x08, 0xbb, 0x08, 0x03, 0x09, 0x33, 0x09, 0x7e, 0x09, + 0xc3, 0x09, 0xa7, 0x09, 0xa2, 0x09, 0x94, 0x09, 0x7f, 0x09, 0x4a, 0x09, + 0xf0, 0x08, 0x74, 0x08, 0x44, 0x08, 0x72, 0x08, 0x3b, 0x08, 0x0c, 0x08, + 0xe2, 0x07, 0x8d, 0x07, 0x66, 0x07, 0x4b, 0x07, 0xf7, 0x06, 0x66, 0x06, + 0xc3, 0x05, 0x3d, 0x05, 0x7c, 0x04, 0x34, 0x03, 0xd4, 0x01, 0x5a, 0x00, + 0xdd, 0xfe, 0x7b, 0xfd, 0xe8, 0xfb, 0x82, 0xfa, 0xdf, 0xf8, 0xa8, 0xf7, + 0xc5, 0xf6, 0x81, 0xf6, 0xac, 0xf5, 0xdb, 0xf4, 0x1b, 0xf5, 0x78, 0xf4, + 0x6b, 0xf4, 0xe0, 0xf4, 0x96, 0xf4, 0x38, 0xf4, 0x64, 0xf4, 0x78, 0xf4, + 0x86, 0xf4, 0xa4, 0xf4, 0xe4, 0xf4, 0xd1, 0xf4, 0xc2, 0xf4, 0x78, 0xf4, + 0x51, 0xf4, 0x3b, 0xf4, 0xfa, 0xf3, 0x22, 0xf4, 0x4b, 0xf4, 0x64, 0xf4, + 0x52, 0xf5, 0x83, 0xf6, 0x9c, 0xf7, 0xea, 0xf8, 0x81, 0xfa, 0x0b, 0xfc, + 0xb5, 0xfd, 0x85, 0xff, 0xbe, 0x00, 0x55, 0x02, 0x98, 0x03, 0x83, 0x04, + 0x8c, 0x05, 0xf7, 0x05, 0x73, 0x06, 0xca, 0x06, 0x01, 0x07, 0xe5, 0x06, + 0xd5, 0x06, 0x3d, 0x07, 0x7f, 0x07, 0xf2, 0x07, 0xdb, 0x08, 0x5c, 0x09, + 0x8b, 0x09, 0xdb, 0x09, 0x4d, 0x0a, 0x53, 0x0a, 0x23, 0x0a, 0x1e, 0x0a, + 0x0e, 0x0a, 0xfb, 0x09, 0x5a, 0x0a, 0x8f, 0x0a, 0x45, 0x0a, 0x34, 0x0a, + 0x48, 0x0a, 0xdb, 0x09, 0x6a, 0x09, 0x2d, 0x09, 0xc8, 0x08, 0x91, 0x08, + 0x27, 0x08, 0xf5, 0x07, 0x7d, 0x07, 0x7d, 0x07, 0x59, 0x07, 0xf0, 0x06, + 0x9a, 0x06, 0xa4, 0x05, 0x20, 0x05, 0xea, 0x03, 0xbf, 0x02, 0xce, 0x01, + 0x6a, 0x00, 0xc0, 0xff, 0x9e, 0xfe, 0x50, 0xfd, 0xb6, 0xfb, 0x8c, 0xf9, + 0xea, 0xf7, 0x68, 0xf6, 0x7b, 0xf4, 0x7d, 0xf3, 0xcb, 0xf2, 0x75, 0xf2, + 0x80, 0xf2, 0xf1, 0xf2, 0x3e, 0xf3, 0xe5, 0xf3, 0x8c, 0xf4, 0xaf, 0xf4, + 0xb9, 0xf4, 0xc5, 0xf4, 0x91, 0xf4, 0xcf, 0xf4, 0xe6, 0xf4, 0x4d, 0xf4, + 0x1b, 0xf4, 0xfa, 0xf3, 0xa0, 0xf3, 0xaf, 0xf3, 0xc3, 0xf3, 0x98, 0xf3, + 0xcb, 0xf3, 0x29, 0xf4, 0x1e, 0xf5, 0x22, 0xf6, 0x93, 0xf7, 0x15, 0xf9, + 0x9e, 0xfa, 0x81, 0xfc, 0x38, 0xfe, 0x19, 0x00, 0xc9, 0x01, 0x12, 0x03, + 0xae, 0x04, 0xe2, 0x05, 0xc7, 0x06, 0x50, 0x07, 0x9a, 0x07, 0xc6, 0x07, + 0xe2, 0x07, 0x16, 0x08, 0x0a, 0x08, 0x36, 0x08, 0x98, 0x08, 0xf2, 0x08, + 0xca, 0x09, 0x01, 0x0a, 0x01, 0x0a, 0x54, 0x0a, 0x6c, 0x0a, 0x90, 0x0a, + 0xb5, 0x0a, 0xde, 0x0a, 0x90, 0x0a, 0xa7, 0x0a, 0xc5, 0x0a, 0xb3, 0x0a, + 0xbd, 0x0a, 0x71, 0x0a, 0xc8, 0x09, 0x2d, 0x09, 0xd6, 0x08, 0x76, 0x08, + 0x50, 0x08, 0x21, 0x08, 0x40, 0x08, 0x1e, 0x08, 0xda, 0x07, 0xc2, 0x07, + 0xe9, 0x06, 0x3c, 0x06, 0xc1, 0x05, 0xe9, 0x04, 0xd4, 0x03, 0xf0, 0x02, + 0x2a, 0x02, 0xeb, 0x00, 0xde, 0xff, 0xd0, 0xfe, 0xe4, 0xfc, 0x83, 0xfb, + 0xfc, 0xf9, 0xdd, 0xf7, 0xa4, 0xf6, 0xff, 0xf4, 0x83, 0xf4, 0x0a, 0xf4, + 0x8a, 0xf3, 0xc6, 0xf3, 0x88, 0xf3, 0x22, 0xf4, 0x6f, 0xf4, 0x12, 0xf4, + 0x90, 0xf4, 0xa9, 0xf4, 0x5e, 0xf4, 0xf8, 0xf4, 0xe7, 0xf4, 0x79, 0xf4, + 0xa9, 0xf4, 0x4f, 0xf4, 0x18, 0xf4, 0x35, 0xf4, 0x79, 0xf3, 0x45, 0xf3, + 0x98, 0xf3, 0x7d, 0xf3, 0x03, 0xf4, 0x0c, 0xf5, 0x0c, 0xf6, 0x6a, 0xf7, + 0xff, 0xf8, 0xa1, 0xfa, 0x95, 0xfc, 0x4b, 0xfe, 0xe0, 0xff, 0x79, 0x01, + 0xd2, 0x02, 0xfa, 0x03, 0x36, 0x05, 0x25, 0x06, 0x93, 0x06, 0x10, 0x07, + 0x13, 0x07, 0x0b, 0x07, 0x96, 0x07, 0x7b, 0x07, 0x63, 0x07, 0x94, 0x07, + 0xdc, 0x07, 0x4c, 0x08, 0xd4, 0x08, 0x47, 0x09, 0x94, 0x09, 0x1b, 0x0a, + 0x6c, 0x0a, 0x03, 0x0b, 0xc8, 0x0b, 0x99, 0x0b, 0xa2, 0x0b, 0xb2, 0x0b, + 0xfa, 0x0a, 0xb2, 0x0a, 0x09, 0x0a, 0x2c, 0x09, 0x0b, 0x09, 0xaf, 0x08, + 0x7e, 0x08, 0xfb, 0x08, 0xa2, 0x08, 0xa3, 0x08, 0x1d, 0x09, 0xc7, 0x08, + 0x46, 0x08, 0x3e, 0x09, 0x27, 0x09, 0x3b, 0x08, 0x1c, 0x08, 0x6e, 0x06, + 0x67, 0x04, 0xe7, 0x02, 0x08, 0x01, 0xf3, 0xfe, 0xf8, 0xfc, 0x96, 0xfb, + 0x24, 0xfa, 0x42, 0xf8, 0x12, 0xf7, 0xb8, 0xf5, 0x43, 0xf4, 0x3c, 0xf4, + 0xdc, 0xf3, 0x46, 0xf3, 0x75, 0xf3, 0x90, 0xf3, 0x24, 0xf4, 0x9a, 0xf4, + 0x4e, 0xf5, 0x0d, 0xf5, 0x85, 0xf4, 0xf4, 0xf4, 0x5b, 0xf4, 0x46, 0xf4, + 0x2e, 0xf4, 0x3f, 0xf3, 0x57, 0xf3, 0x27, 0xf3, 0x41, 0xf3, 0x97, 0xf3, + 0xf2, 0xf2, 0x60, 0xf3, 0xb9, 0xf3, 0x51, 0xf4, 0xba, 0xf5, 0xc4, 0xf6, + 0x53, 0xf8, 0x18, 0xfa, 0x08, 0xfc, 0xf6, 0xfd, 0xe4, 0xff, 0x6d, 0x01, + 0x90, 0x02, 0xcf, 0x03, 0x97, 0x04, 0x24, 0x05, 0xf4, 0x05, 0x27, 0x06, + 0xae, 0x06, 0x6d, 0x07, 0xdc, 0x07, 0xc9, 0x08, 0x49, 0x09, 0x94, 0x09, + 0x27, 0x0a, 0x75, 0x0a, 0x84, 0x0a, 0x99, 0x0a, 0x56, 0x0b, 0xc5, 0x0a, + 0x82, 0x0a, 0xff, 0x0a, 0xa0, 0x0a, 0xba, 0x0a, 0xb8, 0x0a, 0x65, 0x0a, + 0x36, 0x09, 0xf2, 0x08, 0x86, 0x08, 0x0b, 0x08, 0x12, 0x08, 0xa2, 0x08, + 0x4b, 0x08, 0x6d, 0x08, 0xc7, 0x08, 0xcf, 0x08, 0xa4, 0x08, 0xbe, 0x07, + 0x6e, 0x07, 0xed, 0x05, 0x40, 0x05, 0x35, 0x05, 0xa4, 0x04, 0xee, 0x03, + 0x5b, 0x03, 0x5a, 0x02, 0x69, 0x01, 0x0b, 0x00, 0x42, 0xfe, 0x8d, 0xfc, + 0x7e, 0xfa, 0x8a, 0xf8, 0x36, 0xf7, 0xd6, 0xf5, 0xbd, 0xf4, 0x75, 0xf4, + 0xec, 0xf3, 0x04, 0xf4, 0x68, 0xf4, 0x6f, 0xf4, 0xe6, 0xf4, 0x88, 0xf5, + 0xe6, 0xf5, 0x23, 0xf6, 0xd7, 0xf6, 0x0a, 0xf7, 0xd0, 0xf6, 0xdb, 0xf6, + 0xc0, 0xf6, 0x76, 0xf6, 0x0e, 0xf6, 0x12, 0xf6, 0x70, 0xf5, 0xf9, 0xf4, + 0xd8, 0xf4, 0x8b, 0xf4, 0xc9, 0xf4, 0x78, 0xf5, 0x2c, 0xf6, 0x0e, 0xf7, + 0x9a, 0xf8, 0xbe, 0xf9, 0xa6, 0xfb, 0xcf, 0xfd, 0x5b, 0xff, 0x52, 0x01, + 0x33, 0x03, 0xa0, 0x04, 0xf9, 0x05, 0x3d, 0x07, 0x00, 0x08, 0x71, 0x08, + 0xdd, 0x08, 0x8a, 0x08, 0x13, 0x08, 0xdc, 0x07, 0x45, 0x07, 0xeb, 0x06, + 0x5d, 0x06, 0x1c, 0x06, 0x55, 0x06, 0xab, 0x06, 0x08, 0x08, 0xed, 0x08, + 0xb8, 0x09, 0x9e, 0x0a, 0x07, 0x0b, 0xb0, 0x0b, 0xdc, 0x0b, 0x79, 0x0b, + 0xcf, 0x0a, 0x14, 0x0a, 0x2f, 0x09, 0xb5, 0x08, 0x38, 0x08, 0x31, 0x07, + 0x98, 0x06, 0xff, 0x05, 0xeb, 0x05, 0x6b, 0x06, 0x9d, 0x06, 0xf6, 0x06, + 0x66, 0x07, 0xb3, 0x07, 0x47, 0x08, 0x58, 0x08, 0xd8, 0x07, 0x81, 0x06, + 0x25, 0x05, 0xb7, 0x03, 0x2b, 0x01, 0x7c, 0x00, 0x8c, 0xfe, 0x17, 0xfc, + 0x7a, 0xfb, 0xd0, 0xf8, 0x18, 0xf7, 0x4c, 0xf5, 0x92, 0xf3, 0x65, 0xf2, + 0xec, 0xf0, 0xda, 0xf0, 0xc5, 0xf0, 0x55, 0xf1, 0x55, 0xf2, 0x25, 0xf3, + 0x4b, 0xf4, 0x56, 0xf5, 0x66, 0xf6, 0xd9, 0xf6, 0xf3, 0xf6, 0x3a, 0xf7, + 0x7c, 0xf6, 0xcb, 0xf6, 0x73, 0xf6, 0x83, 0xf5, 0xc7, 0xf5, 0x48, 0xf5, + 0x81, 0xf4, 0x30, 0xf5, 0xda, 0xf4, 0x94, 0xf4, 0x28, 0xf6, 0x9d, 0xf6, + 0xf6, 0xf7, 0x98, 0xfa, 0x19, 0xfc, 0x5c, 0xfe, 0x73, 0x01, 0xf5, 0x02, + 0x0d, 0x05, 0xe9, 0x06, 0x91, 0x07, 0x8b, 0x08, 0x51, 0x09, 0x31, 0x09, + 0x00, 0x09, 0x0d, 0x09, 0x21, 0x08, 0xda, 0x07, 0x7b, 0x07, 0x6e, 0x06, + 0x83, 0x06, 0x3d, 0x06, 0x21, 0x06, 0xf1, 0x06, 0x5a, 0x07, 0xfe, 0x07, + 0x61, 0x08, 0xea, 0x09, 0x33, 0x0a, 0xdc, 0x0a, 0xdd, 0x0b, 0x1f, 0x0b, + 0xef, 0x0b, 0x82, 0x0b, 0x94, 0x0a, 0x66, 0x0a, 0xf4, 0x08, 0x40, 0x08, + 0xd6, 0x07, 0xdf, 0x06, 0x57, 0x06, 0x2d, 0x06, 0x74, 0x06, 0x66, 0x06, + 0x37, 0x07, 0xca, 0x07, 0xd2, 0x07, 0xe1, 0x08, 0xaa, 0x09, 0x59, 0x09, + 0x41, 0x08, 0xcc, 0x06, 0x4f, 0x04, 0xfc, 0x01, 0xb9, 0xff, 0x0e, 0xfd, + 0x5a, 0xfa, 0xf9, 0xf7, 0xb7, 0xf5, 0xa1, 0xf3, 0x37, 0xf2, 0x0f, 0xf1, + 0x16, 0xf0, 0x59, 0xef, 0x5d, 0xef, 0x1e, 0xef, 0xa9, 0xef, 0xe6, 0xf0, + 0x51, 0xf1, 0x4b, 0xf2, 0xbb, 0xf3, 0xd0, 0xf3, 0x0a, 0xf5, 0x71, 0xf5, + 0x34, 0xf5, 0x11, 0xf6, 0x94, 0xf5, 0xf8, 0xf5, 0x00, 0xf6, 0xf6, 0xf5, + 0xf6, 0xf5, 0x0c, 0xf6, 0xb6, 0xf6, 0xcf, 0xf6, 0xd2, 0xf7, 0x99, 0xf8, + 0x90, 0xf9, 0x23, 0xfb, 0x1c, 0xfc, 0x08, 0xfe, 0x35, 0x00, 0x92, 0x01, + 0x18, 0x04, 0xc7, 0x05, 0xfc, 0x06, 0x36, 0x09, 0x1a, 0x0a, 0xe5, 0x0a, + 0x49, 0x0b, 0x99, 0x0b, 0x23, 0x0b, 0xee, 0x0a, 0xce, 0x0a, 0x7a, 0x09, + 0x0f, 0x09, 0xff, 0x07, 0x88, 0x07, 0x2f, 0x07, 0x6f, 0x06, 0x4f, 0x06, + 0x2b, 0x06, 0x9b, 0x06, 0x13, 0x07, 0xe4, 0x07, 0x49, 0x08, 0xad, 0x08, + 0x86, 0x09, 0xfc, 0x09, 0x44, 0x0a, 0x31, 0x0a, 0x53, 0x09, 0xc7, 0x08, + 0x21, 0x0a, 0x7d, 0x09, 0x1d, 0x09, 0xf3, 0x08, 0xbd, 0x07, 0xdc, 0x07, + 0xfa, 0x07, 0x56, 0x07, 0x21, 0x07, 0xb9, 0x06, 0xcc, 0x05, 0xb0, 0x05, + 0x50, 0x04, 0x32, 0x02, 0xa7, 0x01, 0xca, 0xff, 0x6b, 0xff, 0x58, 0xfe, + 0x3d, 0xfc, 0x64, 0xfb, 0xae, 0xf8, 0xc0, 0xf6, 0x3a, 0xf5, 0x9d, 0xf2, + 0x4b, 0xf1, 0xe8, 0xef, 0x05, 0xef, 0x70, 0xef, 0x5e, 0xef, 0xa9, 0xf0, + 0x2b, 0xf1, 0x23, 0xf2, 0x26, 0xf3, 0x8d, 0xf3, 0x9a, 0xf4, 0x4b, 0xf5, + 0x92, 0xf5, 0x59, 0xf6, 0x84, 0xf6, 0x10, 0xf7, 0xc2, 0xf7, 0xc5, 0xf7, + 0x06, 0xf8, 0xdd, 0xf7, 0xed, 0xf7, 0x02, 0xf8, 0x2b, 0xf8, 0xdd, 0xf8, + 0x60, 0xf9, 0x4a, 0xfa, 0xec, 0xfb, 0x32, 0xfd, 0x3d, 0xff, 0x77, 0x01, + 0xfd, 0x02, 0x34, 0x05, 0x8f, 0x06, 0xda, 0x07, 0x2e, 0x09, 0x8c, 0x09, + 0x2a, 0x0a, 0x04, 0x0a, 0x85, 0x09, 0x09, 0x09, 0x63, 0x08, 0xab, 0x07, + 0xf0, 0x06, 0x61, 0x06, 0x3e, 0x06, 0x5f, 0x06, 0x4e, 0x07, 0xd4, 0x07, + 0x71, 0x08, 0x49, 0x09, 0x58, 0x09, 0xf0, 0x09, 0x34, 0x0a, 0x33, 0x0a, + 0x0b, 0x0a, 0x44, 0x0a, 0x0a, 0x0a, 0x32, 0x0a, 0x55, 0x0a, 0x3f, 0x0a, + 0x56, 0x0a, 0xac, 0x09, 0x9e, 0x09, 0xb4, 0x09, 0xfc, 0x08, 0x1d, 0x09, + 0xbf, 0x08, 0x23, 0x08, 0xe2, 0x07, 0xc4, 0x07, 0xe9, 0x06, 0x0b, 0x06, + 0x45, 0x05, 0xaa, 0x03, 0x76, 0x02, 0xcd, 0x00, 0xa1, 0xfe, 0xe1, 0xfc, + 0x84, 0xfa, 0x87, 0xf8, 0xb8, 0xf6, 0x74, 0xf4, 0x55, 0xf2, 0x65, 0xf0, + 0x9a, 0xef, 0x36, 0xee, 0xef, 0xed, 0x57, 0xee, 0x55, 0xee, 0x62, 0xef, + 0x5b, 0xf0, 0xcf, 0xf1, 0xfe, 0xf2, 0x2c, 0xf4, 0x98, 0xf5, 0xc9, 0xf5, + 0x15, 0xf6, 0x4f, 0xf7, 0xf9, 0xf6, 0x0d, 0xf7, 0x09, 0xf8, 0xf5, 0xf6, + 0xcc, 0xf7, 0x26, 0xf8, 0xf3, 0xf7, 0xfc, 0xf8, 0x79, 0xf9, 0x28, 0xfa, + 0x93, 0xfb, 0x38, 0xfd, 0x73, 0xfe, 0xc0, 0x00, 0x6c, 0x02, 0x88, 0x03, + 0xfb, 0x05, 0xef, 0x06, 0x3f, 0x08, 0xa5, 0x09, 0xf4, 0x09, 0x4e, 0x0a, + 0x66, 0x0a, 0x46, 0x0a, 0xb2, 0x09, 0x26, 0x09, 0x12, 0x09, 0xf8, 0x07, + 0x4a, 0x07, 0x70, 0x07, 0x7c, 0x06, 0x96, 0x06, 0xce, 0x06, 0x12, 0x06, + 0x8e, 0x06, 0x0a, 0x07, 0x69, 0x07, 0xba, 0x07, 0x9c, 0x08, 0x6a, 0x08, + 0xf5, 0x08, 0x8f, 0x09, 0xf4, 0x08, 0xee, 0x08, 0x1f, 0x08, 0x54, 0x07, + 0xdc, 0x06, 0x7f, 0x06, 0x28, 0x06, 0x20, 0x06, 0x50, 0x06, 0x83, 0x06, + 0x04, 0x07, 0x46, 0x07, 0x60, 0x07, 0xdf, 0x06, 0x18, 0x06, 0xce, 0x04, + 0x1b, 0x03, 0x9c, 0x00, 0xbb, 0xfe, 0x33, 0xfd, 0x0a, 0xfb, 0x50, 0xf9, + 0x42, 0xf7, 0xde, 0xf4, 0x8b, 0xf2, 0x4d, 0xf1, 0x7d, 0xef, 0x88, 0xee, + 0xd2, 0xed, 0xc9, 0xed, 0xfd, 0xed, 0x05, 0xf0, 0x6f, 0xf1, 0x7c, 0xf2, + 0x0e, 0xf5, 0x7b, 0xf5, 0x47, 0xf7, 0x98, 0xf8, 0xc9, 0xf8, 0x6d, 0xf9, + 0x55, 0xf9, 0x08, 0xf9, 0x20, 0xf9, 0xfd, 0xf8, 0x5d, 0xf9, 0x2a, 0xf9, + 0x6b, 0xf9, 0xcf, 0xf9, 0x03, 0xfa, 0x41, 0xfb, 0xc6, 0xfb, 0x71, 0xfd, + 0xbf, 0xfe, 0x0e, 0x00, 0x5f, 0x02, 0xd9, 0x03, 0xa5, 0x05, 0x69, 0x07, + 0x23, 0x08, 0xef, 0x08, 0x5b, 0x09, 0x22, 0x09, 0xc4, 0x08, 0x61, 0x08, + 0x83, 0x07, 0xcd, 0x06, 0x7d, 0x06, 0x0e, 0x06, 0x93, 0x05, 0xe2, 0x05, + 0xf3, 0x05, 0x14, 0x06, 0xd2, 0x06, 0x12, 0x07, 0xbe, 0x07, 0xca, 0x08, + 0x00, 0x09, 0x94, 0x09, 0xd8, 0x09, 0xa3, 0x09, 0x07, 0x09, 0x79, 0x08, + 0xb5, 0x07, 0xf7, 0x06, 0xb4, 0x06, 0x7c, 0x06, 0x47, 0x06, 0x43, 0x06, + 0x3d, 0x06, 0x71, 0x06, 0x8c, 0x06, 0xbe, 0x06, 0x02, 0x07, 0x0f, 0x06, + 0xd0, 0x05, 0x75, 0x04, 0x29, 0x03, 0xfb, 0x01, 0x6a, 0x00, 0x32, 0xff, + 0xf3, 0xfc, 0xa9, 0xfa, 0x49, 0xf9, 0x7c, 0xf6, 0xfa, 0xf4, 0x57, 0xf3, + 0x05, 0xf1, 0xf3, 0xef, 0xb6, 0xee, 0x89, 0xee, 0xf4, 0xed, 0x94, 0xee, + 0x4e, 0xef, 0xa8, 0xf0, 0xa4, 0xf2, 0x26, 0xf4, 0xbb, 0xf5, 0xed, 0xf6, + 0x6a, 0xf8, 0x2e, 0xf9, 0xf7, 0xf9, 0x75, 0xfa, 0xfe, 0xf9, 0x5d, 0xfa, + 0x54, 0xfa, 0xea, 0xf9, 0xe4, 0xf9, 0x97, 0xf9, 0x9d, 0xf9, 0x03, 0xfa, + 0x05, 0xfb, 0xd6, 0xfb, 0x06, 0xfd, 0xa7, 0xfe, 0x40, 0x00, 0x50, 0x02, + 0x78, 0x04, 0x7b, 0x06, 0xd3, 0x07, 0xec, 0x08, 0xa5, 0x09, 0xa6, 0x09, + 0xd5, 0x09, 0x86, 0x09, 0xa8, 0x08, 0x26, 0x08, 0x5a, 0x07, 0x66, 0x06, + 0x7a, 0x06, 0x0a, 0x06, 0xfc, 0x05, 0x5a, 0x06, 0x56, 0x06, 0xf8, 0x06, + 0xcd, 0x07, 0x92, 0x08, 0x58, 0x09, 0x96, 0x09, 0xfd, 0x09, 0x07, 0x0a, + 0x12, 0x0a, 0x50, 0x0a, 0x89, 0x09, 0xfa, 0x08, 0x16, 0x08, 0x56, 0x07, + 0xe7, 0x06, 0x48, 0x06, 0xcb, 0x05, 0x6f, 0x05, 0x0c, 0x05, 0x3e, 0x05, + 0x65, 0x05, 0x45, 0x05, 0x57, 0x05, 0x99, 0x04, 0x90, 0x03, 0x51, 0x03, + 0x8e, 0x01, 0x0a, 0x00, 0xfb, 0xfe, 0x55, 0xfc, 0xc6, 0xf9, 0xd6, 0xf7, + 0x60, 0xf4, 0x93, 0xf1, 0x51, 0xef, 0x20, 0xec, 0x60, 0xea, 0xa2, 0xe9, + 0xf3, 0xe8, 0x97, 0xe9, 0x8b, 0xeb, 0xec, 0xec, 0x94, 0xef, 0xed, 0xf2, + 0x1d, 0xf5, 0xba, 0xf7, 0xc3, 0xfa, 0x62, 0xfb, 0xfe, 0xfc, 0xa9, 0xfd, + 0xf8, 0xfc, 0xaa, 0xfd, 0xe2, 0xfc, 0xf8, 0xfb, 0xcc, 0xfb, 0xe2, 0xfa, + 0x05, 0xfb, 0x45, 0xfb, 0x1f, 0xfc, 0xd2, 0xfc, 0xfd, 0xfd, 0x2f, 0x00, + 0x9d, 0x01, 0x69, 0x04, 0x7e, 0x06, 0x2f, 0x08, 0x26, 0x0a, 0x3b, 0x0b, + 0xb9, 0x0b, 0xc3, 0x0b, 0x23, 0x0b, 0xd5, 0x09, 0xc4, 0x08, 0x70, 0x07, + 0xa9, 0x05, 0x83, 0x04, 0xde, 0x03, 0x1b, 0x03, 0x75, 0x03, 0xdc, 0x03, + 0x31, 0x04, 0xb2, 0x05, 0x36, 0x07, 0x6e, 0x08, 0x1b, 0x0a, 0x15, 0x0b, + 0xb4, 0x0b, 0xcb, 0x0c, 0xe8, 0x0c, 0x73, 0x0c, 0xe2, 0x0b, 0xe0, 0x0a, + 0x75, 0x09, 0x70, 0x08, 0xfe, 0x06, 0xae, 0x05, 0x36, 0x05, 0x72, 0x04, + 0x6c, 0x04, 0xc4, 0x04, 0x0a, 0x05, 0xb0, 0x05, 0x76, 0x06, 0x0c, 0x06, + 0x83, 0x05, 0x2d, 0x04, 0xab, 0x02, 0xab, 0x00, 0xb8, 0xfd, 0x2b, 0xfb, + 0xa0, 0xf7, 0xfd, 0xf3, 0xe3, 0xf0, 0xd7, 0xec, 0x53, 0xe9, 0xb8, 0xe6, + 0x73, 0xe4, 0xb1, 0xe3, 0xfe, 0xe4, 0xf5, 0xe5, 0xf9, 0xe7, 0xd2, 0xeb, + 0xd0, 0xed, 0xbe, 0xf2, 0x82, 0xf6, 0xdc, 0xf8, 0x13, 0xfc, 0x42, 0xfd, + 0x88, 0xfe, 0xc3, 0xff, 0x24, 0x00, 0x9a, 0xff, 0x12, 0xff, 0x6b, 0xfe, + 0x3f, 0xfd, 0x8c, 0xfd, 0x78, 0xfd, 0x20, 0xfd, 0x41, 0xfe, 0x27, 0xff, + 0xbb, 0x00, 0xba, 0x02, 0x0a, 0x05, 0x08, 0x07, 0x4e, 0x09, 0x8d, 0x0b, + 0x56, 0x0c, 0xf9, 0x0c, 0xdf, 0x0c, 0xd7, 0x0b, 0x8d, 0x0a, 0xf8, 0x08, + 0x3c, 0x06, 0x69, 0x04, 0xf9, 0x02, 0xbc, 0x01, 0xa6, 0x01, 0x89, 0x01, + 0xb1, 0x01, 0xe5, 0x02, 0x36, 0x04, 0xbd, 0x05, 0xa1, 0x07, 0x1a, 0x09, + 0x14, 0x0a, 0xaa, 0x0b, 0xbd, 0x0c, 0x25, 0x0d, 0xe7, 0x0d, 0xe7, 0x0d, + 0x14, 0x0d, 0xea, 0x0c, 0xef, 0x0b, 0x6d, 0x0a, 0x07, 0x0a, 0xc8, 0x08, + 0xae, 0x07, 0xdd, 0x07, 0x7b, 0x07, 0x70, 0x07, 0x01, 0x08, 0xa6, 0x07, + 0xe3, 0x06, 0xff, 0x05, 0xaa, 0x03, 0x41, 0x01, 0xf9, 0xfe, 0xde, 0xfb, + 0x10, 0xf9, 0x2a, 0xf6, 0xa2, 0xf2, 0xc3, 0xef, 0xbf, 0xec, 0xeb, 0xe8, + 0x0e, 0xe6, 0x74, 0xe2, 0xe9, 0xdf, 0xf9, 0xde, 0xc8, 0xde, 0x8f, 0xe0, + 0x07, 0xe3, 0xfe, 0xe6, 0x4d, 0xeb, 0xa7, 0xf0, 0xbf, 0xf5, 0x66, 0xfa, + 0x2b, 0xfe, 0xc7, 0x00, 0x29, 0x02, 0x2d, 0x03, 0xd8, 0x03, 0x20, 0x03, + 0x90, 0x03, 0x90, 0x02, 0xfb, 0x01, 0xc3, 0x01, 0x59, 0x01, 0x25, 0x01, + 0xcc, 0x01, 0x0b, 0x02, 0x40, 0x03, 0x93, 0x04, 0x78, 0x06, 0xa0, 0x08, + 0xc8, 0x0a, 0xd0, 0x0c, 0x8e, 0x0d, 0x22, 0x0e, 0x3b, 0x0d, 0xe5, 0x0b, + 0x1b, 0x0a, 0xa7, 0x07, 0x0f, 0x05, 0xa3, 0x02, 0x7b, 0x00, 0x43, 0xff, + 0xa5, 0xfe, 0xcd, 0xfe, 0x40, 0xff, 0x87, 0x00, 0x35, 0x02, 0x6e, 0x04, + 0x60, 0x07, 0xf1, 0x09, 0xf9, 0x0c, 0xf9, 0x0f, 0xd4, 0x11, 0xe1, 0x13, + 0xc4, 0x14, 0xa2, 0x14, 0x2c, 0x14, 0x7c, 0x12, 0xa2, 0x10, 0x3c, 0x0e, + 0xb5, 0x0b, 0x83, 0x09, 0x17, 0x07, 0x2e, 0x06, 0xbd, 0x04, 0x36, 0x04, + 0x85, 0x04, 0x60, 0x03, 0x93, 0x03, 0x41, 0x02, 0x2a, 0x00, 0xf2, 0xfd, + 0x12, 0xfb, 0xf2, 0xf6, 0x43, 0xf4, 0x70, 0xef, 0x2d, 0xeb, 0x0c, 0xe7, + 0x97, 0xe1, 0x25, 0xde, 0x72, 0xda, 0xd3, 0xd7, 0x05, 0xd8, 0xe7, 0xd7, + 0x33, 0xdb, 0x03, 0xdf, 0x2a, 0xe4, 0xa1, 0xeb, 0x0a, 0xf2, 0x87, 0xf9, + 0xe2, 0xfe, 0x2b, 0x04, 0x59, 0x07, 0x58, 0x0a, 0x63, 0x0b, 0x2a, 0x0b, + 0xd6, 0x09, 0x63, 0x08, 0x91, 0x06, 0xd5, 0x04, 0x22, 0x04, 0x44, 0x02, + 0xf3, 0x01, 0x17, 0x02, 0xc1, 0x02, 0x4e, 0x04, 0xad, 0x06, 0x14, 0x08, + 0x16, 0x0a, 0xca, 0x0b, 0xbb, 0x0c, 0x4c, 0x0d, 0xeb, 0x0c, 0xe9, 0x0a, + 0x45, 0x08, 0x02, 0x06, 0x2c, 0x02, 0xca, 0xff, 0x2b, 0xfd, 0x38, 0xfb, + 0xa0, 0xfa, 0x2f, 0xfb, 0x83, 0xfc, 0xeb, 0xfe, 0x47, 0x02, 0xa8, 0x05, + 0xb5, 0x09, 0xc4, 0x0d, 0x3e, 0x11, 0x0a, 0x15, 0xd2, 0x17, 0xb3, 0x19, + 0x83, 0x1a, 0xe9, 0x19, 0x2f, 0x18, 0x6c, 0x16, 0x16, 0x13, 0xf5, 0x0f, + 0xc8, 0x0c, 0x2e, 0x09, 0x4c, 0x07, 0x8b, 0x05, 0x7a, 0x04, 0x2d, 0x04, + 0x8e, 0x03, 0xf8, 0x02, 0xf5, 0x01, 0x22, 0x00, 0xc1, 0xfd, 0x45, 0xfa, + 0x9d, 0xf6, 0x3d, 0xf2, 0x42, 0xed, 0x6f, 0xe8, 0x56, 0xe2, 0xed, 0xdc, + 0x7b, 0xd7, 0xe6, 0xd2, 0x5e, 0xd0, 0x09, 0xcf, 0x49, 0xd1, 0x29, 0xd4, + 0x02, 0xdb, 0x40, 0xe3, 0x18, 0xec, 0x6d, 0xf6, 0x20, 0xff, 0xb9, 0x06, + 0x5c, 0x0b, 0x2b, 0x10, 0x98, 0x10, 0x94, 0x10, 0x0f, 0x10, 0x72, 0x0c, + 0x7d, 0x0a, 0x03, 0x08, 0xae, 0x05, 0x0c, 0x04, 0xbf, 0x02, 0x55, 0x01, + 0x4b, 0x01, 0x8f, 0x01, 0xfb, 0x02, 0xd8, 0x04, 0x8c, 0x06, 0x18, 0x08, + 0x7d, 0x09, 0x6d, 0x09, 0x2b, 0x09, 0x58, 0x07, 0x64, 0x04, 0x7b, 0x01, + 0xc4, 0xfd, 0x9f, 0xfa, 0x82, 0xf8, 0x1e, 0xf7, 0xf0, 0xf6, 0x26, 0xf8, + 0x57, 0xfa, 0xab, 0xfd, 0x19, 0x02, 0xff, 0x06, 0x09, 0x0c, 0xe1, 0x10, + 0x84, 0x15, 0x29, 0x19, 0x55, 0x1c, 0x08, 0x1e, 0x75, 0x1e, 0x88, 0x1d, + 0x6a, 0x1b, 0xb3, 0x18, 0x5c, 0x15, 0x36, 0x12, 0x38, 0x0e, 0x1e, 0x0b, + 0xa5, 0x08, 0x93, 0x06, 0xcd, 0x05, 0x9d, 0x05, 0x4a, 0x05, 0x66, 0x05, + 0xc7, 0x04, 0x5f, 0x02, 0x6a, 0x00, 0xc5, 0xfb, 0x86, 0xf7, 0x17, 0xf3, + 0x68, 0xec, 0xa0, 0xe6, 0x5b, 0xdf, 0xe9, 0xd7, 0x47, 0xd1, 0xc1, 0xcb, + 0x69, 0xc8, 0xba, 0xc7, 0x92, 0xca, 0x2a, 0xcf, 0x3a, 0xd7, 0x97, 0xe1, + 0x44, 0xed, 0x92, 0xfa, 0x0c, 0x06, 0xba, 0x0f, 0x1b, 0x16, 0xbb, 0x1a, + 0xa9, 0x1c, 0xd8, 0x1c, 0x05, 0x1a, 0x7e, 0x15, 0xed, 0x0f, 0x5c, 0x0a, + 0xad, 0x05, 0x25, 0x01, 0xe9, 0xfc, 0x43, 0xfa, 0xdf, 0xf8, 0x11, 0xf9, + 0x6f, 0xfb, 0x77, 0xfd, 0x19, 0x00, 0xf2, 0x02, 0xd5, 0x04, 0x08, 0x06, + 0xb5, 0x05, 0x3d, 0x03, 0xbe, 0x00, 0x3e, 0xfd, 0x3a, 0xfa, 0xf8, 0xf6, + 0xd9, 0xf4, 0xeb, 0xf3, 0x54, 0xf4, 0x59, 0xf7, 0xb2, 0xfa, 0xa6, 0xff, + 0x95, 0x05, 0xf6, 0x0b, 0x08, 0x13, 0x9a, 0x19, 0x68, 0x1e, 0x47, 0x22, + 0xec, 0x23, 0x5a, 0x24, 0xf0, 0x22, 0x13, 0x1f, 0x8f, 0x1a, 0xcb, 0x14, + 0xff, 0x0f, 0x19, 0x0c, 0xbf, 0x08, 0x76, 0x06, 0x51, 0x05, 0x6a, 0x05, + 0x34, 0x06, 0xb8, 0x07, 0xb2, 0x07, 0x4d, 0x07, 0xad, 0x05, 0x82, 0x02, + 0x7e, 0xfe, 0xc9, 0xf9, 0x0b, 0xf3, 0xd7, 0xec, 0x24, 0xe5, 0x07, 0xdc, + 0xe1, 0xd3, 0xaf, 0xc9, 0x86, 0xc3, 0xd0, 0xbf, 0x20, 0xc0, 0x01, 0xc5, + 0xc0, 0xcc, 0xb9, 0xd8, 0xdf, 0xe6, 0x76, 0xf7, 0x84, 0x06, 0xa1, 0x13, + 0x61, 0x1d, 0x16, 0x23, 0xd0, 0x25, 0xb4, 0x24, 0xfc, 0x20, 0x56, 0x1b, + 0x97, 0x15, 0x89, 0x0e, 0x6b, 0x08, 0x71, 0x01, 0xc7, 0xfb, 0x75, 0xf7, + 0xa2, 0xf4, 0xad, 0xf3, 0xa8, 0xf3, 0x38, 0xf5, 0x11, 0xf8, 0x8d, 0xfc, + 0xb2, 0xff, 0xcb, 0x01, 0x20, 0x02, 0x6c, 0x01, 0x36, 0xff, 0xd9, 0xfc, + 0x2e, 0xf9, 0xfd, 0xf4, 0x97, 0xf3, 0xab, 0xf2, 0xe2, 0xf3, 0x15, 0xf7, + 0xc5, 0xf9, 0xb6, 0xfe, 0xbc, 0x05, 0xf9, 0x0b, 0x40, 0x13, 0xfb, 0x19, + 0x46, 0x1e, 0x47, 0x23, 0x35, 0x26, 0xc8, 0x25, 0x4e, 0x24, 0xbd, 0x20, + 0x6f, 0x1b, 0x28, 0x17, 0x71, 0x12, 0xa5, 0x0c, 0x11, 0x0a, 0x8f, 0x07, + 0xaf, 0x06, 0xed, 0x07, 0x5a, 0x08, 0x27, 0x09, 0x4e, 0x0a, 0x2b, 0x09, + 0xad, 0x07, 0xd3, 0x03, 0x8d, 0xfe, 0x73, 0xf8, 0x9f, 0xf1, 0x28, 0xea, + 0x5d, 0xe2, 0x1c, 0xda, 0xf1, 0xd0, 0x2c, 0xc9, 0x5a, 0xc2, 0x41, 0xbf, + 0x59, 0xbf, 0xb7, 0xc4, 0x85, 0xcd, 0x12, 0xda, 0x9e, 0xea, 0xd1, 0xfb, + 0x7b, 0x0c, 0x97, 0x1b, 0xd8, 0x25, 0x9b, 0x2b, 0x9e, 0x2d, 0x95, 0x2a, + 0xa8, 0x24, 0x2a, 0x1f, 0x0e, 0x17, 0xc9, 0x0e, 0x98, 0x08, 0xc8, 0x00, + 0x6f, 0xfa, 0x1c, 0xf7, 0xc3, 0xf2, 0x3f, 0xf1, 0xd5, 0xf0, 0xa1, 0xf0, + 0x41, 0xf2, 0x1e, 0xf5, 0x88, 0xf7, 0xd0, 0xf9, 0x2a, 0xfb, 0x74, 0xf9, + 0x72, 0xf8, 0x74, 0xf6, 0x6c, 0xf4, 0x4d, 0xf3, 0x22, 0xf3, 0x22, 0xf3, + 0xcc, 0xf5, 0x0a, 0xfa, 0x3d, 0xff, 0x86, 0x06, 0xc9, 0x0d, 0xda, 0x13, + 0xcb, 0x19, 0x15, 0x1f, 0x74, 0x22, 0xba, 0x25, 0x84, 0x26, 0x77, 0x24, + 0x33, 0x21, 0xff, 0x1c, 0x00, 0x18, 0xf0, 0x13, 0x6e, 0x0f, 0x65, 0x0b, + 0xea, 0x08, 0xc5, 0x07, 0x84, 0x08, 0x19, 0x0a, 0xec, 0x0b, 0xb2, 0x0c, + 0x50, 0x0c, 0x3f, 0x0a, 0x00, 0x06, 0x4d, 0x00, 0x24, 0xf9, 0x06, 0xf2, + 0xd0, 0xe9, 0xd0, 0xe1, 0xbc, 0xd9, 0x89, 0xd0, 0x96, 0xc9, 0xad, 0xc3, + 0x63, 0xc0, 0x66, 0xc1, 0xed, 0xc5, 0xf1, 0xce, 0xfa, 0xdb, 0x0f, 0xed, + 0xe3, 0xfd, 0xa8, 0x0f, 0xce, 0x1e, 0xc8, 0x28, 0xb5, 0x2f, 0x32, 0x31, + 0x03, 0x2e, 0xe2, 0x28, 0xbc, 0x20, 0xa3, 0x17, 0xa3, 0x0e, 0x09, 0x06, + 0x38, 0xfe, 0x9d, 0xf7, 0x1c, 0xf2, 0x7b, 0xed, 0x04, 0xec, 0xf1, 0xea, + 0x36, 0xec, 0x92, 0xee, 0x8f, 0xf0, 0xff, 0xf2, 0xa6, 0xf5, 0xbf, 0xf6, + 0x76, 0xf7, 0xe4, 0xf7, 0xf9, 0xf6, 0xd5, 0xf5, 0x9d, 0xf5, 0xb7, 0xf4, + 0x5b, 0xf6, 0x3c, 0xf9, 0x06, 0xfd, 0xb2, 0x01, 0x26, 0x07, 0x9b, 0x0c, + 0xfc, 0x12, 0x39, 0x19, 0x59, 0x1e, 0x03, 0x22, 0xef, 0x23, 0x41, 0x24, + 0xf1, 0x22, 0x24, 0x21, 0x3e, 0x1d, 0xeb, 0x18, 0x58, 0x14, 0xae, 0x0f, + 0xe1, 0x0b, 0x6a, 0x09, 0xdc, 0x07, 0xc2, 0x07, 0xe2, 0x08, 0xa9, 0x09, + 0x38, 0x0a, 0x62, 0x09, 0x90, 0x06, 0x4f, 0x01, 0x5c, 0xfa, 0x00, 0xf2, + 0x43, 0xe9, 0xd1, 0xe1, 0x3f, 0xda, 0x08, 0xd3, 0x01, 0xcc, 0x3f, 0xc6, + 0x5e, 0xc3, 0xcd, 0xc4, 0xf2, 0xca, 0xf9, 0xd3, 0x16, 0xe1, 0x5b, 0xef, + 0xa0, 0x00, 0x3b, 0x12, 0x38, 0x22, 0x6e, 0x2e, 0x3f, 0x33, 0xd1, 0x34, + 0xeb, 0x30, 0x0b, 0x2b, 0x74, 0x23, 0xe8, 0x18, 0x6f, 0x0e, 0xb4, 0x03, + 0x19, 0xfa, 0x7f, 0xf2, 0xe1, 0xec, 0xd4, 0xe8, 0x5a, 0xe6, 0x6b, 0xe5, + 0x9a, 0xe5, 0xa1, 0xe7, 0x3a, 0xeb, 0x8a, 0xee, 0xd9, 0xf1, 0x93, 0xf3, + 0xe3, 0xf2, 0xc1, 0xf3, 0xc0, 0xf3, 0xcd, 0xf4, 0xd5, 0xf6, 0xcd, 0xf7, + 0xd6, 0xf9, 0x9c, 0xfd, 0xe6, 0x02, 0x0d, 0x09, 0x4d, 0x0f, 0xa2, 0x13, + 0xa3, 0x17, 0xd0, 0x1a, 0xfc, 0x1c, 0x7d, 0x1e, 0xd9, 0x1d, 0x9b, 0x1b, + 0x9b, 0x18, 0x2e, 0x15, 0x7a, 0x12, 0x41, 0x10, 0xc2, 0x0e, 0x5a, 0x0d, + 0x6e, 0x0c, 0x27, 0x0c, 0x12, 0x0c, 0xed, 0x0c, 0xbf, 0x0d, 0x61, 0x0e, + 0x64, 0x0c, 0x32, 0x09, 0x2c, 0x03, 0x33, 0xfb, 0x4d, 0xf3, 0x89, 0xeb, + 0x11, 0xe2, 0x1a, 0xda, 0x3e, 0xd2, 0x0e, 0xca, 0xff, 0xc6, 0x79, 0xc5, + 0xbe, 0xc7, 0xac, 0xcf, 0x65, 0xda, 0x86, 0xe9, 0xac, 0xfb, 0xd5, 0x0c, + 0x6e, 0x1e, 0x5b, 0x2b, 0xe0, 0x34, 0x89, 0x38, 0x91, 0x36, 0xcc, 0x31, + 0xbe, 0x28, 0x0b, 0x1f, 0x8d, 0x14, 0x49, 0x09, 0x72, 0xfd, 0x4f, 0xf4, + 0x21, 0xec, 0xa3, 0xe7, 0xdc, 0xe4, 0x7a, 0xe3, 0x47, 0xe3, 0x23, 0xe5, + 0x4a, 0xe8, 0xd7, 0xec, 0x30, 0xf1, 0x06, 0xf4, 0xb7, 0xf5, 0x09, 0xf6, + 0x3e, 0xf5, 0x93, 0xf4, 0x3f, 0xf5, 0xd6, 0xf5, 0x04, 0xf8, 0x47, 0xfa, + 0x50, 0xfd, 0xe4, 0x00, 0x29, 0x07, 0x9b, 0x0c, 0x13, 0x11, 0x1e, 0x15, + 0x7e, 0x16, 0x6b, 0x18, 0x4c, 0x1a, 0x11, 0x1b, 0x09, 0x1a, 0x0c, 0x18, + 0xa0, 0x14, 0x15, 0x12, 0xa9, 0x10, 0xbf, 0x0e, 0xc4, 0x0d, 0xd4, 0x0b, + 0x1d, 0x0b, 0xd3, 0x0a, 0x64, 0x0b, 0xb5, 0x0b, 0x4f, 0x0b, 0x13, 0x09, + 0x10, 0x04, 0x62, 0xfd, 0xd3, 0xf4, 0x86, 0xec, 0x79, 0xe5, 0x8d, 0xde, + 0x60, 0xd7, 0xc0, 0xd0, 0x96, 0xca, 0x4f, 0xc8, 0xff, 0xca, 0x49, 0xd1, + 0xd2, 0xdc, 0x72, 0xea, 0x51, 0xfa, 0x32, 0x0c, 0xd5, 0x1d, 0x04, 0x2d, + 0x55, 0x37, 0x49, 0x3b, 0xcd, 0x38, 0x88, 0x33, 0x43, 0x2b, 0x8e, 0x21, + 0x4a, 0x17, 0xfc, 0x0a, 0x13, 0x00, 0x16, 0xf6, 0x18, 0xee, 0xa2, 0xe8, + 0x44, 0xe5, 0xc5, 0xe2, 0x81, 0xe2, 0x69, 0xe3, 0x82, 0xe4, 0xd6, 0xe7, + 0xef, 0xeb, 0xf3, 0xef, 0x56, 0xf2, 0x36, 0xf3, 0xf9, 0xf2, 0x87, 0xf3, + 0x99, 0xf5, 0x16, 0xf8, 0x92, 0xfa, 0x12, 0xfd, 0x66, 0x00, 0xc3, 0x04, + 0x04, 0x0a, 0x6d, 0x0e, 0xa2, 0x11, 0xa9, 0x13, 0x71, 0x14, 0x3f, 0x14, + 0x65, 0x13, 0x21, 0x12, 0x5b, 0x10, 0x6c, 0x0f, 0x6e, 0x0e, 0xfe, 0x0c, + 0x7a, 0x0c, 0x1f, 0x0c, 0xa5, 0x0c, 0xcb, 0x0d, 0xe3, 0x0d, 0xb1, 0x0d, + 0x3e, 0x0d, 0x79, 0x0c, 0xa7, 0x0a, 0x5d, 0x07, 0xc4, 0x00, 0x88, 0xf8, + 0x0a, 0xf0, 0xe5, 0xe8, 0x9c, 0xe2, 0x5e, 0xdd, 0x97, 0xd6, 0x17, 0xcf, + 0x16, 0xca, 0x61, 0xc8, 0x79, 0xcc, 0x17, 0xd5, 0x79, 0xe2, 0xad, 0xf1, + 0x78, 0x04, 0x48, 0x18, 0x86, 0x2a, 0x80, 0x38, 0xae, 0x3e, 0x3d, 0x3f, + 0x9f, 0x3a, 0xd4, 0x33, 0x68, 0x2a, 0xbe, 0x1f, 0x3c, 0x14, 0xcd, 0x08, + 0xde, 0xfb, 0x59, 0xf0, 0x9e, 0xe6, 0x53, 0xdf, 0x64, 0xdd, 0xc1, 0xdc, + 0xf3, 0xdd, 0x78, 0xe1, 0x14, 0xe6, 0x01, 0xec, 0xf6, 0xf2, 0x4e, 0xf7, + 0x83, 0xf8, 0x31, 0xf9, 0xb3, 0xf8, 0x87, 0xf9, 0x08, 0xfc, 0x1f, 0xfe, + 0xc2, 0xff, 0x0c, 0x02, 0x50, 0x04, 0x19, 0x07, 0x17, 0x0a, 0xa6, 0x0b, + 0x9d, 0x0c, 0x0e, 0x0d, 0x04, 0x0d, 0xe0, 0x0c, 0xad, 0x0c, 0xc5, 0x0c, + 0x59, 0x0b, 0x17, 0x0b, 0x38, 0x0a, 0x5e, 0x0a, 0x02, 0x0c, 0xd7, 0x0d, + 0x77, 0x0f, 0x81, 0x10, 0x93, 0x10, 0x05, 0x10, 0x5d, 0x10, 0x8c, 0x0d, + 0x40, 0x09, 0x61, 0x01, 0x5a, 0xf7, 0x59, 0xeb, 0x56, 0xe2, 0xa9, 0xd9, + 0x7e, 0xd3, 0xa0, 0xcd, 0x1f, 0xc8, 0x5c, 0xc5, 0xd9, 0xc6, 0x7e, 0xcf, + 0x10, 0xdc, 0xfc, 0xec, 0xb1, 0xfe, 0x02, 0x11, 0xb3, 0x23, 0x31, 0x35, + 0x65, 0x40, 0x09, 0x45, 0x96, 0x43, 0x05, 0x3c, 0x92, 0x32, 0x81, 0x26, + 0x6c, 0x18, 0x8d, 0x0a, 0x82, 0xfd, 0x64, 0xf3, 0x00, 0xeb, 0xc6, 0xe4, + 0xd8, 0xe0, 0x0b, 0xdf, 0xd4, 0xe0, 0x3c, 0xe4, 0x78, 0xe8, 0xc6, 0xec, + 0xbc, 0xf1, 0xfd, 0xf5, 0xd0, 0xf8, 0x7e, 0xfa, 0x00, 0xfa, 0x83, 0xf9, + 0x5c, 0xfa, 0xb7, 0xfb, 0x16, 0xfe, 0xd6, 0x00, 0xf6, 0x03, 0xb2, 0x08, + 0x2f, 0x0b, 0x07, 0x0d, 0x75, 0x0d, 0xfd, 0x0b, 0x1e, 0x0b, 0x12, 0x0b, + 0xe2, 0x08, 0x37, 0x08, 0x5f, 0x07, 0x0c, 0x06, 0xb6, 0x06, 0x31, 0x08, + 0x34, 0x0a, 0xda, 0x0c, 0x6f, 0x0f, 0xc7, 0x0f, 0x82, 0x10, 0x3d, 0x10, + 0x11, 0x0e, 0xdb, 0x09, 0xa7, 0x02, 0x26, 0xf8, 0x1b, 0xee, 0xf4, 0xe4, + 0x57, 0xdd, 0x99, 0xd6, 0x20, 0xd0, 0x4a, 0xc8, 0x8c, 0xc3, 0x8c, 0xc3, + 0x52, 0xc9, 0xb5, 0xd6, 0xc5, 0xe8, 0x48, 0xfd, 0xd3, 0x11, 0x55, 0x25, + 0xe2, 0x36, 0xbe, 0x42, 0x5b, 0x47, 0xc1, 0x44, 0xea, 0x3b, 0x42, 0x2f, + 0x9d, 0x23, 0xee, 0x16, 0xc1, 0x09, 0x64, 0xfe, 0x1b, 0xf3, 0x9d, 0xe9, + 0x73, 0xe3, 0x6c, 0xe0, 0xa4, 0xdf, 0x8f, 0xe3, 0x43, 0xe8, 0x78, 0xed, + 0xec, 0xf3, 0x33, 0xf9, 0xd5, 0xfd, 0x38, 0x00, 0xf7, 0xff, 0x47, 0xfe, + 0xc7, 0xfc, 0x86, 0xfc, 0xe2, 0xfd, 0x51, 0xff, 0x3a, 0x01, 0x03, 0x03, + 0x3e, 0x05, 0x11, 0x08, 0xba, 0x09, 0xa9, 0x0a, 0xf7, 0x09, 0x79, 0x09, + 0xc7, 0x07, 0x7c, 0x05, 0xa3, 0x03, 0x71, 0x02, 0x02, 0x02, 0x6c, 0x03, + 0x42, 0x05, 0x4c, 0x08, 0x76, 0x0c, 0xba, 0x0f, 0x2a, 0x12, 0xd7, 0x12, + 0xa4, 0x11, 0x86, 0x0e, 0x27, 0x09, 0xb2, 0x01, 0x4e, 0xf8, 0xc2, 0xee, + 0x0e, 0xe5, 0xa9, 0xdc, 0x1b, 0xd3, 0x63, 0xca, 0xca, 0xc2, 0x0a, 0xc0, + 0xeb, 0xc3, 0xa1, 0xcd, 0x37, 0xdd, 0x6b, 0xf0, 0x3d, 0x04, 0xb0, 0x18, + 0x06, 0x2b, 0x42, 0x38, 0xa5, 0x40, 0x08, 0x44, 0x02, 0x41, 0x01, 0x3a, + 0xb3, 0x2e, 0xe4, 0x20, 0xa4, 0x13, 0x68, 0x05, 0x63, 0xf8, 0xeb, 0xeb, + 0xe1, 0xe2, 0xe7, 0xdc, 0x48, 0xdc, 0x4d, 0xdf, 0xe1, 0xe3, 0x40, 0xeb, + 0xbb, 0xf2, 0x4c, 0xf9, 0xd5, 0xff, 0xe8, 0x03, 0x25, 0x04, 0xa7, 0x04, + 0x09, 0x03, 0xb6, 0x01, 0xc0, 0x02, 0xf9, 0x02, 0x6f, 0x03, 0x6b, 0x04, + 0x6b, 0x04, 0xca, 0x04, 0x7c, 0x06, 0x0a, 0x06, 0xfc, 0x05, 0x71, 0x05, + 0xec, 0x03, 0x40, 0x03, 0xa5, 0x02, 0xf0, 0x00, 0x31, 0x00, 0x9b, 0x00, + 0x7e, 0x02, 0x62, 0x06, 0x61, 0x0a, 0xb4, 0x0e, 0x36, 0x12, 0x23, 0x14, + 0xdd, 0x14, 0x96, 0x12, 0xe1, 0x0d, 0x90, 0x06, 0xd4, 0xfc, 0x3a, 0xf2, + 0x1d, 0xe7, 0x91, 0xdc, 0x6d, 0xd3, 0x04, 0xca, 0xf4, 0xc1, 0x18, 0xbe, + 0x8c, 0xc0, 0xfe, 0xc8, 0x8e, 0xda, 0x90, 0xee, 0x54, 0x02, 0x00, 0x17, + 0x04, 0x28, 0xeb, 0x36, 0x89, 0x41, 0xac, 0x44, 0x18, 0x41, 0x31, 0x39, + 0x20, 0x2d, 0xd6, 0x1e, 0x64, 0x11, 0x4a, 0x02, 0x95, 0xf4, 0x92, 0xe9, + 0x71, 0xdf, 0x27, 0xdb, 0x86, 0xdb, 0xbd, 0xdf, 0x18, 0xe8, 0x50, 0xf1, + 0x9d, 0xf8, 0x77, 0xff, 0x02, 0x05, 0x98, 0x07, 0x2e, 0x09, 0xd8, 0x07, + 0x36, 0x05, 0x5d, 0x02, 0xaa, 0x00, 0xcd, 0xff, 0xa8, 0xff, 0x65, 0xff, + 0xb4, 0xff, 0xee, 0x00, 0xa7, 0x02, 0x8f, 0x05, 0xdf, 0x06, 0xed, 0x06, + 0x4b, 0x06, 0x9b, 0x04, 0x4b, 0x02, 0xe3, 0x00, 0x6a, 0x00, 0x6c, 0x01, + 0xec, 0x04, 0x5a, 0x09, 0xd1, 0x0c, 0x90, 0x0f, 0x40, 0x11, 0xf0, 0x11, + 0x55, 0x12, 0xe3, 0x0f, 0x20, 0x0b, 0x08, 0x03, 0x0f, 0xf9, 0x5b, 0xee, + 0x21, 0xe3, 0xc4, 0xd7, 0x78, 0xce, 0x0e, 0xc6, 0xa0, 0xc0, 0xfb, 0xbf, + 0x41, 0xc6, 0x60, 0xd3, 0x97, 0xe6, 0x30, 0xfc, 0x9c, 0x0f, 0x9c, 0x21, + 0x3a, 0x30, 0xf7, 0x3a, 0x21, 0x41, 0xfe, 0x40, 0x28, 0x3b, 0x51, 0x31, + 0x33, 0x23, 0x36, 0x14, 0x3f, 0x05, 0xdb, 0xf7, 0xba, 0xec, 0xb1, 0xe4, + 0xb6, 0xdf, 0x06, 0xdf, 0xe4, 0xe2, 0x2f, 0xea, 0x67, 0xf2, 0xd7, 0xf9, + 0x08, 0xff, 0x56, 0x02, 0x71, 0x05, 0x0b, 0x07, 0x89, 0x07, 0xa0, 0x06, + 0x05, 0x06, 0x61, 0x04, 0xbe, 0x02, 0x0a, 0x02, 0x7c, 0x00, 0x7d, 0xff, + 0x40, 0x00, 0x3a, 0x01, 0x33, 0x02, 0xa0, 0x04, 0xb8, 0x04, 0x9a, 0x03, + 0x8e, 0x01, 0x57, 0xfe, 0x1f, 0xfd, 0x34, 0xfe, 0x0e, 0x00, 0x4e, 0x03, + 0xb2, 0x06, 0xea, 0x09, 0x63, 0x0d, 0x7a, 0x10, 0x45, 0x11, 0x20, 0x11, + 0xe0, 0x0e, 0xf4, 0x07, 0x1e, 0x00, 0xc7, 0xf7, 0x8a, 0xed, 0xe5, 0xe3, + 0x85, 0xd9, 0x1b, 0xcd, 0x82, 0xc3, 0x82, 0xc0, 0x9a, 0xc3, 0x21, 0xce, + 0xa0, 0xdf, 0x5d, 0xf2, 0x81, 0x06, 0x78, 0x1a, 0xe1, 0x2a, 0x07, 0x37, + 0x5a, 0x3d, 0x2b, 0x3e, 0x08, 0x39, 0x26, 0x31, 0x97, 0x25, 0x6c, 0x17, + 0x67, 0x09, 0x5c, 0xfa, 0xac, 0xec, 0xcb, 0xe3, 0x4f, 0xde, 0xe4, 0xde, + 0x97, 0xe3, 0x43, 0xea, 0x6c, 0xf3, 0xf2, 0xfb, 0x4c, 0x02, 0x26, 0x08, + 0x62, 0x0b, 0xe8, 0x0b, 0xe7, 0x0a, 0x5d, 0x08, 0x2a, 0x05, 0xcf, 0x03, + 0xf0, 0x02, 0xac, 0x01, 0xf9, 0x00, 0x45, 0x00, 0xf9, 0xff, 0x40, 0x01, + 0xce, 0x01, 0x55, 0x01, 0xa0, 0x00, 0xea, 0xfe, 0x6c, 0xfd, 0x6a, 0xfc, + 0xe1, 0xfb, 0x72, 0xfc, 0xe9, 0xfd, 0x89, 0x00, 0x63, 0x04, 0x8f, 0x08, + 0xf8, 0x0c, 0xd4, 0x10, 0xb8, 0x11, 0x52, 0x10, 0x4d, 0x0c, 0x55, 0x06, + 0x3b, 0xff, 0x23, 0xf7, 0xfa, 0xed, 0x67, 0xe2, 0xf8, 0xd5, 0x1c, 0xc9, + 0xc7, 0xc1, 0x27, 0xc0, 0x1a, 0xc9, 0xb5, 0xd6, 0x75, 0xe9, 0x2c, 0xfe, + 0x99, 0x0f, 0x32, 0x22, 0x0c, 0x2f, 0x78, 0x37, 0x3e, 0x3a, 0xa5, 0x38, + 0x48, 0x33, 0xaf, 0x2a, 0x3f, 0x1f, 0xfe, 0x10, 0xc1, 0x01, 0x34, 0xf3, + 0xa4, 0xe7, 0x25, 0xe0, 0x64, 0xde, 0xb5, 0xe1, 0xc3, 0xe8, 0xf6, 0xf1, + 0x40, 0xfb, 0x9b, 0x02, 0x24, 0x07, 0xb6, 0x09, 0x20, 0x0b, 0x39, 0x0a, + 0xef, 0x09, 0xde, 0x08, 0x27, 0x07, 0xce, 0x05, 0xb2, 0x04, 0x4f, 0x03, + 0xb5, 0x01, 0x11, 0x02, 0xc7, 0x01, 0xc1, 0x01, 0x8a, 0x02, 0x8a, 0x01, + 0xfd, 0x00, 0x2b, 0xfe, 0xd2, 0xfa, 0x33, 0xf8, 0xae, 0xf6, 0x99, 0xf7, + 0xfd, 0xfa, 0x0e, 0xff, 0xf9, 0x04, 0xc4, 0x0a, 0x99, 0x10, 0xaf, 0x13, + 0x74, 0x14, 0x73, 0x12, 0x37, 0x0d, 0x64, 0x05, 0x6e, 0xfb, 0x3c, 0xf0, + 0xe7, 0xe2, 0x64, 0xd6, 0xe8, 0xc8, 0x98, 0xbe, 0x38, 0xbc, 0xdf, 0xc2, + 0xac, 0xd1, 0xef, 0xe5, 0xe9, 0xfa, 0x83, 0x0d, 0x3e, 0x1f, 0xa8, 0x2f, + 0x91, 0x39, 0x1a, 0x3d, 0xc2, 0x38, 0xda, 0x30, 0x21, 0x27, 0x50, 0x1b, + 0xe1, 0x0e, 0x1e, 0x01, 0x1c, 0xf5, 0xf3, 0xeb, 0xe5, 0xe4, 0xb3, 0xe2, + 0x3b, 0xe5, 0xbe, 0xeb, 0xcc, 0xf4, 0x32, 0xfd, 0x15, 0x03, 0xbe, 0x07, + 0x1f, 0x0a, 0x30, 0x0b, 0x30, 0x09, 0x06, 0x07, 0xb8, 0x03, 0x87, 0x03, + 0xd7, 0x05, 0x8e, 0x06, 0x4d, 0x07, 0x1d, 0x06, 0xea, 0x03, 0xc4, 0x03, + 0x63, 0x03, 0x08, 0x02, 0x7f, 0x00, 0x98, 0xfd, 0x4c, 0xfa, 0xb9, 0xfa, + 0x64, 0xfa, 0x69, 0xfa, 0xdc, 0xfb, 0xde, 0xfb, 0x47, 0xff, 0xbe, 0x04, + 0xf9, 0x0a, 0x96, 0x10, 0xe2, 0x13, 0x5a, 0x14, 0xb7, 0x12, 0x79, 0x0e, + 0xa2, 0x06, 0xf4, 0xfa, 0xd9, 0xed, 0xeb, 0xde, 0xc4, 0xd1, 0x85, 0xc5, + 0xe7, 0xbc, 0x81, 0xbd, 0xe3, 0xc4, 0x29, 0xd4, 0x54, 0xe8, 0xc0, 0xfc, + 0x18, 0x11, 0x95, 0x21, 0x30, 0x2f, 0x42, 0x36, 0x74, 0x39, 0x2f, 0x36, + 0x24, 0x30, 0xf1, 0x24, 0x5d, 0x1a, 0xac, 0x0d, 0x4d, 0x01, 0x76, 0xf6, + 0x17, 0xed, 0x5c, 0xe6, 0x15, 0xe7, 0x76, 0xea, 0xda, 0xef, 0x00, 0xf9, + 0x1a, 0xfe, 0x22, 0x02, 0xef, 0x04, 0xd4, 0x03, 0x88, 0x02, 0x3f, 0x03, + 0x47, 0x02, 0x9c, 0x02, 0x59, 0x03, 0xa7, 0x04, 0xde, 0x06, 0x72, 0x0a, + 0xdb, 0x0b, 0xe6, 0x0b, 0x56, 0x0b, 0xf4, 0x08, 0x15, 0x07, 0x84, 0x03, + 0x31, 0xff, 0x9d, 0xfa, 0xcf, 0xf6, 0x4f, 0xf4, 0xcc, 0xf3, 0xfa, 0xf4, + 0x37, 0xf8, 0xdd, 0xfc, 0x67, 0x02, 0xa7, 0x09, 0x28, 0x10, 0x30, 0x15, + 0xaa, 0x16, 0x56, 0x14, 0x38, 0x0e, 0x55, 0x06, 0x97, 0xfb, 0xab, 0xed, + 0x71, 0xdf, 0x7a, 0xd0, 0x11, 0xc2, 0x69, 0xbb, 0x24, 0xbb, 0xe6, 0xc4, + 0x6b, 0xd5, 0xac, 0xeb, 0x2c, 0x01, 0x2e, 0x15, 0xc6, 0x25, 0xae, 0x30, + 0xff, 0x36, 0x0f, 0x37, 0xab, 0x33, 0xcf, 0x2c, 0x21, 0x21, 0xb3, 0x13, + 0x5f, 0x05, 0xb1, 0xf9, 0x93, 0xf2, 0x5c, 0xf0, 0x07, 0xef, 0x5f, 0xf0, + 0x97, 0xf2, 0x9c, 0xf5, 0x76, 0xfb, 0x08, 0xfe, 0x0b, 0x01, 0xfc, 0xff, + 0xd1, 0xff, 0xaf, 0x00, 0x1a, 0x01, 0x6d, 0x02, 0x21, 0x03, 0xe6, 0x03, + 0x51, 0x06, 0x4b, 0x0a, 0xa6, 0x0d, 0x13, 0x10, 0x56, 0x10, 0x72, 0x0d, + 0xbe, 0x08, 0x98, 0x03, 0x20, 0xfd, 0xea, 0xf8, 0xd7, 0xf5, 0x27, 0xf4, + 0x65, 0xf4, 0x22, 0xf6, 0xc0, 0xf9, 0xa1, 0xfe, 0xcf, 0x03, 0x34, 0x09, + 0xe3, 0x0d, 0x00, 0x11, 0x0d, 0x13, 0xa3, 0x11, 0x41, 0x0d, 0xa5, 0x05, + 0x45, 0xfc, 0xee, 0xef, 0x1b, 0xe4, 0x5d, 0xd5, 0xb1, 0xc5, 0x76, 0xbd, + 0xa5, 0xbb, 0xdf, 0xc8, 0x53, 0xdb, 0xa8, 0xf1, 0x71, 0x06, 0xa3, 0x16, + 0xc2, 0x23, 0x44, 0x2c, 0x9d, 0x30, 0x2d, 0x2f, 0x56, 0x29, 0x2a, 0x22, + 0xc3, 0x15, 0x4f, 0x0b, 0xb4, 0xfe, 0x42, 0xf7, 0xb0, 0xf3, 0xb0, 0xf2, + 0x70, 0xf6, 0x6f, 0xfa, 0xd1, 0xff, 0x42, 0x04, 0x51, 0x06, 0x2b, 0x06, + 0xca, 0x03, 0xd3, 0xff, 0xf8, 0xfa, 0xf3, 0xf8, 0x32, 0xf8, 0x1f, 0xf9, + 0x0a, 0xfe, 0xfe, 0x01, 0x27, 0x09, 0x84, 0x0f, 0xd7, 0x13, 0xec, 0x15, + 0x17, 0x15, 0x13, 0x11, 0xa5, 0x0c, 0x19, 0x05, 0xd8, 0xfc, 0x98, 0xf6, + 0x10, 0xf2, 0x1b, 0xef, 0xb8, 0xf0, 0x14, 0xf3, 0x37, 0xf7, 0x9b, 0xfd, + 0xbf, 0x03, 0x0c, 0x09, 0xc7, 0x0e, 0x7a, 0x0f, 0x3f, 0x0f, 0x15, 0x0d, + 0xee, 0x06, 0xbe, 0xff, 0xf5, 0xf4, 0x78, 0xe7, 0xb5, 0xd9, 0x45, 0xcb, + 0xa5, 0xc2, 0xab, 0xc0, 0xbb, 0xc7, 0xd4, 0xd9, 0xf9, 0xed, 0x62, 0x04, + 0x8b, 0x16, 0xdc, 0x22, 0xa0, 0x2a, 0xca, 0x2c, 0xf8, 0x28, 0x07, 0x23, + 0x82, 0x1c, 0xfe, 0x12, 0x0a, 0x0c, 0xa6, 0x03, 0x98, 0xfb, 0xf2, 0xf6, + 0x44, 0xf5, 0x06, 0xf7, 0xfc, 0xfa, 0x6c, 0xfe, 0x54, 0x02, 0x46, 0x05, + 0x9b, 0x04, 0xab, 0x02, 0x67, 0x01, 0x04, 0xfc, 0x61, 0xf9, 0x26, 0xf9, + 0x49, 0xfa, 0xa8, 0xff, 0x68, 0x06, 0xad, 0x0b, 0xc9, 0x10, 0x92, 0x14, + 0xc1, 0x15, 0xa1, 0x15, 0xa3, 0x12, 0x7b, 0x0c, 0xf1, 0x04, 0xba, 0xfc, + 0x5b, 0xf5, 0x82, 0xf1, 0xc0, 0xee, 0xb9, 0xee, 0xb5, 0xf1, 0x40, 0xf7, + 0xf6, 0xfc, 0xa9, 0x04, 0x4d, 0x08, 0xd9, 0x0b, 0x17, 0x0c, 0x40, 0x0b, + 0x86, 0x07, 0xf1, 0x04, 0x00, 0xff, 0xe9, 0xf5, 0x47, 0xea, 0x18, 0xdd, + 0x9c, 0xcd, 0x54, 0xc3, 0x2f, 0xc1, 0xab, 0xc7, 0xcc, 0xd8, 0x0f, 0xee, + 0xe0, 0x04, 0xfb, 0x17, 0xd0, 0x24, 0xc5, 0x2a, 0x08, 0x2f, 0xa8, 0x28, + 0x5c, 0x24, 0x30, 0x1c, 0xf7, 0x12, 0x35, 0x0a, 0xd8, 0x02, 0x46, 0xfd, + 0xc4, 0xfa, 0xa5, 0xfc, 0x57, 0xfc, 0xd0, 0xfd, 0x69, 0xfe, 0x35, 0xfe, + 0xc8, 0x00, 0x83, 0xff, 0x0c, 0xfc, 0xd5, 0xf8, 0xe5, 0xf4, 0x7c, 0xf3, + 0x77, 0xf6, 0xb2, 0xf8, 0x4d, 0x00, 0xe0, 0x08, 0x71, 0x11, 0xc5, 0x18, + 0xc5, 0x1d, 0xad, 0x1c, 0x49, 0x18, 0x7b, 0x11, 0x61, 0x09, 0xa0, 0x02, + 0x6e, 0xfc, 0x93, 0xf5, 0x1f, 0xf2, 0xfa, 0xef, 0x1f, 0xf1, 0x0e, 0xf6, + 0x77, 0xfa, 0xec, 0xfe, 0x37, 0x03, 0x19, 0x05, 0xaa, 0x06, 0xb2, 0x05, + 0x89, 0x03, 0xea, 0x01, 0xf0, 0xfc, 0xe6, 0xf7, 0xa8, 0xf0, 0xa0, 0xe5, + 0x7c, 0xd8, 0xdf, 0xcb, 0xc5, 0xc2, 0x13, 0xc5, 0x09, 0xd1, 0x2f, 0xe6, + 0xce, 0xfb, 0x7d, 0x0c, 0xaa, 0x19, 0x8a, 0x22, 0x39, 0x28, 0x00, 0x2c, + 0xf1, 0x24, 0xea, 0x1d, 0x0d, 0x16, 0xd3, 0x0f, 0xda, 0x0d, 0xa9, 0x08, + 0x2d, 0x05, 0x57, 0x01, 0x95, 0xff, 0x53, 0xff, 0x46, 0x00, 0xdc, 0x00, + 0x34, 0xfe, 0xa9, 0xfa, 0x90, 0xf4, 0xc7, 0xf1, 0x95, 0xf0, 0x9b, 0xf1, + 0x12, 0xf5, 0x74, 0xfa, 0x15, 0x01, 0x00, 0x0a, 0x0a, 0x12, 0x54, 0x17, + 0xef, 0x19, 0xf1, 0x17, 0x59, 0x12, 0x97, 0x0d, 0xa0, 0x07, 0xc5, 0x03, + 0x53, 0x00, 0x2f, 0xfd, 0x4b, 0xfa, 0xb4, 0xf8, 0x67, 0xf8, 0x32, 0xf8, + 0xf6, 0xfa, 0x04, 0xfc, 0xfa, 0xfd, 0x1d, 0x01, 0xa7, 0x02, 0x01, 0x04, + 0xa6, 0x03, 0xa9, 0x02, 0x86, 0x01, 0x75, 0xff, 0x04, 0xf9, 0xff, 0xf0, + 0x1c, 0xe3, 0xc4, 0xd4, 0x09, 0xc7, 0x64, 0xc0, 0x7f, 0xc4, 0x34, 0xd2, + 0xa6, 0xe8, 0x5f, 0xfd, 0x55, 0x0d, 0x31, 0x1a, 0x01, 0x22, 0x4e, 0x29, + 0xbe, 0x2a, 0x6d, 0x27, 0x9e, 0x1e, 0x96, 0x17, 0x76, 0x11, 0x3a, 0x0b, + 0xc5, 0x09, 0xb9, 0x04, 0xc5, 0x03, 0x80, 0x03, 0x82, 0x02, 0x6a, 0x02, + 0xea, 0xfe, 0x34, 0xfa, 0xc5, 0xf5, 0xdd, 0xf0, 0xb9, 0xed, 0x6c, 0xed, + 0x0a, 0xef, 0xeb, 0xf0, 0xee, 0xf8, 0xea, 0xff, 0x69, 0x0a, 0xcc, 0x15, + 0xf4, 0x1b, 0x34, 0x1d, 0x24, 0x1d, 0xb2, 0x16, 0x8f, 0x0f, 0xa6, 0x0b, + 0x42, 0x04, 0x21, 0x01, 0x96, 0xfe, 0xd4, 0xfb, 0x90, 0xfa, 0xe6, 0xfa, + 0x8e, 0xf9, 0x8d, 0xfa, 0x21, 0xfb, 0x1e, 0xfb, 0x08, 0xfd, 0x92, 0xfe, + 0x4e, 0x00, 0x78, 0x04, 0x35, 0x05, 0xc5, 0x05, 0x5b, 0x02, 0x5a, 0xfc, + 0x9c, 0xf0, 0x35, 0xe1, 0x52, 0xd0, 0x06, 0xc3, 0x23, 0xc0, 0xd3, 0xc8, + 0x69, 0xdc, 0xbc, 0xf0, 0xbc, 0x03, 0x3a, 0x12, 0xa9, 0x1b, 0xcb, 0x1e, + 0x91, 0x1f, 0x30, 0x1b, 0x62, 0x16, 0x1a, 0x14, 0x40, 0x13, 0x1d, 0x13, + 0x66, 0x11, 0x41, 0x0f, 0x55, 0x0e, 0x86, 0x0d, 0x67, 0x0c, 0xc4, 0x07, + 0x1e, 0x04, 0x4b, 0xff, 0x11, 0xfa, 0x10, 0xf5, 0xbf, 0xee, 0x1a, 0xec, + 0xd4, 0xec, 0x01, 0xf1, 0xdc, 0xf7, 0x7a, 0xfe, 0x12, 0x06, 0x11, 0x09, + 0x49, 0x0d, 0xf7, 0x0d, 0xca, 0x0d, 0x43, 0x0c, 0x49, 0x0a, 0x25, 0x08, + 0x30, 0x08, 0xf2, 0x08, 0x1b, 0x09, 0xac, 0x07, 0x73, 0x04, 0x1f, 0x03, + 0xff, 0x00, 0xc1, 0xff, 0xc0, 0xfd, 0x78, 0xfb, 0x51, 0xfa, 0xb8, 0xfb, + 0x7f, 0xfe, 0x01, 0x03, 0x77, 0x07, 0x15, 0x07, 0x30, 0x05, 0x9a, 0xff, + 0x1a, 0xf7, 0xab, 0xeb, 0x67, 0xdd, 0x26, 0xce, 0xcb, 0xc4, 0x2f, 0xc3, + 0x54, 0xd0, 0x18, 0xe1, 0x7b, 0xf5, 0x3d, 0x04, 0xa4, 0x0a, 0x1b, 0x10, + 0x48, 0x14, 0x5c, 0x17, 0xc2, 0x17, 0x61, 0x13, 0x8b, 0x0e, 0x9d, 0x0d, + 0xe7, 0x10, 0x3f, 0x14, 0x73, 0x16, 0xcd, 0x16, 0xa4, 0x12, 0x1e, 0x13, + 0xaf, 0x10, 0xae, 0x0a, 0x13, 0x04, 0xc4, 0xf9, 0x02, 0xf1, 0x0a, 0xed, + 0x3e, 0xee, 0xf3, 0xf1, 0x4b, 0xf8, 0x39, 0xfb, 0xec, 0xfc, 0x64, 0xff, + 0xef, 0xff, 0x22, 0x03, 0x1f, 0x06, 0x6f, 0x06, 0xb1, 0x05, 0x48, 0x05, + 0x4a, 0x04, 0xe0, 0x05, 0xad, 0x09, 0x68, 0x0a, 0xda, 0x0a, 0x7a, 0x0a, + 0xf5, 0x04, 0x0b, 0x03, 0xa2, 0xff, 0x1c, 0xff, 0x29, 0xff, 0x4b, 0xff, + 0xe5, 0xff, 0x52, 0x01, 0x08, 0x05, 0xb1, 0x06, 0xb8, 0x07, 0x07, 0x06, + 0x88, 0x00, 0x64, 0xf9, 0xdc, 0xf1, 0xec, 0xe5, 0xfe, 0xd7, 0xec, 0xc6, + 0x22, 0xc3, 0x7d, 0xc9, 0x39, 0xd9, 0x6e, 0xf2, 0xea, 0xfd, 0x30, 0x0a, + 0x6e, 0x0b, 0x26, 0x0c, 0xa8, 0x09, 0xf4, 0x07, 0xe8, 0x05, 0x8a, 0x07, + 0x7f, 0x0e, 0xa5, 0x12, 0x18, 0x19, 0xf7, 0x1d, 0x75, 0x1c, 0x0d, 0x1d, + 0xc5, 0x17, 0xef, 0x11, 0x95, 0x0b, 0xae, 0x03, 0x56, 0xfc, 0x10, 0xf6, + 0x01, 0xf2, 0x45, 0xf3, 0xc9, 0xf8, 0x06, 0xfd, 0x06, 0x00, 0x24, 0xfe, + 0x02, 0xfb, 0x8f, 0xfa, 0xae, 0xf8, 0x65, 0xf8, 0xf2, 0xf9, 0xd6, 0xfb, + 0xba, 0xfe, 0x77, 0x04, 0x02, 0x06, 0xba, 0x08, 0x6a, 0x0a, 0x65, 0x0b, + 0x6c, 0x0b, 0x3a, 0x09, 0x15, 0x06, 0x42, 0x03, 0xe5, 0xff, 0xf9, 0xff, + 0xf2, 0x01, 0xde, 0x03, 0x60, 0x08, 0x58, 0x0a, 0xc3, 0x08, 0x90, 0x06, + 0x59, 0x05, 0xb9, 0x02, 0x48, 0x04, 0x24, 0x01, 0xfb, 0xf9, 0xf5, 0xef, + 0x23, 0xe1, 0xaa, 0xcf, 0x80, 0xc7, 0x3e, 0xc4, 0xa0, 0xcf, 0x84, 0xe4, + 0xb8, 0xf8, 0x5b, 0x05, 0x84, 0x07, 0xf2, 0x04, 0xb2, 0xff, 0x1b, 0xfe, + 0x92, 0x01, 0x3b, 0x02, 0xee, 0x0b, 0x38, 0x12, 0x78, 0x1a, 0x8f, 0x20, + 0xa6, 0x21, 0x60, 0x21, 0x39, 0x1c, 0xb0, 0x14, 0x8f, 0x0c, 0x1f, 0x02, + 0xbd, 0xfd, 0x3b, 0xfd, 0x70, 0xfb, 0x9a, 0xfc, 0xd3, 0xfd, 0x7d, 0xfe, + 0x96, 0x01, 0x37, 0xff, 0x75, 0xfa, 0xcc, 0xf4, 0x01, 0xf3, 0x26, 0xf5, + 0xd9, 0xf8, 0xe1, 0xfb, 0xbe, 0xfc, 0x40, 0xff, 0x43, 0x01, 0xe3, 0x05, + 0x50, 0x08, 0xfc, 0x08, 0xde, 0x07, 0xba, 0x03, 0x8d, 0x01, 0xd4, 0xff, + 0x87, 0xfd, 0x6d, 0x00, 0x0a, 0x03, 0x8c, 0x05, 0x21, 0x07, 0x3c, 0x07, + 0x40, 0x05, 0x6e, 0x05, 0x45, 0x03, 0x59, 0x02, 0x96, 0x02, 0xb0, 0x00, + 0x35, 0xff, 0x29, 0xfb, 0xeb, 0xed, 0xfd, 0xde, 0xe8, 0xd0, 0x0d, 0xc9, + 0x5d, 0xd3, 0xf5, 0xe6, 0xc1, 0xfa, 0x51, 0x07, 0x19, 0x07, 0x55, 0xfe, + 0xa3, 0xfa, 0xcf, 0xf4, 0x05, 0xf8, 0x63, 0xfe, 0x1b, 0x06, 0xa5, 0x10, + 0x1f, 0x17, 0xb1, 0x17, 0x5e, 0x18, 0x12, 0x1a, 0x07, 0x19, 0xaa, 0x17, + 0x7f, 0x12, 0xe8, 0x0b, 0x3b, 0x07, 0xdd, 0x03, 0xe1, 0x00, 0x5a, 0x03, + 0xe2, 0x04, 0xef, 0x05, 0xc7, 0x05, 0xbc, 0x01, 0xc0, 0xfb, 0x68, 0xf6, + 0x07, 0xf4, 0x18, 0xf3, 0x58, 0xf5, 0xb7, 0xf9, 0x8f, 0xfc, 0x5c, 0x00, + 0xe9, 0xfe, 0xea, 0xfe, 0xe5, 0xfd, 0xea, 0xfc, 0xe7, 0xfa, 0xde, 0xfa, + 0x45, 0xfb, 0x57, 0xfd, 0x71, 0x01, 0xe6, 0x03, 0x08, 0x09, 0x99, 0x0c, + 0xe9, 0x0c, 0x11, 0x0b, 0x5e, 0x07, 0xc7, 0x03, 0xd1, 0x02, 0x69, 0x03, + 0xc8, 0x04, 0xc1, 0x07, 0x78, 0x07, 0x72, 0x03, 0xa7, 0xfb, 0x27, 0xef, + 0x97, 0xe4, 0xde, 0xd6, 0xd8, 0xcf, 0x4d, 0xd3, 0x26, 0xdf, 0x9e, 0xf5, + 0x09, 0x05, 0xe2, 0x06, 0x7c, 0xfe, 0x3a, 0xf3, 0xc5, 0xed, 0x65, 0xf4, + 0x74, 0xfb, 0x2e, 0x04, 0xcb, 0x08, 0xb1, 0x0b, 0xdd, 0x10, 0x6f, 0x16, + 0x69, 0x1a, 0x94, 0x17, 0x89, 0x15, 0x3e, 0x10, 0xb1, 0x0d, 0x45, 0x0d, + 0x67, 0x0b, 0xb3, 0x0b, 0xde, 0x0b, 0xa2, 0x0a, 0xd4, 0x09, 0x5d, 0x07, + 0xaf, 0x04, 0x1a, 0xff, 0xe5, 0xf9, 0x94, 0xf6, 0xcd, 0xf5, 0x38, 0xfa, + 0x63, 0xfc, 0x17, 0xfc, 0xe7, 0xf8, 0xc9, 0xf5, 0x96, 0xf3, 0xe3, 0xf5, + 0x48, 0xf3, 0x3b, 0xf4, 0xba, 0xf8, 0xb0, 0xfb, 0x6b, 0xff, 0x4a, 0x02, + 0x97, 0x03, 0x94, 0x06, 0x89, 0x0b, 0xbc, 0x09, 0xef, 0x09, 0x18, 0x07, + 0xb9, 0x02, 0x5f, 0x03, 0x0f, 0x05, 0x02, 0x06, 0x91, 0x0b, 0x0d, 0x0c, + 0xf5, 0x0a, 0x3f, 0x02, 0x4d, 0xf9, 0x09, 0xeb, 0x7e, 0xde, 0xfd, 0xd7, + 0x4d, 0xd5, 0x9b, 0xe0, 0xa0, 0xf4, 0xa4, 0x04, 0xbc, 0x09, 0xa0, 0x03, + 0xdc, 0xf2, 0xf1, 0xe7, 0x41, 0xe9, 0x21, 0xef, 0x41, 0xfb, 0x5c, 0x05, + 0x36, 0x09, 0xeb, 0x10, 0x49, 0x13, 0xbb, 0x14, 0xad, 0x16, 0xf3, 0x14, + 0x87, 0x0f, 0x22, 0x0f, 0x3e, 0x0a, 0x63, 0x09, 0xdc, 0x0b, 0xf0, 0x0d, + 0x3f, 0x12, 0xbc, 0x14, 0xc1, 0x10, 0x0a, 0x0a, 0x5d, 0x03, 0xed, 0xfa, + 0x08, 0xf8, 0x19, 0xf6, 0xc9, 0xf9, 0x52, 0xfd, 0xb3, 0xfd, 0x7e, 0xfb, + 0x0a, 0xf9, 0x63, 0xf9, 0xab, 0xf7, 0xa7, 0xf7, 0x67, 0xf5, 0xe3, 0xee, + 0xa6, 0xf0, 0xb2, 0xf4, 0x28, 0xfb, 0x14, 0x03, 0x71, 0x05, 0xbd, 0x06, + 0xb7, 0x05, 0x4c, 0x03, 0x93, 0x02, 0x36, 0x02, 0x13, 0x04, 0xba, 0x09, + 0x90, 0x0d, 0xc6, 0x0b, 0x69, 0x0a, 0x96, 0x06, 0xdf, 0x03, 0xd0, 0x01, + 0xf3, 0xf9, 0xe3, 0xef, 0x9f, 0xe5, 0x8c, 0xdb, 0xb2, 0xde, 0x26, 0xec, + 0xf2, 0xfa, 0x89, 0x05, 0x6b, 0x02, 0x15, 0xf5, 0x17, 0xea, 0x30, 0xe8, + 0xa0, 0xef, 0x4d, 0xf6, 0xdd, 0xfc, 0xc6, 0x02, 0x1e, 0x07, 0xe1, 0x0b, + 0x74, 0x0e, 0x43, 0x0f, 0xfd, 0x0a, 0x3d, 0x0d, 0x0b, 0x09, 0x9e, 0x0a, + 0x42, 0x08, 0xe6, 0x0c, 0x80, 0x0e, 0x0a, 0x14, 0x05, 0x12, 0xe4, 0x0f, + 0x5e, 0x0e, 0x51, 0x09, 0x14, 0x05, 0x54, 0xff, 0xba, 0xfb, 0x52, 0xfb, + 0xd6, 0x01, 0x02, 0x03, 0xf0, 0x04, 0x01, 0x00, 0x80, 0xf9, 0xc7, 0xf2, + 0xdc, 0xee, 0x2c, 0xef, 0xa3, 0xed, 0xf2, 0xf1, 0x6d, 0xf3, 0xf1, 0xf6, + 0x11, 0xfb, 0x47, 0xff, 0x18, 0x02, 0x83, 0x00, 0x15, 0xff, 0x2c, 0x00, + 0x33, 0x03, 0xd8, 0x07, 0x09, 0x0c, 0x22, 0x0b, 0x3e, 0x0f, 0x1b, 0x11, + 0x79, 0x15, 0x5f, 0x12, 0x39, 0x10, 0xcd, 0x03, 0x44, 0xfc, 0x87, 0xf3, + 0xe7, 0xea, 0xc4, 0xe1, 0x9f, 0xe0, 0xfa, 0xe7, 0xfe, 0xf8, 0xc1, 0x03, + 0x28, 0x06, 0x4f, 0xf9, 0xe2, 0xe6, 0xe4, 0xdf, 0xd8, 0xe1, 0x2a, 0xec, + 0xba, 0xf8, 0x97, 0x02, 0x60, 0x06, 0xc8, 0x07, 0x77, 0x06, 0x47, 0x01, + 0x71, 0x03, 0x0e, 0x0a, 0xb7, 0x08, 0xf7, 0x09, 0x59, 0x07, 0x22, 0x07, + 0x34, 0x10, 0xcb, 0x14, 0x1d, 0x18, 0xb4, 0x16, 0xa0, 0x0f, 0xd3, 0x0b, + 0xb6, 0x07, 0xff, 0x04, 0x33, 0x01, 0xd5, 0x02, 0x85, 0x04, 0xac, 0x07, + 0xe2, 0x06, 0xc7, 0x00, 0x00, 0xfd, 0x05, 0xf7, 0x81, 0xf3, 0x9a, 0xee, + 0x48, 0xec, 0x88, 0xee, 0x3b, 0xf5, 0x65, 0xf7, 0x8f, 0xfc, 0x9c, 0xfa, + 0x15, 0xfc, 0x99, 0xfb, 0xe1, 0xf7, 0x4c, 0xf7, 0xbe, 0xfb, 0x78, 0x08, + 0x4c, 0x12, 0x93, 0x14, 0x4b, 0x11, 0xdc, 0x08, 0xd8, 0x09, 0xc4, 0x0f, + 0x08, 0x12, 0xe3, 0x11, 0x47, 0x09, 0xcd, 0x00, 0xf6, 0xf7, 0x1c, 0xef, + 0x46, 0xe9, 0x94, 0xe5, 0x4a, 0xeb, 0xfd, 0xf7, 0x32, 0x00, 0x7c, 0x02, + 0xb1, 0xf6, 0x6d, 0xe9, 0x9c, 0xe2, 0x52, 0xe4, 0xa6, 0xed, 0x87, 0xf8, + 0x77, 0x00, 0x4c, 0x05, 0xa9, 0x02, 0x13, 0x04, 0xc2, 0xfb, 0x8b, 0xff, + 0x79, 0x00, 0x48, 0x06, 0xae, 0x0a, 0x79, 0x0e, 0xe7, 0x0e, 0x40, 0x10, + 0x32, 0x14, 0x2f, 0x16, 0x3b, 0x15, 0xbf, 0x10, 0xe4, 0x07, 0x18, 0x05, + 0x98, 0x04, 0x94, 0x08, 0xc2, 0x0b, 0x79, 0x0b, 0xbe, 0x09, 0x61, 0x05, + 0xbf, 0xff, 0x4a, 0xf8, 0xa5, 0xf1, 0x79, 0xf1, 0x04, 0xf1, 0xcf, 0xf4, + 0x23, 0xf8, 0xbc, 0xf6, 0xae, 0xf6, 0x51, 0xf4, 0xca, 0xf2, 0x4f, 0xf2, + 0xc4, 0xf1, 0x8f, 0xf4, 0xdc, 0xf7, 0x07, 0x00, 0xb6, 0x07, 0x5a, 0x0c, + 0x1e, 0x10, 0xdd, 0x10, 0x1a, 0x10, 0x08, 0x0f, 0x27, 0x0c, 0x55, 0x0b, + 0x49, 0x0c, 0xc7, 0x0e, 0xdf, 0x10, 0x5f, 0x0d, 0xcc, 0x07, 0x72, 0xfe, + 0x63, 0xf5, 0x02, 0xe7, 0x95, 0xdf, 0xbf, 0xe1, 0xc7, 0xee, 0xa3, 0xfe, + 0x23, 0x07, 0x1c, 0xff, 0xd7, 0xeb, 0x52, 0xe0, 0x36, 0xe0, 0xf5, 0xea, + 0xd0, 0xf9, 0x26, 0x00, 0x8e, 0x01, 0xf2, 0xfc, 0x8a, 0xff, 0xc5, 0xfd, + 0x6d, 0x01, 0x40, 0x01, 0xc0, 0x04, 0x9e, 0x06, 0x82, 0x0a, 0x6b, 0x0d, + 0xd4, 0x0e, 0x72, 0x0e, 0xa3, 0x0f, 0xfc, 0x0e, 0x86, 0x0f, 0x54, 0x0e, + 0x50, 0x0b, 0x01, 0x06, 0xc5, 0x03, 0xc5, 0x04, 0x1d, 0x07, 0x18, 0x09, + 0x73, 0x08, 0xf6, 0x02, 0x21, 0xfc, 0xbe, 0xf8, 0x9b, 0xf4, 0xc3, 0xf5, + 0x0f, 0xf7, 0x1e, 0xf6, 0x4a, 0xf8, 0x38, 0xf5, 0xa7, 0xf3, 0x50, 0xf3, + 0x2f, 0xf2, 0x77, 0xf4, 0xad, 0xfb, 0xcd, 0xfd, 0x66, 0x02, 0x35, 0x05, + 0x57, 0x06, 0x5e, 0x0a, 0xee, 0x0b, 0x8f, 0x0e, 0xd0, 0x0d, 0xcd, 0x11, + 0x83, 0x10, 0xa5, 0x0d, 0xda, 0x0d, 0x8c, 0x0d, 0xf7, 0x0c, 0xc4, 0x08, + 0x0c, 0x03, 0x0e, 0xf9, 0xae, 0xe9, 0x77, 0xe2, 0x8f, 0xdf, 0x5c, 0xec, + 0x5e, 0xfb, 0xbd, 0x07, 0x41, 0x04, 0x9c, 0xf7, 0xee, 0xe4, 0x56, 0xdc, + 0x27, 0xdf, 0x5d, 0xef, 0x94, 0xff, 0x3f, 0x07, 0x48, 0x0b, 0x79, 0x01, + 0x6b, 0x00, 0xcb, 0xf9, 0x8c, 0xfb, 0x42, 0x00, 0x29, 0x04, 0x3c, 0x0d, + 0xc1, 0x0d, 0xf5, 0x0e, 0x10, 0x0e, 0x8c, 0x0b, 0x71, 0x09, 0x18, 0x08, + 0x29, 0x09, 0x1a, 0x0a, 0x6b, 0x0a, 0x76, 0x09, 0x48, 0x05, 0x00, 0x03, + 0x03, 0x08, 0xc4, 0x07, 0xfb, 0x05, 0xb9, 0x00, 0xd0, 0xf7, 0x8e, 0xf5, + 0x54, 0xf2, 0xb6, 0xf9, 0xb1, 0xfb, 0x31, 0xfc, 0xf3, 0xf9, 0xc8, 0xf3, + 0x85, 0xf1, 0xa8, 0xf2, 0xf6, 0xf4, 0x8f, 0xf8, 0xb7, 0xfd, 0x80, 0x01, + 0x89, 0x03, 0xce, 0x04, 0xc7, 0x03, 0x62, 0x05, 0xcd, 0x08, 0x0f, 0x0c, + 0x58, 0x10, 0x75, 0x0f, 0x0b, 0x0c, 0xef, 0x09, 0x0d, 0x09, 0xc9, 0x09, + 0x07, 0x08, 0x87, 0x06, 0xdc, 0x03, 0xd1, 0xfd, 0x37, 0xf5, 0x6b, 0xe9, + 0xb9, 0xdf, 0xca, 0xe3, 0x5c, 0xf5, 0x6a, 0x05, 0x60, 0x0c, 0x9e, 0x02, + 0xf4, 0xf0, 0x5f, 0xe4, 0xba, 0xe5, 0xa4, 0xed, 0xec, 0xfb, 0x9b, 0x02, + 0xe7, 0x0a, 0x1c, 0x0b, 0x26, 0x04, 0xf8, 0x02, 0x41, 0xfa, 0x33, 0xf9, + 0x0d, 0xfe, 0x85, 0x05, 0xf2, 0x0b, 0xba, 0x0e, 0xf4, 0x0c, 0xbb, 0x09, + 0xd1, 0x07, 0x16, 0x04, 0x1d, 0x03, 0xeb, 0x03, 0x98, 0x04, 0xa3, 0x05, + 0xf9, 0x06, 0xa2, 0x05, 0x7b, 0x05, 0x36, 0x04, 0x5e, 0x00, 0xb8, 0xfd, + 0x3f, 0xfb, 0xf1, 0xfb, 0xb5, 0xfb, 0x9c, 0xfb, 0xfe, 0xfc, 0xe2, 0xfa, + 0x0d, 0xfb, 0x73, 0xf7, 0x1b, 0xf7, 0x74, 0xf5, 0xed, 0xf8, 0x06, 0xfc, + 0xfa, 0x00, 0x7e, 0x02, 0x9d, 0x01, 0x78, 0x01, 0x4c, 0xff, 0x27, 0x01, + 0x15, 0x07, 0xd3, 0x08, 0x51, 0x0c, 0x0f, 0x0e, 0xcc, 0x0c, 0xec, 0x0a, + 0xee, 0x09, 0x62, 0x04, 0x93, 0x07, 0x04, 0x08, 0x5b, 0x09, 0xde, 0x08, + 0x07, 0x02, 0x9b, 0xf8, 0x68, 0xef, 0x62, 0xea, 0x61, 0xe6, 0xab, 0xf2, + 0xa1, 0xfc, 0x49, 0x0c, 0x47, 0x0b, 0x19, 0xfe, 0x05, 0xee, 0xc4, 0xe5, + 0x94, 0xe8, 0x56, 0xf7, 0x44, 0x03, 0x00, 0x0c, 0x0c, 0x0c, 0xc8, 0x06, + 0x7a, 0xfe, 0x6c, 0xf9, 0xf1, 0xf6, 0x87, 0xfd, 0xc0, 0x01, 0xf5, 0x07, + 0x44, 0x08, 0xcf, 0x05, 0xaf, 0xff, 0x2c, 0x00, 0xbb, 0xff, 0x3f, 0x03, + 0x2c, 0x06, 0x52, 0x03, 0xcf, 0x01, 0x0c, 0xfd, 0xb4, 0xfa, 0xf1, 0xfd, + 0xe5, 0x02, 0xc9, 0x02, 0x23, 0x05, 0x45, 0xff, 0x88, 0xfa, 0xfa, 0xf9, + 0x4e, 0xf8, 0xe1, 0xfb, 0x39, 0xff, 0x6d, 0x01, 0x45, 0x00, 0x85, 0xfc, + 0xc6, 0xfa, 0xeb, 0xf7, 0xa4, 0xfa, 0x95, 0xfd, 0xcd, 0x01, 0x37, 0x03, + 0x91, 0x03, 0xaa, 0x02, 0x4d, 0x02, 0xd4, 0x01, 0xef, 0x03, 0xe6, 0x05, + 0x95, 0x09, 0x28, 0x0d, 0x03, 0x0d, 0xb1, 0x0a, 0x9d, 0x08, 0x3a, 0x07, + 0x98, 0x08, 0xf7, 0x0a, 0x67, 0x0c, 0xd9, 0x09, 0x1a, 0x03, 0xe8, 0xfb, + 0xa2, 0xf4, 0xdb, 0xf2, 0xe7, 0xf2, 0xd0, 0xf5, 0xbc, 0xf7, 0xe1, 0x02, + 0x32, 0x09, 0x04, 0x0b, 0xd5, 0xff, 0x98, 0xf0, 0x71, 0xeb, 0xe2, 0xec, + 0xa9, 0xfa, 0x8f, 0x05, 0x2f, 0x0c, 0xa4, 0x0a, 0x2f, 0x05, 0x26, 0xfb, + 0x14, 0xf6, 0x0b, 0xf0, 0x37, 0xf4, 0x6d, 0xfd, 0x45, 0x06, 0x26, 0x09, + 0x0e, 0x07, 0x3f, 0xfb, 0x8c, 0xf5, 0x1c, 0xf5, 0x50, 0xfa, 0x87, 0x00, + 0x2a, 0x03, 0x00, 0x00, 0x77, 0xfc, 0x19, 0xf9, 0x01, 0xfb, 0x19, 0xfd, + 0x7c, 0x00, 0x16, 0x02, 0x6e, 0x01, 0xbf, 0xfc, 0xcc, 0xf8, 0x0d, 0xfa, + 0xf9, 0xfc, 0x1b, 0x00, 0x14, 0x03, 0x47, 0x00, 0xf6, 0xfd, 0x1b, 0xfa, + 0x3e, 0xf9, 0xa9, 0xf6, 0x3e, 0xfd, 0x4b, 0x02, 0x4a, 0x06, 0x88, 0x06, + 0x03, 0x03, 0xa5, 0xff, 0xb4, 0xfc, 0x7e, 0xff, 0x97, 0x02, 0x5b, 0x07, + 0x7c, 0x0a, 0xc4, 0x0c, 0xe6, 0x0c, 0x38, 0x0a, 0x26, 0x07, 0x83, 0x06, + 0x3b, 0x07, 0xee, 0x0a, 0x99, 0x0c, 0xaa, 0x0c, 0x7a, 0x07, 0xdf, 0x00, + 0x85, 0xf9, 0x7e, 0xf7, 0xf8, 0xf4, 0x02, 0xfa, 0x18, 0xff, 0x3c, 0x08, + 0xe7, 0x0b, 0x21, 0x08, 0xdb, 0xfd, 0xc0, 0xf2, 0xf6, 0xef, 0xfd, 0xf5, + 0x75, 0x00, 0x0b, 0x09, 0xdb, 0x0a, 0x47, 0x05, 0x6b, 0xfb, 0x20, 0xf3, + 0x07, 0xef, 0xc5, 0xf4, 0x9c, 0xfa, 0x24, 0x01, 0x59, 0x02, 0x31, 0xff, + 0x94, 0xfa, 0x0c, 0xf7, 0xb5, 0xf4, 0xd8, 0xf5, 0xa9, 0xf7, 0xe8, 0xfa, + 0xcb, 0xfd, 0x58, 0xfd, 0x4a, 0xf9, 0x55, 0xf8, 0xb7, 0xf8, 0x21, 0xfd, + 0xda, 0xff, 0xad, 0xfe, 0xb2, 0xfb, 0x8c, 0xf9, 0x4f, 0xfa, 0x79, 0xfe, + 0x48, 0x01, 0x09, 0x03, 0xab, 0x02, 0x1e, 0x00, 0xa9, 0xfd, 0xb2, 0xfc, + 0x2d, 0xfb, 0x19, 0xff, 0xf3, 0x02, 0xe5, 0x07, 0x76, 0x08, 0x4f, 0x04, + 0xbe, 0xff, 0xeb, 0xfc, 0x9d, 0xfe, 0x6c, 0x02, 0x51, 0x07, 0x40, 0x0a, + 0x51, 0x0a, 0xec, 0x07, 0x2f, 0x04, 0xa0, 0x02, 0x61, 0x05, 0x28, 0x08, + 0x24, 0x0d, 0x28, 0x0d, 0x8d, 0x0a, 0xdc, 0x06, 0x97, 0x04, 0x27, 0x04, + 0x25, 0x05, 0xe1, 0x04, 0x05, 0x04, 0xaf, 0xff, 0xe3, 0xfa, 0xc0, 0xf7, + 0x87, 0xf8, 0xfc, 0xff, 0xd4, 0x07, 0x5f, 0x0a, 0xf4, 0x02, 0x38, 0xf9, + 0x50, 0xf4, 0xef, 0xf4, 0xf3, 0xfb, 0x2c, 0x01, 0xf5, 0x04, 0x29, 0x04, + 0x8f, 0xff, 0x8c, 0xf8, 0x3b, 0xf4, 0x0e, 0xf1, 0x16, 0xf5, 0x59, 0xfa, + 0x2f, 0xff, 0x27, 0xff, 0x4b, 0xfc, 0x91, 0xf6, 0x56, 0xf2, 0x8c, 0xf2, + 0x7a, 0xf5, 0xd1, 0xf7, 0x0b, 0xfc, 0xaa, 0xfd, 0x41, 0xfc, 0x25, 0xfa, + 0x8b, 0xf8, 0x0d, 0xf9, 0x2e, 0xfb, 0xaa, 0xfc, 0xda, 0xfd, 0x9f, 0xfe, + 0x0f, 0xfe, 0xf1, 0xff, 0xfe, 0xff, 0xbb, 0x00, 0x98, 0x00, 0x5d, 0x00, + 0x68, 0x01, 0xc8, 0x00, 0xdd, 0x01, 0x7c, 0x01, 0xac, 0x03, 0xf5, 0x04, + 0x8a, 0x05, 0x04, 0x03, 0xa4, 0x01, 0xa3, 0x01, 0xde, 0x03, 0xe7, 0x03, + 0xe6, 0x05, 0x5a, 0x06, 0x7c, 0x06, 0xee, 0x06, 0x17, 0x07, 0x3f, 0x06, + 0x74, 0x06, 0xd5, 0x06, 0x7c, 0x0a, 0xe2, 0x0a, 0x25, 0x0b, 0x4e, 0x08, + 0xa2, 0x07, 0x54, 0x05, 0x74, 0x06, 0xa0, 0x05, 0x9c, 0x04, 0x1c, 0x02, + 0x22, 0x00, 0xab, 0xfd, 0x38, 0xfb, 0x96, 0xfa, 0xee, 0xfc, 0xfe, 0x04, + 0x5a, 0x09, 0xfb, 0x08, 0xe7, 0xff, 0x24, 0xf7, 0xb0, 0xf0, 0xb7, 0xf8, + 0x16, 0x00, 0xbc, 0x08, 0x0d, 0x07, 0x00, 0xff, 0x86, 0xf6, 0xf2, 0xf2, + 0x16, 0xf2, 0x0f, 0xf6, 0x22, 0xf8, 0x35, 0xfb, 0xc8, 0xfb, 0xb5, 0xfa, + 0xa9, 0xf5, 0xea, 0xf1, 0x80, 0xef, 0x21, 0xf2, 0xbd, 0xf6, 0x9b, 0xfb, + 0x1f, 0xfb, 0x94, 0xf9, 0xeb, 0xf6, 0x96, 0xf7, 0x4b, 0xfa, 0xa4, 0xfd, + 0x13, 0xfe, 0x0e, 0xfe, 0x62, 0xfd, 0x8c, 0xfe, 0x37, 0x01, 0xe4, 0x01, + 0xa9, 0x01, 0xfe, 0x01, 0x88, 0x01, 0xd2, 0x03, 0x6f, 0x04, 0xc9, 0x03, + 0x43, 0x03, 0x87, 0x06, 0x33, 0x09, 0x8f, 0x0b, 0xb9, 0x09, 0xab, 0x04, + 0xfd, 0x01, 0xb0, 0x01, 0x98, 0x05, 0x63, 0x0a, 0xae, 0x0d, 0xc2, 0x0c, + 0xef, 0x08, 0xb2, 0x03, 0x0f, 0x01, 0xd9, 0x02, 0x6b, 0x06, 0x60, 0x0b, + 0x57, 0x0f, 0xdc, 0x0d, 0x48, 0x09, 0x8c, 0x06, 0x3e, 0x03, 0xb1, 0x03, + 0x88, 0x04, 0xc4, 0x05, 0xf9, 0x06, 0xa3, 0x06, 0x65, 0x02, 0x14, 0xfd, + 0x88, 0xfa, 0x93, 0xf9, 0x91, 0xfd, 0x6d, 0xff, 0xef, 0x02, 0x3a, 0x03, + 0xe6, 0x00, 0xf5, 0xfc, 0xce, 0xf8, 0x45, 0xf8, 0xf0, 0xf9, 0x11, 0xfb, + 0xfc, 0xfe, 0x16, 0xff, 0x0a, 0xff, 0xe3, 0xfa, 0x0a, 0xf7, 0x67, 0xf3, + 0xdf, 0xf3, 0xd1, 0xf5, 0xd0, 0xfa, 0x4b, 0xfc, 0x23, 0xfc, 0xc2, 0xf7, + 0xb6, 0xf4, 0xc1, 0xf2, 0x18, 0xf4, 0x06, 0xf8, 0x8e, 0xfa, 0xc1, 0xfb, + 0xda, 0xfb, 0x97, 0xfa, 0xd6, 0xfa, 0x49, 0xfa, 0xa5, 0xfb, 0x42, 0xfd, + 0x97, 0xfe, 0xc3, 0xff, 0x1f, 0xff, 0xc5, 0xff, 0xa2, 0x00, 0x70, 0x02, + 0xe3, 0x03, 0x64, 0x04, 0x87, 0x03, 0xdd, 0x02, 0xea, 0x01, 0x41, 0x03, + 0x9d, 0x04, 0x18, 0x06, 0x56, 0x06, 0x79, 0x06, 0x54, 0x06, 0xed, 0x04, + 0x1e, 0x04, 0x57, 0x04, 0xf6, 0x03, 0xc6, 0x06, 0xfe, 0x07, 0xf5, 0x06, + 0x77, 0x06, 0x50, 0x05, 0x3f, 0x05, 0x10, 0x07, 0xe6, 0x07, 0xa4, 0x07, + 0x9a, 0x08, 0x0d, 0x08, 0x97, 0x08, 0x91, 0x08, 0x5d, 0x07, 0x66, 0x06, + 0xd3, 0x04, 0x47, 0x05, 0x41, 0x04, 0x9e, 0x03, 0xb5, 0x02, 0xa1, 0x01, + 0xa2, 0x00, 0xae, 0xfe, 0x13, 0xfe, 0xe0, 0xfe, 0x0d, 0x02, 0xd8, 0x04, + 0xa6, 0x04, 0xb5, 0x01, 0x7f, 0xfd, 0x51, 0xfa, 0x48, 0xfa, 0x63, 0xfc, + 0x93, 0xff, 0x92, 0x01, 0x7f, 0x00, 0x0f, 0xfd, 0xb3, 0xf9, 0x49, 0xf6, + 0xa5, 0xf5, 0x00, 0xf7, 0x30, 0xf9, 0xee, 0xfa, 0xe8, 0xfa, 0x71, 0xf8, + 0xe7, 0xf5, 0xe7, 0xf3, 0x0f, 0xf4, 0xaf, 0xf5, 0xda, 0xf7, 0xac, 0xf9, + 0xd7, 0xf9, 0xa4, 0xf8, 0x58, 0xf8, 0xc3, 0xf8, 0x88, 0xfa, 0xfd, 0xfb, + 0x91, 0xfd, 0xeb, 0xfd, 0x5a, 0xfd, 0xd7, 0xfc, 0x0c, 0xfe, 0x59, 0xff, + 0x15, 0x01, 0x65, 0x01, 0xdb, 0x01, 0xa1, 0x01, 0xfc, 0x01, 0x95, 0x02, + 0xee, 0x03, 0x2e, 0x05, 0x62, 0x05, 0x7c, 0x06, 0x00, 0x06, 0xd2, 0x05, + 0x63, 0x05, 0xd9, 0x05, 0xb4, 0x05, 0x5a, 0x06, 0x72, 0x06, 0x17, 0x07, + 0x36, 0x07, 0x60, 0x07, 0x3b, 0x07, 0x0e, 0x07, 0x14, 0x06, 0xd7, 0x05, + 0xb4, 0x05, 0xa5, 0x07, 0x98, 0x08, 0x7b, 0x08, 0x05, 0x08, 0x55, 0x06, + 0xe3, 0x04, 0x02, 0x05, 0x51, 0x05, 0xce, 0x05, 0x0e, 0x05, 0x45, 0x04, + 0x42, 0x03, 0xe3, 0x02, 0x53, 0x02, 0x7f, 0x02, 0x18, 0x02, 0x72, 0x02, + 0x1b, 0x03, 0x89, 0x03, 0x8d, 0x03, 0x09, 0x04, 0xc6, 0x02, 0x45, 0x01, + 0x9f, 0xff, 0x8e, 0xfd, 0xd3, 0xfc, 0xc7, 0xfc, 0x9e, 0xfd, 0xb0, 0xfd, + 0x36, 0xfd, 0xaa, 0xfb, 0x77, 0xf9, 0x49, 0xf7, 0xf8, 0xf5, 0xe7, 0xf5, + 0x23, 0xf7, 0x0b, 0xf8, 0x29, 0xf8, 0x29, 0xf7, 0xbb, 0xf5, 0xfc, 0xf4, + 0x3c, 0xf5, 0x58, 0xf6, 0x3f, 0xf7, 0x07, 0xf8, 0x3f, 0xf8, 0xdc, 0xf7, + 0x4e, 0xf8, 0x58, 0xf9, 0xfe, 0xfa, 0x47, 0xfc, 0x10, 0xfd, 0x77, 0xfd, + 0x65, 0xfd, 0x81, 0xfd, 0xdc, 0xfe, 0x31, 0x00, 0xb5, 0x01, 0xfe, 0x02, + 0x2f, 0x03, 0x72, 0x02, 0xd9, 0x01, 0x09, 0x02, 0x2c, 0x03, 0x41, 0x04, + 0x3c, 0x05, 0xcd, 0x05, 0x9b, 0x05, 0x24, 0x05, 0xb5, 0x03, 0xbf, 0x03, + 0x3a, 0x04, 0xfa, 0x04, 0xbd, 0x05, 0x42, 0x05, 0x97, 0x04, 0xc3, 0x03, + 0xac, 0x03, 0xec, 0x03, 0x21, 0x04, 0xdb, 0x03, 0x95, 0x03, 0x58, 0x03, + 0xd4, 0x02, 0xa2, 0x02, 0xbd, 0x02, 0x70, 0x03, 0x04, 0x04, 0x4e, 0x04, + 0x42, 0x04, 0xa0, 0x03, 0x18, 0x03, 0x14, 0x03, 0x6b, 0x03, 0xca, 0x03, + 0x2f, 0x04, 0x81, 0x04, 0xbe, 0x04, 0xcf, 0x04, 0x5f, 0x04, 0xf2, 0x03, + 0x8b, 0x03, 0x4a, 0x03, 0x1b, 0x03, 0x1e, 0x03, 0xe8, 0x02, 0xbe, 0x02, + 0x5c, 0x02, 0xa7, 0x01, 0xfa, 0x00, 0x3e, 0x00, 0x99, 0xff, 0xe0, 0xfe, + 0x51, 0xfe, 0xb5, 0xfd, 0x1e, 0xfd, 0x8a, 0xfc, 0xe3, 0xfb, 0x76, 0xfb, + 0x2d, 0xfb, 0xb6, 0xfa, 0x34, 0xfa, 0x7e, 0xf9, 0xe8, 0xf8, 0x37, 0xf8, + 0x69, 0xf8, 0xc2, 0xf8, 0x42, 0xf9, 0x4d, 0xf9, 0xa0, 0xf8, 0xa4, 0xf8, + 0xf7, 0xf8, 0x80, 0xf9, 0x8b, 0xfa, 0x62, 0xfb, 0xf3, 0xfb, 0x04, 0xfc, + 0x58, 0xfc, 0xb2, 0xfc, 0x55, 0xfd, 0x32, 0xfe, 0x23, 0xff, 0xde, 0xff, + 0x27, 0x00, 0x31, 0x00, 0x47, 0x00, 0x91, 0x00, 0x07, 0x01, 0xac, 0x01, + 0xe8, 0x01, 0xe2, 0x01, 0xcd, 0x01, 0x9f, 0x01, 0x99, 0x01, 0xc6, 0x01, + 0xfa, 0x01, 0xe2, 0x01, 0x80, 0x01, 0x2f, 0x01, 0xeb, 0x00, 0xb9, 0x00, + 0x76, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x70, 0x00, 0x92, 0x00, 0x93, 0x00, + 0x7b, 0x00, 0x6b, 0x00, 0x42, 0x00, 0x49, 0x00, 0x62, 0x00, 0x9c, 0x00, + 0x26, 0x01, 0xc7, 0x01, 0x46, 0x02, 0x9c, 0x02, 0x9b, 0x02, 0x9a, 0x02, + 0xbc, 0x02, 0x0d, 0x03, 0x7e, 0x03, 0xef, 0x03, 0x2f, 0x04, 0x45, 0x04, + 0x2f, 0x04, 0x26, 0x04, 0x2b, 0x04, 0x12, 0x04, 0x02, 0x04, 0xf4, 0x03, + 0xe2, 0x03, 0xad, 0x03, 0x69, 0x03, 0x10, 0x03, 0xc6, 0x02, 0x74, 0x02, + 0x11, 0x02, 0xa4, 0x01, 0x39, 0x01, 0xe6, 0x00, 0x87, 0x00, 0x12, 0x00, + 0x88, 0xff, 0x08, 0xff, 0xb0, 0xfe, 0x6a, 0xfe, 0x28, 0xfe, 0xd5, 0xfd, + 0x6b, 0xfd, 0x1c, 0xfd, 0xfc, 0xfc, 0xfd, 0xfc, 0x01, 0xfd, 0xe8, 0xfc, + 0xcb, 0xfc, 0x97, 0xfc, 0x7b, 0xfc, 0x86, 0xfc, 0xb9, 0xfc, 0xee, 0xfc, + 0x22, 0xfd, 0x35, 0xfd, 0x37, 0xfd, 0x40, 0xfd, 0x4d, 0xfd, 0x5e, 0xfd, + 0x75, 0xfd, 0xb0, 0xfd, 0xf8, 0xfd, 0x29, 0xfe, 0x32, 0xfe, 0x1c, 0xfe, + 0x25, 0xfe, 0x3e, 0xfe, 0x62, 0xfe, 0x73, 0xfe, 0x6b, 0xfe, 0x63, 0xfe, + 0x5a, 0xfe, 0x60, 0xfe, 0x88, 0xfe, 0xbf, 0xfe, 0xcb, 0xfe, 0xb9, 0xfe, + 0xb0, 0xfe, 0xaa, 0xfe, 0xc4, 0xfe, 0xeb, 0xfe, 0x21, 0xff, 0x49, 0xff, + 0x74, 0xff, 0x9c, 0xff, 0xb7, 0xff, 0xdd, 0xff, 0x1a, 0x00, 0x67, 0x00, + 0xca, 0x00, 0x18, 0x01, 0x47, 0x01, 0x69, 0x01, 0x83, 0x01, 0xb2, 0x01, + 0xf1, 0x01, 0x41, 0x02, 0x90, 0x02, 0xc0, 0x02, 0xca, 0x02, 0xd0, 0x02, + 0xe7, 0x02, 0x0f, 0x03, 0x3b, 0x03, 0x57, 0x03, 0x5b, 0x03, 0x53, 0x03, + 0x3e, 0x03, 0x21, 0x03, 0x0c, 0x03, 0x17, 0x03, 0x27, 0x03, 0x0d, 0x03, + 0xdb, 0x02, 0xa3, 0x02, 0x6b, 0x02, 0x40, 0x02, 0x28, 0x02, 0x16, 0x02, + 0xf9, 0x01, 0xe4, 0x01, 0xc2, 0x01, 0x96, 0x01, 0x57, 0x01, 0x1e, 0x01, + 0xf1, 0x00, 0xd3, 0x00, 0xbd, 0x00, 0xa1, 0x00, 0x7f, 0x00, 0x58, 0x00, + 0x32, 0x00, 0x11, 0x00, 0xe9, 0xff, 0xbe, 0xff, 0x98, 0xff, 0x81, 0xff, + 0x6e, 0xff, 0x61, 0xff, 0x4c, 0xff, 0x32, 0xff, 0x15, 0xff, 0xf5, 0xfe, + 0xd3, 0xfe, 0xb0, 0xfe, 0x99, 0xfe, 0x8c, 0xfe, 0x7a, 0xfe, 0x6a, 0xfe, + 0x57, 0xfe, 0x38, 0xfe, 0x17, 0xfe, 0xf4, 0xfd, 0xd9, 0xfd, 0xd4, 0xfd, + 0xd7, 0xfd, 0xdf, 0xfd, 0xea, 0xfd, 0xeb, 0xfd, 0xdf, 0xfd, 0xd4, 0xfd, + 0xda, 0xfd, 0xee, 0xfd, 0x0e, 0xfe, 0x30, 0xfe, 0x52, 0xfe, 0x6d, 0xfe, + 0x86, 0xfe, 0xa4, 0xfe, 0xc7, 0xfe, 0xfb, 0xfe, 0x2a, 0xff, 0x5a, 0xff, + 0x81, 0xff, 0xa6, 0xff, 0xca, 0xff, 0xf5, 0xff, 0x2c, 0x00, 0x5d, 0x00, + 0x85, 0x00, 0xa2, 0x00, 0xba, 0x00, 0xd9, 0x00, 0xf9, 0x00, 0x19, 0x01, + 0x33, 0x01, 0x40, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x4c, 0x01, 0x5c, 0x01, + 0x6a, 0x01, 0x76, 0x01, 0x74, 0x01, 0x5d, 0x01, 0x46, 0x01, 0x38, 0x01, + 0x34, 0x01, 0x40, 0x01, 0x47, 0x01, 0x3e, 0x01, 0x28, 0x01, 0x19, 0x01, + 0x11, 0x01, 0x1a, 0x01, 0x25, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x1f, 0x01, + 0x14, 0x01, 0x0d, 0x01, 0x16, 0x01, 0x25, 0x01, 0x35, 0x01, 0x39, 0x01, + 0x31, 0x01, 0x1a, 0x01, 0x01, 0x01, 0xf3, 0x00, 0xf1, 0x00, 0xeb, 0x00, + 0xe1, 0x00, 0xcc, 0x00, 0xab, 0x00, 0x89, 0x00, 0x64, 0x00, 0x4c, 0x00, + 0x38, 0x00, 0x22, 0x00, 0x08, 0x00, 0xe9, 0xff, 0xbb, 0xff, 0x8b, 0xff, + 0x66, 0xff, 0x51, 0xff, 0x45, 0xff, 0x39, 0xff, 0x28, 0xff, 0x10, 0xff, + 0xf8, 0xfe, 0xe5, 0xfe, 0xda, 0xfe, 0xd4, 0xfe, 0xdd, 0xfe, 0xdf, 0xfe, + 0xe9, 0xfe, 0xf2, 0xfe, 0xf2, 0xfe, 0xf6, 0xfe, 0x01, 0xff, 0x11, 0xff, + 0x29, 0xff, 0x38, 0xff, 0x44, 0xff, 0x49, 0xff, 0x51, 0xff, 0x64, 0xff, + 0x6e, 0xff, 0x7e, 0xff, 0x87, 0xff, 0x93, 0xff, 0x9c, 0xff, 0xa0, 0xff, + 0xa8, 0xff, 0xb3, 0xff, 0xbc, 0xff, 0xc3, 0xff, 0xc6, 0xff, 0xc8, 0xff, + 0xcb, 0xff, 0xd2, 0xff, 0xe0, 0xff, 0xf0, 0xff, 0x00, 0x00, 0x08, 0x00, + 0x0d, 0x00, 0x14, 0x00, 0x21, 0x00, 0x32, 0x00, 0x43, 0x00, 0x60, 0x00, + 0x76, 0x00, 0x89, 0x00, 0x93, 0x00, 0x94, 0x00, 0x9e, 0x00, 0xb0, 0x00, + 0xc9, 0x00, 0xe0, 0x00, 0xe9, 0x00, 0xe9, 0x00, 0xe5, 0x00, 0xe3, 0x00, + 0xe5, 0x00, 0xee, 0x00, 0xf4, 0x00, 0xf4, 0x00, 0xee, 0x00, 0xdd, 0x00, + 0xce, 0x00, 0xcd, 0x00, 0xc9, 0x00, 0xc5, 0x00, 0xb9, 0x00, 0xa2, 0x00, + 0x8f, 0x00, 0x7d, 0x00, 0x72, 0x00, 0x6a, 0x00, 0x62, 0x00, 0x54, 0x00, + 0x43, 0x00, 0x2d, 0x00, 0x17, 0x00, 0xfe, 0xff, 0xee, 0xff, 0xeb, 0xff, + 0xe6, 0xff, 0xdf, 0xff, 0xcf, 0xff, 0xb6, 0xff, 0x9a, 0xff, 0x84, 0xff, + 0x79, 0xff, 0x7c, 0xff, 0x86, 0xff, 0x87, 0xff, 0x81, 0xff, 0x6f, 0xff, + 0x5f, 0xff, 0x54, 0xff, 0x55, 0xff, 0x5c, 0xff, 0x69, 0xff, 0x72, 0xff, + 0x74, 0xff, 0x6c, 0xff, 0x68, 0xff, 0x6a, 0xff, 0x72, 0xff, 0x7d, 0xff, + 0x89, 0xff, 0x97, 0xff, 0x9b, 0xff, 0x99, 0xff, 0x9b, 0xff, 0xa6, 0xff, + 0xb9, 0xff, 0xd1, 0xff, 0xe1, 0xff, 0xec, 0xff, 0xef, 0xff, 0xf5, 0xff, + 0xfe, 0xff, 0x0f, 0x00, 0x29, 0x00, 0x40, 0x00, 0x50, 0x00, 0x5b, 0x00, + 0x62, 0x00, 0x6e, 0x00, 0x7f, 0x00, 0x97, 0x00, 0xaa, 0x00, 0xbb, 0x00, + 0xc3, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc9, 0x00, 0xd2, 0x00, 0xdf, 0x00, + 0xe7, 0x00, 0xe5, 0x00, 0xdc, 0x00, 0xcf, 0x00, 0xc1, 0x00, 0xb8, 0x00, + 0xb5, 0x00, 0xb2, 0x00, 0xac, 0x00, 0x99, 0x00, 0x84, 0x00, 0x6e, 0x00, + 0x5e, 0x00, 0x52, 0x00, 0x4a, 0x00, 0x3f, 0x00, 0x2f, 0x00, 0x19, 0x00, + 0x07, 0x00, 0xfb, 0xff, 0xed, 0xff, 0xe6, 0xff, 0xdc, 0xff, 0xd1, 0xff, + 0xc5, 0xff, 0xb8, 0xff, 0xaf, 0xff, 0xac, 0xff, 0xaa, 0xff, 0xa6, 0xff, + 0xa1, 0xff, 0x99, 0xff, 0x93, 0xff, 0x90, 0xff, 0x93, 0xff, 0x99, 0xff, + 0x9c, 0xff, 0x99, 0xff, 0x94, 0xff, 0x8f, 0xff, 0x8c, 0xff, 0x90, 0xff, + 0x98, 0xff, 0x9f, 0xff, 0x9f, 0xff, 0x9d, 0xff, 0x9c, 0xff, 0x99, 0xff, + 0x9c, 0xff, 0xa1, 0xff, 0xa9, 0xff, 0xb0, 0xff, 0xb3, 0xff, 0xb6, 0xff, + 0xb6, 0xff, 0xb7, 0xff, 0xbd, 0xff, 0xc5, 0xff, 0xcf, 0xff, 0xd7, 0xff, + 0xe0, 0xff, 0xe3, 0xff, 0xea, 0xff, 0xf4, 0xff, 0xfd, 0xff, 0x06, 0x00, + 0x0c, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1e, 0x00, 0x27, 0x00, 0x32, 0x00, + 0x3d, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x48, 0x00, 0x47, 0x00, + 0x4b, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x52, 0x00, 0x4d, 0x00, 0x48, 0x00, + 0x42, 0x00, 0x3d, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x37, 0x00, 0x33, 0x00, + 0x2d, 0x00, 0x25, 0x00, 0x1f, 0x00, 0x18, 0x00, 0x16, 0x00, 0x14, 0x00, + 0x11, 0x00, 0x0d, 0x00, 0x06, 0x00, 0x01, 0x00, 0xfb, 0xff, 0xf6, 0xff, + 0xf4, 0xff, 0xf2, 0xff, 0xf1, 0xff, 0xed, 0xff, 0xe6, 0xff, 0xe1, 0xff, + 0xd8, 0xff, 0xd3, 0xff, 0xd5, 0xff, 0xd4, 0xff, 0xd5, 0xff, 0xd2, 0xff, + 0xcb, 0xff, 0xc4, 0xff, 0xbe, 0xff, 0xbd, 0xff, 0xbd, 0xff, 0xbe, 0xff, + 0xbf, 0xff, 0xbb, 0xff, 0xb4, 0xff, 0xad, 0xff, 0xaa, 0xff, 0xa9, 0xff, + 0xad, 0xff, 0xae, 0xff, 0xb1, 0xff, 0xb0, 0xff, 0xb1, 0xff, 0xaf, 0xff, + 0xb1, 0xff, 0xb3, 0xff, 0xbb, 0xff, 0xc3, 0xff, 0xc9, 0xff, 0xcd, 0xff, + 0xd2, 0xff, 0xd8, 0xff, 0xe0, 0xff, 0xe8, 0xff, 0xf1, 0xff, 0xfa, 0xff, + 0x02, 0x00, 0x09, 0x00, 0x0f, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x26, 0x00, + 0x2e, 0x00, 0x33, 0x00, 0x36, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3f, 0x00, + 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x44, 0x00, 0x40, 0x00, 0x41, 0x00, + 0x3f, 0x00, 0x3e, 0x00, 0x3a, 0x00, 0x34, 0x00, 0x30, 0x00, 0x2a, 0x00, + 0x27, 0x00, 0x25, 0x00, 0x22, 0x00, 0x1e, 0x00, 0x1a, 0x00, 0x12, 0x00, + 0x0d, 0x00, 0x0a, 0x00, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xf2, 0xff, 0xed, 0xff, 0xed, 0xff, 0xea, 0xff, 0xea, 0xff, + 0xe7, 0xff, 0xe2, 0xff, 0xdb, 0xff, 0xd4, 0xff, 0xd2, 0xff, 0xd0, 0xff, + 0xd1, 0xff, 0xcf, 0xff, 0xcf, 0xff, 0xca, 0xff, 0xc6, 0xff, 0xc1, 0xff, + 0xc1, 0xff, 0xc1, 0xff, 0xbf, 0xff, 0xc0, 0xff, 0xbe, 0xff, 0xbc, 0xff, + 0xbb, 0xff, 0xbb, 0xff, 0xbe, 0xff, 0xbf, 0xff, 0xc1, 0xff, 0xc3, 0xff, + 0xc4, 0xff, 0xc7, 0xff, 0xca, 0xff, 0xca, 0xff, 0xcc, 0xff, 0xd4, 0xff, + 0xd5, 0xff, 0xda, 0xff, 0xdf, 0xff, 0xe4, 0xff, 0xe8, 0xff, 0xed, 0xff, + 0xf2, 0xff, 0xf8, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x03, 0x00, 0x09, 0x00, + 0x0f, 0x00, 0x13, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x22, 0x00, + 0x27, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x32, 0x00, 0x37, 0x00, + 0x37, 0x00, 0x39, 0x00, 0x39, 0x00, 0x39, 0x00, 0x3b, 0x00, 0x3b, 0x00, + 0x3b, 0x00, 0x3a, 0x00, 0x39, 0x00, 0x39, 0x00, 0x38, 0x00, 0x35, 0x00, + 0x34, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x2c, 0x00, 0x26, 0x00, 0x23, 0x00, + 0x1f, 0x00, 0x1c, 0x00, 0x17, 0x00, 0x14, 0x00, 0x14, 0x00, 0x0f, 0x00, + 0x0c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xf8, 0xff, + 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf2, 0xff, 0xf1, 0xff, 0xed, 0xff, + 0xed, 0xff, 0xec, 0xff, 0xeb, 0xff, 0xe8, 0xff, 0xe4, 0xff, 0xe1, 0xff, + 0xdf, 0xff, 0xdd, 0xff, 0xdb, 0xff, 0xd9, 0xff, 0xd6, 0xff, 0xd2, 0xff, + 0xd0, 0xff, 0xcd, 0xff, 0xcb, 0xff, 0xc9, 0xff, 0xc9, 0xff, 0xc8, 0xff, + 0xc6, 0xff, 0xc3, 0xff, 0xc1, 0xff, 0xbf, 0xff, 0xbe, 0xff, 0xbe, 0xff, + 0xbf, 0xff, 0xbe, 0xff, 0xbd, 0xff, 0xbf, 0xff, 0xbf, 0xff, 0xbe, 0xff, + 0xbf, 0xff, 0xc0, 0xff, 0xc1, 0xff, 0xc2, 0xff, 0xc4, 0xff, 0xc7, 0xff, + 0xca, 0xff, 0xcd, 0xff, 0xd1, 0xff, 0xd1, 0xff, 0xd5, 0xff, 0xd9, 0xff, + 0xda, 0xff, 0xde, 0xff, 0xe3, 0xff, 0xea, 0xff, 0xec, 0xff, 0xf3, 0xff, + 0xf6, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0c, 0x00, + 0x11, 0x00, 0x18, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x27, 0x00, 0x2a, 0x00, + 0x30, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x41, 0x00, 0x42, 0x00, + 0x46, 0x00, 0x4a, 0x00, 0x4c, 0x00, 0x4e, 0x00, 0x53, 0x00, 0x53, 0x00, + 0x53, 0x00, 0x55, 0x00, 0x5a, 0x00, 0x58, 0x00, 0x59, 0x00, 0x56, 0x00, + 0x55, 0x00, 0x54, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4c, 0x00, 0x4b, 0x00, + 0x46, 0x00, 0x42, 0x00, 0x3e, 0x00, 0x3b, 0x00, 0x36, 0x00, 0x31, 0x00, + 0x2e, 0x00, 0x29, 0x00, 0x25, 0x00, 0x20, 0x00, 0x1f, 0x00, 0x18, 0x00, + 0x13, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xfd, 0xff, 0xf6, 0xff, 0xf3, 0xff, 0xef, 0xff, 0xeb, 0xff, 0xe5, 0xff, + 0xe3, 0xff, 0xdd, 0xff, 0xdb, 0xff, 0xd6, 0xff, 0xd2, 0xff, 0xcf, 0xff, + 0xcc, 0xff, 0xc9, 0xff, 0xc8, 0xff, 0xc4, 0xff, 0xc3, 0xff, 0xc0, 0xff, + 0xc0, 0xff, 0xbd, 0xff, 0xbc, 0xff, 0xbb, 0xff, 0xbb, 0xff, 0xbb, 0xff, + 0xbc, 0xff, 0xbd, 0xff, 0xbd, 0xff, 0xbc, 0xff, 0xbe, 0xff, 0xc0, 0xff, + 0xc0, 0xff, 0xc2, 0xff, 0xc6, 0xff, 0xc8, 0xff, 0xc7, 0xff, 0xcb, 0xff, + 0xd0, 0xff, 0xd2, 0xff, 0xd5, 0xff, 0xd8, 0xff, 0xda, 0xff, 0xdd, 0xff, + 0xe3, 0xff, 0xe7, 0xff, 0xea, 0xff, 0xef, 0xff, 0xf1, 0xff, 0xf5, 0xff, + 0xf9, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x0b, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x13, 0x00, 0x17, 0x00, + 0x15, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1b, 0x00, + 0x1d, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x1f, 0x00, + 0x1f, 0x00, 0x20, 0x00, 0x20, 0x00, 0x1d, 0x00, 0x1c, 0x00, 0x1b, 0x00, + 0x1b, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x19, 0x00, 0x17, 0x00, 0x16, 0x00, + 0x15, 0x00, 0x13, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x11, 0x00, + 0x10, 0x00, 0x12, 0x00, 0x11, 0x00, 0x13, 0x00, 0x0f, 0x00, 0x11, 0x00, + 0x13, 0x00, 0x13, 0x00, 0x14, 0x00, 0x12, 0x00, 0x13, 0x00, 0x13, 0x00, + 0x12, 0x00, 0x14, 0x00, 0x13, 0x00, 0x13, 0x00, 0x13, 0x00, 0x0e, 0x00, + 0x0f, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0xfb, 0xff, 0xf9, 0xff, 0xf7, 0xff, 0xf5, 0xff, 0xf2, 0xff, 0xf1, 0xff, + 0xf0, 0xff, 0xee, 0xff, 0xed, 0xff, 0xe9, 0xff, 0xe8, 0xff, 0xe6, 0xff, + 0xe4, 0xff, 0xe3, 0xff, 0xe1, 0xff, 0xe0, 0xff, 0xdd, 0xff, 0xd9, 0xff, + 0xda, 0xff, 0xdb, 0xff, 0xd9, 0xff, 0xd9, 0xff, 0xd8, 0xff, 0xda, 0xff, + 0xda, 0xff, 0xd9, 0xff, 0xdb, 0xff, 0xd8, 0xff, 0xdb, 0xff, 0xdb, 0xff, + 0xdb, 0xff, 0xdd, 0xff, 0xde, 0xff, 0xe1, 0xff, 0xe0, 0xff, 0xe2, 0xff, + 0xe3, 0xff, 0xe6, 0xff, 0xe7, 0xff, 0xe9, 0xff, 0xeb, 0xff, 0xf0, 0xff, + 0xf2, 0xff, 0xf3, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0xfa, 0xff, 0xfb, 0xff, + 0xfe, 0xff, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x13, 0x00, + 0x14, 0x00, 0x16, 0x00, 0x16, 0x00, 0x19, 0x00, 0x1b, 0x00, 0x1b, 0x00, + 0x1b, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1b, 0x00, 0x1c, 0x00, + 0x1b, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x1a, 0x00, 0x1a, 0x00, + 0x19, 0x00, 0x18, 0x00, 0x18, 0x00, 0x16, 0x00, 0x15, 0x00, 0x16, 0x00, + 0x15, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x11, 0x00, 0x0e, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x08, 0x00, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfe, 0xff, + 0xfd, 0xff, 0xfb, 0xff, 0xf9, 0xff, 0xf7, 0xff, 0xf6, 0xff, 0xf6, 0xff, + 0xf6, 0xff, 0xf5, 0xff, 0xf4, 0xff, 0xf4, 0xff, 0xf3, 0xff, 0xf3, 0xff, + 0xf3, 0xff, 0xf1, 0xff, 0xf1, 0xff, 0xec, 0xff, 0xed, 0xff, 0xed, 0xff, + 0xee, 0xff, 0xed, 0xff, 0xec, 0xff, 0xeb, 0xff, 0xec, 0xff, 0xed, 0xff, + 0xeb, 0xff, 0xeb, 0xff, 0xed, 0xff, 0xec, 0xff, 0xec, 0xff, 0xed, 0xff, + 0xec, 0xff, 0xed, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0xeb, 0xff, + 0xea, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xe9, 0xff, 0xea, 0xff, 0xe9, 0xff, + 0xea, 0xff, 0xea, 0xff, 0xea, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xeb, 0xff, + 0xee, 0xff, 0xee, 0xff, 0xee, 0xff, 0xef, 0xff, 0xf0, 0xff, 0xf2, 0xff, + 0xf2, 0xff, 0xf3, 0xff, 0xf5, 0xff, 0xf5, 0xff, 0xf6, 0xff, 0xf5, 0xff, + 0xf7, 0xff, 0xf8, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfe, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0x05, 0x00, 0x07, 0x00, 0x06, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0a, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0b, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x06, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xff, + 0xfb, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0xf3, 0xff, 0xf3, 0xff, + 0xf0, 0xff, 0xef, 0xff, 0xec, 0xff, 0xea, 0xff, 0xe6, 0xff, 0xe6, 0xff, + 0xe4, 0xff, 0xe2, 0xff, 0xdf, 0xff, 0xde, 0xff, 0xdc, 0xff, 0xdc, 0xff, + 0xd9, 0xff, 0xd6, 0xff, 0xd5, 0xff, 0xd5, 0xff, 0xd2, 0xff, 0xd1, 0xff, + 0xd0, 0xff, 0xd1, 0xff, 0xcd, 0xff, 0xd0, 0xff, 0xd0, 0xff, 0xcf, 0xff, + 0xd3, 0xff, 0xd0, 0xff, 0xd2, 0xff, 0xd3, 0xff, 0xd4, 0xff, 0xd6, 0xff, + 0xd7, 0xff, 0xd6, 0xff, 0xd6, 0xff, 0xd8, 0xff, 0xd8, 0xff, 0xda, 0xff, + 0xda, 0xff, 0xdd, 0xff, 0xdd, 0xff, 0xdf, 0xff, 0xe1, 0xff, 0xe4, 0xff, + 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0xff, 0xe7, 0xff, 0xeb, 0xff, 0xec, 0xff, + 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xf1, 0xff, 0xf2, 0xff, 0xf4, 0xff, + 0xf5, 0xff, 0xf6, 0xff, 0xf8, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xfb, 0xff, + 0xfd, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, + 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0xf6, 0xff, + 0xf4, 0xff, 0xf1, 0xff, 0xec, 0xff, 0xec, 0xff, 0xe9, 0xff, 0xe8, 0xff, + 0xe7, 0xff, 0xe6, 0xff, 0xe5, 0xff, 0xe4, 0xff, 0xe2, 0xff, 0xdd, 0xff, + 0xdc, 0xff, 0xdc, 0xff, 0xd9, 0xff, 0xd9, 0xff, 0xdc, 0xff, 0xd8, 0xff, + 0xd3, 0xff, 0xd5, 0xff, 0xd1, 0xff, 0xd0, 0xff, 0xd0, 0xff, 0xcf, 0xff, + 0xcd, 0xff, 0xcf, 0xff, 0xcd, 0xff, 0xce, 0xff, 0xcd, 0xff, 0xcd, 0xff, + 0xcc, 0xff, 0xcb, 0xff, 0xcc, 0xff, 0xcb, 0xff, 0xcc, 0xff, 0xcc, 0xff, + 0xcc, 0xff, 0xcc, 0xff, 0xcd, 0xff, 0xd2, 0xff, 0xd0, 0xff, 0xd2, 0xff, + 0xd2, 0xff, 0xd4, 0xff, 0xd2, 0xff, 0xd5, 0xff, 0xd8, 0xff, 0xd8, 0xff, + 0xda, 0xff, 0xda, 0xff, 0xd7, 0xff, 0xd9, 0xff, 0xda, 0xff, 0xd9, 0xff, + 0xdb, 0xff, 0xdb, 0xff, 0xdd, 0xff, 0xdf, 0xff, 0xde, 0xff, 0xe0, 0xff, + 0xe1, 0xff, 0xe1, 0xff, 0xe2, 0xff, 0xe4, 0xff, 0xe5, 0xff, 0xe5, 0xff, + 0xe7, 0xff, 0xe7, 0xff, 0xe8, 0xff, 0xe7, 0xff, 0xe9, 0xff, 0xeb, 0xff, + 0xe9, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xea, 0xff, 0xec, 0xff, 0xeb, 0xff, + 0xeb, 0xff, 0xed, 0xff, 0xee, 0xff, 0xed, 0xff, 0xeb, 0xff, 0xeb, 0xff, + 0xeb, 0xff, 0xeb, 0xff, 0xeb, 0xff, 0xe9, 0xff, 0xe9, 0xff, 0xeb, 0xff, + 0xeb, 0xff, 0xe9, 0xff, 0xeb, 0xff, 0xe9, 0xff, 0xea, 0xff, 0xe9, 0xff, + 0xea, 0xff, 0xe7, 0xff, 0xe8, 0xff, 0xe8, 0xff, 0xe5, 0xff, 0xe7, 0xff, + 0xe6, 0xff, 0xe7, 0xff, 0xe6, 0xff, 0xe7, 0xff, 0xe7, 0xff, 0xe5, 0xff, + 0xe7, 0xff, 0xe7, 0xff, 0xe8, 0xff, 0xe8, 0xff, 0xe8, 0xff, 0xe7, 0xff, + 0xe9, 0xff, 0xe9, 0xff, 0xeb, 0xff, 0xea, 0xff, 0xea, 0xff, 0xec, 0xff, + 0xec, 0xff, 0xea, 0xff, 0xea, 0xff, 0xeb, 0xff, 0xed, 0xff, 0xee, 0xff, + 0xf1, 0xff, 0xf0, 0xff, 0xf2, 0xff, 0xf2, 0xff, 0xf2, 0xff, 0xf5, 0xff, + 0xf6, 0xff, 0xf7, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0xfa, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x07, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x0a, 0x00, + 0x0b, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x10, 0x00, + 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x16, 0x00, 0x17, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x18, 0x00, 0x1b, 0x00, 0x1b, 0x00, 0x21, 0x00, + 0x24, 0x00, 0x29, 0x00, 0x29, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x2a, 0x00, + 0x2c, 0x00, 0x30, 0x00, 0x30, 0x00, 0x35, 0x00, 0x38, 0x00, 0x3d, 0x00, + 0x45, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x57, 0x00, 0x5d, 0x00, + 0x6a, 0x00, 0x80, 0x00, 0xa8, 0x00, 0xee, 0x00, 0x53, 0x01, 0x9a, 0x01, + 0x38, 0x02, 0xd9, 0x02, 0xf2, 0x03, 0x6c, 0x04, 0x74, 0x05, 0xa3, 0x04, + 0xfc, 0x00, 0x24, 0x00, 0x21, 0x00, 0x7f, 0xff, 0xc6, 0xff, 0xb8, 0x00, + 0xa9, 0xff, 0x7a, 0xff, 0xdd, 0x00, 0x46, 0x00, 0xa2, 0x00, 0xf2, 0xff, + 0xa0, 0xfe, 0x78, 0xfe, 0x26, 0xfb, 0x3c, 0xfe, 0x0e, 0x02, 0x5d, 0x00, + 0xc4, 0xff, 0x5d, 0xff, 0xda, 0xfe, 0xb9, 0xfe, 0xf8, 0xfe, 0xdc, 0xfe, + 0xfc, 0xfe, 0x7b, 0xff, 0xdc, 0x00, 0xf8, 0x00, 0x31, 0xff, 0x46, 0xff, + 0x0e, 0x00, 0x8c, 0xff, 0x7c, 0xfe, 0xae, 0xfe, 0x91, 0xff, 0xee, 0xff, + 0x39, 0x00, 0x2f, 0x00, 0x7e, 0x00, 0x74, 0xff, 0x18, 0x00, 0x8c, 0x00, + 0x34, 0x00, 0x2f, 0x00, 0x7a, 0x00, 0x59, 0xff, 0xb5, 0xff, 0x1b, 0x01, + 0xbb, 0x00, 0x98, 0x00, 0xff, 0x00, 0xd1, 0x00, 0x86, 0x00, 0x5d, 0xfd, + 0x76, 0xff, 0x82, 0x00, 0x82, 0xfe, 0x35, 0xff, 0x62, 0x00, 0x00, 0x03, + 0xfa, 0x02, 0xd6, 0x01, 0xab, 0xfe, 0xe0, 0xfe, 0x5f, 0x00, 0x70, 0x01, + 0x4e, 0x02, 0xe2, 0x00, 0x39, 0x00, 0x5a, 0x00, 0xb9, 0x00, 0xb3, 0x01, + 0x8d, 0x00, 0x7d, 0x00, 0xd4, 0xff, 0x5b, 0x00, 0x53, 0x01, 0x03, 0x01, + 0x77, 0x00, 0x00, 0x00, 0xd3, 0xff, 0x2e, 0x00, 0x5d, 0xff, 0x4d, 0xff, + 0xee, 0xfe, 0x3f, 0xff, 0x8b, 0xff, 0xd2, 0xff, 0x55, 0x01, 0x0c, 0x01, + 0x94, 0xfe, 0x17, 0xff, 0xdb, 0x00, 0x30, 0x01, 0xf5, 0xfe, 0xf5, 0xfe, + 0xea, 0x00, 0xca, 0x01, 0x97, 0x01, 0x1f, 0xfe, 0x49, 0xfd, 0x6a, 0xff, + 0x91, 0x00, 0xa6, 0x00, 0x08, 0x00, 0x01, 0xff, 0xa4, 0xfe, 0xc5, 0xff, + 0x2d, 0x00, 0x79, 0x00, 0x37, 0xff, 0x7d, 0xff, 0x21, 0x00, 0x93, 0x00, + 0x2a, 0x01, 0x6a, 0xfe, 0x53, 0xff, 0x49, 0x00, 0x53, 0xff, 0x3a, 0x01, + 0x22, 0x02, 0x3f, 0xff, 0x85, 0xfe, 0xda, 0xff, 0xca, 0x00, 0xb6, 0xff, + 0xad, 0x00, 0xe9, 0xfd, 0x38, 0xfe, 0x34, 0x00, 0xcc, 0x00, 0x26, 0xff, + 0x87, 0x01, 0xef, 0xfe, 0x43, 0xfd, 0x63, 0x00, 0x53, 0x01, 0x94, 0x00, + 0x01, 0xff, 0xd9, 0xfe, 0x68, 0x00, 0xd0, 0x01, 0x27, 0xff, 0xb1, 0xfe, + 0x7a, 0x00, 0x05, 0x01, 0x5f, 0x00, 0xf6, 0x00, 0x61, 0x00, 0x94, 0x00, + 0xb8, 0xff, 0xa5, 0xff, 0x0e, 0x01, 0x29, 0x00, 0x06, 0x02, 0x84, 0x03, + 0x00, 0xfd, 0x39, 0xfd, 0x71, 0xfe, 0x68, 0x02, 0x78, 0x04, 0xd0, 0x02, + 0x44, 0xfd, 0x80, 0xfc, 0x02, 0x01, 0x08, 0x01, 0x80, 0x05, 0x93, 0x03, + 0xb6, 0xfc, 0x30, 0xfd, 0x44, 0x01, 0x77, 0x01, 0xe5, 0x01, 0x9f, 0x03, + 0x51, 0xff, 0x16, 0xfd, 0x32, 0x01, 0x69, 0x00, 0xf9, 0xff, 0x91, 0x02, + 0xa1, 0xff, 0xc4, 0xfe, 0x4b, 0x00, 0x95, 0xfe, 0xab, 0xff, 0xdb, 0x01, + 0x88, 0x01, 0x5c, 0xfe, 0x62, 0xfe, 0xf9, 0x00, 0xe0, 0xfd, 0x4f, 0xff, + 0xaf, 0xff, 0x18, 0x00, 0x4d, 0xfe, 0xfc, 0xff, 0xd4, 0xff, 0x91, 0xfd, + 0x3a, 0xfe, 0x8f, 0xfe, 0x59, 0x01, 0x49, 0x00, 0xb2, 0xfe, 0x34, 0xff, + 0xb8, 0xff, 0x95, 0xfc, 0x74, 0x00, 0xa5, 0x05, 0xeb, 0xff, 0x46, 0xfb, + 0x7f, 0x00, 0x1b, 0x01, 0x0e, 0x00, 0x0d, 0x01, 0x47, 0x02, 0xb0, 0xfe, + 0x07, 0xff, 0xc2, 0xff, 0x4a, 0x00, 0x50, 0x01, 0x9d, 0x01, 0xb1, 0xff, + 0x5c, 0xfe, 0xb6, 0x01, 0x76, 0x02, 0x8d, 0xff, 0x57, 0xfe, 0xd3, 0x01, + 0x78, 0x01, 0x69, 0x00, 0x52, 0x00, 0xa0, 0xfe, 0x1e, 0xfe, 0xfa, 0xff, + 0x44, 0x02, 0x0c, 0x01, 0x15, 0xfe, 0xcc, 0xfd, 0x24, 0x00, 0x7c, 0x01, + 0x6c, 0x02, 0xae, 0xfe, 0x3e, 0xfe, 0x9e, 0x03, 0x80, 0xff, 0x1d, 0xfe, + 0x2a, 0x01, 0xd2, 0x03, 0xcc, 0xfe, 0x56, 0xfe, 0x5f, 0x00, 0xde, 0xff, + 0x1b, 0x01, 0xbe, 0x01, 0x2f, 0x00, 0x44, 0xfb, 0x14, 0xfe, 0x03, 0x04, + 0x4a, 0x00, 0xa5, 0xfd, 0x89, 0xff, 0xd5, 0xfd, 0xc6, 0xfd, 0xf4, 0xfe, + 0x6e, 0x02, 0x23, 0x02, 0xcb, 0xfc, 0xf0, 0x00, 0xf0, 0x01, 0xb0, 0xfa, + 0x67, 0x04, 0x82, 0x07, 0x9b, 0xf9, 0xee, 0xf9, 0x7f, 0x03, 0xa0, 0x02, + 0x09, 0x00, 0xfd, 0x00, 0xf5, 0xfe, 0x92, 0xff, 0x07, 0xff, 0x21, 0x01, + 0xe9, 0xff, 0x74, 0xfe, 0xb9, 0xfd, 0x3e, 0xfa, 0x1d, 0x03, 0xc0, 0x06, + 0xff, 0xfb, 0xe8, 0xfd, 0xbd, 0x01, 0x49, 0xfd, 0xa5, 0xff, 0x06, 0x03, + 0x07, 0x00, 0x3c, 0xfb, 0xb5, 0x05, 0x02, 0xff, 0xb2, 0xf8, 0x7f, 0x02, + 0x48, 0x02, 0x71, 0xff, 0xfb, 0x00, 0x1b, 0xff, 0xdf, 0xfd, 0xaa, 0x02, + 0x52, 0x06, 0xc6, 0xf9, 0xff, 0xf8, 0xc5, 0x03, 0x70, 0x00, 0x86, 0x00, + 0x9f, 0x06, 0xb9, 0xfc, 0x58, 0xf9, 0x41, 0x03, 0x9b, 0x03, 0x66, 0xfc, + 0x96, 0x00, 0x83, 0x05, 0xb3, 0xfe, 0x22, 0xf8, 0x5b, 0xff, 0x6c, 0x04, + 0xd9, 0x00, 0x7c, 0x01, 0x88, 0x03, 0x7b, 0x01, 0x40, 0xfa, 0xed, 0xfd, + 0x5f, 0x02, 0x25, 0x02, 0xdd, 0x01, 0x30, 0xfe, 0x55, 0xfe, 0x5a, 0xfd, + 0xe1, 0x00, 0x7b, 0x03, 0x12, 0x02, 0x66, 0x02, 0x09, 0xfc, 0x9b, 0xf9, + 0x12, 0x01, 0x95, 0x03, 0x10, 0x00, 0xb0, 0x01, 0x2e, 0x00, 0xdd, 0xfc, + 0x07, 0x00, 0x1a, 0x05, 0xdc, 0xfc, 0xc1, 0xfd, 0xc6, 0x01, 0x57, 0xfd, + 0xd4, 0xfe, 0xc2, 0x05, 0xb2, 0xfc, 0xc0, 0xfe, 0xff, 0x03, 0x15, 0x00, + 0x72, 0xfd, 0xbc, 0x00, 0xaa, 0xfe, 0x37, 0xfe, 0x45, 0x03, 0xce, 0x03, + 0x8c, 0xfa, 0x12, 0xfc, 0x35, 0x04, 0x74, 0x00, 0xfe, 0xfe, 0x5d, 0x04, + 0xa9, 0x00, 0x10, 0xfd, 0x0d, 0xff, 0x47, 0xfe, 0x32, 0x00, 0x7d, 0x06, + 0xf9, 0x00, 0xab, 0xfc, 0x76, 0xfc, 0xca, 0x02, 0x90, 0x03, 0xd2, 0xff, + 0x1b, 0xff, 0xeb, 0xfd, 0x00, 0xff, 0x39, 0xff, 0xf8, 0x02, 0x08, 0x04, + 0x9c, 0xfd, 0x8b, 0xfa, 0x20, 0x01, 0xfd, 0x03, 0xfe, 0xff, 0x77, 0xfc, + 0x6d, 0x02, 0x7d, 0xfe, 0x00, 0xfb, 0x0e, 0x04, 0x02, 0x06, 0xf9, 0xfc, + 0x4d, 0xfb, 0x96, 0x00, 0x4b, 0x06, 0xc1, 0xfc, 0x5f, 0xfa, 0xa4, 0x02, + 0x69, 0x02, 0xd5, 0xfd, 0x30, 0x03, 0x79, 0xfa, 0x39, 0xf8, 0x28, 0x08, + 0x9a, 0x09, 0x75, 0xfa, 0xdb, 0xfb, 0x8c, 0x01, 0x51, 0xfc, 0x04, 0x00, + 0x71, 0x08, 0x5b, 0xff, 0x01, 0xfa, 0xf9, 0x00, 0x50, 0xff, 0xc1, 0xfd, + 0x73, 0x06, 0xe1, 0x02, 0x1d, 0xff, 0xa2, 0xff, 0x6f, 0xf9, 0x27, 0xfd, + 0x8f, 0x05, 0x5b, 0x03, 0x8b, 0xfe, 0xea, 0xfe, 0xdc, 0xfc, 0x68, 0xfc, + 0xdc, 0x04, 0xe2, 0x07, 0x9b, 0xfe, 0x75, 0xfd, 0x3a, 0xfe, 0x69, 0xfd, + 0xf3, 0xff, 0x62, 0x05, 0xfa, 0x01, 0x93, 0xfe, 0x3f, 0xfe, 0x08, 0xff, + 0x30, 0x01, 0x3d, 0x00, 0x65, 0xff, 0xed, 0x01, 0xcc, 0xfe, 0x7a, 0xfd, + 0x09, 0xfe, 0xf2, 0x01, 0xbf, 0x05, 0x71, 0xfe, 0x2c, 0xfc, 0x8f, 0xff, + 0x78, 0xff, 0x50, 0xfb, 0xbc, 0x01, 0xfd, 0x09, 0xa2, 0xfe, 0x3f, 0xf9, + 0x28, 0xfc, 0x56, 0xfc, 0xd4, 0x04, 0x4b, 0x08, 0xfc, 0xfe, 0xc2, 0xfc, + 0x09, 0xfd, 0xf6, 0xfc, 0x6e, 0x02, 0x0f, 0x02, 0x62, 0xff, 0x1c, 0x01, + 0xee, 0xfe, 0xc8, 0x00, 0x15, 0xfc, 0xb8, 0xfc, 0x5f, 0x06, 0xdc, 0x00, + 0x6a, 0xfb, 0x59, 0xfe, 0x8b, 0x00, 0x3d, 0xff, 0xc1, 0x00, 0x68, 0x01, + 0xc3, 0xff, 0x1c, 0x01, 0xd9, 0xfe, 0x6b, 0x03, 0xd9, 0xff, 0xdb, 0xfb, + 0x68, 0x02, 0x88, 0x01, 0x27, 0xfe, 0x85, 0xfd, 0xb1, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x2d, 0xfd, 0x2f, 0xff, 0x03, 0x04, 0x5b, 0x00, 0x0a, 0xfd, + 0x2a, 0xff, 0xb2, 0xfd, 0x80, 0xff, 0xb3, 0x04, 0x3c, 0x01, 0xc6, 0xfe, + 0xca, 0xfe, 0x37, 0xff, 0x27, 0x00, 0xef, 0x00, 0x29, 0x01, 0xe9, 0xff, + 0x0d, 0x00, 0x91, 0xf8, 0xca, 0x01, 0x3a, 0x09, 0x2a, 0x03, 0x98, 0xfe, + 0xb7, 0xf8, 0xba, 0xfc, 0x40, 0x03, 0x9d, 0x01, 0xfd, 0x01, 0x92, 0x03, + 0x0b, 0xfa, 0x87, 0xfe, 0xb0, 0x03, 0x1e, 0xff, 0xdb, 0xfc, 0x70, 0x01, + 0x7b, 0x01, 0xb9, 0xff, 0x0c, 0x01, 0x6e, 0xff, 0x94, 0x00, 0x3c, 0x02, + 0x54, 0xff, 0x55, 0xfe, 0xbe, 0xff, 0xc9, 0x01, 0x06, 0xff, 0xa5, 0xfd, + 0x2e, 0x01, 0x4d, 0x03, 0xf1, 0x00, 0xd1, 0xfa, 0xe1, 0xf9, 0x94, 0x04, + 0x9c, 0x03, 0x3c, 0xfb, 0xde, 0x02, 0xab, 0x05, 0x26, 0xfc, 0xd6, 0xfe, + 0x66, 0x01, 0x4c, 0xf8, 0xf2, 0xff, 0xa2, 0x0b, 0x47, 0x02, 0xec, 0xf3, + 0x63, 0xff, 0x9c, 0x04, 0x34, 0x02, 0x89, 0xfd, 0x56, 0xfa, 0xbb, 0xfd, + 0xc2, 0x05, 0x52, 0x03, 0x92, 0xfd, 0x67, 0xfc, 0xfd, 0x01, 0x10, 0x02, + 0x3f, 0xfc, 0x59, 0xff, 0x18, 0x02, 0x1b, 0x00, 0x35, 0x02, 0x23, 0xfd, + 0xb3, 0xfd, 0xd8, 0x05, 0xa3, 0x00, 0x90, 0xfa, 0x1a, 0xff, 0x75, 0xff, + 0xde, 0x02, 0xef, 0x01, 0x1d, 0xfe, 0xd4, 0x00, 0x51, 0x00, 0x41, 0xff, + 0x88, 0x02, 0x70, 0x01, 0xfa, 0xfc, 0xaa, 0xff, 0xcc, 0xfd, 0x44, 0x06, + 0xfa, 0x00, 0x88, 0xf7, 0xbb, 0x02, 0x83, 0x05, 0x8c, 0x01, 0xc6, 0xfe, + 0xb5, 0xf6, 0x55, 0xfd, 0x0e, 0x0a, 0xb0, 0x02, 0x95, 0xfa, 0x34, 0x03, + 0x92, 0x02, 0xcc, 0xf9, 0xe8, 0xf8, 0x25, 0x02, 0x82, 0x03, 0x27, 0x00, + 0x39, 0xff, 0x71, 0x02, 0xba, 0xfe, 0xbb, 0x04, 0x4a, 0x04, 0x05, 0xf9, + 0x23, 0xfa, 0xb1, 0x04, 0x06, 0x05, 0x2d, 0xfc, 0x76, 0x03, 0xe0, 0xfd, + 0xb7, 0xf8, 0x44, 0x05, 0x83, 0x06, 0x7d, 0xfd, 0x01, 0xfa, 0xe4, 0xfc, + 0x7b, 0x00, 0xe5, 0x05, 0x34, 0x05, 0x92, 0xfe, 0x3a, 0xfb, 0x03, 0x00, + 0xe7, 0xff, 0xa8, 0xfa, 0xbe, 0x04, 0x09, 0x0b, 0x23, 0xfe, 0x64, 0xf6, + 0x4f, 0xfd, 0x60, 0x01, 0xd7, 0x01, 0xe6, 0x00, 0x9f, 0x03, 0x62, 0x04, + 0x91, 0xfc, 0xe8, 0xf4, 0xab, 0xfc, 0x3b, 0x0a, 0x04, 0x06, 0xbb, 0xfe, + 0xf8, 0xff, 0x8d, 0xf9, 0x8b, 0xfb, 0xd9, 0x0a, 0x87, 0x08, 0x89, 0xfb, + 0xf5, 0xf8, 0x8a, 0xfd, 0x2b, 0x02, 0xf2, 0x04, 0x74, 0x04, 0x92, 0xf9, + 0x1d, 0xf9, 0x17, 0x04, 0xf7, 0x04, 0xb4, 0xfe, 0xb4, 0x03, 0x72, 0x00, + 0xd1, 0xf8, 0xa8, 0xfd, 0x39, 0x02, 0x89, 0x01, 0xa1, 0x04, 0x38, 0x02, + 0xb8, 0xf9, 0xbd, 0xfd, 0x90, 0xff, 0x7b, 0x06, 0xf1, 0x04, 0x40, 0xf8, + 0xf0, 0x02, 0xcd, 0x02, 0x87, 0xf9, 0x8c, 0xfb, 0x02, 0x03, 0x43, 0x09, + 0xa2, 0x00, 0x95, 0xfd, 0xb4, 0xfd, 0xca, 0xf9, 0x5e, 0xfe, 0xf5, 0x08, + 0xe5, 0x02, 0xa8, 0xfa, 0x13, 0x00, 0xb9, 0xff, 0x19, 0xfc, 0xf1, 0x05, + 0x1d, 0x05, 0xe9, 0xfb, 0xe0, 0xfe, 0xf0, 0xfc, 0x85, 0xfd, 0xb9, 0x04, + 0x2b, 0x02, 0xca, 0xfd, 0x0e, 0xfe, 0x84, 0xff, 0x2b, 0xff, 0x47, 0x06, + 0x6c, 0x03, 0x6d, 0xf9, 0x44, 0xfc, 0x61, 0x01, 0xb7, 0x01, 0x23, 0x01, + 0x6f, 0x00, 0xc7, 0xfd, 0x3e, 0x01, 0xd4, 0xff, 0xc3, 0xfe, 0x38, 0x00, + 0x76, 0x01, 0x65, 0xfe, 0x57, 0x02, 0x27, 0xff, 0x72, 0xfa, 0x59, 0x02, + 0x55, 0x03, 0x6c, 0x02, 0x0c, 0x02, 0x38, 0xfc, 0x82, 0xfc, 0x07, 0x01, + 0xd0, 0x03, 0xa0, 0xff, 0x28, 0xff, 0x08, 0x04, 0xd2, 0x00, 0x5a, 0xfc, + 0x37, 0xfb, 0x93, 0x01, 0x18, 0x02, 0x1a, 0xff, 0xb3, 0xfc, 0x5e, 0x01, + 0x10, 0x07, 0x4d, 0x00, 0xb5, 0xf9, 0xa0, 0x01, 0x3c, 0x00, 0xf4, 0xf9, + 0x19, 0x03, 0xc0, 0x09, 0x31, 0x01, 0x5a, 0xfb, 0xa5, 0xf8, 0xec, 0xff, + 0x6b, 0x04, 0xad, 0x04, 0x92, 0x03, 0xbf, 0xf9, 0x52, 0xf6, 0xe4, 0x02, + 0x13, 0x03, 0x1a, 0xfe, 0x3c, 0x09, 0x67, 0x03, 0xda, 0xf3, 0x9b, 0xfb, + 0x74, 0x04, 0x67, 0x07, 0x1e, 0x01, 0xd1, 0xf9, 0x73, 0xfd, 0x6a, 0x02, + 0x4d, 0x05, 0x41, 0x01, 0xa5, 0xfc, 0xf4, 0xfa, 0xd0, 0x03, 0xc9, 0x05, + 0x96, 0xfb, 0xaf, 0xfd, 0x6a, 0x04, 0xd4, 0xfd, 0x94, 0xf9, 0xd7, 0x03, + 0x4b, 0x04, 0x66, 0xfc, 0x5b, 0x01, 0x98, 0x02, 0x22, 0xfd, 0xe8, 0xfe, + 0xbb, 0xff, 0x94, 0xfa, 0x54, 0x01, 0x27, 0x05, 0xd3, 0x03, 0x97, 0xff, + 0x33, 0xfd, 0x15, 0xfb, 0x88, 0xfa, 0x0f, 0x0e, 0xd3, 0x0b, 0xcd, 0xf3, + 0x09, 0xf4, 0x24, 0x06, 0xbc, 0x00, 0x86, 0xfe, 0x63, 0x03, 0xdf, 0xff, + 0x81, 0xff, 0x9c, 0xff, 0x15, 0xfe, 0x92, 0xff, 0x56, 0x00, 0x8c, 0x01, + 0xb4, 0x00, 0x6e, 0xf4, 0x93, 0xff, 0x5b, 0x0e, 0x32, 0x02, 0xda, 0xf8, + 0x74, 0x03, 0xdd, 0x00, 0x5e, 0xf7, 0x01, 0xff, 0x82, 0x08, 0x6d, 0x00, + 0xce, 0xfa, 0x4a, 0xff, 0x0f, 0x01, 0x93, 0x01, 0xbd, 0xfe, 0xdf, 0xfc, + 0x84, 0x06, 0xd8, 0x01, 0xf8, 0xf4, 0x25, 0xfd, 0xde, 0x09, 0x1e, 0x01, + 0x1f, 0xfd, 0xdf, 0x02, 0xdc, 0xff, 0x23, 0xfc, 0x93, 0x01, 0xbf, 0x02, + 0xa0, 0x00, 0xf1, 0xfc, 0xfc, 0x00, 0xe2, 0x01, 0xed, 0xfb, 0x37, 0x00, + 0x73, 0x02, 0x22, 0xfd, 0x63, 0xfd, 0x8b, 0x02, 0xe6, 0x02, 0x33, 0x01, + 0xb0, 0x01, 0xac, 0xfd, 0xd2, 0xf6, 0x1a, 0xfd, 0xd6, 0x08, 0x1b, 0x0b, + 0x95, 0xfc, 0xb5, 0xf4, 0x01, 0xfe, 0x0a, 0x03, 0x18, 0x05, 0xe9, 0x04, + 0x4d, 0xfd, 0xa5, 0xf7, 0x7b, 0xfb, 0x85, 0x03, 0xf6, 0x06, 0xd3, 0x03, + 0xff, 0xfc, 0x25, 0xf7, 0xb2, 0xfe, 0xf8, 0x08, 0x8a, 0x06, 0x2a, 0xfa, + 0x14, 0xf8, 0xc2, 0x01, 0x73, 0x00, 0xbf, 0x00, 0xfa, 0x04, 0x1f, 0xff, + 0xf3, 0xfb, 0x31, 0x03, 0xf1, 0xff, 0x6d, 0xfe, 0xfe, 0xfc, 0xf5, 0xfb, + 0x04, 0x04, 0x09, 0x08, 0xdb, 0xfa, 0xf4, 0xf6, 0xb9, 0x01, 0xd5, 0x09, + 0x73, 0x02, 0x3a, 0xf9, 0xd5, 0xfd, 0x4e, 0x00, 0xcc, 0x00, 0xec, 0x03, + 0xab, 0x02, 0x90, 0xfc, 0x2c, 0xfb, 0x7c, 0xfe, 0x1c, 0x03, 0x76, 0x04, + 0x8f, 0x04, 0xb8, 0xfd, 0xf5, 0xf8, 0x26, 0xfd, 0x4b, 0x03, 0x8c, 0x03, + 0x28, 0x00, 0x06, 0x01, 0x0c, 0x01, 0x13, 0xfb, 0xed, 0xfa, 0xc7, 0x05, + 0x72, 0x05, 0x03, 0xf9, 0xfc, 0xfe, 0x80, 0x04, 0x39, 0xfd, 0x70, 0xfd, + 0xec, 0x08, 0xfc, 0xff, 0x2d, 0xf8, 0x11, 0x03, 0x82, 0x00, 0xc6, 0xf9, + 0xab, 0x05, 0x5f, 0x07, 0xcb, 0xf9, 0xc7, 0xf9, 0x52, 0xfb, 0x4d, 0x01, + 0x73, 0x00, 0xc8, 0x03, 0x7e, 0x04, 0xb7, 0xfe, 0x7d, 0xfa, 0x5b, 0xfe, + 0x4f, 0x01, 0xcc, 0xff, 0x9a, 0x04, 0x60, 0x03, 0x9f, 0xfc, 0xa3, 0xfa, + 0x65, 0x02, 0x74, 0x03, 0x6f, 0xfe, 0x42, 0xff, 0xe2, 0x02, 0x1f, 0xff, + 0xbb, 0xfc, 0x43, 0x03, 0x7a, 0x04, 0xbe, 0xf9, 0x24, 0xfb, 0x78, 0x08, + 0x3f, 0xfd, 0x53, 0xf7, 0xca, 0x0a, 0x3d, 0x04, 0x4a, 0xf2, 0xf1, 0x00, + 0x6c, 0x08, 0x65, 0xfc, 0x5c, 0xff, 0x83, 0x03, 0x97, 0x03, 0x0e, 0xf8, + 0x44, 0xf6, 0x48, 0x09, 0xef, 0x08, 0x52, 0xfd, 0x8a, 0xfb, 0xde, 0xfe, + 0x21, 0xfd, 0x23, 0x01, 0x87, 0x04, 0xa5, 0xff, 0x45, 0xfd, 0x54, 0x02, + 0xa7, 0xff, 0xa0, 0xfc, 0xc3, 0x00, 0x47, 0x06, 0x5c, 0xff, 0x60, 0xf9, + 0x39, 0xfe, 0x49, 0x03, 0x92, 0x03, 0x7b, 0xff, 0x84, 0x00, 0x1d, 0x04, + 0xd5, 0xfc, 0x9d, 0xf9, 0xa4, 0x03, 0xff, 0x06, 0x53, 0xfd, 0x09, 0xfe, + 0x9b, 0x01, 0x0b, 0xff, 0x5a, 0xfb, 0xb8, 0x00, 0xee, 0x07, 0x77, 0xfe, + 0x23, 0xfa, 0x9a, 0x01, 0x4e, 0x02, 0x5c, 0xf6, 0x3b, 0x00, 0xe0, 0x0d, + 0x08, 0xfe, 0xb5, 0xf7, 0x4d, 0x02, 0x75, 0x01, 0x58, 0xff, 0x0e, 0x00, + 0xbd, 0xff, 0x05, 0xfb, 0xe5, 0xfe, 0x34, 0x07, 0xb5, 0x02, 0xab, 0xfc, + 0x5d, 0xfd, 0x4d, 0x01, 0x55, 0x01, 0xe3, 0xfd, 0xde, 0x00, 0x4c, 0x02, + 0x1b, 0xfe, 0xeb, 0xfe, 0x19, 0x01, 0x92, 0x00, 0xfc, 0xfe, 0xe5, 0xfe, + 0x51, 0x02, 0x2c, 0x02, 0xf1, 0xfd, 0x9c, 0xfe, 0x40, 0xfc, 0x89, 0x00, + 0x44, 0x06, 0x84, 0xff, 0x8a, 0xfc, 0x40, 0x05, 0xd2, 0xfe, 0x76, 0xf6, + 0xdd, 0x02, 0xe9, 0x09, 0x87, 0x02, 0x5d, 0xf6, 0xa7, 0xf9, 0x69, 0x05, + 0x8c, 0x02, 0xba, 0xff, 0x0b, 0x03, 0xe2, 0xfe, 0xa4, 0xfd, 0xed, 0x00, + 0x5f, 0x00, 0x39, 0xff, 0x2b, 0x00, 0x45, 0x02, 0x9a, 0x00, 0xd1, 0x00, + 0x52, 0xff, 0xb8, 0xfd, 0x20, 0x00, 0x83, 0x01, 0xb7, 0xff, 0x87, 0x02, + 0xf4, 0x01, 0x1b, 0xfb, 0xc9, 0xfd, 0xf7, 0x02, 0x05, 0x00, 0xc4, 0xfd, + 0x51, 0xfd, 0x2c, 0x02, 0x4b, 0x07, 0xe7, 0xfe, 0xeb, 0xf5, 0x11, 0x01, + 0x5b, 0x07, 0x3d, 0xf9, 0x0a, 0xfd, 0x13, 0x0e, 0x25, 0x01, 0x4b, 0xf4, + 0xb3, 0x00, 0x4c, 0xfe, 0x64, 0xfe, 0x66, 0x09, 0x4c, 0x04, 0xe0, 0xf9, + 0xa5, 0xfe, 0x86, 0xfd, 0x8a, 0xff, 0xd1, 0x02, 0x5c, 0x04, 0x5d, 0xff, + 0x40, 0xfa, 0x05, 0x01, 0xb7, 0x04, 0xdd, 0xfc, 0xe9, 0xfe, 0x91, 0x03, + 0x85, 0xfd, 0xef, 0xff, 0xe3, 0x05, 0xa9, 0x02, 0x27, 0xfc, 0x51, 0xfd, + 0x9a, 0xfc, 0x66, 0x03, 0x9c, 0x07, 0xa2, 0xfe, 0xa0, 0xfb, 0x42, 0xfc, + 0x8e, 0xfd, 0x13, 0x05, 0x57, 0x07, 0x0e, 0xfd, 0xf3, 0xff, 0xbe, 0x01, + 0x2c, 0xf8, 0x04, 0xfb, 0xa5, 0x09, 0xfb, 0x06, 0x71, 0xfa, 0x5c, 0xfd, + 0x3e, 0x01, 0x28, 0xfd, 0xa2, 0xff, 0x8a, 0x03, 0xf9, 0x02, 0x35, 0xfe, + 0x74, 0xfd, 0x29, 0xfe, 0x68, 0xfe, 0x05, 0x03, 0x33, 0x09, 0x75, 0x01, + 0x6f, 0xf3, 0xab, 0xf6, 0xbc, 0x08, 0xc2, 0x0c, 0x54, 0xfe, 0x68, 0xfc, + 0xc0, 0xfc, 0x84, 0xf6, 0x26, 0x03, 0xc9, 0x0a, 0x65, 0xfb, 0x27, 0xf7, + 0x12, 0x07, 0x4c, 0x03, 0x4d, 0xf9, 0xe1, 0x03, 0x0b, 0x07, 0x4c, 0xf6, + 0xd2, 0xf8, 0x84, 0x09, 0xe3, 0x05, 0x90, 0x00, 0x1d, 0xfd, 0xc5, 0xff, + 0x5c, 0xff, 0x31, 0xfd, 0x2b, 0x03, 0x1c, 0x03, 0xf7, 0x00, 0xb6, 0xff, + 0x3c, 0xfe, 0x39, 0xfe, 0xec, 0x03, 0x18, 0xfe, 0x88, 0xfc, 0xba, 0x05, + 0x53, 0x02, 0x0a, 0x00, 0x02, 0xfd, 0x84, 0x00, 0x60, 0x01, 0x03, 0xfc, + 0x8f, 0x01, 0xa2, 0x05, 0x8d, 0xfb, 0x53, 0xf9, 0xa1, 0x00, 0xb6, 0x05, + 0xfb, 0x02, 0xbc, 0xfa, 0x24, 0xf9, 0x08, 0x07, 0xf1, 0x05, 0x19, 0xf9, + 0x4e, 0x00, 0x08, 0x03, 0x57, 0xf9, 0x6a, 0x00, 0x01, 0x07, 0x79, 0x04, + 0x0d, 0xfd, 0x55, 0xfc, 0xa2, 0xfe, 0x97, 0xfd, 0xb7, 0x00, 0xba, 0x0a, + 0x3f, 0x03, 0xf2, 0xf8, 0xf6, 0xfa, 0x89, 0xff, 0x5f, 0x00, 0x52, 0x02, + 0xfd, 0x01, 0x14, 0x03, 0x84, 0x01, 0x9e, 0xfa, 0xb1, 0xfd, 0xed, 0x01, + 0xa2, 0x01, 0xde, 0x02, 0x84, 0xff, 0xfe, 0xf9, 0xce, 0x00, 0xf3, 0xfe, + 0x36, 0x04, 0xc8, 0x06, 0x6f, 0xf6, 0xd7, 0xfc, 0xb1, 0x05, 0x1a, 0xfc, + 0xab, 0xfb, 0x86, 0x0c, 0x2b, 0x03, 0x3a, 0xf9, 0x2d, 0xfc, 0x32, 0xfc, + 0x89, 0x01, 0x6b, 0x01, 0x1c, 0x09, 0x02, 0x07, 0x42, 0xf9, 0x27, 0xf6, + 0x53, 0xfd, 0x41, 0x00, 0xdb, 0x01, 0xec, 0x0b, 0x6c, 0x06, 0xf2, 0xf3, + 0x24, 0xfc, 0xc7, 0x05, 0xa8, 0xf9, 0x52, 0xf9, 0xd7, 0x0c, 0x70, 0x06, + 0xd0, 0xf3, 0x07, 0xfe, 0x87, 0x07, 0x87, 0xfd, 0xe0, 0xfe, 0x82, 0x06, + 0x25, 0xfe, 0x2d, 0xf5, 0xc6, 0xfe, 0x72, 0x07, 0x01, 0x03, 0x1a, 0x02, + 0x40, 0x02, 0x7e, 0xfd, 0x83, 0xf9, 0x28, 0xfd, 0x26, 0x05, 0x25, 0x02, + 0x32, 0x04, 0xa8, 0xf9, 0x8b, 0xf8, 0x74, 0x0a, 0xb5, 0x0d, 0x3c, 0xf8, + 0x2f, 0xf2, 0x10, 0x08, 0x88, 0x03, 0xa2, 0xfa, 0xf1, 0x05, 0x5a, 0x05, + 0xf4, 0xf8, 0x7c, 0xf9, 0xb6, 0x06, 0xc7, 0x09, 0x2a, 0xfe, 0x95, 0xf8, + 0x3c, 0xfd, 0x32, 0xfe, 0x13, 0xfd, 0xfe, 0xfe, 0x61, 0x08, 0x0c, 0x0e, + 0x70, 0xf7, 0x9e, 0xf5, 0xe7, 0x07, 0xcb, 0x01, 0xa8, 0xf3, 0x92, 0x04, + 0xce, 0x0a, 0x8f, 0x00, 0xe6, 0x01, 0xac, 0xf9, 0xa3, 0xf4, 0xb2, 0xfe, + 0x0e, 0x02, 0x13, 0x06, 0x40, 0x01, 0x91, 0xf9, 0xe2, 0xff, 0xdb, 0x00, + 0xc7, 0xfd, 0x25, 0xfd, 0xe7, 0x01, 0x99, 0x08, 0xf8, 0x05, 0xdf, 0xf6, + 0x5b, 0xf8, 0x43, 0x05, 0xed, 0x02, 0x88, 0xf3, 0x1d, 0x03, 0x36, 0x08, + 0xb8, 0xfc, 0x79, 0x08, 0x09, 0x02, 0x60, 0xf7, 0xe0, 0xf3, 0xff, 0xfe, + 0xf0, 0x0c, 0x7e, 0x11, 0x8b, 0x02, 0x64, 0xed, 0x7a, 0xf5, 0xa5, 0x07, + 0x26, 0x08, 0x5a, 0x02, 0xd0, 0x06, 0x1a, 0x03, 0xda, 0xf0, 0x55, 0xf4, + 0x2e, 0x09, 0xd6, 0x07, 0xc9, 0x04, 0xbd, 0xfb, 0x71, 0xf8, 0xad, 0xfb, + 0xcf, 0x05, 0x04, 0x07, 0x4a, 0xfe, 0xad, 0xfb, 0x41, 0x00, 0xc4, 0xff, + 0x04, 0xfd, 0xff, 0x0b, 0x9b, 0x04, 0x13, 0xf1, 0xe3, 0xf8, 0x77, 0x04, + 0xc2, 0xff, 0x4e, 0x07, 0x14, 0x05, 0xbc, 0xf2, 0xd4, 0xfa, 0x6a, 0x06, + 0xfe, 0xff, 0xeb, 0x05, 0x65, 0x00, 0x07, 0xf5, 0xf2, 0x00, 0x13, 0x0a, + 0x37, 0x00, 0x90, 0xfd, 0x5f, 0x02, 0x6d, 0xfb, 0xf8, 0xf8, 0xa0, 0x07, + 0x56, 0x0e, 0x8e, 0xef, 0xcf, 0xfa, 0xf0, 0x15, 0x77, 0xf6, 0x9e, 0xf1, + 0x15, 0x11, 0x34, 0x01, 0x44, 0xee, 0xf4, 0xfd, 0xbb, 0x0b, 0x52, 0x00, + 0x4c, 0xfd, 0x8e, 0x07, 0x91, 0xf8, 0x34, 0xf9, 0xe8, 0x10, 0xa8, 0x05, + 0xd5, 0xf9, 0x71, 0x02, 0xaf, 0xf8, 0x99, 0xf4, 0x61, 0x09, 0x93, 0x09, + 0x66, 0xfd, 0xc7, 0x01, 0x1f, 0xf8, 0x30, 0xf7, 0x8d, 0xfe, 0xcb, 0x00, + 0x47, 0x07, 0x1a, 0x04, 0x24, 0xf9, 0x43, 0x02, 0x46, 0x00, 0xc2, 0xfa, + 0xdd, 0x05, 0x11, 0x06, 0x00, 0xf9, 0x32, 0xfe, 0x44, 0x03, 0x5f, 0xf6, + 0x33, 0xff, 0xc1, 0x09, 0x53, 0xfe, 0x37, 0x0c, 0xef, 0x00, 0x27, 0xe5, + 0xb8, 0xfa, 0x05, 0x1b, 0x13, 0x0c, 0xa4, 0xed, 0xd3, 0xee, 0x64, 0x04, + 0x9f, 0x03, 0xf5, 0x00, 0xc0, 0x10, 0x12, 0xfa, 0xc7, 0xed, 0xb2, 0x02, + 0xc2, 0x08, 0x2b, 0xfd, 0x25, 0x06, 0x13, 0x10, 0x25, 0xf6, 0x00, 0xeb, + 0x52, 0x04, 0x01, 0x0c, 0x21, 0x05, 0x49, 0xf7, 0x0e, 0xf8, 0x59, 0x0a, + 0xd8, 0x03, 0x2e, 0xf8, 0x3d, 0x00, 0xd2, 0xfb, 0x90, 0x00, 0x48, 0x05, + 0xf2, 0x02, 0x52, 0xfe, 0x8c, 0xfc, 0x76, 0x05, 0x3e, 0x05, 0x35, 0xfc, + 0xbf, 0xfe, 0xb1, 0x05, 0x23, 0x00, 0xbf, 0xfa, 0x1a, 0xf7, 0xf7, 0x04, + 0x85, 0x0e, 0xba, 0xeb, 0x0b, 0xf7, 0x2a, 0x13, 0xd1, 0xfc, 0xf5, 0xf2, + 0xd0, 0x06, 0xae, 0x08, 0x1d, 0xf2, 0xf6, 0x01, 0xb9, 0x09, 0x6f, 0xf9, + 0xa0, 0xfb, 0x73, 0xfe, 0xe6, 0x08, 0x2f, 0xff, 0xc4, 0xf7, 0x8e, 0x09, + 0xc7, 0x01, 0x57, 0xef, 0xb7, 0x06, 0xa4, 0x0a, 0xb6, 0xf7, 0x04, 0x07, + 0xad, 0xff, 0x0d, 0xee, 0xe8, 0x06, 0xd1, 0x0d, 0x15, 0xfd, 0xdc, 0x07, + 0xa4, 0xfb, 0x46, 0xe8, 0xd7, 0xff, 0x6e, 0x1e, 0x36, 0x08, 0xf3, 0xea, + 0xa4, 0xf5, 0x2d, 0x03, 0x63, 0x00, 0x09, 0x08, 0x6d, 0x0b, 0xfb, 0xf6, + 0xdc, 0xe5, 0xb6, 0xf9, 0xe0, 0x1a, 0xbd, 0x0d, 0xb3, 0xfb, 0xbc, 0xfa, + 0x87, 0xf3, 0x92, 0xf1, 0xf1, 0x09, 0x2e, 0x14, 0xb2, 0x00, 0xaa, 0xf9, + 0xdd, 0xf4, 0xd6, 0xf5, 0x2f, 0x04, 0xfd, 0x10, 0x5d, 0xf4, 0x05, 0xf7, + 0x3f, 0x11, 0xf8, 0x02, 0xa4, 0xf2, 0xe2, 0x00, 0x2b, 0xf9, 0x81, 0xfb, + 0x99, 0x10, 0xc6, 0x0e, 0xa4, 0xfb, 0xee, 0xf0, 0x9c, 0xfe, 0xa6, 0x06, + 0x9f, 0xfc, 0x75, 0x03, 0x06, 0x05, 0x8c, 0x0f, 0xd2, 0xf9, 0x7e, 0xdd, + 0x46, 0x04, 0xef, 0x15, 0x87, 0xf4, 0x70, 0xf9, 0x0b, 0x12, 0x98, 0xfe, + 0x81, 0xf2, 0x66, 0xfd, 0x4c, 0x07, 0x93, 0xfa, 0x4f, 0xfc, 0x4f, 0x00, + 0x5d, 0x03, 0x05, 0x0b, 0x82, 0x09, 0xdc, 0xf3, 0xed, 0xf4, 0x43, 0x0a, + 0x60, 0x04, 0x68, 0xf4, 0x15, 0x05, 0xe3, 0x0b, 0xf2, 0xf4, 0x90, 0xf5, + 0x2b, 0x09, 0x98, 0x03, 0x8a, 0xfb, 0x8c, 0x02, 0xe1, 0x03, 0x24, 0xfc, + 0x48, 0xf9, 0x54, 0x01, 0x02, 0xfb, 0x2e, 0xfa, 0xa2, 0x0d, 0x94, 0x09, + 0xdc, 0xf8, 0xcb, 0xfc, 0x9b, 0x0d, 0x18, 0xfe, 0x1c, 0xe9, 0x98, 0x04, + 0x8e, 0x12, 0xf3, 0xf5, 0x34, 0xfd, 0x88, 0x0e, 0xeb, 0xf8, 0xf6, 0xec, + 0xfe, 0xff, 0x1f, 0x19, 0x22, 0x11, 0x56, 0xf3, 0x82, 0xe6, 0xb4, 0xfc, + 0xa5, 0x12, 0xfa, 0x04, 0xcb, 0xf5, 0xc8, 0x04, 0x05, 0x09, 0xc0, 0xf8, + 0xa5, 0xed, 0xe0, 0x03, 0x18, 0x11, 0xbc, 0x02, 0xc5, 0xf1, 0x72, 0xf9, + 0x25, 0x08, 0x7b, 0xfb, 0x53, 0xf2, 0x2d, 0x14, 0xfb, 0x15, 0x71, 0xf1, + 0x27, 0xf1, 0x4b, 0x01, 0x99, 0xf9, 0x41, 0x06, 0x2b, 0x14, 0x26, 0xf9, + 0xf9, 0xe9, 0x87, 0x07, 0xba, 0x0c, 0xe3, 0xf8, 0x6e, 0xfe, 0x28, 0x02, + 0x64, 0x05, 0x5f, 0xfe, 0x83, 0xfd, 0xae, 0xfe, 0x94, 0x03, 0x8e, 0x03, + 0x2c, 0x04, 0xa3, 0xf8, 0x23, 0xf5, 0x0d, 0x0c, 0x84, 0x0c, 0xb6, 0xfa, + 0x79, 0xff, 0x77, 0xf9, 0x51, 0xf3, 0x79, 0x03, 0x11, 0x08, 0x1a, 0xfa, + 0xf3, 0xf9, 0x8a, 0x0c, 0xb6, 0x08, 0x85, 0xed, 0x6b, 0xf9, 0x92, 0x0b, + 0x54, 0x00, 0x6d, 0xfd, 0xcb, 0x06, 0x17, 0xfd, 0xd2, 0xf7, 0xe6, 0x03, + 0x74, 0xfa, 0xa6, 0xf5, 0x4f, 0x10, 0x82, 0x0d, 0x21, 0xf7, 0x81, 0x02, + 0xe6, 0x03, 0x7c, 0xee, 0x9d, 0xf6, 0x98, 0x0f, 0xcd, 0x06, 0x3d, 0xf7, + 0x21, 0x10, 0xdd, 0x06, 0x64, 0xe6, 0x66, 0xf5, 0xe8, 0x14, 0xc7, 0x05, + 0xda, 0xf7, 0xee, 0x03, 0x09, 0xfe, 0x22, 0xf5, 0xfc, 0x00, 0xa1, 0x05, + 0xf6, 0x02, 0x9d, 0x09, 0xff, 0xfa, 0xff, 0xee, 0x29, 0xfa, 0xfd, 0x08, + 0x86, 0x12, 0x8d, 0xf7, 0x17, 0xef, 0xf6, 0x0b, 0x11, 0x01, 0x1e, 0xef, + 0x7e, 0x0d, 0x18, 0x15, 0x4b, 0xf7, 0x20, 0xed, 0x7d, 0xfb, 0xa5, 0xff, + 0x9f, 0x0c, 0x83, 0x0e, 0x60, 0xec, 0xa9, 0xf6, 0xd1, 0x12, 0xef, 0x02, + 0xdb, 0x04, 0xbd, 0x07, 0x66, 0xee, 0xaa, 0xfb, 0x6b, 0x0b, 0x54, 0xfc, + 0x84, 0xf8, 0x87, 0x09, 0xf1, 0x0d, 0xde, 0xfe, 0x69, 0xe8, 0xd1, 0xf8, + 0x42, 0x13, 0x51, 0x1f, 0xea, 0xf8, 0x29, 0xe7, 0x1d, 0xf7, 0x2c, 0xfc, + 0xf9, 0xf8, 0x55, 0x0a, 0x22, 0x13, 0xdf, 0xf2, 0x2e, 0xf2, 0xb5, 0x04, + 0x58, 0x03, 0x65, 0x01, 0xd3, 0x09, 0xb7, 0xff, 0x22, 0xf4, 0xec, 0xfc, + 0x4a, 0xff, 0x78, 0x04, 0xfe, 0x11, 0x74, 0x03, 0x5f, 0xf8, 0xa3, 0xfc, + 0x46, 0x01, 0x74, 0xfe, 0x7e, 0xfc, 0x3a, 0x03, 0xe9, 0xfe, 0xf3, 0x00, + 0x6d, 0xfa, 0x11, 0xfe, 0x52, 0x08, 0xde, 0x04, 0x7e, 0xfe, 0x5a, 0xfc, + 0xc2, 0xfc, 0x54, 0xfd, 0xa9, 0x06, 0xf9, 0x0b, 0x66, 0x03, 0x2c, 0xee, + 0x39, 0xf5, 0x4d, 0x11, 0xda, 0x04, 0xe3, 0xf6, 0x2f, 0xfa, 0x74, 0xfc, + 0x5a, 0x0c, 0xa8, 0x05, 0xe8, 0xf4, 0xb5, 0x05, 0xf0, 0xfa, 0x32, 0xea, + 0x5f, 0x0a, 0x91, 0x1c, 0xad, 0xff, 0x42, 0xeb, 0x09, 0x01, 0x74, 0x08, + 0xd6, 0xf7, 0x14, 0x04, 0xef, 0x12, 0xb2, 0xf9, 0xf7, 0xe4, 0x8e, 0xfa, + 0x2c, 0x10, 0xd4, 0x0a, 0x15, 0xfd, 0x16, 0xfd, 0xb7, 0xfc, 0x6c, 0x00, + 0xb9, 0xf9, 0x1e, 0xf7, 0xf9, 0x07, 0x63, 0x0d, 0xd9, 0xfc, 0xc6, 0xf6, + 0xca, 0x07, 0xf6, 0xfe, 0x51, 0xf8, 0x9b, 0x05, 0xa6, 0x07, 0x74, 0xfd, + 0xd8, 0xfc, 0xfc, 0xfc, 0xa0, 0x06, 0xe2, 0x0e, 0x2a, 0xf0, 0xf7, 0xed, + 0x72, 0xfc, 0xed, 0x02, 0x79, 0x16, 0x19, 0x08, 0x79, 0xf1, 0x93, 0xf8, + 0xe2, 0x00, 0x5d, 0xff, 0x9c, 0xfc, 0x76, 0x03, 0xa4, 0x10, 0x4d, 0x0e, + 0xb6, 0xf6, 0xcd, 0xed, 0x6a, 0x02, 0xcb, 0x02, 0xf3, 0x01, 0x47, 0x08, + 0x7d, 0x05, 0xb7, 0xf7, 0x0b, 0xf9, 0xd7, 0x02, 0xb9, 0x01, 0xb1, 0xf7, + 0x23, 0xfe, 0x93, 0x13, 0x7f, 0x0a, 0xb2, 0xef, 0x57, 0xf4, 0x77, 0x02, + 0xce, 0x00, 0x85, 0x03, 0xc8, 0xfe, 0xaf, 0xfb, 0x39, 0x10, 0x79, 0x03, + 0xab, 0xed, 0x1d, 0xfe, 0x62, 0x01, 0xcc, 0xfc, 0xce, 0x06, 0x2f, 0xfd, + 0x5e, 0xf5, 0x24, 0x02, 0x6c, 0x04, 0x29, 0x03, 0x72, 0x00, 0xbd, 0x07, + 0xc7, 0xfc, 0xc1, 0xee, 0x36, 0xf9, 0xe5, 0x11, 0x60, 0x0a, 0x22, 0xfe, + 0xa4, 0xf7, 0x14, 0xfa, 0xd5, 0x02, 0x09, 0x00, 0x7a, 0xf9, 0x34, 0x03, + 0x07, 0x0c, 0xbf, 0xfb, 0x11, 0x01, 0x6f, 0xfb, 0x71, 0xfc, 0x52, 0x04, + 0xb0, 0x01, 0xe0, 0x02, 0x3d, 0xff, 0x6e, 0xfc, 0x57, 0xfd, 0x1f, 0xfb, + 0xc1, 0x03, 0x25, 0x09, 0x5e, 0x07, 0xaf, 0xf7, 0x20, 0xf8, 0x27, 0x04, + 0x26, 0x06, 0xf3, 0x06, 0xe6, 0xf5, 0x2b, 0xfa, 0x8b, 0x08, 0x53, 0xee, + 0xc8, 0x00, 0x2c, 0x1a, 0x82, 0x04, 0x97, 0xf9, 0x9a, 0xfc, 0xb4, 0xf0, + 0x1b, 0xec, 0xc1, 0x0b, 0x86, 0x10, 0x9e, 0x02, 0x7e, 0xf8, 0xd3, 0xfd, + 0x03, 0xf2, 0xfd, 0xf6, 0x35, 0x14, 0x88, 0x11, 0x84, 0xec, 0x75, 0xed, + 0xf7, 0x07, 0x4d, 0x00, 0x13, 0x06, 0xa4, 0x12, 0x6c, 0x01, 0x0c, 0xee, + 0xa3, 0xf3, 0xfe, 0x09, 0x9f, 0x14, 0x2c, 0x02, 0x8a, 0xf8, 0xda, 0xfd, + 0x9e, 0x09, 0x91, 0xfd, 0x3c, 0xf9, 0xca, 0x05, 0xc7, 0x0a, 0xd7, 0xfd, + 0xda, 0xea, 0x49, 0xec, 0x4e, 0x10, 0x6d, 0x1a, 0xb3, 0xf7, 0x69, 0xeb, + 0x42, 0x00, 0x31, 0x10, 0x8d, 0x02, 0x28, 0xf2, 0x3c, 0x05, 0x82, 0xf6, + 0x88, 0xf6, 0x16, 0x04, 0x4e, 0x00, 0xb4, 0x0a, 0x1b, 0x0b, 0x9f, 0xf5, + 0xbe, 0xed, 0x22, 0xf9, 0xcf, 0xfc, 0x9c, 0x0e, 0xac, 0x08, 0xd7, 0xf9, + 0x5f, 0xfa, 0x22, 0xfd, 0x03, 0xff, 0x1b, 0x11, 0xa0, 0x07, 0x04, 0xf2, + 0x48, 0x00, 0xcd, 0x08, 0x13, 0xff, 0xab, 0x03, 0x3f, 0x02, 0x1e, 0xfb, + 0xe9, 0xff, 0x96, 0xf4, 0x4d, 0xf3, 0x9e, 0x03, 0x2b, 0x10, 0x5f, 0x09, + 0xa6, 0xf8, 0x27, 0xf4, 0xbf, 0xf1, 0x64, 0xfd, 0xdd, 0x0c, 0x6c, 0x0c, + 0x32, 0xf8, 0x4d, 0xfa, 0x9c, 0x05, 0xfa, 0xf9, 0xbb, 0xfa, 0xb5, 0x09, + 0xe9, 0x08, 0x37, 0xff, 0x48, 0xf4, 0x39, 0xf5, 0x0a, 0x02, 0xf9, 0x09, + 0x98, 0x07, 0x5b, 0xfe, 0xa6, 0xff, 0x4a, 0x00, 0x3d, 0xf8, 0xae, 0x04, + 0xb3, 0x09, 0x32, 0x03, 0xe5, 0xfd, 0xd7, 0xf9, 0xab, 0xf2, 0x4a, 0x02, + 0xae, 0x0f, 0xf2, 0x0b, 0x8b, 0xff, 0x4c, 0xdf, 0x6b, 0xee, 0x91, 0x23, + 0x77, 0x11, 0x47, 0xe6, 0xe9, 0xf6, 0xac, 0x06, 0x91, 0xf4, 0xe1, 0xf5, + 0xe0, 0x06, 0xde, 0x0b, 0xa0, 0x03, 0x38, 0xfe, 0xb1, 0xfb, 0x8f, 0xf9, + 0x0d, 0xfa, 0x1a, 0x04, 0x9b, 0xfe, 0xfd, 0x07, 0xe1, 0x0b, 0x0d, 0xfe, + 0x2b, 0xef, 0x9a, 0xf8, 0x95, 0x0c, 0xa8, 0x02, 0x58, 0xfc, 0xd0, 0xff, + 0xf1, 0xfc, 0xa1, 0xf9, 0x79, 0xfe, 0x14, 0x00, 0x0a, 0x08, 0x98, 0x07, + 0xd7, 0xfc, 0x67, 0xe9, 0xf2, 0xf5, 0x3d, 0x10, 0xf4, 0x19, 0x63, 0x09, + 0xa7, 0xf7, 0x95, 0xf0, 0x2e, 0xf1, 0x14, 0xfd, 0xa5, 0x10, 0x63, 0x0f, + 0xef, 0x10, 0x85, 0xf8, 0x80, 0xeb, 0x61, 0xf7, 0x77, 0x06, 0x5c, 0x10, + 0xc6, 0x09, 0xcb, 0x05, 0xed, 0xf5, 0x4e, 0xe7, 0x73, 0xf3, 0x94, 0x1a, + 0x8a, 0x13, 0xf9, 0xfc, 0x1b, 0xf5, 0x4a, 0xf8, 0x78, 0xfd, 0xa6, 0xf8, + 0x6f, 0x05, 0xc0, 0x13, 0x87, 0xfd, 0xb7, 0xe8, 0x35, 0xfd, 0xe3, 0xfe, + 0x26, 0x06, 0x14, 0x09, 0x26, 0xf5, 0xf2, 0xf6, 0x98, 0x06, 0x14, 0xfb, + 0xb1, 0xf3, 0x3e, 0x04, 0xfc, 0x0b, 0x36, 0xfe, 0x4b, 0xf5, 0x59, 0xfd, + 0xe3, 0x02, 0x44, 0x04, 0x85, 0xfe, 0xad, 0xfd, 0xe3, 0x0b, 0x28, 0x04, + 0xb2, 0xf5, 0xe8, 0x07, 0xd5, 0x06, 0x5b, 0xfb, 0x86, 0x14, 0xac, 0x09, + 0xdc, 0xe6, 0x53, 0xf9, 0xf7, 0x14, 0xee, 0x03, 0x3d, 0xfe, 0xf5, 0xfd, + 0xe6, 0xfa, 0xa9, 0xf9, 0x47, 0x00, 0x9a, 0x03, 0xbc, 0xff, 0xbf, 0x07, + 0x44, 0x03, 0xbb, 0x01, 0x28, 0xfc, 0x97, 0x04, 0x0a, 0x0b, 0x6c, 0xf7, + 0x6d, 0xf2, 0xf6, 0xf9, 0xa8, 0xfd, 0xec, 0x0b, 0xa3, 0x06, 0x79, 0xfb, + 0x8f, 0xf8, 0xfb, 0xf2, 0x32, 0xf8, 0xd1, 0x00, 0x3e, 0x04, 0xb7, 0x07, + 0x60, 0xfe, 0x51, 0xf8, 0xcf, 0xfa, 0xbf, 0xfb, 0xae, 0x01, 0x0e, 0x0c, + 0x51, 0x04, 0xa2, 0xfd, 0xef, 0xff, 0xad, 0xfd, 0x0a, 0xff, 0x29, 0x07, + 0x25, 0x04, 0x07, 0x06, 0x27, 0xfe, 0x2f, 0xfe, 0x89, 0xff, 0xbf, 0x05, + 0x5f, 0x06, 0xb1, 0x00, 0x3e, 0xf9, 0xf6, 0xfa, 0x23, 0x01, 0x10, 0x04, + 0xc6, 0x0a, 0x15, 0xfb, 0x2f, 0xf7, 0x61, 0xfe, 0x62, 0x01, 0xfe, 0x03, + 0x5d, 0x01, 0x89, 0x00, 0x6d, 0xfb, 0xd4, 0xff, 0x21, 0x02, 0xb0, 0x05, + 0xd1, 0x03, 0x1f, 0xfc, 0x73, 0xfe, 0x45, 0x04, 0xd1, 0xf6, 0xef, 0xf5, + 0xcd, 0x05, 0xaa, 0x0e, 0xc0, 0x06, 0x12, 0xf6, 0xdc, 0xf7, 0xbe, 0x01, + 0x80, 0xfe, 0xdb, 0xfa, 0xa3, 0x04, 0xd1, 0x02, 0x99, 0xef, 0xf1, 0x02, + 0xfd, 0x0c, 0xba, 0x03, 0x95, 0x07, 0xdb, 0xfb, 0x6d, 0xf3, 0x24, 0xfe, + 0x5d, 0x07, 0xec, 0xff, 0x7c, 0x04, 0xb2, 0xf9, 0x48, 0xfa, 0xf7, 0xff, + 0x0c, 0x02, 0x2b, 0x00, 0xca, 0x0b, 0xd8, 0x03, 0x55, 0xf4, 0x6c, 0xf4, + 0x7c, 0xfe, 0x20, 0xfd, 0x0c, 0xfd, 0x2c, 0x05, 0xcb, 0x0a, 0x67, 0x08, + 0x30, 0xfc, 0xe0, 0xfd, 0xb4, 0x00, 0x1d, 0xff, 0x52, 0x06, 0x4b, 0x0d, + 0x93, 0x07, 0x02, 0x01, 0xef, 0xf1, 0x09, 0xf7, 0xb4, 0x07, 0xf4, 0x05, + 0x49, 0xf8, 0x19, 0x00, 0xf3, 0x09, 0x1d, 0xfe, 0x1b, 0xfe, 0xb3, 0x04, + 0xbc, 0x01, 0x21, 0xf3, 0x1d, 0xf7, 0xbc, 0xfc, 0x7a, 0x02, 0xab, 0x04, + 0xca, 0x05, 0xe0, 0x02, 0xa4, 0x00, 0x96, 0xfd, 0x80, 0x00, 0xdd, 0x06, + 0x18, 0x0a, 0xf2, 0xfe, 0xd3, 0xf7, 0x40, 0xfe, 0x80, 0xfb, 0xdb, 0x04, + 0xde, 0x08, 0xe6, 0xfa, 0xb8, 0xfa, 0x46, 0x02, 0xd9, 0xff, 0x99, 0xfe, + 0x45, 0x04, 0x77, 0x00, 0x8d, 0xf9, 0x1b, 0x03, 0xf7, 0x03, 0x77, 0x0d, + 0xd4, 0x09, 0x61, 0xfb, 0xbe, 0xfb, 0x96, 0xfd, 0xf7, 0x00, 0x84, 0x02, + 0xed, 0x05, 0xc3, 0x04, 0x62, 0xff, 0x50, 0xfa, 0x47, 0xff, 0x03, 0x00, + 0x26, 0xf9, 0x5d, 0xf7, 0x9f, 0x00, 0x88, 0x05, 0x2c, 0x04, 0x45, 0xff, + 0xc1, 0xf6, 0x0d, 0xf9, 0x19, 0x00, 0x17, 0x04, 0x06, 0x0a, 0x42, 0x04, + 0x30, 0xfe, 0x83, 0xfb, 0x4a, 0xfb, 0x4f, 0x00, 0xbc, 0x05, 0x88, 0x0c, + 0xbc, 0x04, 0x20, 0x00, 0xd0, 0x00, 0x7f, 0xfe, 0x51, 0xfc, 0x19, 0xfd, + 0xaf, 0x00, 0x39, 0x06, 0x9e, 0x03, 0xdc, 0xff, 0x21, 0x00, 0x79, 0x01, + 0xd3, 0xfd, 0xc3, 0xfb, 0x2f, 0xff, 0x2a, 0x08, 0x15, 0x05, 0x5b, 0xfb, + 0x01, 0xfa, 0x43, 0xfa, 0x7a, 0xfd, 0x3b, 0x04, 0xc0, 0xfd, 0x2b, 0xfd, + 0x2d, 0x06, 0xcc, 0x02, 0x66, 0x00, 0xaa, 0x02, 0x8c, 0xfc, 0x3d, 0xf8, + 0x3f, 0x04, 0x8b, 0x06, 0x82, 0x0a, 0x7c, 0x08, 0x73, 0xf6, 0x86, 0xf7, + 0x80, 0x04, 0xcf, 0x02, 0x53, 0x02, 0x2c, 0x06, 0x93, 0xfe, 0x79, 0xfa, + 0x55, 0x00, 0x4f, 0x03, 0x2f, 0xff, 0x66, 0xfd, 0x29, 0xfc, 0x45, 0x06, + 0x91, 0x03, 0xa9, 0xff, 0xf2, 0xf8, 0x29, 0xfb, 0x16, 0x05, 0xdf, 0x06, + 0x0d, 0x08, 0xb5, 0x08, 0x2b, 0xff, 0x2b, 0xf9, 0x37, 0xfe, 0x68, 0xfa, + 0xe1, 0xfb, 0xdd, 0x07, 0xe6, 0x05, 0x43, 0xff, 0x7d, 0x06, 0x0f, 0xfe, + 0xbc, 0xfb, 0x7f, 0xfe, 0x73, 0x03, 0xfa, 0x04, 0xc7, 0xfd, 0x6f, 0xf6, + 0x2f, 0xfa, 0xea, 0x07, 0xc9, 0x06, 0x12, 0xff, 0x6d, 0x07, 0xd8, 0x07, + 0xe4, 0xfe, 0xd6, 0xfc, 0xd0, 0x03, 0x32, 0x07, 0x30, 0xfe, 0xf9, 0xf7, + 0xe7, 0xff, 0xef, 0x08, 0x57, 0x08, 0xbf, 0x09, 0x73, 0x01, 0xf4, 0xf1, + 0xf1, 0xf0, 0x5a, 0x01, 0x0f, 0x06, 0xf9, 0x01, 0xff, 0x02, 0x91, 0xfe, + 0x7e, 0xf8, 0xf0, 0xf9, 0xdc, 0x01, 0xc0, 0x04, 0xa1, 0x01, 0xa0, 0x00, + 0xc6, 0x00, 0x70, 0xff, 0x78, 0xfc, 0xb7, 0x00, 0x18, 0xfa, 0x77, 0xf1, + 0x10, 0x01, 0xd7, 0x0b, 0xe0, 0x07, 0x5e, 0x03, 0x58, 0xff, 0xa1, 0xfc, + 0x5d, 0xfa, 0x03, 0xfe, 0x99, 0x03, 0x38, 0x02, 0x3d, 0xfa, 0x96, 0xff, + 0x8f, 0x09, 0x0d, 0x03, 0xa2, 0xff, 0x83, 0x07, 0x7f, 0x07, 0x80, 0x00, + 0x37, 0xfc, 0x4e, 0x02, 0xc0, 0x03, 0xc3, 0xff, 0x38, 0xff, 0x73, 0xff, + 0x20, 0xfe, 0xfb, 0x00, 0xa6, 0x02, 0x5f, 0xfe, 0x5c, 0xfd, 0xae, 0x06, + 0xcd, 0x01, 0x0c, 0xfc, 0x58, 0xfd, 0xcc, 0xfe, 0x80, 0xfc, 0x9a, 0xfb, + 0xc3, 0xfd, 0x89, 0x02, 0x9f, 0x07, 0x63, 0x05, 0x19, 0x00, 0x25, 0xff, + 0xc1, 0xff, 0x14, 0xf8, 0xf5, 0xf8, 0x8d, 0x02, 0xa6, 0x09, 0x26, 0x07, + 0xbd, 0x01, 0x56, 0xfd, 0x1b, 0xfa, 0x1c, 0xfb, 0x4f, 0x00, 0xaf, 0x03, + 0x57, 0x07, 0xc0, 0x03, 0x3f, 0x02, 0x20, 0x01, 0x7a, 0xff, 0x3e, 0xfd, + 0xfa, 0xff, 0x7d, 0x00, 0xbc, 0x03, 0xdc, 0x05, 0x89, 0x07, 0xec, 0x04, + 0xc4, 0xfe, 0xa3, 0xfc, 0x67, 0xfd, 0xec, 0x00, 0xc3, 0xfe, 0xd1, 0xff, + 0x0b, 0x05, 0x78, 0x01, 0x49, 0xfe, 0x33, 0xfc, 0x27, 0xfc, 0x1a, 0xfe, + 0xf8, 0x01, 0x91, 0xff, 0x9b, 0xfd, 0xa7, 0xff, 0x0e, 0xff, 0x41, 0xfe, + 0xc7, 0xfe, 0x1e, 0x00, 0xc5, 0x01, 0xb6, 0xfe, 0x04, 0x00, 0x3e, 0x00, + 0xcf, 0xfe, 0xf3, 0x01, 0xc0, 0x01, 0xf3, 0x00, 0x5a, 0x04, 0x83, 0x01, + 0x01, 0xfd, 0x8d, 0xfd, 0x14, 0xfc, 0x0e, 0xfb, 0xe9, 0x01, 0x86, 0x03, + 0x8d, 0x02, 0x03, 0x01, 0x24, 0xfe, 0xcd, 0xfc, 0xea, 0xfc, 0x84, 0xfe, + 0xde, 0x00, 0x9b, 0x01, 0x38, 0x00, 0x33, 0xff, 0x25, 0xff, 0xd8, 0xfc, + 0x98, 0xfa, 0x50, 0x00, 0xd2, 0x04, 0x91, 0x05, 0xf1, 0x04, 0xc7, 0x03, + 0xac, 0x00, 0x15, 0xff, 0xe6, 0xff, 0x1b, 0xff, 0x30, 0xfe, 0xe2, 0x00, + 0x3e, 0x01, 0x4c, 0x03, 0x54, 0xff, 0x8e, 0xfe, 0x80, 0xff, 0xbd, 0x00, + 0xf2, 0x01, 0x32, 0x02, 0x8d, 0xfe, 0x81, 0x00, 0xa9, 0xfe, 0xda, 0xfc, + 0x18, 0x00, 0x70, 0x02, 0x18, 0x01, 0x58, 0x00, 0xa9, 0x00, 0x4c, 0x02, + 0xf0, 0x03, 0xf2, 0x01, 0xa2, 0xff, 0x6e, 0xfe, 0x7f, 0xfe, 0x30, 0xfe, + 0x0e, 0x03, 0xa5, 0x04, 0x9b, 0x05, 0x56, 0x05, 0xf7, 0x04, 0xea, 0xff, + 0xb0, 0xfd, 0xe1, 0xfc, 0xe8, 0xfc, 0xb1, 0x01, 0x73, 0x06, 0x45, 0x08, + 0x08, 0x06, 0xc0, 0x02, 0x7e, 0xff, 0x85, 0x00, 0x67, 0x00, 0xcd, 0x02, + 0x64, 0x01, 0xdb, 0xfd, 0x7b, 0xfc, 0x4a, 0xfc, 0x73, 0xfc, 0x56, 0x00, + 0xf2, 0x02, 0x6f, 0x00, 0x1e, 0xfe, 0x21, 0xfd, 0x9b, 0xfc, 0xb4, 0xfd, + 0x44, 0xfe, 0x27, 0xfc, 0x42, 0xfb, 0x8b, 0xfc, 0xf8, 0xfc, 0x76, 0xfe, + 0xf3, 0x00, 0xdc, 0xfe, 0xe9, 0xfc, 0x36, 0xfe, 0xd3, 0xfb, 0x5c, 0xfb, + 0x4b, 0xfb, 0x0f, 0xfb, 0x6f, 0xfd, 0xd3, 0xfd, 0xe9, 0xff, 0x63, 0x00, + 0xae, 0xfd, 0x87, 0xfc, 0xdc, 0xfa, 0x3f, 0xfa, 0xd2, 0xfa, 0x14, 0xfa, + 0x88, 0xfa, 0x01, 0xfd, 0x55, 0xfe, 0x47, 0xfe, 0x90, 0xff, 0xcb, 0xff, + 0x26, 0x00, 0x7b, 0xfd, 0xee, 0xfa, 0x1d, 0xfb, 0xab, 0xfd, 0x45, 0xfe, + 0x41, 0xfd, 0x6b, 0xfe, 0x6c, 0xfc, 0x54, 0xfe, 0x3b, 0x01, 0xc6, 0x00, + 0xc5, 0x00, 0x95, 0x02, 0x64, 0x02, 0xa3, 0x00, 0xd8, 0xfe, 0xfa, 0xfe, + 0xf6, 0xfc, 0xa4, 0xfd, 0xf2, 0xff, 0x9e, 0x02, 0x19, 0x06, 0x90, 0x07, + 0x52, 0x04, 0xda, 0x02, 0x34, 0x02, 0x61, 0x02, 0xc6, 0x02, 0x24, 0x06, + 0xc4, 0x0a, 0xf1, 0x08, 0x66, 0x08, 0x02, 0x08, 0x26, 0x08, 0x27, 0x07, + 0xde, 0x08, 0x99, 0x06, 0x72, 0x04, 0x94, 0x02, 0x14, 0x03, 0xec, 0x04, + 0xe9, 0x02, 0x80, 0x01, 0x32, 0x05, 0xe2, 0x06, 0xa0, 0x06, 0xcc, 0x06, + 0x8b, 0x05, 0x17, 0x01, 0x98, 0xff, 0xf4, 0xff, 0x52, 0xfd, 0xbb, 0xf8, + 0xfb, 0xf9, 0xb0, 0xfe, 0x15, 0x04, 0xfd, 0x09, 0x1a, 0x05, 0x26, 0xff, + 0x9b, 0xfa, 0x27, 0xfb, 0x89, 0xfc, 0x37, 0xfd, 0x42, 0xfc, 0x6e, 0xf9, + 0xbe, 0xf8, 0xb3, 0xf8, 0xdb, 0xfb, 0x55, 0xfb, 0x30, 0xfc, 0x63, 0xf9, + 0x0f, 0xf6, 0x31, 0xf4, 0x83, 0xf4, 0x75, 0xf5, 0x48, 0xf8, 0x3c, 0xfa, + 0x5c, 0xfa, 0x09, 0xf8, 0x75, 0xf6, 0x34, 0xf7, 0xf3, 0xf5, 0x77, 0xf7, + 0x5f, 0xf8, 0xa2, 0xf8, 0x75, 0xf7, 0x88, 0xf5, 0x11, 0xf7, 0x57, 0xf7, + 0x7f, 0xfa, 0x73, 0xfd, 0x9d, 0xfd, 0x58, 0xfd, 0xfb, 0xfa, 0x80, 0xf9, + 0xa0, 0xf6, 0x74, 0xf9, 0xba, 0xff, 0x36, 0x04, 0x3b, 0x05, 0x59, 0x01, + 0xc1, 0xff, 0x63, 0xfd, 0xb9, 0x00, 0x19, 0x04, 0xaa, 0x07, 0xcf, 0x04, + 0x5e, 0x02, 0x9c, 0x00, 0x83, 0x01, 0x21, 0x08, 0x36, 0x0c, 0xed, 0x0b, + 0xaa, 0x09, 0xc7, 0x06, 0x2e, 0x05, 0x81, 0x07, 0x84, 0x08, 0xe4, 0x07, + 0xec, 0x07, 0x36, 0x08, 0x91, 0x07, 0x4d, 0x0b, 0x85, 0x0e, 0x87, 0x0d, + 0x8d, 0x0a, 0xc7, 0x08, 0xd4, 0x04, 0x31, 0x00, 0xd6, 0x02, 0x5d, 0x05, + 0x77, 0x06, 0xb5, 0x07, 0x24, 0x09, 0x7b, 0x0a, 0xf8, 0x09, 0x43, 0x09, + 0xf5, 0x04, 0x3d, 0x03, 0x25, 0x01, 0xfe, 0x01, 0x21, 0x02, 0xf5, 0x03, + 0xae, 0x07, 0x2f, 0x07, 0xdc, 0x04, 0xc6, 0x02, 0xc3, 0xff, 0x4a, 0xff, + 0x52, 0xfd, 0xe2, 0xfd, 0x3e, 0xfb, 0xe2, 0xfa, 0xde, 0xfa, 0xfc, 0xfa, + 0xa1, 0xf8, 0xeb, 0xf6, 0x3f, 0xf2, 0x6c, 0xef, 0xbc, 0xec, 0x0a, 0xec, + 0x11, 0xef, 0x65, 0xf1, 0x19, 0xf2, 0x3d, 0xf1, 0x72, 0xef, 0x0a, 0xed, + 0x61, 0xef, 0xe3, 0xf2, 0x42, 0xf2, 0x4c, 0xf1, 0xe1, 0xf1, 0x44, 0xf2, + 0xd1, 0xf1, 0x14, 0xf2, 0x60, 0xf7, 0x39, 0xfc, 0xbf, 0xff, 0x6d, 0xff, + 0xb9, 0x07, 0x1e, 0x07, 0xc7, 0x06, 0x6d, 0x01, 0xae, 0xf5, 0xc5, 0xf3, + 0xf3, 0xf7, 0x37, 0xfe, 0xf9, 0x02, 0x8e, 0x06, 0x64, 0x02, 0xd7, 0xfc, + 0x4c, 0xfc, 0x79, 0xfd, 0x83, 0x01, 0x0b, 0x05, 0xb0, 0x08, 0x5d, 0x06, + 0xca, 0x00, 0x69, 0xff, 0x9d, 0xfe, 0x12, 0x02, 0x2b, 0x07, 0x8d, 0x0a, + 0x4f, 0x0d, 0x0a, 0x0f, 0xd4, 0x0e, 0xe3, 0x0d, 0x63, 0x0c, 0x35, 0x0a, + 0x70, 0x07, 0xb3, 0x08, 0x02, 0x08, 0xc5, 0x0a, 0xa5, 0x0d, 0xbc, 0x10, + 0xbf, 0x12, 0xd1, 0x11, 0x34, 0x0d, 0x17, 0x07, 0xd9, 0x04, 0xc4, 0x04, + 0x83, 0x06, 0xf0, 0x07, 0x17, 0x09, 0x6e, 0x09, 0x1e, 0x0d, 0x45, 0x0f, + 0xec, 0x0e, 0x48, 0x0d, 0x4a, 0x08, 0xcf, 0x05, 0xa2, 0x02, 0x84, 0x00, + 0x51, 0xff, 0x9b, 0xfd, 0xc9, 0xfc, 0x8b, 0xfd, 0x4d, 0xfe, 0xbd, 0x00, + 0x93, 0xff, 0x7d, 0xff, 0x93, 0xf9, 0x14, 0xf5, 0x9a, 0xf0, 0xf1, 0xef, + 0x1a, 0xf0, 0xbe, 0xf0, 0xac, 0xf0, 0x25, 0xec, 0x9d, 0xee, 0x38, 0xed, + 0xcb, 0xed, 0xc3, 0xed, 0x77, 0xed, 0x9e, 0xec, 0xb6, 0xee, 0x49, 0xf0, + 0x66, 0xf1, 0xd8, 0xf6, 0x4d, 0xf7, 0x61, 0xf6, 0xd4, 0xf4, 0x5c, 0xf2, + 0x70, 0xf3, 0x08, 0xf4, 0xd1, 0xf6, 0x75, 0xfb, 0x4c, 0xfe, 0x53, 0xfe, + 0x26, 0x01, 0xe5, 0xff, 0x84, 0x07, 0x74, 0x05, 0xf6, 0x03, 0x0a, 0x02, + 0xc5, 0xfb, 0x7f, 0xf6, 0xf1, 0xf6, 0x63, 0xfa, 0x82, 0xfd, 0x03, 0x01, + 0xd1, 0x02, 0xa2, 0xff, 0x2e, 0xfe, 0x8e, 0xfb, 0xa3, 0xfb, 0x16, 0xff, + 0x68, 0xff, 0xdb, 0x02, 0xd7, 0x08, 0xc6, 0x0b, 0x0c, 0x0d, 0x8b, 0x0d, + 0x35, 0x0c, 0x0a, 0x0f, 0xda, 0x11, 0xbe, 0x13, 0x26, 0x14, 0xff, 0x12, + 0x61, 0x10, 0x4b, 0x12, 0x90, 0x12, 0xfc, 0x12, 0x79, 0x12, 0x12, 0x11, + 0x18, 0x0d, 0x1e, 0x0b, 0x2c, 0x08, 0x26, 0x08, 0x57, 0x09, 0xad, 0x09, + 0x72, 0x09, 0xf6, 0x0a, 0x48, 0x0a, 0xd8, 0x0d, 0xfa, 0x0d, 0x19, 0x0c, + 0xe3, 0x09, 0x69, 0x05, 0x07, 0x04, 0x25, 0x05, 0x16, 0x06, 0x5a, 0x06, + 0x4d, 0x05, 0x15, 0x04, 0xf1, 0x00, 0xb5, 0xff, 0x08, 0xfc, 0x51, 0xf5, + 0x79, 0xf0, 0x8e, 0xec, 0x7e, 0xeb, 0x48, 0xef, 0xdf, 0xf0, 0x4d, 0xf5, + 0x13, 0xf5, 0xcc, 0xf4, 0xa2, 0xf1, 0xbb, 0xed, 0xd1, 0xea, 0xe8, 0xe6, + 0xea, 0xe7, 0xca, 0xe9, 0x2f, 0xef, 0xe9, 0xf0, 0x3d, 0xf0, 0xbb, 0xeb, + 0xe5, 0xed, 0x12, 0xf3, 0x6b, 0xfa, 0x1f, 0xfe, 0xbb, 0xfe, 0x8f, 0xf8, + 0x05, 0xf5, 0xa4, 0xf3, 0xcf, 0xf5, 0xb1, 0xfb, 0xb3, 0x01, 0xa2, 0xfe, + 0x30, 0xfe, 0x17, 0xfc, 0xd4, 0xfd, 0x69, 0x01, 0x97, 0x01, 0x6a, 0xfe, + 0x53, 0xf9, 0x95, 0xf5, 0x38, 0xf4, 0xf0, 0xf3, 0x13, 0xf5, 0x4d, 0xfa, + 0x4e, 0xfc, 0x32, 0x00, 0x65, 0x02, 0x5b, 0x04, 0x75, 0x03, 0xe4, 0x05, + 0x10, 0x07, 0x51, 0x06, 0x47, 0x07, 0x10, 0x0a, 0xe0, 0x0b, 0x3f, 0x0f, + 0x96, 0x11, 0xcf, 0x14, 0x73, 0x15, 0xe3, 0x16, 0xb8, 0x14, 0x1f, 0x11, + 0xc2, 0x0c, 0x28, 0x0c, 0x40, 0x0d, 0x31, 0x0e, 0xef, 0x0e, 0x83, 0x0f, + 0xd8, 0x0f, 0x7e, 0x0f, 0x18, 0x0f, 0x82, 0x0d, 0xce, 0x0d, 0x26, 0x0d, + 0x0f, 0x0d, 0x59, 0x0c, 0x36, 0x0b, 0x56, 0x0a, 0x1c, 0x0c, 0x8e, 0x0c, + 0x05, 0x0d, 0xe3, 0x0a, 0x81, 0x0a, 0xa9, 0x07, 0xf0, 0x04, 0x45, 0x02, + 0x2c, 0xfd, 0xad, 0xf8, 0xb4, 0xf6, 0x8b, 0xf5, 0xdb, 0xf6, 0x12, 0xf9, + 0x11, 0xf9, 0xcb, 0xf9, 0xf2, 0xf7, 0x2e, 0xf5, 0x64, 0xf0, 0x58, 0xed, + 0xb5, 0xeb, 0x8f, 0xeb, 0x56, 0xee, 0xf4, 0xec, 0xce, 0xe9, 0x90, 0xe9, + 0x7b, 0xe7, 0xc1, 0xe8, 0x04, 0xed, 0x56, 0xf1, 0x19, 0xf5, 0xac, 0xf5, + 0xc1, 0xf6, 0x16, 0xf3, 0x69, 0xf2, 0xf5, 0xf1, 0xea, 0xf5, 0xc4, 0xf9, + 0x21, 0xf9, 0xa4, 0xfb, 0x2a, 0xfc, 0x09, 0xfe, 0x01, 0x01, 0x04, 0x00, + 0xee, 0x00, 0x16, 0xfd, 0xce, 0xfb, 0x5b, 0xfb, 0x2a, 0xf8, 0x12, 0xf9, + 0xfb, 0xf4, 0xbb, 0xf8, 0xec, 0xf7, 0x46, 0xfc, 0x6d, 0xfd, 0xba, 0xfb, + 0x15, 0xfd, 0x39, 0xfb, 0x55, 0xfb, 0x57, 0xfc, 0xe8, 0xfe, 0xfc, 0xfd, + 0xec, 0x01, 0xd2, 0x03, 0x04, 0x06, 0x7f, 0x0e, 0x20, 0x0f, 0x1d, 0x0e, + 0x8b, 0x0d, 0x4e, 0x0b, 0xaf, 0x0c, 0xbe, 0x13, 0xed, 0x13, 0x75, 0x13, + 0x40, 0x14, 0x8f, 0x13, 0x81, 0x14, 0x58, 0x16, 0x38, 0x17, 0x51, 0x17, + 0xa9, 0x16, 0xc8, 0x11, 0x41, 0x0e, 0xd7, 0x0b, 0xb8, 0x0a, 0x29, 0x0d, + 0x46, 0x0d, 0x18, 0x0d, 0xc1, 0x0a, 0x6d, 0x09, 0x5c, 0x09, 0x3a, 0x0a, + 0xcc, 0x0b, 0x80, 0x0d, 0xae, 0x0c, 0xcf, 0x09, 0xab, 0x05, 0x83, 0x01, + 0xc2, 0xff, 0x35, 0xff, 0x1a, 0x00, 0x11, 0xfe, 0x1e, 0xfc, 0xde, 0xf9, + 0x46, 0xf9, 0x0d, 0xf9, 0xb8, 0xf6, 0xb4, 0xf3, 0x1c, 0xf1, 0x70, 0xeb, + 0x7d, 0xeb, 0xf2, 0xe9, 0x93, 0xeb, 0x0d, 0xec, 0xf8, 0xec, 0x69, 0xeb, + 0x93, 0xeb, 0x15, 0xec, 0x4a, 0xec, 0x2e, 0xed, 0x29, 0xec, 0x6b, 0xef, + 0x7d, 0xf1, 0xbb, 0xf6, 0xb2, 0xf9, 0x87, 0xfb, 0x6d, 0xfa, 0x4a, 0xf8, + 0x5e, 0xf9, 0xb6, 0xfc, 0x93, 0x00, 0x5b, 0x00, 0x97, 0x01, 0x19, 0x00, + 0xbf, 0xfc, 0x18, 0xfa, 0x27, 0xfa, 0xab, 0xf6, 0x4b, 0xf5, 0x85, 0xf1, + 0xb8, 0xf0, 0xd8, 0xf4, 0x2e, 0xf6, 0xc4, 0xfb, 0x97, 0xfb, 0xa2, 0xf6, + 0xeb, 0xf5, 0x6e, 0xf4, 0x46, 0xf9, 0x9e, 0xfe, 0x23, 0x02, 0x0d, 0x08, + 0xd8, 0x06, 0x89, 0x05, 0x91, 0x03, 0xe1, 0x05, 0xd9, 0x08, 0x73, 0x0f, + 0x49, 0x10, 0xf9, 0x11, 0xc8, 0x10, 0x4b, 0x0d, 0x81, 0x0b, 0x26, 0x0a, + 0xe0, 0x0a, 0x2e, 0x0f, 0xf6, 0x12, 0xd4, 0x14, 0xf1, 0x16, 0xbd, 0x13, + 0xda, 0x14, 0x51, 0x14, 0x92, 0x15, 0x72, 0x15, 0x24, 0x15, 0x2e, 0x14, + 0xd9, 0x11, 0xe6, 0x0d, 0x22, 0x0d, 0xfa, 0x0c, 0x94, 0x0d, 0xc6, 0x0f, + 0x5f, 0x0e, 0xbc, 0x0b, 0x15, 0x0a, 0xa1, 0x07, 0x13, 0x07, 0x45, 0x08, + 0xc9, 0x06, 0xe1, 0x04, 0x7c, 0x02, 0xdd, 0xff, 0x73, 0xfe, 0x5e, 0xfe, + 0x83, 0xfd, 0x13, 0xfe, 0x93, 0xfc, 0x02, 0xfe, 0xa7, 0xf9, 0xc8, 0xf8, + 0x2e, 0xf5, 0xd8, 0xf2, 0x3f, 0xf0, 0x90, 0xec, 0x2b, 0xe9, 0xad, 0xe5, + 0x58, 0xe5, 0x81, 0xe3, 0xbd, 0xe2, 0x2b, 0xe1, 0xee, 0xdf, 0x28, 0xe3, + 0x0b, 0xe8, 0x59, 0xeb, 0xf2, 0xf0, 0x52, 0xf6, 0x1b, 0xf9, 0x47, 0xff, + 0x63, 0x01, 0x7d, 0x01, 0xd9, 0x01, 0x55, 0x01, 0x44, 0x02, 0xce, 0x03, + 0x96, 0x05, 0x75, 0x03, 0x64, 0x01, 0xfd, 0xfd, 0xf1, 0xfa, 0x4d, 0xf8, + 0xb7, 0xf4, 0x70, 0xf0, 0x90, 0xee, 0xfc, 0xed, 0x1a, 0xee, 0xda, 0xee, + 0x24, 0xf1, 0x1f, 0xf2, 0x83, 0xf3, 0xdc, 0xf5, 0x58, 0xf9, 0x0c, 0xfd, + 0x0f, 0x02, 0xc7, 0x04, 0xfb, 0x05, 0x77, 0x08, 0xdb, 0x07, 0x05, 0x07, + 0x0e, 0x08, 0x91, 0x08, 0x10, 0x0b, 0x6b, 0x0e, 0x0d, 0x0e, 0x44, 0x0c, + 0xf5, 0x0b, 0xb4, 0x0a, 0x8d, 0x0b, 0xbc, 0x0e, 0x88, 0x0d, 0x77, 0x10, + 0xb2, 0x12, 0xfa, 0x14, 0x6b, 0x19, 0x2b, 0x1c, 0x61, 0x1e, 0xb3, 0x1e, + 0x39, 0x1e, 0x1c, 0x1a, 0xc0, 0x16, 0xb1, 0x12, 0x65, 0x10, 0xc7, 0x0d, + 0xc1, 0x0b, 0x5b, 0x08, 0x77, 0x07, 0x9a, 0x06, 0xce, 0x05, 0xaa, 0x04, + 0x4b, 0x02, 0x20, 0x01, 0xc2, 0x00, 0x9d, 0x02, 0x04, 0x04, 0xc9, 0x04, + 0x8e, 0x04, 0xcb, 0x02, 0x41, 0x02, 0x30, 0x02, 0x66, 0x04, 0x4a, 0x04, + 0x0e, 0x05, 0x5e, 0x01, 0xa9, 0xfd, 0xb3, 0xf8, 0x1f, 0xf3, 0xb6, 0xee, + 0x82, 0xea, 0xdd, 0xe6, 0xc3, 0xe1, 0x5d, 0xdd, 0x90, 0xd8, 0xfd, 0xd6, + 0xab, 0xd8, 0xda, 0xda, 0x9b, 0xdf, 0x73, 0xe4, 0xe7, 0xe7, 0x8d, 0xf0, + 0x43, 0xf8, 0x3c, 0x00, 0x1f, 0x05, 0xa3, 0x07, 0xaa, 0x08, 0xbd, 0x08, + 0x97, 0x09, 0x09, 0x06, 0x7f, 0x04, 0x06, 0x02, 0xb6, 0xff, 0x1a, 0xff, + 0x29, 0xfb, 0x60, 0xf7, 0x0e, 0xf2, 0x92, 0xef, 0x17, 0xec, 0xf9, 0xea, + 0xfa, 0xe8, 0xcc, 0xe9, 0x9f, 0xea, 0x30, 0xee, 0xea, 0xf2, 0x0f, 0xf7, + 0x50, 0xfc, 0x65, 0xff, 0xd2, 0x00, 0x42, 0x02, 0x5b, 0x05, 0xfc, 0x06, + 0x48, 0x09, 0x4f, 0x0d, 0x93, 0x0d, 0x20, 0x0e, 0x71, 0x0d, 0x77, 0x08, + 0x21, 0x06, 0x87, 0x04, 0xa2, 0x01, 0x36, 0x03, 0xf9, 0x05, 0x6c, 0x0c, + 0x89, 0x11, 0xaf, 0x13, 0x0c, 0x14, 0x35, 0x14, 0xb1, 0x16, 0x2d, 0x19, + 0xd8, 0x1c, 0x5e, 0x1e, 0x5f, 0x1e, 0x13, 0x1d, 0x0b, 0x1c, 0xfc, 0x19, + 0x4d, 0x19, 0x50, 0x18, 0x55, 0x16, 0x27, 0x13, 0x2f, 0x0f, 0xbd, 0x09, + 0x60, 0x04, 0xb1, 0xff, 0xd9, 0xfd, 0xf0, 0xfd, 0xe4, 0xfe, 0x16, 0x00, + 0xcb, 0x00, 0x95, 0x00, 0xf6, 0x01, 0xce, 0x03, 0x37, 0x06, 0x85, 0x07, + 0xc9, 0x07, 0x7d, 0x05, 0x81, 0x03, 0x3b, 0x01, 0x09, 0x00, 0x61, 0xff, + 0x0e, 0xff, 0x9b, 0xfd, 0xc4, 0xf9, 0x46, 0xf3, 0x7a, 0xeb, 0x46, 0xe2, + 0x43, 0xdc, 0xe3, 0xd7, 0xce, 0xd4, 0xb7, 0xd3, 0xb0, 0xd2, 0x49, 0xd6, + 0x36, 0xdd, 0xbb, 0xe4, 0x45, 0xec, 0xdc, 0xf2, 0x41, 0xf7, 0x62, 0xfb, + 0xf2, 0xff, 0x37, 0x05, 0x14, 0x08, 0xcf, 0x0b, 0x9e, 0x0b, 0x89, 0x0a, + 0x4e, 0x0b, 0x9b, 0x09, 0x43, 0x04, 0x7e, 0xfe, 0xe4, 0xf6, 0x0f, 0xf1, + 0x6c, 0xec, 0x52, 0xea, 0xec, 0xe5, 0xc5, 0xe4, 0xa6, 0xe4, 0x5e, 0xe6, + 0x0c, 0xe9, 0xe6, 0xee, 0xad, 0xf4, 0xc3, 0xfa, 0xe3, 0xff, 0x7e, 0x04, + 0x16, 0x08, 0x51, 0x0f, 0x7b, 0x14, 0x52, 0x15, 0x3a, 0x15, 0xdc, 0x0f, + 0xce, 0x0a, 0x1b, 0x07, 0xe5, 0x02, 0xff, 0xfe, 0x51, 0xff, 0x9f, 0xfe, + 0x5e, 0xfe, 0xe5, 0xff, 0x74, 0x01, 0xa7, 0x03, 0x2c, 0x09, 0x61, 0x0c, + 0x44, 0x10, 0xa2, 0x15, 0x5d, 0x19, 0xe8, 0x1d, 0xdc, 0x21, 0x5f, 0x25, + 0x70, 0x27, 0x32, 0x27, 0x14, 0x25, 0xab, 0x21, 0x1e, 0x1e, 0xe1, 0x19, + 0x84, 0x16, 0x1e, 0x11, 0x90, 0x0b, 0x83, 0x08, 0x58, 0x04, 0xa4, 0x00, + 0xe9, 0xfe, 0x6b, 0xfb, 0xe2, 0xfa, 0x18, 0xfb, 0xc5, 0xfa, 0x21, 0xfd, + 0x88, 0xff, 0x0a, 0x02, 0x5d, 0x07, 0xa3, 0x0a, 0x57, 0x0b, 0xfc, 0x0b, + 0x91, 0x0a, 0xcc, 0x06, 0xe7, 0x04, 0x8b, 0x02, 0x60, 0xff, 0xd3, 0xf9, + 0x5c, 0xf6, 0x17, 0xf0, 0xf8, 0xec, 0x38, 0xe9, 0x1a, 0xe5, 0x7c, 0xe1, + 0xf6, 0xdc, 0x68, 0xd9, 0x0f, 0xd7, 0x67, 0xd6, 0x0b, 0xd5, 0x38, 0xd6, + 0xa6, 0xd9, 0x1d, 0xe0, 0x26, 0xe9, 0xaf, 0xf4, 0xd3, 0xff, 0x08, 0x0a, + 0x64, 0x0f, 0xbb, 0x10, 0x67, 0x0f, 0x93, 0x0e, 0x8b, 0x0c, 0x8e, 0x09, + 0x0f, 0x05, 0xb6, 0xfe, 0x25, 0xfc, 0x86, 0xf6, 0xb4, 0xf0, 0x5b, 0xec, + 0xd1, 0xe8, 0xc6, 0xe5, 0x0d, 0xe7, 0x02, 0xe7, 0x62, 0xe7, 0xfc, 0xea, + 0xb3, 0xed, 0x9e, 0xf2, 0x7a, 0xf8, 0x2b, 0xff, 0x64, 0x06, 0x03, 0x0d, + 0x87, 0x11, 0x96, 0x12, 0x31, 0x10, 0xc2, 0x10, 0x94, 0x0f, 0x00, 0x0d, + 0xfc, 0x09, 0xda, 0x04, 0xcb, 0x00, 0x38, 0xfe, 0x80, 0xfa, 0x17, 0xf8, + 0x9a, 0xf9, 0xdd, 0xfb, 0x10, 0xfe, 0xc9, 0x02, 0xc1, 0x07, 0xd3, 0x0c, + 0x8f, 0x12, 0x71, 0x17, 0x86, 0x1b, 0x1f, 0x20, 0xd2, 0x23, 0xdc, 0x25, + 0xa9, 0x27, 0xac, 0x27, 0xc0, 0x26, 0x4a, 0x24, 0x23, 0x20, 0x4e, 0x1b, + 0xde, 0x14, 0xc1, 0x0d, 0x64, 0x06, 0x45, 0x00, 0x57, 0xfc, 0x4a, 0xfb, + 0x15, 0xfb, 0xcf, 0xfa, 0xc9, 0xfa, 0x87, 0xfc, 0x1f, 0xff, 0xd6, 0x03, + 0x89, 0x07, 0x64, 0x08, 0xfb, 0x07, 0x83, 0x06, 0xb4, 0x05, 0x22, 0x05, + 0x69, 0x05, 0x49, 0x06, 0xf8, 0x06, 0x0d, 0x06, 0xe0, 0x02, 0x5a, 0xfe, + 0xfd, 0xf7, 0x6b, 0xf1, 0x04, 0xed, 0x66, 0xea, 0xf2, 0xe8, 0x21, 0xe9, + 0x5f, 0xe6, 0xed, 0xe1, 0xad, 0xdb, 0x19, 0xd8, 0xaa, 0xd5, 0x47, 0xd5, + 0x45, 0xd8, 0xeb, 0xda, 0x5b, 0xdf, 0xcb, 0xe5, 0x23, 0xed, 0xfb, 0xf6, + 0xca, 0x02, 0x3f, 0x0e, 0xdc, 0x15, 0xd8, 0x18, 0xea, 0x17, 0x0e, 0x13, + 0x45, 0x0e, 0xda, 0x05, 0x96, 0xff, 0x50, 0xf8, 0x4f, 0xef, 0x5b, 0xe8, + 0x75, 0xe2, 0x8b, 0xdf, 0xb0, 0xe3, 0xfe, 0xe7, 0x32, 0xeb, 0x1f, 0xef, + 0x0b, 0xf2, 0x63, 0xf6, 0x96, 0xfb, 0x7a, 0x00, 0xc5, 0x02, 0xbd, 0x07, + 0xbb, 0x09, 0xfd, 0x0d, 0x2c, 0x11, 0x49, 0x12, 0x86, 0x11, 0x2f, 0x0e, + 0x9e, 0x0a, 0xea, 0x06, 0xaf, 0x02, 0x3a, 0xfe, 0xb2, 0xf9, 0xe5, 0xf5, + 0x13, 0xf2, 0x15, 0xf3, 0x77, 0xf7, 0x1f, 0xfd, 0x43, 0x05, 0x2f, 0x0c, + 0x81, 0x13, 0x59, 0x19, 0xc5, 0x1e, 0x4a, 0x21, 0x52, 0x23, 0x39, 0x24, + 0xff, 0x24, 0xc8, 0x24, 0xc1, 0x23, 0xf7, 0x21, 0x50, 0x1f, 0x65, 0x1a, + 0x99, 0x14, 0x15, 0x0e, 0xae, 0x08, 0x9f, 0x04, 0x03, 0x01, 0x97, 0xfd, + 0x04, 0xfb, 0xb7, 0xf9, 0x18, 0xfa, 0xef, 0xfb, 0x9a, 0xfe, 0xb5, 0x02, + 0x5b, 0x06, 0x1c, 0x08, 0xd8, 0x08, 0xe4, 0x09, 0x75, 0x09, 0xa9, 0x0a, + 0x33, 0x0a, 0xc3, 0x08, 0x35, 0x05, 0x30, 0x01, 0x94, 0xfe, 0x43, 0xfc, + 0xea, 0xfb, 0xd4, 0xfa, 0x36, 0xf9, 0xfe, 0xf4, 0xe3, 0xf1, 0xea, 0xee, + 0xf4, 0xee, 0x8f, 0xf0, 0xb4, 0xef, 0x37, 0xed, 0xe2, 0xe7, 0x4f, 0xe1, + 0xd0, 0xdb, 0xf3, 0xd5, 0x33, 0xd1, 0x9c, 0xce, 0x77, 0xcd, 0xb6, 0xd2, + 0x0e, 0xdd, 0x68, 0xeb, 0xbc, 0xfc, 0xf6, 0x0a, 0xea, 0x14, 0x60, 0x1c, + 0xf7, 0x1e, 0xe0, 0x1d, 0xca, 0x19, 0x57, 0x10, 0xb6, 0x06, 0xcc, 0xfc, + 0xa0, 0xf3, 0xc2, 0xeb, 0x44, 0xe7, 0xef, 0xe1, 0xb1, 0xe2, 0xe6, 0xe6, + 0x04, 0xea, 0x4b, 0xee, 0x99, 0xf1, 0xeb, 0xf2, 0x22, 0xf5, 0x22, 0xf9, + 0xb0, 0xfc, 0x6a, 0x02, 0x4e, 0x08, 0x5f, 0x0c, 0x7c, 0x0e, 0xda, 0x10, + 0xc3, 0x0f, 0x59, 0x10, 0x7e, 0x0f, 0x40, 0x0d, 0xfb, 0x09, 0x26, 0x04, + 0xc9, 0xfd, 0xca, 0xf6, 0x2d, 0xf4, 0x1d, 0xf2, 0x48, 0xf5, 0x30, 0xfb, + 0xec, 0x00, 0x1a, 0x08, 0x9a, 0x0d, 0x6f, 0x12, 0x2c, 0x17, 0x86, 0x1b, + 0x42, 0x1e, 0x07, 0x21, 0x15, 0x23, 0xfd, 0x22, 0xd7, 0x22, 0xac, 0x20, + 0xaa, 0x1d, 0x87, 0x1a, 0x35, 0x15, 0xa4, 0x11, 0x1a, 0x0d, 0x41, 0x08, + 0x0a, 0x04, 0x47, 0xff, 0x55, 0xfb, 0xcf, 0xf9, 0xfe, 0xfa, 0xb2, 0xfd, + 0x7e, 0x00, 0xbf, 0x02, 0x6b, 0x03, 0x09, 0x04, 0x28, 0x04, 0x81, 0x05, + 0xe6, 0x07, 0x06, 0x09, 0xc5, 0x09, 0x77, 0x08, 0x09, 0x06, 0xf1, 0x03, + 0xf7, 0x03, 0xd8, 0x03, 0x7a, 0x01, 0x36, 0x02, 0x2c, 0xff, 0x98, 0xfc, + 0xe3, 0xf9, 0xb5, 0xf5, 0x2d, 0xf1, 0xed, 0xed, 0xbc, 0xec, 0x66, 0xeb, + 0x84, 0xec, 0x49, 0xeb, 0x02, 0xea, 0x3a, 0xe7, 0x1c, 0xe4, 0xb2, 0xde, + 0xa7, 0xd7, 0x07, 0xd0, 0x33, 0xcb, 0x6a, 0xcb, 0x6b, 0xd3, 0x87, 0xe1, + 0x33, 0xf1, 0xd6, 0x05, 0xb1, 0x16, 0x5c, 0x21, 0xb4, 0x26, 0x50, 0x25, + 0x9c, 0x1f, 0xd2, 0x19, 0xa5, 0x10, 0x22, 0x03, 0xfb, 0xf6, 0x37, 0xeb, + 0x7b, 0xe0, 0x93, 0xdd, 0xd1, 0xde, 0x3c, 0xe1, 0xd0, 0xe7, 0xbf, 0xee, + 0x03, 0xf3, 0x7a, 0xf7, 0x86, 0xfb, 0xa8, 0xfc, 0x15, 0xff, 0xc6, 0x03, + 0x35, 0x07, 0x37, 0x0b, 0x27, 0x0e, 0x1e, 0x0f, 0x58, 0x10, 0x32, 0x12, + 0xa9, 0x11, 0x2d, 0x10, 0x32, 0x0c, 0x5f, 0x05, 0x5c, 0x00, 0x56, 0xfb, + 0x3b, 0xf7, 0xdb, 0xf4, 0x39, 0xf4, 0xf2, 0xf4, 0x4f, 0xf9, 0x01, 0x00, + 0xdf, 0x06, 0xc9, 0x0e, 0xae, 0x15, 0x81, 0x19, 0x32, 0x1d, 0x8f, 0x1f, + 0x57, 0x21, 0xa9, 0x22, 0xc2, 0x21, 0x91, 0x1f, 0x5f, 0x1c, 0xf3, 0x18, + 0x8b, 0x14, 0xb0, 0x0f, 0x74, 0x0a, 0xa4, 0x05, 0x18, 0x01, 0x37, 0xfd, + 0x6f, 0xfa, 0x0a, 0xf9, 0x80, 0xf9, 0x9f, 0xfb, 0x97, 0xfe, 0xae, 0x01, + 0xb3, 0x04, 0x44, 0x07, 0x94, 0x0a, 0x28, 0x0c, 0x80, 0x0d, 0xf9, 0x0c, + 0x01, 0x0b, 0x76, 0x08, 0x59, 0x06, 0x5e, 0x04, 0x6a, 0x02, 0x79, 0x00, + 0x47, 0xfe, 0x1a, 0xfd, 0xca, 0xfc, 0x87, 0xfd, 0x74, 0xfd, 0x38, 0xfc, + 0x8c, 0xf9, 0xcc, 0xf5, 0x29, 0xf1, 0xbd, 0xee, 0x4b, 0xef, 0x06, 0xf0, + 0xe9, 0xf0, 0xfe, 0xef, 0xd2, 0xec, 0xe8, 0xe8, 0x7d, 0xe6, 0x2f, 0xe2, + 0xf8, 0xdb, 0x6d, 0xd3, 0x46, 0xc9, 0xb4, 0xc4, 0x87, 0xca, 0x04, 0xdb, + 0xe2, 0xf3, 0xe7, 0x0a, 0x07, 0x1d, 0x72, 0x25, 0x15, 0x29, 0xc8, 0x28, + 0x68, 0x26, 0x86, 0x22, 0xc7, 0x19, 0xc7, 0x0a, 0xb1, 0xf6, 0x5f, 0xe6, + 0xfc, 0xd9, 0x69, 0xd6, 0x2d, 0xd8, 0xcc, 0xdb, 0xe6, 0xe2, 0xc3, 0xea, + 0x98, 0xf1, 0x29, 0xf9, 0xe2, 0xfd, 0x4c, 0x01, 0xd9, 0x05, 0x8a, 0x0a, + 0x31, 0x0d, 0xfd, 0x0f, 0x95, 0x0f, 0xd1, 0x0d, 0x57, 0x0e, 0x76, 0x0f, + 0xe9, 0x0f, 0xb2, 0x0f, 0xf0, 0x0a, 0xa2, 0x04, 0x59, 0xff, 0xeb, 0xf9, + 0x72, 0xf6, 0xd8, 0xf5, 0x67, 0xf5, 0x93, 0xf6, 0x1f, 0xf9, 0x4b, 0xfd, + 0x89, 0x04, 0x26, 0x0d, 0xc7, 0x13, 0x7e, 0x19, 0x6c, 0x1d, 0x2d, 0x20, + 0x34, 0x22, 0x3a, 0x22, 0x7f, 0x20, 0xf1, 0x1c, 0x2a, 0x18, 0x53, 0x13, + 0x83, 0x0e, 0x0f, 0x0a, 0x76, 0x05, 0x77, 0x01, 0x3a, 0xfe, 0xc2, 0xfb, + 0xa1, 0xfa, 0xdb, 0xfa, 0x72, 0xfc, 0x6d, 0xff, 0xe3, 0x02, 0x5e, 0x05, + 0x35, 0x08, 0xbd, 0x09, 0x5e, 0x0b, 0xa3, 0x0d, 0x75, 0x0e, 0x87, 0x0d, + 0x7f, 0x0b, 0xb7, 0x07, 0x9a, 0x04, 0xc7, 0x02, 0x02, 0x01, 0xa4, 0xff, + 0x0b, 0xff, 0xe6, 0xfd, 0x8a, 0xfe, 0x31, 0x00, 0x46, 0x00, 0x46, 0x00, + 0x6e, 0xff, 0x13, 0xfb, 0xcc, 0xf7, 0x5e, 0xf3, 0x18, 0xf0, 0x80, 0xef, + 0xd8, 0xee, 0xb0, 0xee, 0xe5, 0xed, 0x53, 0xed, 0x5f, 0xea, 0xdf, 0xe6, + 0xc3, 0xe0, 0x2e, 0xda, 0xcc, 0xd2, 0x74, 0xcd, 0x0c, 0xcb, 0x6d, 0xcf, + 0xb2, 0xdb, 0x0e, 0xee, 0xfa, 0x04, 0x86, 0x19, 0x55, 0x29, 0x1f, 0x30, + 0x7d, 0x30, 0xe3, 0x29, 0x13, 0x20, 0xf5, 0x13, 0xee, 0x04, 0x6e, 0xf5, + 0x6e, 0xe6, 0xeb, 0xda, 0xb7, 0xd3, 0xde, 0xd2, 0x76, 0xd7, 0x99, 0xdf, + 0x27, 0xea, 0xf1, 0xf3, 0xf5, 0xfc, 0xce, 0x03, 0xc8, 0x08, 0x18, 0x0c, + 0xa7, 0x0d, 0xb0, 0x0d, 0xab, 0x0c, 0x24, 0x0b, 0x2f, 0x0b, 0x8e, 0x0b, + 0x33, 0x0c, 0x1e, 0x0c, 0xa7, 0x0b, 0xbe, 0x0a, 0x5c, 0x08, 0xe7, 0x03, + 0xb0, 0xfe, 0x4f, 0xf9, 0x70, 0xf5, 0x80, 0xf4, 0x36, 0xf5, 0xb3, 0xf7, + 0x06, 0xfc, 0xdc, 0x01, 0x21, 0x09, 0xde, 0x11, 0x8b, 0x19, 0x9c, 0x1e, + 0xcf, 0x21, 0x2a, 0x22, 0xfc, 0x20, 0x02, 0x1f, 0xb1, 0x1b, 0x15, 0x16, + 0x47, 0x10, 0x6c, 0x0a, 0x23, 0x06, 0x90, 0x03, 0x5f, 0x01, 0x7f, 0xff, + 0x08, 0xfe, 0x7e, 0xfd, 0xbc, 0xfd, 0x62, 0xff, 0x72, 0x01, 0x85, 0x03, + 0x31, 0x05, 0x62, 0x06, 0x81, 0x07, 0x2d, 0x09, 0x67, 0x0a, 0x45, 0x0c, + 0xe4, 0x0c, 0xd5, 0x0c, 0x1d, 0x0c, 0xd0, 0x09, 0x5a, 0x07, 0x6c, 0x05, + 0x79, 0x03, 0xba, 0x01, 0x66, 0x00, 0x79, 0xfe, 0x59, 0xfd, 0x46, 0xfc, + 0x03, 0xfc, 0x83, 0xfb, 0x6a, 0xfb, 0x99, 0xf9, 0xbd, 0xf7, 0xa9, 0xf4, + 0x7d, 0xf1, 0xac, 0xef, 0x17, 0xef, 0x7e, 0xef, 0x44, 0xf0, 0xd2, 0xef, + 0xba, 0xed, 0x97, 0xe9, 0x92, 0xe3, 0x1e, 0xdd, 0xcb, 0xd5, 0xc7, 0xce, + 0x37, 0xca, 0x6d, 0xca, 0x31, 0xd2, 0x0b, 0xe4, 0x8c, 0xfa, 0x59, 0x10, + 0x81, 0x21, 0xe1, 0x2b, 0x8c, 0x2f, 0x25, 0x2f, 0x3a, 0x28, 0xf9, 0x1b, + 0x1b, 0x0c, 0xda, 0xf9, 0xf6, 0xe7, 0x56, 0xdb, 0xb3, 0xd3, 0x1b, 0xd2, + 0xf0, 0xd5, 0x5e, 0xdd, 0x78, 0xe6, 0x65, 0xf1, 0xd8, 0xfb, 0xac, 0x04, + 0x2e, 0x0c, 0xbf, 0x0f, 0x79, 0x10, 0xef, 0x0f, 0x2a, 0x0d, 0xc1, 0x0a, + 0x00, 0x09, 0x43, 0x07, 0x48, 0x07, 0xe6, 0x08, 0x1e, 0x0a, 0x80, 0x0a, + 0x8f, 0x09, 0x08, 0x07, 0x6a, 0x04, 0xae, 0x00, 0x04, 0xfc, 0x5a, 0xf7, + 0x41, 0xf4, 0x61, 0xf4, 0xa7, 0xf7, 0x81, 0xfd, 0x38, 0x06, 0x53, 0x0f, + 0x67, 0x17, 0x77, 0x1e, 0x59, 0x23, 0x0c, 0x26, 0x3a, 0x26, 0x10, 0x23, + 0x74, 0x1c, 0x6e, 0x15, 0xc5, 0x0d, 0x9d, 0x07, 0xee, 0x02, 0x49, 0xff, + 0x54, 0xfd, 0x8b, 0xfc, 0xc1, 0xfb, 0x0c, 0xfc, 0xc8, 0xfd, 0x42, 0x00, + 0x5c, 0x03, 0x3f, 0x06, 0x98, 0x07, 0x27, 0x08, 0xf2, 0x08, 0xbb, 0x09, + 0xba, 0x0a, 0x61, 0x0c, 0x1c, 0x0d, 0x1a, 0x0d, 0x22, 0x0c, 0xa7, 0x09, + 0x17, 0x07, 0x10, 0x05, 0xc5, 0x02, 0xc5, 0x00, 0xf0, 0xfe, 0xa7, 0xfc, + 0x75, 0xfb, 0xb5, 0xfb, 0x65, 0xfc, 0x01, 0xfd, 0x38, 0xfc, 0x29, 0xfb, + 0x9f, 0xfa, 0xeb, 0xf9, 0xad, 0xf8, 0x28, 0xf6, 0xe6, 0xf2, 0x3a, 0xef, + 0x5f, 0xed, 0xed, 0xec, 0xd5, 0xec, 0xab, 0xec, 0x99, 0xea, 0x77, 0xe6, + 0x69, 0xe0, 0xee, 0xd8, 0xa2, 0xd1, 0xca, 0xcb, 0x9e, 0xcb, 0x67, 0xd1, + 0xca, 0xdf, 0x32, 0xf3, 0xa4, 0x08, 0x93, 0x1a, 0x4d, 0x26, 0x84, 0x2b, + 0xac, 0x2b, 0x24, 0x28, 0x02, 0x20, 0x60, 0x13, 0x68, 0x03, 0x15, 0xf2, + 0x1b, 0xe3, 0xda, 0xd8, 0xb9, 0xd3, 0x5f, 0xd4, 0x57, 0xda, 0x0e, 0xe3, + 0x2b, 0xee, 0xfe, 0xf9, 0x00, 0x03, 0xfc, 0x09, 0x9a, 0x0e, 0x0e, 0x10, + 0x24, 0x10, 0xdc, 0x0e, 0xe7, 0x0a, 0x1e, 0x07, 0xd2, 0x04, 0xd9, 0x03, + 0xf9, 0x05, 0x2e, 0x09, 0x94, 0x0b, 0x86, 0x0c, 0xa8, 0x0a, 0x8e, 0x06, + 0x62, 0x02, 0x0a, 0xff, 0x18, 0xfc, 0xa2, 0xf9, 0xc4, 0xf7, 0xea, 0xf7, + 0xfe, 0xfb, 0x47, 0x03, 0x97, 0x0b, 0x0e, 0x14, 0xca, 0x1a, 0xa5, 0x1f, + 0x84, 0x22, 0x2c, 0x23, 0x54, 0x21, 0x44, 0x1d, 0x70, 0x17, 0x51, 0x10, + 0xbe, 0x09, 0xf9, 0x04, 0x76, 0x00, 0x07, 0xfd, 0x63, 0xfa, 0x51, 0xf9, + 0x38, 0xfa, 0x99, 0xfc, 0x17, 0xff, 0xa7, 0x01, 0xec, 0x03, 0xb0, 0x05, + 0x43, 0x07, 0x35, 0x09, 0x13, 0x0b, 0xb9, 0x0c, 0x81, 0x0c, 0xee, 0x0b, + 0x4a, 0x0b, 0x31, 0x0a, 0x8a, 0x09, 0xbf, 0x07, 0x46, 0x05, 0xde, 0x02, + 0xbb, 0x00, 0x16, 0xff, 0xc1, 0xfd, 0x4e, 0xfd, 0xb3, 0xfe, 0x47, 0xff, + 0xd5, 0xff, 0x73, 0xff, 0x96, 0xfd, 0xd7, 0xfb, 0x6c, 0xfa, 0x34, 0xf8, + 0x72, 0xf5, 0x9a, 0xf2, 0x48, 0xef, 0x21, 0xec, 0x06, 0xeb, 0x85, 0xeb, + 0xbe, 0xed, 0x82, 0xef, 0xa2, 0xef, 0x48, 0xed, 0x09, 0xe9, 0xb7, 0xe2, + 0xf9, 0xda, 0x11, 0xd3, 0x8b, 0xcd, 0x5d, 0xce, 0x2f, 0xd7, 0x20, 0xe6, + 0xbd, 0xf9, 0x03, 0x0c, 0x23, 0x1a, 0xe4, 0x23, 0x3c, 0x29, 0xf9, 0x28, + 0x6a, 0x25, 0x60, 0x1d, 0x02, 0x10, 0xf8, 0x00, 0xe3, 0xef, 0xb4, 0xe0, + 0x67, 0xd8, 0xd6, 0xd6, 0x5d, 0xda, 0xe6, 0xe1, 0x9d, 0xeb, 0x6a, 0xf4, + 0x15, 0xfd, 0xce, 0x04, 0x96, 0x07, 0xc7, 0x0a, 0x95, 0x0d, 0x6f, 0x0d, + 0x74, 0x0b, 0x4b, 0x09, 0xd9, 0x04, 0xd0, 0x03, 0x19, 0x06, 0x65, 0x08, + 0x32, 0x0c, 0x98, 0x0e, 0xa4, 0x0c, 0xe7, 0x0a, 0x23, 0x08, 0x6f, 0x04, + 0xbd, 0x01, 0x3f, 0xff, 0xc2, 0xfb, 0x32, 0xfa, 0x19, 0xfa, 0x89, 0xfd, + 0xdc, 0x03, 0xc9, 0x0b, 0x24, 0x13, 0xe1, 0x18, 0xc1, 0x1c, 0x9e, 0x1e, + 0xd9, 0x1e, 0x10, 0x1d, 0x32, 0x1a, 0x04, 0x15, 0x5d, 0x0f, 0xe5, 0x09, + 0x41, 0x04, 0x91, 0xff, 0xa0, 0xfb, 0x00, 0xf9, 0xfc, 0xf8, 0xd9, 0xfa, + 0x24, 0xfd, 0x94, 0xff, 0x64, 0x00, 0x72, 0x01, 0x22, 0x04, 0x84, 0x07, + 0x02, 0x0b, 0x13, 0x0d, 0xc9, 0x0d, 0x4e, 0x0d, 0xe8, 0x0c, 0xf8, 0x0b, + 0xc1, 0x0a, 0xf3, 0x08, 0xb8, 0x06, 0xb9, 0x03, 0x11, 0x01, 0x16, 0xff, + 0x13, 0xfe, 0x69, 0xfd, 0x33, 0xfd, 0xbf, 0xfc, 0x19, 0xfd, 0x51, 0xfd, + 0xef, 0xfc, 0x8c, 0xfc, 0x5d, 0xfb, 0x01, 0xfa, 0x7c, 0xf8, 0xa2, 0xf6, + 0x13, 0xf3, 0x07, 0xf0, 0xf0, 0xed, 0x00, 0xee, 0xbd, 0xf0, 0x91, 0xf3, + 0xa1, 0xf4, 0x12, 0xf2, 0x50, 0xed, 0x9c, 0xe7, 0x92, 0xe1, 0x0c, 0xdb, + 0xb4, 0xd4, 0x3c, 0xcf, 0xd2, 0xce, 0xc4, 0xd4, 0x9f, 0xe1, 0x86, 0xf3, + 0x78, 0x06, 0x60, 0x15, 0xc6, 0x1f, 0x51, 0x25, 0x66, 0x27, 0x23, 0x25, + 0x6e, 0x20, 0xb2, 0x15, 0x89, 0x07, 0xdb, 0xf6, 0xfb, 0xe7, 0xd3, 0xdd, + 0x06, 0xda, 0xe0, 0xdb, 0x92, 0xe1, 0xe9, 0xe8, 0xfa, 0xef, 0x4f, 0xf7, + 0xd2, 0xfe, 0x44, 0x06, 0x05, 0x0c, 0xf7, 0x0e, 0x7d, 0x0d, 0x65, 0x0a, + 0xe7, 0x06, 0xe8, 0x05, 0x49, 0x06, 0x3e, 0x08, 0x81, 0x09, 0x00, 0x0b, + 0x9f, 0x0c, 0xac, 0x0d, 0x94, 0x0d, 0xf7, 0x0b, 0xd0, 0x08, 0x81, 0x04, + 0x0d, 0x00, 0xfa, 0xfb, 0x9f, 0xf9, 0xd7, 0xf9, 0xc9, 0xfc, 0xb1, 0x02, + 0x51, 0x09, 0xfe, 0x0e, 0x4c, 0x14, 0x25, 0x18, 0x3d, 0x1b, 0x66, 0x1d, + 0xc5, 0x1c, 0x68, 0x19, 0x5a, 0x14, 0xbb, 0x0e, 0x68, 0x09, 0x5b, 0x05, + 0x3e, 0x01, 0x5c, 0xfe, 0x8c, 0xfc, 0xa2, 0xfb, 0xfa, 0xfb, 0x35, 0xfd, + 0x41, 0xfe, 0xa0, 0x00, 0xb8, 0x02, 0xfe, 0x03, 0x97, 0x05, 0x8d, 0x06, + 0x4f, 0x07, 0x76, 0x08, 0x49, 0x09, 0x43, 0x0a, 0x4c, 0x0b, 0x76, 0x0b, + 0x9d, 0x0a, 0xe4, 0x08, 0xdc, 0x06, 0xfc, 0x04, 0x2a, 0x03, 0xe1, 0x00, + 0xe0, 0xfe, 0x8d, 0xfd, 0xaf, 0xfc, 0x68, 0xfc, 0x3f, 0xfc, 0x2b, 0xfc, + 0x37, 0xfc, 0x55, 0xfc, 0x97, 0xfb, 0xa5, 0xfa, 0xfa, 0xf8, 0x3f, 0xf7, + 0xea, 0xf4, 0xba, 0xf2, 0x07, 0xf1, 0xd3, 0xf0, 0x3c, 0xf0, 0x6f, 0xf0, + 0x11, 0xef, 0x15, 0xed, 0x6f, 0xea, 0xc3, 0xe6, 0x26, 0xe2, 0x5f, 0xdc, + 0x0d, 0xd6, 0x31, 0xd2, 0xa4, 0xd2, 0x8c, 0xd8, 0x41, 0xe5, 0x4a, 0xf5, + 0xbf, 0x05, 0xab, 0x13, 0x85, 0x1e, 0x0e, 0x25, 0x0e, 0x29, 0x59, 0x28, + 0xba, 0x21, 0x5c, 0x14, 0x9d, 0x05, 0xb8, 0xf4, 0x1c, 0xe6, 0x8b, 0xdc, + 0x61, 0xd7, 0x18, 0xd8, 0x92, 0xdd, 0x88, 0xe5, 0xd0, 0xee, 0xf8, 0xf9, + 0xab, 0x03, 0x02, 0x0b, 0xa7, 0x0f, 0x56, 0x10, 0x18, 0x0e, 0xff, 0x0a, + 0x70, 0x07, 0x4e, 0x05, 0x1f, 0x04, 0x1e, 0x04, 0xd3, 0x05, 0x5b, 0x09, + 0x4c, 0x0d, 0xa9, 0x0f, 0x16, 0x10, 0x4f, 0x0e, 0xc1, 0x0a, 0x1d, 0x06, + 0x33, 0x01, 0xd0, 0xfc, 0x00, 0xfa, 0xea, 0xf9, 0xc5, 0xfb, 0x4d, 0x00, + 0x82, 0x06, 0xc8, 0x0d, 0xe8, 0x14, 0xd8, 0x1a, 0xe2, 0x1d, 0x75, 0x1e, + 0x73, 0x1c, 0xa8, 0x18, 0xf7, 0x13, 0x07, 0x0e, 0x49, 0x08, 0xe2, 0x02, + 0xde, 0xfe, 0xf9, 0xfb, 0xfa, 0xfb, 0xb5, 0xfc, 0x9d, 0xfd, 0x29, 0xff, + 0x77, 0x00, 0xf1, 0x01, 0xc5, 0x04, 0x36, 0x06, 0x80, 0x06, 0xef, 0x05, + 0x51, 0x05, 0x16, 0x06, 0x17, 0x08, 0xd6, 0x09, 0x55, 0x0a, 0x2c, 0x0a, + 0xd7, 0x08, 0xcf, 0x08, 0xc9, 0x08, 0x70, 0x08, 0xdb, 0x06, 0x73, 0x03, + 0x0d, 0x00, 0x7a, 0xfd, 0xa4, 0xfc, 0x53, 0xfc, 0x36, 0xfc, 0x3b, 0xfb, + 0x4f, 0xfa, 0x7f, 0xfa, 0xb6, 0xfa, 0x04, 0xfb, 0x61, 0xfa, 0x01, 0xf9, + 0xeb, 0xf7, 0x72, 0xf5, 0xc0, 0xf2, 0x41, 0xf0, 0x2b, 0xef, 0xac, 0xef, + 0xf1, 0xf0, 0xe1, 0xf0, 0x27, 0xee, 0x1b, 0xe9, 0x8f, 0xe4, 0x8a, 0xdf, + 0x4f, 0xdb, 0x7b, 0xd7, 0xfb, 0xd3, 0x51, 0xd2, 0x10, 0xd8, 0x7d, 0xe4, + 0x56, 0xf7, 0x76, 0x0b, 0x15, 0x1b, 0xcd, 0x22, 0x7f, 0x25, 0x74, 0x25, + 0x3d, 0x23, 0x0d, 0x1d, 0x61, 0x10, 0x17, 0x00, 0xbf, 0xee, 0x4d, 0xe3, + 0x24, 0xdb, 0x5d, 0xda, 0x63, 0xdd, 0x32, 0xe3, 0x1c, 0xea, 0x55, 0xf2, + 0xe0, 0xfa, 0xbc, 0x02, 0x90, 0x08, 0xc0, 0x0b, 0x8f, 0x0c, 0xa6, 0x0a, + 0xa5, 0x06, 0x4e, 0x04, 0x73, 0x04, 0xe8, 0x06, 0x01, 0x0b, 0x14, 0x0e, + 0x72, 0x11, 0xd7, 0x13, 0x7f, 0x14, 0x0c, 0x12, 0x7c, 0x0e, 0xad, 0x09, + 0x38, 0x04, 0xa2, 0xfe, 0xf8, 0xf8, 0x53, 0xf7, 0xdf, 0xf7, 0x26, 0xfc, + 0xf4, 0x01, 0x23, 0x08, 0x12, 0x0f, 0x24, 0x16, 0xd3, 0x19, 0x0d, 0x1c, + 0x3f, 0x1c, 0x3e, 0x1a, 0x1f, 0x17, 0x85, 0x12, 0x93, 0x0c, 0xbc, 0x07, + 0x6e, 0x03, 0x5f, 0x00, 0x98, 0xfe, 0xeb, 0xfd, 0xc7, 0xfd, 0x7e, 0xfe, + 0xd9, 0xff, 0x4a, 0x00, 0x0c, 0x02, 0xfe, 0x02, 0x78, 0x03, 0x47, 0x04, + 0x1d, 0x04, 0x20, 0x04, 0x9d, 0x05, 0xc2, 0x06, 0xea, 0x08, 0xcf, 0x0a, + 0xe7, 0x0b, 0x9f, 0x0b, 0xcd, 0x0a, 0x76, 0x09, 0xa5, 0x07, 0xdb, 0x05, + 0x2b, 0x03, 0x20, 0x00, 0xc0, 0xfd, 0xf0, 0xfb, 0xc6, 0xfa, 0x57, 0xfa, + 0x21, 0xfa, 0x16, 0xf9, 0x67, 0xf9, 0xc6, 0xf9, 0x34, 0xfb, 0xdd, 0xfc, + 0x6d, 0xfe, 0x1a, 0xfd, 0xc7, 0xfa, 0x3f, 0xf6, 0x62, 0xf2, 0xff, 0xef, + 0x8f, 0xef, 0x6a, 0xef, 0x3d, 0xee, 0xc7, 0xec, 0x57, 0xe8, 0xef, 0xe5, + 0x5d, 0xe3, 0x4e, 0xe0, 0x08, 0xdd, 0x53, 0xd7, 0xb5, 0xd1, 0xf7, 0xd0, + 0x6e, 0xd7, 0xd4, 0xe5, 0xd8, 0xf9, 0xe9, 0x0b, 0x97, 0x18, 0x80, 0x20, + 0x7f, 0x24, 0x28, 0x27, 0xba, 0x26, 0x07, 0x20, 0x11, 0x13, 0x54, 0x03, + 0x13, 0xf3, 0x5e, 0xe5, 0xec, 0xdd, 0x1d, 0xdb, 0x3e, 0xdd, 0x0f, 0xe1, + 0xc3, 0xe8, 0x1a, 0xf0, 0x21, 0xf8, 0xee, 0xff, 0x07, 0x05, 0x6c, 0x09, + 0x2c, 0x0c, 0xc0, 0x0c, 0x5f, 0x0b, 0x22, 0x0a, 0xee, 0x08, 0xa0, 0x09, + 0x7a, 0x0c, 0xec, 0x0f, 0x2b, 0x12, 0x1f, 0x14, 0x2c, 0x14, 0xd8, 0x11, + 0xf3, 0x0e, 0x1b, 0x0a, 0xe2, 0x03, 0x85, 0xff, 0x7b, 0xfa, 0xb2, 0xf7, + 0xc9, 0xf7, 0x11, 0xfa, 0xa1, 0xfe, 0x74, 0x05, 0x1d, 0x0c, 0xba, 0x12, + 0x04, 0x19, 0x79, 0x1b, 0x1e, 0x1c, 0xf5, 0x1a, 0xb1, 0x17, 0x68, 0x13, + 0x7a, 0x0e, 0xe8, 0x08, 0xaa, 0x04, 0x58, 0x02, 0xd5, 0xfe, 0x95, 0xfd, + 0xb5, 0xfd, 0x14, 0xfd, 0x0c, 0xff, 0xe6, 0xff, 0x12, 0x00, 0xae, 0x00, + 0xee, 0x00, 0x58, 0x00, 0x92, 0x00, 0x56, 0x02, 0x87, 0x03, 0x6d, 0x06, + 0x5f, 0x09, 0x9d, 0x0a, 0xc3, 0x0c, 0x0f, 0x0e, 0x8a, 0x0d, 0x6b, 0x0c, + 0x17, 0x0a, 0xb5, 0x06, 0xc3, 0x03, 0x48, 0x00, 0xe9, 0xfc, 0xfb, 0xfa, + 0x62, 0xf9, 0xf3, 0xf8, 0x30, 0xf9, 0xde, 0xf9, 0x58, 0xfa, 0x7c, 0xfb, + 0x26, 0xfc, 0xdb, 0xfc, 0xee, 0xfc, 0x49, 0xfc, 0x88, 0xfa, 0x5c, 0xf8, + 0x77, 0xf5, 0xe1, 0xf2, 0x07, 0xf2, 0x32, 0xf2, 0x26, 0xf2, 0x21, 0xf0, + 0xb7, 0xec, 0x01, 0xe8, 0x34, 0xe5, 0x21, 0xe3, 0xc8, 0xe0, 0x2d, 0xdc, + 0x3f, 0xd5, 0x63, 0xce, 0x2b, 0xcd, 0xa8, 0xd4, 0xa1, 0xe5, 0x0a, 0xfd, + 0xd8, 0x0e, 0x87, 0x1a, 0x87, 0x1e, 0x50, 0x20, 0xb7, 0x25, 0x6f, 0x2a, + 0xe8, 0x27, 0x58, 0x1b, 0xad, 0x07, 0xe7, 0xf2, 0x8e, 0xe5, 0xca, 0xe0, + 0x5e, 0xe0, 0xf1, 0xe1, 0x74, 0xe3, 0x86, 0xe5, 0x80, 0xea, 0xd1, 0xf3, + 0xe7, 0xfc, 0x76, 0x06, 0x0f, 0x0c, 0xb8, 0x0c, 0x47, 0x0b, 0xe0, 0x08, + 0x8d, 0x07, 0x11, 0x09, 0xf7, 0x0b, 0xb4, 0x0d, 0x7e, 0x0f, 0xad, 0x11, + 0x77, 0x12, 0x9a, 0x13, 0xe6, 0x13, 0xb6, 0x10, 0xa7, 0x0d, 0x72, 0x09, + 0x3c, 0x04, 0x3b, 0xff, 0x7a, 0xfb, 0x91, 0xf8, 0x33, 0xf9, 0x13, 0xfd, + 0xa8, 0x01, 0xb2, 0x07, 0xff, 0x0c, 0xc2, 0x10, 0x13, 0x14, 0xc9, 0x16, + 0x3b, 0x17, 0x5f, 0x16, 0xbe, 0x13, 0xa0, 0x0f, 0xf2, 0x0a, 0xbb, 0x07, + 0xab, 0x04, 0x07, 0x02, 0x4e, 0x00, 0xaa, 0xfe, 0xfe, 0xfd, 0x2e, 0xfe, + 0x90, 0xfe, 0x63, 0xfe, 0x16, 0xff, 0x15, 0xff, 0x6d, 0xff, 0xc1, 0xff, + 0x68, 0x00, 0xe9, 0x00, 0xd5, 0x02, 0x02, 0x05, 0x18, 0x08, 0xd3, 0x0a, + 0xf1, 0x0b, 0xf1, 0x0b, 0x1a, 0x0c, 0xf9, 0x0a, 0xea, 0x09, 0xa3, 0x07, + 0x7c, 0x04, 0xb4, 0x01, 0x31, 0xff, 0x7b, 0xfd, 0x6f, 0xfc, 0x35, 0xfb, + 0xa6, 0xfa, 0x15, 0xfa, 0x1d, 0xfa, 0xf0, 0xfa, 0xd7, 0xfb, 0x38, 0xfc, + 0x3f, 0xfc, 0x53, 0xfb, 0xba, 0xf9, 0xa4, 0xf7, 0x79, 0xf6, 0x80, 0xf4, + 0xc2, 0xf3, 0x22, 0xf3, 0x44, 0xf0, 0x17, 0xee, 0x3e, 0xec, 0x30, 0xea, + 0x34, 0xe9, 0xe7, 0xe5, 0x18, 0xe0, 0x29, 0xd9, 0x72, 0xd3, 0x27, 0xd0, + 0xc4, 0xd3, 0x97, 0xdc, 0x57, 0xeb, 0x65, 0xfc, 0x13, 0x0c, 0x63, 0x18, + 0x26, 0x20, 0x0a, 0x26, 0x83, 0x28, 0x43, 0x28, 0x8f, 0x20, 0x7c, 0x14, + 0x04, 0x04, 0xf4, 0xf5, 0x9e, 0xea, 0xaa, 0xe4, 0xac, 0xe1, 0xe6, 0xe1, + 0xa7, 0xe4, 0xaa, 0xe9, 0xfd, 0xef, 0xd8, 0xf6, 0xca, 0xfd, 0x60, 0x03, + 0xed, 0x06, 0x7c, 0x08, 0x7e, 0x07, 0x7c, 0x06, 0x26, 0x06, 0xac, 0x07, + 0x52, 0x0a, 0x40, 0x0d, 0x3d, 0x10, 0x52, 0x12, 0xd4, 0x14, 0x53, 0x15, + 0x26, 0x15, 0xa3, 0x12, 0xbb, 0x0e, 0x08, 0x0a, 0x58, 0x04, 0xe3, 0xfe, + 0x91, 0xfa, 0xcb, 0xf8, 0x0b, 0xf9, 0xca, 0xfb, 0x5b, 0xff, 0x2f, 0x03, + 0xdf, 0x08, 0xf2, 0x0d, 0xc1, 0x11, 0xc9, 0x13, 0x3b, 0x14, 0x57, 0x12, + 0x94, 0x10, 0xf2, 0x0d, 0x59, 0x0a, 0x33, 0x08, 0xfe, 0x05, 0xc4, 0x03, + 0x2c, 0x02, 0xf1, 0x00, 0xfa, 0xff, 0xcd, 0x00, 0x9a, 0x01, 0xed, 0x00, + 0x77, 0x00, 0xf7, 0xfe, 0x40, 0xfd, 0x11, 0xfd, 0x0a, 0xfe, 0xf2, 0xfe, + 0x5d, 0x00, 0xf8, 0x01, 0x92, 0x02, 0xf1, 0x05, 0x6e, 0x09, 0x00, 0x0c, + 0xed, 0x0d, 0x68, 0x0c, 0x54, 0x0a, 0x01, 0x09, 0x6f, 0x08, 0xcb, 0x07, + 0x37, 0x06, 0x19, 0x03, 0x25, 0x00, 0x7f, 0xfe, 0x7c, 0xfd, 0x11, 0xfe, + 0x70, 0xfd, 0x63, 0xfc, 0x25, 0xfc, 0xac, 0xfa, 0xaf, 0xfa, 0x92, 0xfa, + 0x15, 0xf9, 0x29, 0xf8, 0xfc, 0xf5, 0x22, 0xf4, 0x79, 0xf2, 0x95, 0xf2, + 0xe9, 0xf2, 0xdd, 0xf2, 0xe3, 0xf2, 0xda, 0xef, 0xbd, 0xec, 0xec, 0xe8, + 0x8e, 0xe3, 0x41, 0xdf, 0x0f, 0xd9, 0x48, 0xd5, 0x2c, 0xd3, 0x3b, 0xd7, + 0xf8, 0xdf, 0x34, 0xee, 0x2c, 0xfe, 0x8b, 0x0c, 0x76, 0x18, 0x14, 0x20, + 0xb6, 0x24, 0x0f, 0x25, 0x5a, 0x22, 0xb6, 0x19, 0xa1, 0x0e, 0xe1, 0x01, + 0x08, 0xf5, 0x37, 0xeb, 0xa6, 0xe5, 0x76, 0xe3, 0x66, 0xe5, 0xa6, 0xe9, + 0x45, 0xed, 0x72, 0xf2, 0xf0, 0xf8, 0x7b, 0xfd, 0x05, 0x02, 0x1c, 0x04, + 0xb8, 0x03, 0x80, 0x03, 0x97, 0x03, 0xb6, 0x03, 0xc2, 0x04, 0xfa, 0x06, + 0xf1, 0x09, 0x32, 0x0e, 0xb6, 0x12, 0xae, 0x14, 0x91, 0x15, 0x09, 0x14, + 0x5c, 0x11, 0x18, 0x0e, 0x49, 0x0a, 0x76, 0x05, 0xc7, 0x00, 0x61, 0xfc, + 0xfb, 0xf9, 0x2e, 0xfa, 0x84, 0xfc, 0x7c, 0x00, 0xbd, 0x04, 0xde, 0x08, + 0x0d, 0x0c, 0x98, 0x0e, 0x3e, 0x10, 0x96, 0x10, 0x20, 0x10, 0x63, 0x0e, + 0xb3, 0x0b, 0x31, 0x09, 0x38, 0x06, 0x86, 0x04, 0x91, 0x03, 0x0f, 0x03, + 0xaf, 0x02, 0xcf, 0x02, 0x89, 0x02, 0x12, 0x02, 0x3b, 0x02, 0x13, 0x02, + 0x76, 0x01, 0x68, 0x00, 0x1c, 0xff, 0xbe, 0xfd, 0x50, 0xfe, 0x4d, 0xff, + 0x48, 0x01, 0xd4, 0x02, 0xd5, 0x04, 0x84, 0x06, 0xa2, 0x08, 0xe6, 0x0a, + 0x01, 0x0c, 0x95, 0x0c, 0xa6, 0x0c, 0xa9, 0x0b, 0xd5, 0x0a, 0x3b, 0x09, + 0x16, 0x07, 0xd1, 0x05, 0x82, 0x03, 0x94, 0x01, 0x95, 0xff, 0xe2, 0xfd, + 0x85, 0xfc, 0x28, 0xfc, 0x0e, 0xfb, 0x68, 0xfa, 0xbd, 0xf9, 0x86, 0xf9, + 0xbd, 0xf8, 0xfd, 0xf7, 0xff, 0xf5, 0x89, 0xf3, 0x39, 0xf3, 0x5b, 0xf0, + 0x8c, 0xf1, 0xb3, 0xef, 0xaa, 0xee, 0x50, 0xed, 0x65, 0xea, 0xeb, 0xe7, + 0x58, 0xe3, 0x16, 0xdf, 0x81, 0xd8, 0x74, 0xd6, 0xb9, 0xd6, 0xfb, 0xdd, + 0x4d, 0xea, 0xca, 0xf5, 0xdd, 0x02, 0xa7, 0x0a, 0xb1, 0x13, 0xbc, 0x1a, + 0x99, 0x1f, 0x3f, 0x21, 0xb1, 0x1a, 0xdf, 0x11, 0x95, 0x05, 0x36, 0xfc, + 0x5d, 0xf4, 0x96, 0xef, 0x7f, 0xeb, 0xda, 0xe8, 0x58, 0xe9, 0x67, 0xeb, + 0xa0, 0xef, 0x5a, 0xf5, 0x27, 0xfa, 0x5b, 0xfe, 0xbe, 0x00, 0x26, 0x00, + 0x40, 0xff, 0x6c, 0xff, 0x62, 0x00, 0x4f, 0x02, 0xcf, 0x03, 0xd3, 0x05, + 0x69, 0x08, 0xca, 0x0b, 0xc7, 0x0f, 0xab, 0x12, 0x86, 0x14, 0x95, 0x13, + 0x49, 0x11, 0xc0, 0x0d, 0x1a, 0x0a, 0xdf, 0x06, 0x3b, 0x04, 0x37, 0x01, + 0x47, 0xff, 0x34, 0xfe, 0xeb, 0xff, 0xd0, 0x02, 0x78, 0x06, 0xf2, 0x08, + 0x52, 0x0a, 0x63, 0x0c, 0x53, 0x0c, 0xc8, 0x0c, 0xe8, 0x0b, 0xd0, 0x0a, + 0x21, 0x09, 0x4b, 0x08, 0xe2, 0x06, 0xab, 0x05, 0xc9, 0x04, 0xe4, 0x03, + 0x12, 0x04, 0x47, 0x04, 0x82, 0x04, 0x40, 0x04, 0x1b, 0x03, 0x6f, 0x01, + 0x5f, 0x00, 0x32, 0xff, 0xa0, 0xfe, 0xcb, 0xfe, 0xe6, 0xfe, 0xb9, 0xff, + 0x7c, 0x00, 0x4b, 0x02, 0x75, 0x04, 0xfb, 0x06, 0x84, 0x09, 0x01, 0x0c, + 0x41, 0x0d, 0x4f, 0x0e, 0xc6, 0x0e, 0x75, 0x0e, 0xbb, 0x0d, 0x5a, 0x0c, + 0xcf, 0x0a, 0x65, 0x08, 0x2a, 0x06, 0xbf, 0x03, 0x96, 0x01, 0x21, 0x00, + 0xdc, 0xfe, 0x16, 0xfe, 0xf4, 0xfc, 0xdc, 0xfb, 0x0c, 0xfb, 0x76, 0xfa, + 0x07, 0xfa, 0x19, 0xf9, 0xcf, 0xf6, 0x8c, 0xf4, 0xfd, 0xf1, 0x2b, 0xf1, + 0x94, 0xf0, 0x29, 0xf0, 0xad, 0xee, 0x78, 0xec, 0x2c, 0xeb, 0x7d, 0xe9, + 0xed, 0xe7, 0x6d, 0xe4, 0x96, 0xdf, 0x65, 0xdb, 0x7d, 0xd8, 0x9e, 0xda, + 0x73, 0xe0, 0x12, 0xea, 0x17, 0xf4, 0x5f, 0xfd, 0x1e, 0x05, 0x57, 0x0c, + 0xe2, 0x13, 0x31, 0x18, 0x96, 0x19, 0xf8, 0x14, 0x25, 0x0e, 0x2a, 0x06, + 0x9c, 0xfe, 0xf0, 0xf7, 0x06, 0xf3, 0x0d, 0xf0, 0x50, 0xef, 0x94, 0xef, + 0xdd, 0xf0, 0xb9, 0xf2, 0xbf, 0xf6, 0xa7, 0xfa, 0x02, 0xfe, 0xf5, 0xfe, + 0x14, 0xff, 0x88, 0xfc, 0x72, 0xfc, 0x0b, 0xfd, 0xa5, 0xfd, 0x13, 0x00, + 0x61, 0x01, 0xa6, 0x03, 0xd0, 0x06, 0xb1, 0x0a, 0xe6, 0x0d, 0x91, 0x10, + 0x10, 0x12, 0x0a, 0x12, 0x69, 0x11, 0x71, 0x0e, 0xa0, 0x0a, 0x85, 0x07, + 0xab, 0x05, 0x59, 0x05, 0x7f, 0x05, 0xee, 0x04, 0xe1, 0x04, 0xb4, 0x05, + 0x38, 0x07, 0x6e, 0x09, 0xb9, 0x0a, 0xdc, 0x0a, 0x39, 0x0a, 0x2d, 0x09, + 0xb0, 0x07, 0xed, 0x06, 0x3d, 0x06, 0x54, 0x05, 0x5c, 0x04, 0xcb, 0x03, + 0xc5, 0x02, 0x66, 0x03, 0x16, 0x04, 0x7d, 0x04, 0xce, 0x04, 0xc9, 0x03, + 0xf6, 0x02, 0x19, 0x02, 0x89, 0x01, 0xe2, 0x00, 0x1d, 0x01, 0xb6, 0x01, + 0x40, 0x02, 0x7a, 0x02, 0xf1, 0x02, 0xef, 0x03, 0x94, 0x05, 0xb8, 0x07, + 0x2f, 0x09, 0x18, 0x0a, 0xef, 0x0a, 0x2e, 0x0b, 0x05, 0x0b, 0x2b, 0x0b, + 0xb3, 0x0a, 0x3f, 0x0a, 0xc6, 0x09, 0x6f, 0x08, 0xd9, 0x06, 0x6e, 0x05, + 0x6c, 0x04, 0x0f, 0x03, 0x69, 0x02, 0xe3, 0x00, 0x7b, 0xff, 0x5a, 0xfd, + 0x66, 0xfc, 0x1d, 0xfb, 0x8d, 0xf9, 0x23, 0xf8, 0x58, 0xf5, 0x93, 0xf3, + 0x70, 0xf2, 0x51, 0xf2, 0x1d, 0xf1, 0xbb, 0xf0, 0xd7, 0xee, 0x54, 0xee, + 0x99, 0xed, 0x63, 0xec, 0x92, 0xea, 0x9a, 0xe7, 0x5b, 0xe4, 0x33, 0xe1, + 0x41, 0xdf, 0x99, 0xde, 0xf6, 0xe0, 0xf8, 0xe5, 0xd1, 0xec, 0x31, 0xf4, + 0x12, 0xfb, 0x66, 0x01, 0xb3, 0x07, 0xd8, 0x0c, 0x0b, 0x0f, 0x69, 0x0e, + 0x0f, 0x0b, 0xd7, 0x06, 0xa8, 0x02, 0x53, 0xfe, 0x7e, 0xf9, 0x95, 0xf6, + 0x76, 0xf5, 0xbe, 0xf5, 0xdf, 0xf6, 0xfe, 0xf7, 0xeb, 0xf8, 0xfa, 0xfa, + 0x54, 0xfd, 0xc8, 0xfe, 0x0a, 0xff, 0x85, 0xfe, 0x04, 0xfe, 0x94, 0xfd, + 0x5e, 0xfd, 0x1b, 0xfd, 0x4f, 0xfd, 0xab, 0xfe, 0xd2, 0x00, 0x38, 0x03, + 0xc3, 0x05, 0x76, 0x08, 0x1c, 0x0b, 0x59, 0x0d, 0x49, 0x0e, 0xe9, 0x0d, + 0x4e, 0x0d, 0xf6, 0x0c, 0xfc, 0x0c, 0xf2, 0x0b, 0x08, 0x0a, 0x5a, 0x08, + 0xa8, 0x07, 0x99, 0x08, 0x20, 0x09, 0x21, 0x09, 0xcc, 0x08, 0x6c, 0x08, + 0xce, 0x08, 0xa3, 0x08, 0x3d, 0x08, 0xac, 0x07, 0xd8, 0x06, 0x29, 0x06, + 0xa3, 0x04, 0xaa, 0x02, 0x51, 0x01, 0x84, 0x00, 0x63, 0x00, 0x1c, 0x00, + 0x95, 0xff, 0xc1, 0xff, 0x21, 0x00, 0x46, 0x01, 0xca, 0x01, 0x11, 0x02, + 0xa2, 0x02, 0x43, 0x03, 0x2e, 0x04, 0xb2, 0x04, 0x11, 0x05, 0x36, 0x05, + 0xa2, 0x05, 0x13, 0x06, 0x69, 0x06, 0x3f, 0x06, 0x2f, 0x06, 0x00, 0x06, + 0x54, 0x06, 0xc2, 0x06, 0x09, 0x07, 0xdf, 0x06, 0xd2, 0x06, 0xe4, 0x06, + 0xcc, 0x06, 0x8c, 0x06, 0xdd, 0x05, 0x0f, 0x05, 0x5f, 0x04, 0xac, 0x03, + 0xf5, 0x02, 0x3d, 0x02, 0xcd, 0x01, 0x93, 0x01, 0x62, 0x01, 0x38, 0x01, + 0xd1, 0x00, 0x4e, 0x00, 0xf8, 0xff, 0x41, 0xff, 0x9c, 0xfe, 0xc4, 0xfd, + 0xc4, 0xfc, 0xfb, 0xfb, 0x05, 0xfb, 0x06, 0xfa, 0xce, 0xf8, 0xc9, 0xf7, + 0xde, 0xf6, 0x1c, 0xf5, 0xc8, 0xf3, 0x71, 0xf2, 0x1e, 0xf1, 0xf7, 0xef, + 0x3e, 0xef, 0x27, 0xef, 0x54, 0xf0, 0x95, 0xf2, 0x93, 0xf4, 0x13, 0xf6, + 0x66, 0xf7, 0x85, 0xf8, 0x20, 0xf9, 0x42, 0xf9, 0x2d, 0xf8, 0xaa, 0xf6, + 0x52, 0xf5, 0x08, 0xf4, 0x75, 0xf2, 0x4a, 0xf1, 0xf0, 0xf0, 0x43, 0xf1, + 0x67, 0xf2, 0xb3, 0xf3, 0xdb, 0xf4, 0x57, 0xf6, 0xce, 0xf7, 0x07, 0xf9, + 0x12, 0xfa, 0xd7, 0xfa, 0xe2, 0xfa, 0x06, 0xfb, 0x97, 0xfb, 0x35, 0xfc, + 0xda, 0xfc, 0x42, 0xfd, 0xf4, 0xfd, 0x51, 0xff, 0x51, 0x01, 0xfc, 0x02, + 0xd9, 0x03, 0xa4, 0x04, 0xa4, 0x05, 0xbd, 0x06, 0x52, 0x07, 0x07, 0x07, + 0x89, 0x06, 0x8b, 0x06, 0xd4, 0x06, 0x0f, 0x07, 0x09, 0x07, 0x0c, 0x07, + 0x77, 0x07, 0x0d, 0x08, 0x66, 0x08, 0xb3, 0x08, 0xfb, 0x08, 0xd3, 0x08, + 0x71, 0x08, 0xc4, 0x07, 0x0b, 0x07, 0x8f, 0x06, 0x59, 0x06, 0x65, 0x06, + 0x74, 0x06, 0x90, 0x06, 0x5d, 0x06, 0x50, 0x06, 0xdb, 0x06, 0xb0, 0x07, + 0x94, 0x08, 0x1a, 0x09, 0x44, 0x09, 0x5a, 0x09, 0x50, 0x09, 0x6b, 0x09, + 0x79, 0x09, 0xa8, 0x09, 0xef, 0x09, 0x1a, 0x0a, 0x5f, 0x0a, 0x8c, 0x0a, + 0xe6, 0x0a, 0x34, 0x0b, 0x70, 0x0b, 0x95, 0x0b, 0x9f, 0x0b, 0x6b, 0x0b, + 0xf8, 0x0a, 0x91, 0x0a, 0x6e, 0x0a, 0x45, 0x0a, 0x05, 0x0a, 0xa3, 0x09, + 0x41, 0x09, 0x4d, 0x09, 0x44, 0x09, 0xfd, 0x08, 0x98, 0x08, 0x29, 0x08, + 0xd1, 0x07, 0x42, 0x07, 0x7e, 0x06, 0xab, 0x05, 0xf0, 0x04, 0x6d, 0x04, + 0xb1, 0x03, 0x73, 0x02, 0xf9, 0x00, 0xa2, 0xff, 0x83, 0xfe, 0x29, 0xfd, + 0xac, 0xfb, 0x10, 0xfa, 0x5b, 0xf8, 0x91, 0xf6, 0xf6, 0xf4, 0xa4, 0xf3, + 0x4d, 0xf2, 0xd5, 0xf0, 0x1e, 0xef, 0x8f, 0xed, 0x3f, 0xec, 0x21, 0xeb, + 0x80, 0xea, 0x59, 0xea, 0xcd, 0xea, 0x37, 0xeb, 0x2d, 0xeb, 0xf1, 0xea, + 0xb0, 0xea, 0x9e, 0xea, 0x29, 0xea, 0x59, 0xe9, 0xc3, 0xe8, 0x80, 0xe8, + 0xb8, 0xe8, 0xf6, 0xe8, 0x5b, 0xe9, 0xc3, 0xea, 0xdb, 0xec, 0x84, 0xee, + 0x49, 0xef, 0xf6, 0xef, 0x2b, 0xf1, 0xc6, 0xf2, 0xf2, 0xf3, 0x6c, 0xf4, + 0xf3, 0xf4, 0xbe, 0xf6, 0xbe, 0xf8, 0xf3, 0xf9, 0xf6, 0xfa, 0xc0, 0xfc, + 0x98, 0xff, 0x67, 0x02, 0x30, 0x04, 0x3c, 0x05, 0x61, 0x06, 0xda, 0x07, + 0xe2, 0x08, 0x21, 0x09, 0x1b, 0x09, 0x30, 0x09, 0x7e, 0x09, 0xe3, 0x09, + 0x4e, 0x0a, 0xe1, 0x0a, 0xe8, 0x0b, 0x3b, 0x0d, 0x86, 0x0e, 0x5c, 0x0f, + 0x9f, 0x0f, 0x5f, 0x0f, 0x46, 0x0f, 0x7f, 0x0f, 0x52, 0x0f, 0x94, 0x0e, + 0x90, 0x0d, 0xeb, 0x0c, 0xe1, 0x0c, 0xcb, 0x0c, 0x75, 0x0c, 0x07, 0x0c, + 0x05, 0x0c, 0xa8, 0x0c, 0x1b, 0x0d, 0x14, 0x0d, 0xe1, 0x0c, 0x04, 0x0d, + 0x84, 0x0d, 0xac, 0x0d, 0x37, 0x0d, 0x72, 0x0c, 0x10, 0x0c, 0xe1, 0x0b, + 0xa8, 0x0b, 0x37, 0x0b, 0xf4, 0x0a, 0x39, 0x0b, 0x98, 0x0b, 0x9a, 0x0b, + 0x67, 0x0b, 0x5f, 0x0b, 0x8d, 0x0b, 0x78, 0x0b, 0xf5, 0x0a, 0x4d, 0x0a, + 0xa3, 0x09, 0x5c, 0x09, 0xde, 0x08, 0x1c, 0x08, 0x94, 0x07, 0x21, 0x07, + 0xf8, 0x06, 0xb1, 0x06, 0x19, 0x06, 0x8c, 0x05, 0xfe, 0x04, 0xa3, 0x04, + 0xf7, 0x03, 0x29, 0x03, 0x2a, 0x02, 0x06, 0x01, 0xea, 0xff, 0x82, 0xfe, + 0x06, 0xfd, 0x93, 0xfb, 0x26, 0xfa, 0xe2, 0xf8, 0x6d, 0xf7, 0xe4, 0xf5, + 0x53, 0xf4, 0xe7, 0xf2, 0x80, 0xf1, 0xfe, 0xef, 0x5c, 0xee, 0xad, 0xec, + 0xf4, 0xea, 0x0e, 0xe9, 0xb2, 0xe7, 0xea, 0xe6, 0x04, 0xe7, 0x6f, 0xe7, + 0x2f, 0xe7, 0x02, 0xe7, 0x17, 0xe7, 0x60, 0xe7, 0x38, 0xe7, 0x0e, 0xe6, + 0x20, 0xe5, 0x1c, 0xe5, 0x0f, 0xe6, 0xdb, 0xe6, 0xb5, 0xe6, 0x4b, 0xe7, + 0x69, 0xe9, 0x4d, 0xec, 0x73, 0xee, 0xfa, 0xee, 0x70, 0xef, 0xc5, 0xf0, + 0xcd, 0xf2, 0x32, 0xf4, 0x5d, 0xf4, 0xf4, 0xf4, 0xd7, 0xf6, 0x77, 0xf9, + 0x95, 0xfb, 0xe3, 0xfc, 0x8e, 0xfe, 0x33, 0x01, 0x74, 0x04, 0xec, 0x06, + 0x2f, 0x08, 0x1d, 0x09, 0x42, 0x0a, 0x5b, 0x0b, 0xdc, 0x0b, 0xb5, 0x0b, + 0x64, 0x0b, 0x58, 0x0b, 0xe9, 0x0b, 0xe0, 0x0c, 0xd5, 0x0d, 0xd7, 0x0e, + 0x0f, 0x10, 0x74, 0x11, 0xb0, 0x12, 0x5b, 0x13, 0x68, 0x13, 0x1e, 0x13, + 0xd2, 0x12, 0x81, 0x12, 0xf2, 0x11, 0x29, 0x11, 0x61, 0x10, 0xcb, 0x0f, + 0x66, 0x0f, 0x2e, 0x0f, 0xf5, 0x0e, 0xd2, 0x0e, 0xef, 0x0e, 0xf8, 0x0e, + 0xf3, 0x0e, 0xd2, 0x0e, 0x88, 0x0e, 0x41, 0x0e, 0xaf, 0x0d, 0x00, 0x0d, + 0x35, 0x0c, 0x57, 0x0b, 0xab, 0x0a, 0x0f, 0x0a, 0xb4, 0x09, 0x84, 0x09, + 0x6c, 0x09, 0x5d, 0x09, 0x43, 0x09, 0x1c, 0x09, 0xde, 0x08, 0x9f, 0x08, + 0x49, 0x08, 0xd6, 0x07, 0x55, 0x07, 0xc7, 0x06, 0x52, 0x06, 0xf0, 0x05, + 0x89, 0x05, 0x02, 0x05, 0x89, 0x04, 0x23, 0x04, 0xbe, 0x03, 0x52, 0x03, + 0xce, 0x02, 0x4e, 0x02, 0xe2, 0x01, 0x62, 0x01, 0xcc, 0x00, 0x21, 0x00, + 0x5a, 0xff, 0x78, 0xfe, 0x76, 0xfd, 0x6c, 0xfc, 0x5d, 0xfb, 0x43, 0xfa, + 0x0f, 0xf9, 0xc8, 0xf7, 0x9d, 0xf6, 0x79, 0xf5, 0x41, 0xf4, 0xf5, 0xf2, + 0x92, 0xf1, 0x51, 0xf0, 0x19, 0xef, 0xc5, 0xed, 0x48, 0xec, 0x90, 0xea, + 0x1c, 0xe9, 0x5e, 0xe8, 0x4b, 0xe8, 0x87, 0xe8, 0x62, 0xe8, 0x03, 0xe8, + 0x18, 0xe8, 0xa8, 0xe8, 0xc7, 0xe8, 0x1b, 0xe8, 0x19, 0xe7, 0xe8, 0xe6, + 0xeb, 0xe7, 0x0f, 0xe9, 0x25, 0xe9, 0xf2, 0xe8, 0x63, 0xea, 0x35, 0xed, + 0xc2, 0xef, 0xba, 0xf0, 0xa2, 0xf0, 0xa0, 0xf1, 0x11, 0xf4, 0x15, 0xf6, + 0x6c, 0xf6, 0x6c, 0xf6, 0xee, 0xf7, 0xc3, 0xfa, 0x60, 0xfd, 0xb2, 0xfe, + 0x95, 0xff, 0xb4, 0x01, 0xc3, 0x04, 0x54, 0x07, 0x9d, 0x08, 0x2b, 0x09, + 0x10, 0x0a, 0x5e, 0x0b, 0x4d, 0x0c, 0x61, 0x0c, 0x05, 0x0c, 0xe8, 0x0b, + 0x90, 0x0c, 0xb0, 0x0d, 0x60, 0x0e, 0x96, 0x0e, 0x12, 0x0f, 0x35, 0x10, + 0x7e, 0x11, 0x0e, 0x12, 0xbc, 0x11, 0x3b, 0x11, 0x28, 0x11, 0x70, 0x11, + 0x26, 0x11, 0x0d, 0x10, 0x20, 0x0f, 0xe4, 0x0e, 0x0e, 0x0f, 0xc7, 0x0e, + 0xfd, 0x0d, 0x7e, 0x0d, 0x93, 0x0d, 0xe2, 0x0d, 0xa5, 0x0d, 0x06, 0x0d, + 0xae, 0x0c, 0xa8, 0x0c, 0xb1, 0x0c, 0x21, 0x0c, 0x23, 0x0b, 0x80, 0x0a, + 0x5b, 0x0a, 0x1a, 0x0a, 0x78, 0x09, 0xe8, 0x08, 0xc8, 0x08, 0x07, 0x09, + 0x01, 0x09, 0x85, 0x08, 0x01, 0x08, 0xe7, 0x07, 0xf7, 0x07, 0xb5, 0x07, + 0x32, 0x07, 0x91, 0x06, 0x2f, 0x06, 0x1e, 0x06, 0xe3, 0x05, 0x74, 0x05, + 0xeb, 0x04, 0x7c, 0x04, 0x35, 0x04, 0xe8, 0x03, 0x6e, 0x03, 0xbf, 0x02, + 0x2a, 0x02, 0xd6, 0x01, 0x7f, 0x01, 0xf8, 0x00, 0x0f, 0x00, 0x28, 0xff, + 0x74, 0xfe, 0xc4, 0xfd, 0xc7, 0xfc, 0x7b, 0xfb, 0x30, 0xfa, 0x1c, 0xf9, + 0x05, 0xf8, 0xd4, 0xf6, 0x76, 0xf5, 0x36, 0xf4, 0x26, 0xf3, 0x04, 0xf2, + 0xce, 0xf0, 0x6e, 0xef, 0x27, 0xee, 0xcb, 0xec, 0x54, 0xeb, 0x08, 0xea, + 0x57, 0xe9, 0x63, 0xe9, 0xa3, 0xe9, 0x8f, 0xe9, 0x4b, 0xe9, 0x54, 0xe9, + 0xaa, 0xe9, 0x90, 0xe9, 0xa6, 0xe8, 0xa2, 0xe7, 0xa0, 0xe7, 0x96, 0xe8, + 0x67, 0xe9, 0x59, 0xe9, 0x92, 0xe9, 0x43, 0xeb, 0xe1, 0xed, 0x2b, 0xf0, + 0xff, 0xf0, 0x26, 0xf1, 0x59, 0xf2, 0x6d, 0xf4, 0xfa, 0xf5, 0x48, 0xf6, + 0x77, 0xf6, 0xfb, 0xf7, 0xa9, 0xfa, 0x12, 0xfd, 0x5e, 0xfe, 0x75, 0xff, + 0x8f, 0x01, 0x99, 0x04, 0x27, 0x07, 0x7f, 0x08, 0x21, 0x09, 0xf1, 0x09, + 0x29, 0x0b, 0xfc, 0x0b, 0xee, 0x0b, 0x66, 0x0b, 0x3b, 0x0b, 0x01, 0x0c, + 0x03, 0x0d, 0x85, 0x0d, 0xc0, 0x0d, 0x5d, 0x0e, 0xa4, 0x0f, 0xc9, 0x10, + 0x4b, 0x11, 0x34, 0x11, 0xe0, 0x10, 0xc6, 0x10, 0xac, 0x10, 0x37, 0x10, + 0x63, 0x0f, 0x7a, 0x0e, 0x0f, 0x0e, 0xe0, 0x0d, 0x9f, 0x0d, 0x3c, 0x0d, + 0xdc, 0x0c, 0xe8, 0x0c, 0x28, 0x0d, 0x3a, 0x0d, 0x09, 0x0d, 0xaf, 0x0c, + 0x72, 0x0c, 0x31, 0x0c, 0xc9, 0x0b, 0x37, 0x0b, 0x89, 0x0a, 0xfc, 0x09, + 0x94, 0x09, 0x48, 0x09, 0x20, 0x09, 0x0b, 0x09, 0xfe, 0x08, 0xfb, 0x08, + 0xf7, 0x08, 0xea, 0x08, 0xbc, 0x08, 0x6f, 0x08, 0x1e, 0x08, 0xc1, 0x07, + 0x50, 0x07, 0xcc, 0x06, 0x44, 0x06, 0xe5, 0x05, 0x8d, 0x05, 0x28, 0x05, + 0xc4, 0x04, 0x5b, 0x04, 0x08, 0x04, 0xae, 0x03, 0x35, 0x03, 0xb5, 0x02, + 0x2f, 0x02, 0xb7, 0x01, 0x20, 0x01, 0x5f, 0x00, 0x7f, 0xff, 0x8f, 0xfe, + 0xa7, 0xfd, 0xae, 0xfc, 0x98, 0xfb, 0x59, 0xfa, 0x29, 0xf9, 0x26, 0xf8, + 0x1f, 0xf7, 0xf8, 0xf5, 0xb5, 0xf4, 0x88, 0xf3, 0x7b, 0xf2, 0x5e, 0xf1, + 0x2e, 0xf0, 0xcf, 0xee, 0x86, 0xed, 0x40, 0xec, 0xeb, 0xea, 0xe2, 0xe9, + 0x66, 0xe9, 0x9e, 0xe9, 0x01, 0xea, 0xc4, 0xe9, 0x7f, 0xe9, 0xa7, 0xe9, + 0x08, 0xea, 0xf2, 0xe9, 0xf8, 0xe8, 0x21, 0xe8, 0x5c, 0xe8, 0x6a, 0xe9, + 0x1b, 0xea, 0xec, 0xe9, 0x67, 0xea, 0x64, 0xec, 0x16, 0xef, 0xd8, 0xf0, + 0x43, 0xf1, 0xc7, 0xf1, 0x5b, 0xf3, 0x82, 0xf5, 0xa6, 0xf6, 0xd0, 0xf6, + 0x78, 0xf7, 0x69, 0xf9, 0xe4, 0xfb, 0xb7, 0xfd, 0xe3, 0xfe, 0x69, 0x00, + 0xcf, 0x02, 0x99, 0x05, 0xa7, 0x07, 0xc2, 0x08, 0x92, 0x09, 0xa3, 0x0a, + 0x9d, 0x0b, 0xfe, 0x0b, 0xd7, 0x0b, 0x87, 0x0b, 0x9a, 0x0b, 0x35, 0x0c, + 0xd1, 0x0c, 0x36, 0x0d, 0x8d, 0x0d, 0x54, 0x0e, 0x71, 0x0f, 0x3f, 0x10, + 0x6f, 0x10, 0x40, 0x10, 0x29, 0x10, 0x1f, 0x10, 0xeb, 0x0f, 0x4b, 0x0f, + 0x6c, 0x0e, 0xe6, 0x0d, 0xb2, 0x0d, 0x55, 0x0d, 0xb4, 0x0c, 0x29, 0x0c, + 0x0a, 0x0c, 0x33, 0x0c, 0x60, 0x0c, 0x2c, 0x0c, 0x17, 0x0c, 0x38, 0x0c, + 0x25, 0x0c, 0xec, 0x0b, 0x58, 0x0b, 0xcb, 0x0a, 0x5d, 0x0a, 0xf8, 0x09, + 0x6e, 0x09, 0xd6, 0x08, 0xbf, 0x08, 0xe2, 0x08, 0xf4, 0x08, 0xe6, 0x08, + 0xae, 0x08, 0xa8, 0x08, 0xa4, 0x08, 0x75, 0x08, 0x33, 0x08, 0xdd, 0x07, + 0x94, 0x07, 0x36, 0x07, 0xb4, 0x06, 0x44, 0x06, 0xd8, 0x05, 0x63, 0x05, + 0xe4, 0x04, 0x6c, 0x04, 0x07, 0x04, 0xa1, 0x03, 0x32, 0x03, 0xab, 0x02, + 0x34, 0x02, 0xd3, 0x01, 0x50, 0x01, 0x8c, 0x00, 0x9f, 0xff, 0xa8, 0xfe, + 0xa7, 0xfd, 0x96, 0xfc, 0x6a, 0xfb, 0x3f, 0xfa, 0x32, 0xf9, 0x31, 0xf8, + 0x1b, 0xf7, 0x14, 0xf6, 0x16, 0xf5, 0xe8, 0xf3, 0xd2, 0xf2, 0xb1, 0xf1, + 0x98, 0xf0, 0x5f, 0xef, 0x0b, 0xee, 0xa7, 0xec, 0x48, 0xeb, 0x3b, 0xea, + 0x7a, 0xe9, 0x64, 0xe9, 0xc3, 0xe9, 0x22, 0xea, 0x1a, 0xea, 0x14, 0xea, + 0x4d, 0xea, 0x58, 0xea, 0xff, 0xe9, 0x18, 0xe9, 0x92, 0xe8, 0x06, 0xe9, + 0xc2, 0xe9, 0x28, 0xea, 0x67, 0xea, 0x8a, 0xeb, 0xf3, 0xed, 0x31, 0xf0, + 0x6c, 0xf1, 0xdf, 0xf1, 0xd1, 0xf2, 0xd4, 0xf4, 0x86, 0xf6, 0x43, 0xf7, + 0x81, 0xf7, 0xcd, 0xf8, 0x06, 0xfb, 0x00, 0xfd, 0x4a, 0xfe, 0x46, 0xff, + 0x70, 0x01, 0x48, 0x04, 0x8a, 0x06, 0xef, 0x07, 0xb9, 0x08, 0xe4, 0x09, + 0x1a, 0x0b, 0xe6, 0x0b, 0xef, 0x0b, 0xb2, 0x0b, 0xe9, 0x0b, 0x21, 0x0c, + 0x6c, 0x0c, 0xb4, 0x0c, 0x2a, 0x0d, 0xe3, 0x0d, 0xa4, 0x0e, 0x60, 0x0f, + 0xd2, 0x0f, 0x02, 0x10, 0x02, 0x10, 0xcc, 0x0f, 0x9b, 0x0f, 0x5a, 0x0f, + 0xf0, 0x0e, 0x69, 0x0e, 0x0b, 0x0e, 0xac, 0x0d, 0x30, 0x0d, 0xaf, 0x0c, + 0x2d, 0x0c, 0x10, 0x0c, 0x27, 0x0c, 0x2e, 0x0c, 0x19, 0x0c, 0xfb, 0x0b, + 0x1a, 0x0c, 0x05, 0x0c, 0xb8, 0x0b, 0x44, 0x0b, 0xc3, 0x0a, 0x57, 0x0a, + 0xb8, 0x09, 0x15, 0x09, 0xab, 0x08, 0x95, 0x08, 0xb5, 0x08, 0xac, 0x08, + 0x7c, 0x08, 0x75, 0x08, 0x8b, 0x08, 0x68, 0x08, 0x18, 0x08, 0xcf, 0x07, + 0x7d, 0x07, 0x08, 0x07, 0x7f, 0x06, 0x08, 0x06, 0xa3, 0x05, 0x3c, 0x05, + 0xc5, 0x04, 0x46, 0x04, 0x08, 0x04, 0xcd, 0x03, 0x73, 0x03, 0xeb, 0x02, + 0x53, 0x02, 0xcd, 0x01, 0x36, 0x01, 0x8d, 0x00, 0xb3, 0xff, 0xc1, 0xfe, + 0xcd, 0xfd, 0xd2, 0xfc, 0xe6, 0xfb, 0xd4, 0xfa, 0xef, 0xf9, 0xfd, 0xf8, + 0xb2, 0xf7, 0x50, 0xf6, 0xdb, 0xf4, 0x9b, 0xf3, 0x6c, 0xf2, 0x34, 0xf1, + 0x45, 0xf0, 0x03, 0xef, 0xc4, 0xed, 0x80, 0xec, 0xfa, 0xea, 0x94, 0xe9, + 0x73, 0xe8, 0x10, 0xe8, 0x5a, 0xe8, 0xbe, 0xe8, 0x95, 0xe8, 0xa0, 0xe8, + 0x52, 0xe9, 0x4a, 0xea, 0x9e, 0xea, 0x22, 0xea, 0x70, 0xe9, 0xa1, 0xe9, + 0x60, 0xea, 0xd1, 0xea, 0xce, 0xea, 0x3e, 0xeb, 0x4c, 0xed, 0x83, 0xef, + 0x21, 0xf1, 0x35, 0xf2, 0xf5, 0xf2, 0x9f, 0xf4, 0xde, 0xf6, 0x89, 0xf8, + 0x6c, 0xf9, 0x5e, 0xfa, 0xad, 0xfb, 0xcb, 0xfd, 0xbf, 0xff, 0xbe, 0x00, + 0xf0, 0x01, 0x8d, 0x03, 0xa6, 0x05, 0x90, 0x07, 0xa2, 0x08, 0x82, 0x09, + 0x7e, 0x0a, 0xfa, 0x0b, 0x17, 0x0d, 0x43, 0x0d, 0x80, 0x0d, 0xc9, 0x0d, + 0x23, 0x0e, 0xa1, 0x0e, 0xb2, 0x0e, 0xd2, 0x0e, 0x11, 0x0f, 0xef, 0x0f, + 0x66, 0x10, 0x45, 0x10, 0xcf, 0x0f, 0x79, 0x0f, 0xb5, 0x0f, 0x8b, 0x0f, + 0x05, 0x0f, 0x90, 0x0e, 0x4c, 0x0e, 0x63, 0x0e, 0x07, 0x0e, 0x41, 0x0d, + 0x7b, 0x0c, 0x12, 0x0c, 0x01, 0x0c, 0x8b, 0x0b, 0xe7, 0x0a, 0x62, 0x0a, + 0x49, 0x0a, 0x86, 0x0a, 0x7d, 0x0a, 0x22, 0x0a, 0xe7, 0x09, 0x7b, 0x09, + 0x45, 0x09, 0xf4, 0x08, 0xad, 0x08, 0xa8, 0x08, 0x87, 0x08, 0x48, 0x08, + 0xec, 0x07, 0x73, 0x07, 0x46, 0x07, 0x53, 0x07, 0x5b, 0x07, 0xb8, 0x07, + 0xae, 0x07, 0x84, 0x07, 0xff, 0x06, 0x88, 0x06, 0x55, 0x06, 0x47, 0x06, + 0x22, 0x06, 0x49, 0x05, 0xc0, 0x03, 0xfa, 0x01, 0xa5, 0x00, 0xed, 0xff, + 0x2a, 0x00, 0x6d, 0x00, 0xf7, 0xff, 0x00, 0xff, 0xe5, 0xfd, 0x28, 0xfd, + 0xb7, 0xfc, 0xd3, 0xfb, 0xde, 0xfa, 0x37, 0xf9, 0x30, 0xf7, 0x8d, 0xf4, + 0x70, 0xf2, 0xd0, 0xef, 0x73, 0xee, 0xd8, 0xec, 0xe8, 0xea, 0x0e, 0xe9, + 0xb7, 0xe6, 0x4f, 0xe5, 0x9c, 0xe4, 0x33, 0xe3, 0x18, 0xe2, 0xec, 0xe0, + 0x8e, 0xdf, 0xa8, 0xe1, 0x81, 0xe4, 0x30, 0xe9, 0x1a, 0xed, 0xe7, 0xed, + 0x06, 0xf0, 0xec, 0xf1, 0xf6, 0xf4, 0x24, 0xf9, 0x69, 0xf9, 0x35, 0xf8, + 0xf8, 0xf5, 0x23, 0xf4, 0x5f, 0xf4, 0x5e, 0xf5, 0x86, 0xf6, 0xe7, 0xf7, + 0x68, 0xf8, 0x16, 0xf9, 0xb0, 0xfa, 0x8b, 0xfc, 0x8c, 0xff, 0xcc, 0x01, + 0x19, 0x03, 0x7e, 0x03, 0xe0, 0x02, 0x67, 0x02, 0xc5, 0x01, 0xf6, 0x01, + 0xc8, 0x01, 0x1c, 0x02, 0x94, 0x02, 0x5b, 0x03, 0x16, 0x05, 0xee, 0x06, + 0xc8, 0x09, 0x7c, 0x0c, 0x21, 0x0f, 0xe8, 0x10, 0x5f, 0x11, 0x68, 0x11, + 0xfb, 0x10, 0xa7, 0x10, 0xd0, 0x10, 0xf5, 0x0f, 0x29, 0x0f, 0x23, 0x0e, + 0x33, 0x0d, 0x44, 0x0d, 0x7a, 0x0d, 0xaf, 0x0e, 0xa2, 0x0f, 0x04, 0x10, + 0x0c, 0x10, 0x27, 0x0f, 0x10, 0x0f, 0x65, 0x0e, 0xca, 0x0c, 0xad, 0x0a, + 0x48, 0x08, 0x4a, 0x06, 0x0f, 0x05, 0x65, 0x04, 0x26, 0x03, 0xf5, 0x02, + 0xe0, 0x02, 0x19, 0x03, 0xb5, 0x03, 0x66, 0x04, 0x28, 0x05, 0x1a, 0x06, + 0xcf, 0x06, 0x6b, 0x06, 0x67, 0x06, 0xf5, 0x05, 0xf3, 0x05, 0x41, 0x06, + 0x35, 0x06, 0x8f, 0x06, 0x3c, 0x06, 0xfe, 0x06, 0x9d, 0x07, 0x41, 0x08, + 0x06, 0x09, 0x24, 0x09, 0x3e, 0x09, 0xf0, 0x08, 0x7c, 0x08, 0x8d, 0x07, + 0x30, 0x06, 0x05, 0x05, 0xc6, 0x03, 0xb9, 0x02, 0xa0, 0x01, 0x91, 0x00, + 0xcc, 0xff, 0x36, 0xff, 0x37, 0xff, 0x74, 0xff, 0x4e, 0xff, 0x17, 0x00, + 0x39, 0xff, 0x95, 0xfd, 0xd3, 0xfb, 0x57, 0xf9, 0x21, 0xf7, 0x43, 0xf5, + 0x52, 0xf2, 0x5b, 0xef, 0x5b, 0xec, 0xcf, 0xea, 0x79, 0xe9, 0x49, 0xe9, + 0x6c, 0xe9, 0xb5, 0xe7, 0x49, 0xe7, 0x36, 0xe6, 0x93, 0xe5, 0x42, 0xe4, + 0x22, 0xe2, 0xdb, 0xde, 0xc3, 0xde, 0xb2, 0xdf, 0x2e, 0xe6, 0x7a, 0xec, + 0x3b, 0xf0, 0x10, 0xf4, 0x9f, 0xf4, 0x16, 0xfa, 0x47, 0x00, 0x7e, 0x05, + 0xa0, 0x07, 0xc6, 0x05, 0x4f, 0x03, 0x39, 0x00, 0xed, 0xfd, 0x68, 0xfc, + 0x9e, 0xfa, 0x0a, 0xfa, 0x70, 0xf9, 0x4b, 0xf8, 0xc4, 0xf8, 0xb3, 0xf9, + 0x37, 0xfc, 0x17, 0xff, 0x17, 0x01, 0xf2, 0x02, 0xdb, 0x04, 0xb6, 0x04, + 0xa6, 0x03, 0x6f, 0x01, 0xb2, 0x00, 0x30, 0x01, 0xcc, 0x02, 0x63, 0x03, + 0x0b, 0x03, 0xbd, 0x03, 0x48, 0x05, 0x8f, 0x07, 0xf5, 0x0a, 0xef, 0x0d, + 0x6d, 0x10, 0x50, 0x12, 0x44, 0x12, 0x44, 0x11, 0xbb, 0x10, 0xf5, 0x10, + 0xd9, 0x10, 0x3c, 0x10, 0x5e, 0x0e, 0xfa, 0x0b, 0xc5, 0x0a, 0xf7, 0x09, + 0x0d, 0x09, 0x1a, 0x09, 0x68, 0x09, 0x62, 0x0a, 0xf5, 0x0a, 0xae, 0x09, + 0xff, 0x07, 0x6f, 0x06, 0x1c, 0x06, 0x2c, 0x06, 0xaa, 0x04, 0x79, 0x03, + 0x16, 0x01, 0x9d, 0x00, 0x63, 0x00, 0x27, 0x00, 0xdb, 0x00, 0xb0, 0x01, + 0x65, 0x03, 0xa7, 0x05, 0x8d, 0x06, 0x47, 0x07, 0x8b, 0x07, 0x16, 0x09, + 0x26, 0x0a, 0x70, 0x0b, 0xff, 0x0a, 0xca, 0x0a, 0x03, 0x0a, 0x4c, 0x0a, + 0x55, 0x0a, 0xd6, 0x0a, 0x42, 0x0b, 0x7c, 0x0b, 0xab, 0x0a, 0xc1, 0x09, + 0x51, 0x09, 0x6f, 0x08, 0x49, 0x08, 0xf8, 0x06, 0x4a, 0x05, 0x6c, 0x03, + 0xda, 0x01, 0xa7, 0xff, 0x2f, 0xff, 0xf1, 0xfd, 0xec, 0xfc, 0x51, 0xfc, + 0x60, 0xfb, 0xeb, 0xfa, 0x3c, 0xfb, 0xde, 0xfa, 0x06, 0xfb, 0xf3, 0xf9, + 0x4f, 0xf8, 0x5f, 0xf5, 0xcb, 0xf2, 0x03, 0xf0, 0xed, 0xee, 0xd7, 0xec, + 0x5c, 0xec, 0x1c, 0xea, 0xcf, 0xea, 0x3a, 0xe9, 0x9e, 0xe8, 0x59, 0xe8, + 0x21, 0xe7, 0xd5, 0xe8, 0x2d, 0xe6, 0xeb, 0xe3, 0xbb, 0xdf, 0xe7, 0xdc, + 0xc3, 0xdd, 0x93, 0xe1, 0x37, 0xe7, 0xc7, 0xee, 0xce, 0xf2, 0x78, 0xf8, + 0x5d, 0xfc, 0xcf, 0x02, 0x83, 0x09, 0x8b, 0x0c, 0x90, 0x0e, 0xeb, 0x09, + 0xc1, 0x06, 0x22, 0x03, 0x26, 0xfe, 0x04, 0xfc, 0xfd, 0xf8, 0x21, 0xf8, + 0x5f, 0xf8, 0x62, 0xf8, 0xbf, 0xf8, 0x0d, 0xfa, 0xbb, 0xfd, 0xc8, 0x00, + 0xe7, 0x02, 0x2c, 0x04, 0x30, 0x03, 0xba, 0x02, 0x27, 0x02, 0xe4, 0x00, + 0x51, 0xff, 0x47, 0xff, 0x80, 0xff, 0xfc, 0x00, 0x2a, 0x02, 0x93, 0x03, + 0xf9, 0x05, 0xe3, 0x08, 0x20, 0x0d, 0x14, 0x10, 0x42, 0x12, 0x1b, 0x12, + 0x2a, 0x11, 0x9c, 0x10, 0x25, 0x10, 0x5f, 0x0f, 0xf8, 0x0d, 0xa0, 0x0b, + 0x81, 0x09, 0x46, 0x09, 0x9f, 0x08, 0xab, 0x08, 0x18, 0x08, 0xee, 0x07, + 0xe8, 0x08, 0x81, 0x09, 0xca, 0x09, 0x2c, 0x08, 0x52, 0x07, 0x49, 0x06, + 0x68, 0x05, 0x3d, 0x04, 0x56, 0x03, 0x64, 0x02, 0xc6, 0x01, 0xcb, 0x01, + 0x2f, 0x01, 0xd2, 0x01, 0x0f, 0x03, 0x23, 0x04, 0x72, 0x05, 0xb5, 0x06, + 0x23, 0x07, 0x93, 0x07, 0x36, 0x08, 0x0e, 0x09, 0xbb, 0x09, 0xa5, 0x0a, + 0x60, 0x0a, 0x69, 0x09, 0x3a, 0x09, 0x8f, 0x09, 0xc2, 0x0b, 0x86, 0x0b, + 0xcf, 0x0b, 0x3f, 0x0b, 0xaa, 0x09, 0xf6, 0x09, 0xce, 0x09, 0xcd, 0x08, + 0x85, 0x07, 0x70, 0x05, 0xfc, 0x02, 0xec, 0x00, 0x7e, 0xff, 0xd2, 0xfd, + 0xf4, 0xfc, 0x79, 0xfb, 0x42, 0xfa, 0x5a, 0xf9, 0x08, 0xf9, 0x4c, 0xf9, + 0x6d, 0xf9, 0x3e, 0xf9, 0x02, 0xf9, 0x8e, 0xf9, 0x66, 0xf9, 0x63, 0xf7, + 0x57, 0xf5, 0xd3, 0xf0, 0xec, 0xef, 0x50, 0xee, 0x18, 0xed, 0x6b, 0xeb, + 0xa1, 0xe8, 0x03, 0xe7, 0x34, 0xe6, 0xac, 0xe8, 0xc5, 0xe8, 0x9c, 0xea, + 0x85, 0xe8, 0x43, 0xe7, 0x42, 0xe5, 0xad, 0xe2, 0xee, 0xe0, 0x8b, 0xdf, + 0x62, 0xe3, 0xfa, 0xe8, 0x3a, 0xf0, 0xc1, 0xf5, 0x80, 0xf9, 0x5a, 0xff, + 0x68, 0x06, 0xeb, 0x0e, 0x09, 0x13, 0xcc, 0x12, 0x8d, 0x0f, 0x80, 0x0b, + 0xf2, 0x07, 0x6a, 0x04, 0x5d, 0xff, 0x51, 0xfb, 0xfb, 0xf7, 0x7f, 0xf5, + 0x33, 0xf5, 0x88, 0xf4, 0xfb, 0xf5, 0x41, 0xf9, 0x02, 0xfd, 0x5c, 0x00, + 0xd1, 0x02, 0x06, 0x04, 0x23, 0x04, 0x31, 0x04, 0xef, 0x03, 0x49, 0x04, + 0x2f, 0x04, 0x21, 0x04, 0x3e, 0x04, 0x1d, 0x04, 0xd2, 0x04, 0x77, 0x06, + 0x53, 0x09, 0x21, 0x0c, 0xbf, 0x0e, 0x80, 0x10, 0x1b, 0x11, 0x13, 0x11, + 0x27, 0x11, 0x2c, 0x11, 0x14, 0x11, 0x3d, 0x0f, 0xf9, 0x0c, 0x3e, 0x0a, + 0xae, 0x08, 0x00, 0x08, 0x52, 0x06, 0x8d, 0x05, 0x62, 0x04, 0x6f, 0x04, + 0x2d, 0x05, 0xd5, 0x04, 0x22, 0x05, 0x02, 0x06, 0xe5, 0x06, 0xbb, 0x06, + 0x69, 0x05, 0x96, 0x04, 0xf5, 0x03, 0xde, 0x04, 0x86, 0x04, 0x73, 0x02, + 0xde, 0x00, 0x98, 0x00, 0x0e, 0x01, 0x64, 0x02, 0x87, 0x03, 0xcb, 0x03, + 0x91, 0x04, 0x5a, 0x06, 0x83, 0x07, 0xf4, 0x08, 0x62, 0x0a, 0xe7, 0x0a, + 0xb9, 0x0b, 0xeb, 0x0b, 0x41, 0x0b, 0xa9, 0x0a, 0x3d, 0x0a, 0xb4, 0x09, + 0x59, 0x09, 0xd4, 0x07, 0x52, 0x06, 0x4c, 0x05, 0x71, 0x04, 0x59, 0x03, + 0x2c, 0x02, 0xfd, 0x00, 0xe3, 0xff, 0xfa, 0xfe, 0xa7, 0xfd, 0xf3, 0xfb, + 0xf8, 0xfa, 0x64, 0xfa, 0x12, 0xfa, 0xb7, 0xf9, 0x93, 0xf8, 0x78, 0xf8, + 0x38, 0xf8, 0x2a, 0xf7, 0xfb, 0xf7, 0x08, 0xf8, 0x4b, 0xf6, 0x71, 0xf5, + 0x41, 0xf3, 0x31, 0xf1, 0x65, 0xf2, 0x02, 0xf1, 0x1f, 0xef, 0x4c, 0xed, + 0x82, 0xeb, 0xfc, 0xea, 0xda, 0xeb, 0x93, 0xe9, 0x28, 0xea, 0x56, 0xe9, + 0x2a, 0xe9, 0xad, 0xe8, 0x3c, 0xe6, 0x1e, 0xe5, 0xda, 0xe2, 0xba, 0xe4, + 0x4d, 0xe6, 0x01, 0xeb, 0x97, 0xf0, 0x11, 0xf5, 0x94, 0xfa, 0xb2, 0xff, + 0xb7, 0x06, 0x3b, 0x0d, 0x78, 0x11, 0x82, 0x12, 0xf5, 0x10, 0x65, 0x0e, + 0xc0, 0x0a, 0xe2, 0x07, 0x7d, 0x03, 0x4f, 0xff, 0xce, 0xfc, 0x78, 0xf9, + 0xff, 0xf6, 0xea, 0xf5, 0xa2, 0xf6, 0xd3, 0xf8, 0xa7, 0xfb, 0x5b, 0xfe, + 0xf4, 0xff, 0xae, 0x02, 0x9b, 0x04, 0x27, 0x05, 0xb1, 0x05, 0xbe, 0x06, + 0xa4, 0x07, 0x83, 0x07, 0x28, 0x06, 0x97, 0x04, 0x21, 0x04, 0x0c, 0x06, + 0x03, 0x08, 0x10, 0x09, 0x0b, 0x0a, 0x1b, 0x0b, 0xaa, 0x0c, 0x37, 0x0e, + 0x64, 0x0f, 0x0a, 0x10, 0x97, 0x10, 0xeb, 0x0f, 0x5c, 0x0e, 0x1e, 0x0d, + 0x27, 0x0b, 0x34, 0x0a, 0x5e, 0x08, 0xfe, 0x05, 0xb0, 0x04, 0xf9, 0x03, + 0xee, 0x03, 0x63, 0x04, 0x62, 0x04, 0xd9, 0x04, 0x28, 0x05, 0x46, 0x05, + 0x03, 0x06, 0x39, 0x06, 0x14, 0x06, 0x36, 0x05, 0xca, 0x03, 0x96, 0x02, + 0x83, 0x02, 0xf7, 0x01, 0x42, 0x01, 0x9a, 0x00, 0x3d, 0x01, 0x69, 0x02, + 0x46, 0x03, 0x8b, 0x04, 0x76, 0x05, 0x0e, 0x08, 0x99, 0x09, 0x90, 0x0a, + 0xff, 0x0a, 0x97, 0x0b, 0x50, 0x0c, 0x81, 0x0c, 0x38, 0x0b, 0xb5, 0x09, + 0x34, 0x08, 0x7a, 0x07, 0xb4, 0x05, 0xfa, 0x02, 0xb1, 0x01, 0x68, 0x00, + 0x5b, 0xff, 0x9d, 0xfe, 0x4f, 0xfd, 0xfb, 0xfc, 0x21, 0xfd, 0x02, 0xfc, + 0x7c, 0xfb, 0x3d, 0xfb, 0x57, 0xfb, 0x98, 0xfb, 0x64, 0xfa, 0x14, 0xf9, + 0xef, 0xf8, 0x57, 0xf8, 0x13, 0xf8, 0x48, 0xf7, 0xa0, 0xf5, 0xf7, 0xf4, + 0x0a, 0xf4, 0x3e, 0xf3, 0x53, 0xf1, 0x1a, 0xf1, 0xdb, 0xef, 0x8b, 0xef, + 0xe1, 0xee, 0xf5, 0xed, 0x4b, 0xee, 0x3f, 0xef, 0xff, 0xee, 0x83, 0xee, + 0x89, 0xec, 0xd2, 0xeb, 0xb0, 0xeb, 0x88, 0xe9, 0x11, 0xe7, 0xec, 0xe2, + 0x50, 0xe0, 0x56, 0xe2, 0x97, 0xe6, 0xe0, 0xed, 0xc6, 0xf3, 0x81, 0xf6, + 0x8d, 0xfb, 0xfa, 0x01, 0x50, 0x0b, 0x5b, 0x14, 0x3e, 0x18, 0xc6, 0x15, + 0x11, 0x14, 0xf0, 0x10, 0xaf, 0x0f, 0x6a, 0x0c, 0xbd, 0x06, 0x52, 0x00, + 0x1a, 0xfb, 0x63, 0xf7, 0xe1, 0xf4, 0x45, 0xf4, 0x94, 0xf4, 0x12, 0xf7, + 0xca, 0xfa, 0x0b, 0xfd, 0xf7, 0x00, 0xd4, 0x04, 0xa6, 0x07, 0x23, 0x0a, + 0x16, 0x0b, 0x3a, 0x0b, 0xcb, 0x0b, 0x35, 0x0b, 0x48, 0x09, 0x07, 0x06, + 0x99, 0x03, 0x4f, 0x03, 0x6d, 0x04, 0x83, 0x05, 0x1b, 0x06, 0x3a, 0x06, + 0x5e, 0x08, 0x2f, 0x0b, 0xc0, 0x0e, 0x63, 0x10, 0x64, 0x12, 0x36, 0x13, + 0xc7, 0x12, 0x4d, 0x12, 0x26, 0x0f, 0xaf, 0x0c, 0x13, 0x0b, 0x5e, 0x09, + 0xf1, 0x05, 0x53, 0x02, 0xaa, 0x00, 0x3f, 0x00, 0x44, 0x02, 0x45, 0x03, + 0x72, 0x01, 0x08, 0x02, 0xdc, 0x03, 0x50, 0x06, 0x2f, 0x08, 0x7c, 0x06, + 0xf5, 0x03, 0x01, 0x04, 0x31, 0x03, 0x93, 0x02, 0x62, 0x00, 0xfb, 0xfe, + 0xa6, 0xfe, 0x23, 0xff, 0x61, 0xff, 0x59, 0xff, 0x6d, 0x02, 0xbe, 0x04, + 0xd0, 0x06, 0xd4, 0x08, 0x98, 0x09, 0x70, 0x0b, 0xda, 0x0d, 0x90, 0x0d, + 0x00, 0x0c, 0x62, 0x0a, 0x59, 0x08, 0x32, 0x06, 0x23, 0x04, 0xee, 0x01, + 0x00, 0xff, 0x23, 0xfd, 0x96, 0xfb, 0xaa, 0xf9, 0x9a, 0xf9, 0x8a, 0xf9, + 0x24, 0xf9, 0x52, 0xf9, 0x0d, 0xfa, 0xa9, 0xfa, 0x61, 0xfa, 0x0c, 0xfb, + 0x86, 0xfa, 0x63, 0xfa, 0xeb, 0xfa, 0xd3, 0xf9, 0x37, 0xf9, 0x29, 0xf9, + 0x36, 0xf7, 0x4c, 0xf6, 0xbb, 0xf4, 0x4e, 0xf3, 0x9f, 0xf2, 0x14, 0xf2, + 0xe0, 0xf0, 0x05, 0xef, 0x4a, 0xee, 0xb0, 0xee, 0xa1, 0xee, 0x58, 0xef, + 0xfc, 0xee, 0x38, 0xed, 0x91, 0xed, 0x51, 0xee, 0x67, 0xec, 0x6c, 0xeb, + 0xc1, 0xe8, 0xbd, 0xe5, 0xf7, 0xe4, 0xa4, 0xe7, 0x19, 0xeb, 0x79, 0xf0, + 0x26, 0xf8, 0x67, 0xfa, 0x1a, 0x00, 0xe6, 0x06, 0x2e, 0x0e, 0x3e, 0x17, + 0x2c, 0x1b, 0x53, 0x19, 0xcb, 0x15, 0x4b, 0x13, 0xf1, 0x10, 0xdd, 0x0e, + 0xf4, 0x09, 0x26, 0x02, 0xa9, 0xfa, 0x30, 0xf6, 0x44, 0xf3, 0x53, 0xf3, + 0xaa, 0xf4, 0x4b, 0xf5, 0xcd, 0xf7, 0xe5, 0xfa, 0x0c, 0xfe, 0x23, 0x03, + 0x59, 0x07, 0xfd, 0x09, 0x08, 0x0c, 0x1f, 0x0c, 0x38, 0x0c, 0xc1, 0x0b, + 0x33, 0x0a, 0xd0, 0x07, 0xe5, 0x04, 0x45, 0x03, 0x65, 0x03, 0xa7, 0x03, + 0x3b, 0x04, 0x14, 0x04, 0x14, 0x06, 0x3f, 0x09, 0x63, 0x0c, 0x46, 0x0f, + 0x88, 0x10, 0x1a, 0x11, 0x15, 0x12, 0x22, 0x12, 0x7e, 0x11, 0xb3, 0x0e, + 0xec, 0x0a, 0xdf, 0x07, 0x08, 0x05, 0xde, 0x03, 0xc2, 0x01, 0xe0, 0xff, + 0xef, 0xfd, 0x35, 0xfd, 0xb8, 0xfe, 0x56, 0x00, 0x87, 0x02, 0x92, 0x02, + 0x9a, 0x02, 0xfc, 0x02, 0xb6, 0x03, 0xff, 0x03, 0x3e, 0x03, 0xec, 0x01, + 0xfc, 0xff, 0x82, 0xfe, 0x72, 0xfd, 0xbf, 0xfc, 0x07, 0xfd, 0x3e, 0xfe, + 0xaa, 0xfe, 0xd7, 0xff, 0xc2, 0x01, 0x3d, 0x04, 0x2e, 0x07, 0x7f, 0x09, + 0x03, 0x0b, 0x53, 0x0c, 0x3e, 0x0d, 0x6c, 0x0d, 0x95, 0x0b, 0x93, 0x09, + 0xfb, 0x07, 0x37, 0x06, 0xe4, 0x03, 0x4e, 0x00, 0x3e, 0xfc, 0xf5, 0xf9, + 0xf3, 0xf8, 0xc7, 0xf8, 0xca, 0xf7, 0xcf, 0xf6, 0x5d, 0xf6, 0x1e, 0xf7, + 0x7b, 0xf8, 0x97, 0xf9, 0xf5, 0xfa, 0x05, 0xfb, 0xd2, 0xfb, 0x3d, 0xfc, + 0x2a, 0xfc, 0x41, 0xfc, 0x57, 0xfc, 0x9f, 0xfb, 0x62, 0xfa, 0xff, 0xf8, + 0xda, 0xf6, 0x67, 0xf5, 0x8f, 0xf4, 0x67, 0xf3, 0xce, 0xf2, 0xe2, 0xf1, + 0x45, 0xf0, 0xdb, 0xf0, 0x66, 0xf0, 0x43, 0xf1, 0x31, 0xf1, 0xe6, 0xef, + 0xc5, 0xef, 0xdc, 0xee, 0x0d, 0xee, 0x0e, 0xeb, 0x65, 0xe9, 0x53, 0xe8, + 0x8c, 0xea, 0x7e, 0xee, 0xc9, 0xf1, 0xe7, 0xf4, 0x6c, 0xf8, 0x2a, 0xfe, + 0x5c, 0x04, 0x73, 0x0c, 0xce, 0x12, 0xdc, 0x15, 0x6c, 0x16, 0x56, 0x15, + 0x96, 0x14, 0x4f, 0x14, 0xbe, 0x12, 0x32, 0x0d, 0x9d, 0x06, 0xbc, 0x00, + 0x0a, 0xfc, 0x82, 0xf9, 0xd6, 0xf7, 0x38, 0xf6, 0x41, 0xf6, 0x07, 0xf7, + 0x62, 0xf8, 0x4b, 0xfb, 0x81, 0xfe, 0xd2, 0x01, 0x5d, 0x05, 0x0e, 0x07, + 0xec, 0x07, 0xb1, 0x08, 0xa5, 0x09, 0x7f, 0x08, 0x58, 0x06, 0x0c, 0x04, + 0x45, 0x02, 0xec, 0x01, 0x52, 0x01, 0xed, 0xff, 0xf0, 0xfe, 0x8f, 0x00, + 0xd3, 0x03, 0x4f, 0x06, 0x8d, 0x09, 0xfc, 0x0b, 0xf9, 0x0d, 0xf2, 0x10, + 0x43, 0x13, 0xf7, 0x13, 0x58, 0x13, 0x87, 0x11, 0x8a, 0x0e, 0x16, 0x0c, + 0xaa, 0x09, 0xbf, 0x06, 0x80, 0x02, 0x60, 0xfe, 0xff, 0xfb, 0x13, 0xfb, + 0xcd, 0xfa, 0xaa, 0xfa, 0xe5, 0xf9, 0x73, 0xfa, 0x51, 0xfc, 0xee, 0xfd, + 0x88, 0xff, 0x44, 0x00, 0x75, 0x00, 0x41, 0x01, 0xc9, 0x00, 0x98, 0x01, + 0x77, 0x01, 0x3c, 0x01, 0xb4, 0x00, 0xab, 0xff, 0xf0, 0x00, 0x97, 0x02, + 0xcf, 0x03, 0xf0, 0x04, 0x97, 0x05, 0xfa, 0x06, 0x1b, 0x0a, 0xfc, 0x0b, + 0x5d, 0x0c, 0xc9, 0x0b, 0x60, 0x0b, 0xc3, 0x0a, 0x84, 0x09, 0xb4, 0x07, + 0x70, 0x04, 0xfe, 0x00, 0x21, 0xfe, 0xd0, 0xfb, 0x28, 0xf9, 0x9c, 0xf7, + 0xd7, 0xf5, 0xef, 0xf4, 0x26, 0xf5, 0x91, 0xf5, 0x79, 0xf6, 0x96, 0xf8, + 0x9b, 0xfa, 0x0b, 0xfc, 0x9d, 0xfd, 0x97, 0xfe, 0xcf, 0xff, 0x3e, 0x00, + 0x53, 0x00, 0xe2, 0xff, 0x73, 0xfd, 0xf0, 0xfb, 0x89, 0xf9, 0xe0, 0xf6, + 0x80, 0xf5, 0xf5, 0xf3, 0x39, 0xf2, 0x9d, 0xf1, 0xcb, 0xf0, 0x79, 0xf0, + 0x45, 0xf0, 0xc2, 0xf3, 0x62, 0xf3, 0x21, 0xf3, 0x5b, 0xf6, 0xa1, 0xf2, + 0xeb, 0xf2, 0x19, 0xf1, 0x2e, 0xee, 0xb1, 0xeb, 0x5b, 0xec, 0x74, 0xec, + 0x53, 0xed, 0xca, 0xf0, 0xa1, 0xf2, 0x92, 0xf6, 0x1c, 0xfc, 0x09, 0x04, + 0x79, 0x0b, 0xe0, 0x11, 0x5c, 0x14, 0x17, 0x16, 0x93, 0x17, 0x38, 0x19, + 0x70, 0x1a, 0x6c, 0x16, 0x7d, 0x10, 0x0f, 0x0a, 0x39, 0x04, 0x5a, 0x00, + 0x3d, 0xfc, 0x42, 0xf8, 0x4d, 0xf5, 0xaa, 0xf3, 0x63, 0xf3, 0xd8, 0xf3, + 0x08, 0xf6, 0x9b, 0xf9, 0xb6, 0xfd, 0xd7, 0x00, 0xcb, 0x02, 0x89, 0x04, + 0x62, 0x06, 0x33, 0x08, 0x2c, 0x08, 0x01, 0x07, 0x5e, 0x05, 0xca, 0x03, + 0x5f, 0x02, 0xc6, 0x00, 0x5b, 0xff, 0x32, 0xfe, 0xe0, 0xfe, 0x17, 0x01, + 0x13, 0x03, 0x69, 0x05, 0x78, 0x07, 0x6b, 0x0a, 0xf8, 0x0d, 0xed, 0x10, + 0xd4, 0x12, 0x41, 0x13, 0xc2, 0x12, 0x74, 0x11, 0x86, 0x0f, 0x96, 0x0c, + 0xf6, 0x08, 0xfc, 0x04, 0xa4, 0x01, 0x08, 0xfe, 0xc9, 0xfa, 0xfe, 0xf7, + 0x09, 0xf6, 0x53, 0xf5, 0x1f, 0xf6, 0xb6, 0xf7, 0xa6, 0xf8, 0xd6, 0xf9, + 0x61, 0xfb, 0x19, 0xfd, 0xa6, 0x00, 0x28, 0x03, 0x75, 0x03, 0x67, 0x03, + 0x09, 0x04, 0x05, 0x04, 0xb6, 0x04, 0x3f, 0x05, 0x1b, 0x04, 0x5a, 0x04, + 0xc9, 0x03, 0x51, 0x04, 0x87, 0x04, 0x04, 0x06, 0x6b, 0x08, 0x80, 0x08, + 0xdb, 0x08, 0x06, 0x09, 0xd7, 0x08, 0x59, 0x09, 0x6e, 0x09, 0xf6, 0x07, + 0x03, 0x05, 0xf7, 0x01, 0x92, 0xff, 0x04, 0xfd, 0x40, 0xfb, 0x9f, 0xf9, + 0x03, 0xf7, 0x25, 0xf5, 0x40, 0xf4, 0x71, 0xf4, 0xf5, 0xf5, 0x5d, 0xf8, + 0x91, 0xf9, 0xf9, 0xfa, 0xe8, 0xfc, 0xea, 0xfe, 0x6b, 0x00, 0x1c, 0x02, + 0x62, 0x03, 0xad, 0x02, 0x50, 0x01, 0x1d, 0xff, 0xf7, 0xfc, 0x4f, 0xfb, + 0x11, 0xfa, 0xc4, 0xf9, 0xed, 0xf6, 0x50, 0xf3, 0x94, 0xf2, 0xee, 0xf0, + 0x8f, 0xf2, 0x7a, 0xf3, 0xfc, 0xf3, 0xde, 0xf1, 0x05, 0xf1, 0x7a, 0xf0, + 0xc2, 0xef, 0x89, 0xf0, 0xfc, 0xee, 0x6f, 0xec, 0x9b, 0xeb, 0xc4, 0xed, + 0x09, 0xf1, 0xb9, 0xf4, 0x8f, 0xf6, 0xc6, 0xf9, 0xe0, 0xff, 0xfc, 0x06, + 0x99, 0x0d, 0x9e, 0x11, 0xfd, 0x12, 0x01, 0x16, 0x22, 0x18, 0x2a, 0x18, + 0xd6, 0x16, 0x44, 0x14, 0x47, 0x0f, 0x05, 0x0a, 0x08, 0x04, 0xc9, 0xfe, + 0x57, 0xfb, 0x11, 0xf9, 0x91, 0xf6, 0x05, 0xf3, 0x1c, 0xf1, 0x97, 0xf1, + 0x18, 0xf5, 0x33, 0xf9, 0xc0, 0xfa, 0x21, 0xfc, 0xd3, 0xfe, 0x83, 0x01, + 0xa0, 0x04, 0xcc, 0x05, 0x48, 0x04, 0x21, 0x04, 0x74, 0x03, 0x93, 0x02, + 0x31, 0x01, 0x0f, 0xff, 0x7a, 0xfe, 0xb0, 0xfd, 0x4a, 0xfe, 0x29, 0x00, + 0x53, 0x01, 0xfa, 0x03, 0xaf, 0x07, 0x56, 0x0b, 0xfe, 0x0d, 0x8f, 0x10, + 0xd3, 0x11, 0x08, 0x13, 0xba, 0x14, 0x48, 0x13, 0xd7, 0x0f, 0xd9, 0x0c, + 0x67, 0x09, 0xc0, 0x06, 0x32, 0x03, 0xbd, 0xfd, 0x12, 0xf9, 0x9a, 0xf6, + 0x93, 0xf5, 0xc7, 0xf5, 0xba, 0xf5, 0x80, 0xf4, 0x0d, 0xf5, 0xc9, 0xf7, + 0x9c, 0xfb, 0xb9, 0xff, 0x1b, 0x01, 0xbc, 0x01, 0x03, 0x04, 0x33, 0x06, + 0x05, 0x08, 0xce, 0x08, 0x25, 0x08, 0x89, 0x07, 0x17, 0x07, 0xd3, 0x05, + 0x89, 0x05, 0xfd, 0x05, 0x69, 0x06, 0x5b, 0x06, 0x6d, 0x05, 0x31, 0x05, + 0x85, 0x06, 0x39, 0x08, 0x06, 0x09, 0x14, 0x08, 0x94, 0x06, 0x34, 0x05, + 0x77, 0x05, 0x07, 0x05, 0x3e, 0x02, 0x08, 0xff, 0x37, 0xfc, 0xd2, 0xfa, + 0xe1, 0xf9, 0x7f, 0xf8, 0xf3, 0xf6, 0x20, 0xf6, 0xcf, 0xf6, 0x5e, 0xf8, + 0x38, 0xf9, 0xec, 0xfa, 0x91, 0xfd, 0x7d, 0xff, 0xef, 0x00, 0xf4, 0x01, + 0xcc, 0x02, 0xe3, 0x03, 0xe6, 0x03, 0xe5, 0x02, 0xd0, 0x00, 0xf2, 0xfd, + 0xb0, 0xfc, 0x70, 0xfa, 0xb2, 0xf8, 0x2e, 0xf6, 0xd3, 0xf3, 0x45, 0xf2, + 0x2b, 0xf1, 0xd6, 0xef, 0x33, 0xf0, 0x9b, 0xef, 0xfa, 0xee, 0x51, 0xef, + 0x37, 0xee, 0x89, 0xec, 0x95, 0xea, 0xaa, 0xea, 0x7c, 0xec, 0x3c, 0xf0, + 0x6e, 0xf4, 0x95, 0xf4, 0xd4, 0xf4, 0x06, 0xfb, 0xe2, 0x02, 0x70, 0x0a, + 0xa7, 0x0f, 0x4b, 0x10, 0x39, 0x11, 0x3c, 0x15, 0x78, 0x18, 0x31, 0x18, + 0xdb, 0x15, 0xe5, 0x11, 0xa8, 0x0d, 0xe1, 0x08, 0xf3, 0x02, 0x56, 0xfe, + 0xf6, 0xfa, 0x82, 0xf8, 0x0f, 0xf5, 0x93, 0xf0, 0x20, 0xef, 0xbc, 0xf1, + 0x31, 0xf5, 0x08, 0xf7, 0xdb, 0xf7, 0x88, 0xf9, 0xcc, 0xfd, 0x1b, 0x02, + 0xa9, 0x03, 0x02, 0x03, 0x8d, 0x02, 0xb4, 0x03, 0x91, 0x04, 0x03, 0x03, + 0x6c, 0xff, 0xcf, 0xfc, 0x5d, 0xfc, 0xff, 0xfd, 0x7b, 0xfe, 0x93, 0xfe, + 0x61, 0xff, 0x94, 0x01, 0x01, 0x05, 0xa4, 0x09, 0x81, 0x0d, 0x80, 0x10, + 0x3f, 0x13, 0x2e, 0x14, 0x46, 0x14, 0xa6, 0x14, 0x4d, 0x14, 0xa3, 0x12, + 0xda, 0x0e, 0x7e, 0x09, 0x97, 0x04, 0x32, 0x00, 0x79, 0xfd, 0x60, 0xfa, + 0x59, 0xf6, 0x7e, 0xf3, 0xf7, 0xf1, 0xb1, 0xf2, 0x5d, 0xf4, 0x10, 0xf6, + 0xe9, 0xf7, 0xc2, 0xfa, 0xea, 0xfd, 0xb9, 0x00, 0xb6, 0x03, 0xf0, 0x05, + 0x8f, 0x07, 0xbd, 0x09, 0xd8, 0x09, 0x4a, 0x09, 0x29, 0x09, 0x15, 0x08, + 0x11, 0x08, 0x1f, 0x08, 0x24, 0x07, 0xbd, 0x05, 0x1b, 0x05, 0x8c, 0x05, + 0x9b, 0x06, 0x74, 0x07, 0xfa, 0x07, 0xc5, 0x06, 0xfd, 0x05, 0x13, 0x07, + 0x7f, 0x06, 0x6e, 0x05, 0x01, 0x04, 0xc8, 0x00, 0xe3, 0xfe, 0x83, 0xfd, + 0x81, 0xfb, 0x7f, 0xf9, 0x81, 0xf8, 0x55, 0xf7, 0x4b, 0xf7, 0xc5, 0xf7, + 0x89, 0xf8, 0x27, 0xfa, 0xb4, 0xfc, 0xc5, 0xfe, 0xab, 0x00, 0x52, 0x02, + 0x45, 0x03, 0xf1, 0x04, 0x30, 0x06, 0x21, 0x05, 0xca, 0x03, 0xfc, 0x01, + 0x7a, 0xff, 0xf5, 0xfd, 0xb8, 0xfa, 0x1a, 0xf8, 0x80, 0xf5, 0x82, 0xf2, + 0x00, 0xf1, 0xf7, 0xee, 0x92, 0xed, 0x8a, 0xed, 0x94, 0xec, 0xcc, 0xeb, + 0x90, 0xec, 0x0d, 0xeb, 0x6a, 0xea, 0x52, 0xea, 0x22, 0xea, 0xd7, 0xed, + 0xd7, 0xf1, 0x20, 0xf4, 0x7e, 0xf5, 0xb9, 0xf8, 0x94, 0xfd, 0x36, 0x05, + 0xbb, 0x0b, 0xb8, 0x0e, 0x09, 0x10, 0x33, 0x12, 0x4d, 0x14, 0x12, 0x16, + 0x69, 0x16, 0x72, 0x14, 0x6c, 0x10, 0x64, 0x0b, 0x4a, 0x06, 0x3d, 0x02, + 0xdb, 0xff, 0x97, 0xfc, 0x2c, 0xf8, 0x56, 0xf3, 0x6e, 0xf0, 0x58, 0xf1, + 0xfe, 0xf3, 0x5d, 0xf5, 0x8e, 0xf5, 0x59, 0xf6, 0x18, 0xf9, 0xd4, 0xfc, + 0x26, 0x00, 0x84, 0x01, 0xe7, 0x00, 0x5e, 0x01, 0xd5, 0x01, 0x7c, 0x01, + 0x4c, 0x01, 0x2f, 0x00, 0xe9, 0xfd, 0xba, 0xfc, 0x57, 0xfc, 0xf9, 0xfc, + 0xb7, 0xff, 0x8e, 0x01, 0x22, 0x02, 0x2d, 0x04, 0x0e, 0x08, 0xae, 0x0c, + 0x6b, 0x11, 0x13, 0x13, 0x78, 0x13, 0x53, 0x14, 0x16, 0x15, 0xa1, 0x15, + 0x54, 0x14, 0xcf, 0x10, 0x95, 0x0c, 0x2a, 0x08, 0xe8, 0x03, 0xc9, 0x00, + 0x44, 0xfd, 0xb9, 0xf9, 0x5b, 0xf6, 0xa8, 0xf3, 0x0b, 0xf3, 0xea, 0xf3, + 0x75, 0xf5, 0xf1, 0xf6, 0x8e, 0xf8, 0xe8, 0xfa, 0xe6, 0xfd, 0xdc, 0x00, + 0xea, 0x03, 0x48, 0x06, 0xee, 0x07, 0xf8, 0x08, 0x33, 0x09, 0x80, 0x09, + 0x1f, 0x0a, 0xfd, 0x09, 0x16, 0x09, 0x15, 0x08, 0x43, 0x07, 0x86, 0x06, + 0x7c, 0x06, 0x2a, 0x06, 0xf4, 0x05, 0x46, 0x06, 0xc0, 0x05, 0x46, 0x05, + 0x47, 0x05, 0xcc, 0x04, 0x98, 0x04, 0x77, 0x03, 0xa3, 0x01, 0x7e, 0x00, + 0x1a, 0xff, 0x8b, 0xfd, 0x1f, 0xfc, 0xe3, 0xfa, 0x03, 0xfa, 0xcf, 0xf9, + 0x94, 0xf9, 0xb7, 0xf9, 0xd4, 0xfa, 0x73, 0xfc, 0xc0, 0xfd, 0x85, 0xff, + 0xeb, 0x00, 0x2b, 0x02, 0x9a, 0x03, 0x22, 0x04, 0xd8, 0x03, 0xd8, 0x02, + 0x08, 0x02, 0x9c, 0x00, 0x4e, 0xfd, 0xc7, 0xfb, 0xd2, 0xf8, 0xac, 0xf5, + 0x61, 0xf4, 0x38, 0xf1, 0x79, 0xee, 0x19, 0xee, 0x8b, 0xec, 0xf6, 0xec, + 0x91, 0xeb, 0xa6, 0xea, 0x34, 0xeb, 0xdc, 0xe9, 0xca, 0xea, 0xb3, 0xeb, + 0xe1, 0xec, 0x1a, 0xf0, 0xd8, 0xf3, 0x66, 0xf5, 0xdb, 0xf7, 0xdb, 0xfb, + 0xf7, 0x01, 0xd7, 0x08, 0x7f, 0x0c, 0xd4, 0x0c, 0x13, 0x0e, 0xc7, 0x11, + 0x47, 0x15, 0x51, 0x16, 0x92, 0x13, 0x4d, 0x0f, 0xc7, 0x0c, 0x00, 0x0a, + 0x02, 0x07, 0xf9, 0x02, 0x9f, 0xfe, 0xc2, 0xfa, 0x28, 0xf7, 0xf9, 0xf3, + 0x1e, 0xf2, 0x92, 0xf2, 0x18, 0xf4, 0xb8, 0xf4, 0x6c, 0xf4, 0x08, 0xf5, + 0x83, 0xf7, 0xbc, 0xfb, 0x53, 0xff, 0x8c, 0xff, 0x0f, 0xff, 0x9f, 0xff, + 0x8c, 0x00, 0xdb, 0x01, 0x03, 0x02, 0xcd, 0x00, 0xd3, 0xff, 0xfd, 0xfe, + 0xba, 0xfe, 0x4e, 0xff, 0x48, 0x01, 0x7a, 0x03, 0xe1, 0x04, 0xbc, 0x05, + 0x79, 0x07, 0xb4, 0x0a, 0xe3, 0x0e, 0xdd, 0x11, 0xa3, 0x12, 0xc6, 0x12, + 0x16, 0x12, 0x66, 0x12, 0xd7, 0x12, 0xd5, 0x10, 0xce, 0x0d, 0x3a, 0x0a, + 0x7c, 0x05, 0x61, 0x02, 0x8e, 0xff, 0x49, 0xfc, 0xec, 0xf9, 0x3a, 0xf7, + 0x58, 0xf5, 0x7a, 0xf4, 0xeb, 0xf4, 0xc8, 0xf6, 0x9d, 0xf8, 0x8e, 0xfa, + 0x8a, 0xfc, 0xe9, 0xfe, 0xd4, 0x01, 0x9e, 0x04, 0x27, 0x07, 0xa4, 0x08, + 0xab, 0x09, 0x67, 0x0a, 0x66, 0x0a, 0x92, 0x0a, 0x54, 0x0a, 0xa3, 0x09, + 0xad, 0x08, 0x48, 0x07, 0x8c, 0x06, 0xcf, 0x05, 0xf9, 0x04, 0xbc, 0x04, + 0x27, 0x04, 0x48, 0x03, 0x9a, 0x02, 0x8b, 0x02, 0x4c, 0x02, 0x86, 0x01, + 0xb0, 0x00, 0x8d, 0xff, 0xd3, 0xfe, 0x6a, 0xfe, 0x99, 0xfd, 0x86, 0xfc, + 0x2b, 0xfc, 0xdc, 0xfb, 0x93, 0xfb, 0x18, 0xfc, 0xa5, 0xfc, 0x65, 0xfd, + 0x37, 0xfe, 0x20, 0xff, 0x2e, 0x00, 0x3e, 0x01, 0xe6, 0x01, 0xfd, 0x01, + 0x74, 0x01, 0xff, 0x00, 0x88, 0x00, 0xf7, 0xfe, 0x46, 0xfd, 0xa5, 0xfb, + 0x61, 0xf8, 0x96, 0xf6, 0xcd, 0xf5, 0x9a, 0xf2, 0x06, 0xf1, 0x75, 0xef, + 0xe5, 0xec, 0xbb, 0xec, 0xfd, 0xec, 0xd8, 0xeb, 0xca, 0xea, 0xf0, 0xe9, + 0xa9, 0xe8, 0xc7, 0xe9, 0xe6, 0xeb, 0xc4, 0xef, 0x38, 0xf2, 0x7a, 0xf3, + 0x39, 0xf6, 0xd5, 0xfa, 0x4a, 0x00, 0xa2, 0x06, 0xcf, 0x0a, 0x7a, 0x0c, + 0x92, 0x0f, 0x1a, 0x12, 0xda, 0x13, 0x2c, 0x15, 0x90, 0x14, 0x0d, 0x12, + 0x64, 0x0f, 0x39, 0x0b, 0xe0, 0x07, 0x50, 0x04, 0x92, 0x00, 0x1b, 0xfd, + 0x11, 0xf9, 0x83, 0xf5, 0x73, 0xf3, 0x1e, 0xf3, 0x65, 0xf3, 0xdb, 0xf3, + 0x22, 0xf4, 0x47, 0xf5, 0x6f, 0xf7, 0x05, 0xfa, 0x76, 0xfb, 0x7e, 0xfd, + 0x37, 0xff, 0x00, 0x00, 0xe8, 0x00, 0xa7, 0x00, 0x57, 0x00, 0x9f, 0x01, + 0xa2, 0x01, 0x59, 0x00, 0x58, 0xff, 0x7f, 0xff, 0x15, 0x01, 0x92, 0x02, + 0xd0, 0x03, 0xd2, 0x04, 0x1d, 0x06, 0xf6, 0x08, 0x6e, 0x0c, 0x04, 0x0f, + 0x80, 0x10, 0x94, 0x11, 0x60, 0x12, 0x55, 0x13, 0xe9, 0x13, 0xcc, 0x12, + 0xa7, 0x10, 0xe1, 0x0d, 0x0d, 0x0b, 0x0e, 0x08, 0xd8, 0x04, 0x4a, 0x01, + 0xcc, 0xfd, 0xf3, 0xfa, 0x87, 0xf8, 0xb2, 0xf6, 0x98, 0xf5, 0xbb, 0xf5, + 0xaf, 0xf6, 0x35, 0xf7, 0xb4, 0xf8, 0xf6, 0xfa, 0xd5, 0xfd, 0x64, 0x00, + 0xa6, 0x02, 0x68, 0x04, 0x78, 0x06, 0xd1, 0x08, 0xbf, 0x09, 0xd4, 0x09, + 0x0d, 0x0a, 0x4e, 0x0a, 0x24, 0x0a, 0x2e, 0x09, 0xdf, 0x07, 0xae, 0x06, + 0xd5, 0x05, 0x43, 0x05, 0x1e, 0x04, 0x5f, 0x03, 0x82, 0x02, 0x6b, 0x01, + 0xbc, 0x00, 0x25, 0x00, 0x40, 0x00, 0x07, 0x00, 0x12, 0xff, 0xdf, 0xfd, + 0x41, 0xfd, 0x59, 0xfd, 0x59, 0xfd, 0xdc, 0xfd, 0x2f, 0xfd, 0x31, 0xfc, + 0xba, 0xfc, 0x5c, 0xfd, 0x63, 0xfe, 0x76, 0xff, 0xe3, 0xff, 0xec, 0xff, + 0xf7, 0xff, 0xbd, 0x00, 0x16, 0x01, 0x16, 0x01, 0x5e, 0x00, 0x35, 0xff, + 0x26, 0xfd, 0xa8, 0xfb, 0x53, 0xfa, 0xab, 0xf7, 0x13, 0xf6, 0xb5, 0xf3, + 0xe0, 0xf0, 0x81, 0xef, 0x50, 0xee, 0xb0, 0xeb, 0x38, 0xec, 0xe0, 0xea, + 0x89, 0xe9, 0x8c, 0xea, 0xf5, 0xe8, 0x5b, 0xe9, 0x8d, 0xeb, 0x2a, 0xee, + 0x19, 0xf2, 0xab, 0xf5, 0x63, 0xf7, 0xd4, 0xfa, 0xef, 0xff, 0x41, 0x05, + 0xac, 0x0a, 0xbe, 0x0d, 0x9c, 0x0e, 0xc6, 0x10, 0x1c, 0x13, 0x80, 0x14, + 0x65, 0x14, 0x18, 0x12, 0x4e, 0x10, 0x23, 0x0e, 0xf7, 0x09, 0xe5, 0x05, + 0xdd, 0x01, 0x99, 0xff, 0xdc, 0xfd, 0x62, 0xfa, 0x53, 0xf6, 0xed, 0xf3, + 0x71, 0xf4, 0xe5, 0xf4, 0x0d, 0xf6, 0x70, 0xf6, 0x23, 0xf6, 0x86, 0xf7, + 0x0c, 0xfa, 0xed, 0xfb, 0x7e, 0xfd, 0xbd, 0xfe, 0xf0, 0xfe, 0x76, 0xff, + 0xe9, 0xff, 0xb4, 0xff, 0xd9, 0xff, 0x1e, 0x00, 0x40, 0x00, 0x13, 0x00, + 0xe3, 0xff, 0x8c, 0x00, 0x39, 0x02, 0xf8, 0x03, 0x04, 0x06, 0x0e, 0x08, + 0xef, 0x09, 0xae, 0x0c, 0x0f, 0x0f, 0x65, 0x10, 0x43, 0x12, 0xb6, 0x13, + 0x0f, 0x14, 0x3d, 0x14, 0x93, 0x12, 0xec, 0x0f, 0xf2, 0x0d, 0x9c, 0x0b, + 0xff, 0x08, 0x92, 0x05, 0x0e, 0x01, 0x26, 0xfd, 0x88, 0xfa, 0xb7, 0xf8, + 0x22, 0xf7, 0xe7, 0xf5, 0x02, 0xf5, 0x25, 0xf5, 0xbc, 0xf6, 0xee, 0xf7, + 0xe4, 0xf9, 0xbe, 0xfc, 0x98, 0xfe, 0x39, 0x01, 0x4e, 0x03, 0xb0, 0x04, + 0x69, 0x06, 0xe5, 0x07, 0x9e, 0x08, 0xd8, 0x08, 0x95, 0x08, 0x31, 0x08, + 0x6d, 0x07, 0x61, 0x06, 0x96, 0x05, 0xc7, 0x04, 0x8f, 0x04, 0xba, 0x03, + 0x33, 0x02, 0xd2, 0x00, 0x18, 0x01, 0x8a, 0x01, 0x2f, 0x01, 0xad, 0x00, + 0x2a, 0x00, 0x9b, 0xff, 0xe7, 0xff, 0xa2, 0xff, 0x3b, 0xff, 0x9a, 0xff, + 0x5a, 0xff, 0xce, 0xfe, 0x60, 0xfe, 0x5d, 0xfe, 0x42, 0xff, 0xee, 0xff, + 0x01, 0x00, 0xef, 0xff, 0x29, 0x00, 0x48, 0x00, 0x27, 0x01, 0x45, 0x01, + 0x82, 0x00, 0x02, 0x00, 0x0a, 0xff, 0x9c, 0xfd, 0x07, 0xfd, 0xb6, 0xfb, + 0xc9, 0xf8, 0x73, 0xf7, 0x44, 0xf5, 0x4d, 0xf3, 0x3a, 0xf2, 0xa7, 0xf0, + 0xb2, 0xee, 0xa9, 0xed, 0x1f, 0xec, 0x83, 0xeb, 0xc7, 0xeb, 0x0b, 0xec, + 0x14, 0xeb, 0x76, 0xea, 0xad, 0xeb, 0x28, 0xef, 0x24, 0xf3, 0x94, 0xf6, + 0xd3, 0xf7, 0x4a, 0xfa, 0x1e, 0xff, 0xec, 0x03, 0x04, 0x0a, 0x5c, 0x0d, + 0x62, 0x0e, 0x54, 0x10, 0xbc, 0x11, 0xf7, 0x12, 0x39, 0x14, 0xab, 0x13, + 0x53, 0x11, 0x75, 0x0d, 0xd6, 0x09, 0xe2, 0x06, 0xfe, 0x04, 0x4c, 0x02, + 0x11, 0xfe, 0xe8, 0xf9, 0xfc, 0xf6, 0x26, 0xf6, 0x0e, 0xf6, 0xc9, 0xf5, + 0x94, 0xf4, 0xa3, 0xf4, 0xc7, 0xf5, 0xdc, 0xf7, 0xbf, 0xf9, 0x74, 0xfa, + 0x33, 0xfb, 0xb2, 0xfc, 0x61, 0xfe, 0xdf, 0xfe, 0xe2, 0xfe, 0x0d, 0xff, + 0x16, 0xff, 0x81, 0xff, 0xa8, 0xff, 0x60, 0xff, 0xa8, 0xff, 0x8b, 0x00, + 0x0d, 0x02, 0xfb, 0x02, 0xd0, 0x04, 0xdd, 0x06, 0x53, 0x08, 0x07, 0x0b, + 0x99, 0x0d, 0x10, 0x0f, 0x09, 0x11, 0xe9, 0x11, 0x9c, 0x12, 0x2d, 0x13, + 0xd7, 0x12, 0xc0, 0x11, 0x0a, 0x10, 0x55, 0x0d, 0x8b, 0x0a, 0xda, 0x07, + 0xde, 0x04, 0xec, 0x01, 0xe8, 0xfe, 0xbf, 0xfb, 0x38, 0xf9, 0x9d, 0xf7, + 0xd4, 0xf6, 0x2f, 0xf6, 0x9f, 0xf6, 0x20, 0xf7, 0xbd, 0xf7, 0x3d, 0xf9, + 0xd0, 0xfa, 0x35, 0xfd, 0xbe, 0xff, 0x65, 0x01, 0xa8, 0x02, 0xe9, 0x03, + 0x0f, 0x05, 0x19, 0x06, 0xbe, 0x06, 0xe6, 0x06, 0xb6, 0x06, 0x46, 0x06, + 0x4c, 0x05, 0x52, 0x04, 0x11, 0x04, 0x77, 0x03, 0xe4, 0x02, 0x4f, 0x02, + 0x67, 0x01, 0xae, 0x00, 0x19, 0x00, 0x05, 0x00, 0xbe, 0x00, 0xd0, 0x00, + 0x56, 0x00, 0x08, 0x00, 0x5c, 0xff, 0x74, 0xff, 0xd5, 0x00, 0x3c, 0x01, + 0xf2, 0x00, 0xc1, 0x00, 0x2d, 0x00, 0x83, 0x00, 0x5b, 0x01, 0x13, 0x02, + 0x0b, 0x02, 0x98, 0x01, 0xac, 0x00, 0x4c, 0x00, 0x92, 0xff, 0xc8, 0xfe, + 0xbd, 0xfe, 0x50, 0xfd, 0x4c, 0xfb, 0xf8, 0xf8, 0x59, 0xf7, 0x71, 0xf6, + 0x8f, 0xf4, 0xcc, 0xf3, 0xce, 0xf2, 0xd7, 0xef, 0x97, 0xee, 0xae, 0xee, + 0x1a, 0xee, 0xaa, 0xed, 0xf5, 0xec, 0xc8, 0xeb, 0x67, 0xeb, 0xc5, 0xec, + 0x92, 0xee, 0xea, 0xef, 0x5f, 0xf1, 0x19, 0xf4, 0xea, 0xf7, 0x72, 0xfa, + 0x24, 0xff, 0x89, 0x03, 0x75, 0x05, 0xf4, 0x09, 0x3b, 0x0e, 0x7c, 0x0f, + 0x8f, 0x11, 0x44, 0x13, 0x5a, 0x12, 0x49, 0x12, 0x22, 0x12, 0x5d, 0x0f, + 0x45, 0x0c, 0xc5, 0x08, 0x13, 0x05, 0x54, 0x03, 0x91, 0x00, 0xa7, 0xfc, + 0x15, 0xf9, 0xb5, 0xf6, 0x01, 0xf6, 0x35, 0xf6, 0x72, 0xf5, 0x32, 0xf5, + 0x7c, 0xf5, 0x39, 0xf6, 0xbc, 0xf7, 0x78, 0xf9, 0xe8, 0xfa, 0x85, 0xfc, + 0x4c, 0xfd, 0xe7, 0xfc, 0x70, 0xfd, 0x07, 0xff, 0x01, 0x00, 0x05, 0x00, + 0x0e, 0xff, 0x21, 0xfe, 0x65, 0xff, 0xf0, 0x00, 0x9e, 0x01, 0x10, 0x02, + 0xfb, 0x02, 0x89, 0x04, 0xf4, 0x06, 0x3c, 0x09, 0xf5, 0x0a, 0x14, 0x0d, + 0xce, 0x0e, 0x5b, 0x10, 0x2d, 0x12, 0xf6, 0x12, 0xd2, 0x12, 0x45, 0x12, + 0x74, 0x11, 0xd3, 0x10, 0xd6, 0x0e, 0xa2, 0x0b, 0x3d, 0x08, 0xd7, 0x04, + 0xa8, 0x02, 0x52, 0x00, 0x0b, 0xfd, 0xed, 0xf9, 0xe3, 0xf7, 0x8b, 0xf6, + 0xd9, 0xf5, 0xf1, 0xf5, 0x5e, 0xf6, 0x14, 0xf7, 0xf9, 0xf7, 0x19, 0xf9, + 0xd7, 0xfa, 0x3b, 0xfd, 0xff, 0xff, 0xa4, 0x01, 0x56, 0x02, 0x77, 0x03, + 0xae, 0x04, 0x8f, 0x05, 0x57, 0x06, 0x52, 0x06, 0xa7, 0x05, 0x32, 0x05, + 0x2c, 0x04, 0x15, 0x03, 0x1f, 0x03, 0xce, 0x02, 0xfb, 0x01, 0x21, 0x01, + 0xfb, 0xff, 0x15, 0x00, 0x68, 0x00, 0xf0, 0x00, 0x10, 0x01, 0x9e, 0x00, + 0xe5, 0x00, 0x6b, 0x01, 0xf3, 0x01, 0x47, 0x02, 0xa8, 0x02, 0xa7, 0x02, + 0x12, 0x03, 0xd6, 0x02, 0x5c, 0x02, 0x7b, 0x02, 0x41, 0x02, 0x1d, 0x02, + 0xa5, 0x01, 0x6a, 0x00, 0x04, 0xff, 0x14, 0xfe, 0x1d, 0xfd, 0x09, 0xfc, + 0x28, 0xfb, 0x3b, 0xf9, 0x78, 0xf7, 0x41, 0xf6, 0x4f, 0xf4, 0xb2, 0xf3, + 0x0c, 0xf3, 0x94, 0xf1, 0x4e, 0xf0, 0xb2, 0xee, 0x01, 0xee, 0x12, 0xee, + 0x04, 0xee, 0x6b, 0xed, 0x2a, 0xec, 0xf3, 0xea, 0x45, 0xec, 0x45, 0xef, + 0x46, 0xf2, 0x4c, 0xf4, 0x40, 0xf5, 0x17, 0xf7, 0x8e, 0xfb, 0x6a, 0x01, + 0x9c, 0x06, 0xbf, 0x09, 0x23, 0x0b, 0x26, 0x0d, 0x27, 0x10, 0x49, 0x13, + 0xfb, 0x14, 0xc6, 0x14, 0x63, 0x13, 0xec, 0x10, 0x33, 0x0e, 0x5b, 0x0b, + 0x41, 0x09, 0x8d, 0x07, 0x27, 0x04, 0x54, 0xff, 0x97, 0xfa, 0x8c, 0xf8, + 0x5e, 0xf8, 0xbf, 0xf7, 0xae, 0xf6, 0x4b, 0xf5, 0x73, 0xf4, 0xb7, 0xf5, + 0x5d, 0xf7, 0x7c, 0xf8, 0x83, 0xf9, 0xee, 0xfa, 0x13, 0xfc, 0x8b, 0xfc, + 0x53, 0xfd, 0x9a, 0xfd, 0x0b, 0xfe, 0x00, 0xff, 0x75, 0xff, 0x20, 0xff, + 0x96, 0xfe, 0x3a, 0xfe, 0x05, 0xff, 0xcf, 0x00, 0xdb, 0x02, 0x03, 0x04, + 0x34, 0x04, 0x2e, 0x05, 0xdc, 0x07, 0xfe, 0x0b, 0x90, 0x0e, 0xe9, 0x0f, + 0x71, 0x10, 0x29, 0x11, 0x25, 0x13, 0xdc, 0x14, 0x96, 0x14, 0x77, 0x13, + 0x9c, 0x11, 0xdf, 0x0e, 0xa6, 0x0c, 0x47, 0x0a, 0x97, 0x07, 0xc8, 0x04, + 0xf4, 0x00, 0x26, 0xfd, 0x45, 0xfa, 0x6e, 0xf8, 0x68, 0xf7, 0x9a, 0xf6, + 0x6f, 0xf5, 0x7e, 0xf4, 0xd1, 0xf4, 0x18, 0xf6, 0x41, 0xf8, 0x08, 0xfa, + 0x9e, 0xfb, 0x08, 0xfd, 0xad, 0xfe, 0xc3, 0x00, 0x6b, 0x02, 0xf6, 0x03, + 0xdd, 0x04, 0xf7, 0x04, 0xc0, 0x05, 0xdc, 0x05, 0x08, 0x05, 0xff, 0x04, + 0x58, 0x04, 0xbc, 0x03, 0x23, 0x03, 0x1d, 0x02, 0xef, 0x00, 0xae, 0x00, + 0xcb, 0x00, 0x54, 0x00, 0x42, 0x00, 0x58, 0x00, 0x7f, 0x00, 0xcb, 0x00, + 0x5e, 0x01, 0xd6, 0x01, 0xb4, 0x02, 0x96, 0x03, 0x79, 0x03, 0x99, 0x03, + 0x2f, 0x04, 0x38, 0x04, 0x2e, 0x04, 0x1f, 0x04, 0xb9, 0x02, 0xde, 0x01, + 0x19, 0x01, 0x33, 0xff, 0xd1, 0xfd, 0x94, 0xfc, 0x2b, 0xfa, 0xd4, 0xf8, + 0x36, 0xf7, 0x88, 0xf4, 0x4d, 0xf3, 0x9e, 0xf1, 0x76, 0xf0, 0xee, 0xef, + 0x76, 0xee, 0xb3, 0xed, 0x10, 0xed, 0x1a, 0xec, 0x6a, 0xec, 0x42, 0xec, + 0xf0, 0xeb, 0x74, 0xec, 0x28, 0xed, 0xc9, 0xee, 0xe9, 0xf2, 0xc9, 0xf4, + 0xa9, 0xf5, 0x7d, 0xf8, 0xa6, 0xfc, 0x51, 0x02, 0x74, 0x07, 0xce, 0x08, + 0x22, 0x0a, 0xd7, 0x0c, 0xf4, 0x10, 0xbd, 0x14, 0x0a, 0x15, 0x61, 0x13, + 0x6f, 0x11, 0x78, 0x10, 0x40, 0x10, 0x0d, 0x0f, 0xc9, 0x0b, 0xa4, 0x07, + 0x9c, 0x03, 0x85, 0x00, 0xfb, 0xfe, 0x84, 0xfd, 0x91, 0xfb, 0xb1, 0xf9, + 0x42, 0xf7, 0xe7, 0xf5, 0xda, 0xf6, 0x61, 0xf8, 0x06, 0xf9, 0xd1, 0xf8, + 0x49, 0xf8, 0xa4, 0xf8, 0x2d, 0xfa, 0x90, 0xfb, 0x41, 0xfc, 0x2c, 0xfc, + 0x84, 0xfb, 0x93, 0xfa, 0xd7, 0xfa, 0x5b, 0xfc, 0x4c, 0xfd, 0xf7, 0xfc, + 0x41, 0xfc, 0xab, 0xfc, 0xfd, 0xfe, 0xce, 0x01, 0x29, 0x03, 0x50, 0x04, + 0x8a, 0x06, 0x68, 0x09, 0x43, 0x0c, 0xb1, 0x0e, 0x08, 0x10, 0x72, 0x11, + 0x30, 0x13, 0x93, 0x14, 0xcc, 0x14, 0xaf, 0x13, 0x43, 0x12, 0x97, 0x10, + 0xfa, 0x0e, 0x11, 0x0d, 0xf0, 0x09, 0xb7, 0x06, 0x74, 0x03, 0x48, 0x00, + 0x85, 0xfd, 0xcc, 0xfb, 0x7f, 0xfa, 0x31, 0xf9, 0x3c, 0xf7, 0x99, 0xf5, + 0xc3, 0xf5, 0x67, 0xf7, 0xf1, 0xf8, 0xd6, 0xf9, 0xd4, 0xf9, 0x5a, 0xfa, + 0x3b, 0xfc, 0x5f, 0xfe, 0x34, 0x00, 0x2b, 0x01, 0xfd, 0x00, 0x2c, 0x01, + 0xdd, 0x01, 0x89, 0x02, 0xf1, 0x02, 0xc9, 0x02, 0x34, 0x02, 0xc8, 0x01, + 0x50, 0x01, 0xe4, 0x00, 0x1d, 0x01, 0x55, 0x01, 0x49, 0x01, 0x02, 0x01, + 0xc1, 0x00, 0x75, 0x01, 0x15, 0x02, 0x79, 0x02, 0x43, 0x03, 0xb3, 0x03, + 0x05, 0x04, 0x86, 0x04, 0xde, 0x04, 0x16, 0x05, 0x14, 0x05, 0x60, 0x05, + 0x31, 0x05, 0x82, 0x04, 0x85, 0x03, 0x82, 0x02, 0x99, 0x01, 0x7d, 0x00, + 0x04, 0xff, 0x9f, 0xfd, 0x83, 0xfb, 0x92, 0xf9, 0x5f, 0xf8, 0x6c, 0xf6, + 0x92, 0xf4, 0x70, 0xf3, 0xb4, 0xf1, 0x30, 0xf0, 0x9e, 0xef, 0xd3, 0xee, + 0x49, 0xed, 0xfb, 0xec, 0x9d, 0xec, 0xd3, 0xeb, 0xc1, 0xeb, 0x7a, 0xeb, + 0x2a, 0xec, 0xab, 0xed, 0x97, 0xef, 0x0e, 0xf1, 0x5c, 0xf3, 0x0e, 0xf6, + 0x92, 0xf9, 0x4e, 0xfd, 0xc2, 0x00, 0xee, 0x04, 0xeb, 0x08, 0x4e, 0x0b, + 0x84, 0x0d, 0x11, 0x10, 0xab, 0x12, 0x18, 0x14, 0x21, 0x14, 0x9b, 0x12, + 0xdf, 0x10, 0xf6, 0x0f, 0x72, 0x0e, 0xe0, 0x0b, 0xfb, 0x08, 0xb1, 0x05, + 0x65, 0x02, 0x76, 0xff, 0x87, 0xfd, 0x9f, 0xfc, 0xbf, 0xfb, 0xc7, 0xf9, + 0x9f, 0xf7, 0x24, 0xf7, 0x11, 0xf8, 0x05, 0xfa, 0xc0, 0xfa, 0xbf, 0xf9, + 0x29, 0xf9, 0x28, 0xfa, 0x46, 0xfb, 0x55, 0xfc, 0xaf, 0xfc, 0x8f, 0xfb, + 0xd9, 0xfa, 0xa4, 0xfa, 0xc8, 0xfa, 0x0d, 0xfb, 0xc6, 0xfb, 0x22, 0xfc, + 0xee, 0xfb, 0x38, 0xfc, 0xad, 0xfd, 0x6a, 0x00, 0xf8, 0x02, 0x24, 0x05, + 0x78, 0x06, 0x63, 0x08, 0x55, 0x0b, 0x8d, 0x0e, 0x33, 0x11, 0x24, 0x12, + 0xda, 0x12, 0x6e, 0x13, 0xd5, 0x13, 0xa6, 0x13, 0xac, 0x12, 0x9d, 0x10, + 0x79, 0x0e, 0x62, 0x0c, 0x4c, 0x09, 0x3d, 0x06, 0xa1, 0x03, 0x4b, 0x01, + 0x1a, 0xff, 0xb1, 0xfc, 0x7d, 0xfa, 0x59, 0xf9, 0x84, 0xf8, 0x20, 0xf8, + 0x60, 0xf8, 0xde, 0xf8, 0x5b, 0xf9, 0xe5, 0xf9, 0xb7, 0xfa, 0x1a, 0xfc, + 0x81, 0xfd, 0x75, 0xfe, 0x26, 0xff, 0xa7, 0xff, 0x2d, 0x00, 0x8e, 0x00, + 0x6a, 0x00, 0x72, 0x00, 0xd4, 0x00, 0x5e, 0x00, 0x9f, 0xff, 0x47, 0xff, + 0xe0, 0xfe, 0x08, 0xff, 0x70, 0xff, 0x2e, 0xff, 0x40, 0xff, 0xc3, 0xff, + 0x32, 0x00, 0x28, 0x01, 0x49, 0x02, 0x2c, 0x03, 0x19, 0x04, 0xd9, 0x04, + 0x94, 0x05, 0x3c, 0x06, 0xb8, 0x06, 0x1f, 0x07, 0x41, 0x07, 0xdd, 0x06, + 0xe5, 0x05, 0x2d, 0x05, 0x13, 0x04, 0xc2, 0x02, 0xa7, 0x01, 0xbc, 0xff, + 0xbf, 0xfd, 0xa7, 0xfb, 0xb0, 0xf9, 0x49, 0xf8, 0x79, 0xf6, 0x91, 0xf4, + 0x21, 0xf3, 0x62, 0xf1, 0x17, 0xf0, 0x5c, 0xef, 0x6e, 0xee, 0x98, 0xed, + 0x22, 0xed, 0x77, 0xec, 0x47, 0xeb, 0x54, 0xeb, 0x7b, 0xeb, 0x43, 0xec, + 0xb5, 0xed, 0x10, 0xef, 0x01, 0xf1, 0xff, 0xf2, 0x07, 0xf5, 0xbd, 0xf8, + 0xcf, 0xfc, 0xf5, 0x00, 0x73, 0x04, 0x9d, 0x06, 0xfa, 0x08, 0xd8, 0x0c, + 0x29, 0x10, 0x3a, 0x12, 0xfa, 0x12, 0x99, 0x12, 0x18, 0x12, 0xe8, 0x11, + 0x02, 0x11, 0x5d, 0x0f, 0x0d, 0x0d, 0x22, 0x0a, 0x57, 0x07, 0x8f, 0x04, + 0x9e, 0x02, 0x41, 0x01, 0x0e, 0xff, 0xcc, 0xfc, 0x51, 0xfb, 0x6a, 0xfa, + 0xae, 0xfa, 0xdc, 0xfa, 0xd0, 0xfa, 0x2a, 0xfa, 0xb4, 0xf9, 0x4e, 0xfa, + 0x29, 0xfb, 0xbf, 0xfb, 0xc1, 0xfb, 0xbf, 0xfa, 0x02, 0xfa, 0xec, 0xf9, + 0x64, 0xfa, 0xb2, 0xfa, 0x4a, 0xfa, 0xa5, 0xf9, 0x50, 0xf9, 0x37, 0xfa, + 0xec, 0xfb, 0x69, 0xfd, 0x8b, 0xfe, 0xa3, 0xff, 0xd9, 0x01, 0x9d, 0x04, + 0x04, 0x07, 0xca, 0x09, 0xd1, 0x0b, 0xaa, 0x0d, 0x43, 0x10, 0x86, 0x11, + 0x2a, 0x12, 0x01, 0x13, 0x3f, 0x13, 0x84, 0x12, 0x83, 0x11, 0x09, 0x10, + 0xc1, 0x0d, 0xa9, 0x0b, 0x97, 0x09, 0xea, 0x06, 0x2e, 0x04, 0x99, 0x01, + 0xc8, 0xff, 0x11, 0xfe, 0x23, 0xfc, 0x8e, 0xfa, 0xc4, 0xf9, 0x8e, 0xf9, + 0xb7, 0xf9, 0xb1, 0xf9, 0x92, 0xf9, 0x65, 0xfa, 0x6e, 0xfb, 0x21, 0xfc, + 0xe1, 0xfc, 0xc5, 0xfd, 0x4b, 0xfe, 0x93, 0xfe, 0xb8, 0xfe, 0x1d, 0xff, + 0x55, 0xff, 0x08, 0xff, 0x80, 0xfe, 0x2c, 0xfe, 0x16, 0xfe, 0xdc, 0xfd, + 0x90, 0xfd, 0xa7, 0xfd, 0xbd, 0xfd, 0xff, 0xfd, 0x92, 0xfe, 0x2a, 0xff, + 0x2c, 0x00, 0x52, 0x01, 0x53, 0x02, 0x78, 0x03, 0xb3, 0x04, 0xef, 0x05, + 0xde, 0x06, 0xb6, 0x07, 0x39, 0x08, 0x77, 0x08, 0x8c, 0x08, 0x40, 0x08, + 0x8f, 0x07, 0x65, 0x06, 0xc5, 0x04, 0x2d, 0x03, 0x4b, 0x01, 0x75, 0xff, + 0x7a, 0xfd, 0x4b, 0xfb, 0x25, 0xf9, 0xa4, 0xf6, 0x38, 0xf4, 0x01, 0xf3, + 0xd3, 0xf1, 0xbc, 0xf0, 0x32, 0xef, 0xb8, 0xec, 0x21, 0xec, 0x38, 0xec, + 0xdf, 0xeb, 0x3a, 0xeb, 0x8c, 0xea, 0x66, 0xea, 0xdd, 0xeb, 0x82, 0xed, + 0x17, 0xef, 0xf4, 0xf0, 0x16, 0xf3, 0xdc, 0xf5, 0x1d, 0xf9, 0x6b, 0xfc, + 0x15, 0x00, 0x50, 0x04, 0x2a, 0x07, 0x4a, 0x09, 0xaf, 0x0b, 0x33, 0x0e, + 0x52, 0x11, 0x1b, 0x13, 0x83, 0x12, 0x83, 0x11, 0xca, 0x10, 0x7a, 0x10, + 0xe9, 0x0f, 0x12, 0x0e, 0x22, 0x0b, 0x63, 0x08, 0x70, 0x06, 0x6f, 0x04, + 0xba, 0x02, 0x37, 0x01, 0x74, 0xff, 0x2c, 0xfe, 0x32, 0xfd, 0x0f, 0xfc, + 0x8f, 0xfb, 0xb5, 0xfb, 0xba, 0xfb, 0x9d, 0xfb, 0x21, 0xfb, 0x5e, 0xfa, + 0x64, 0xfa, 0xd8, 0xfa, 0x77, 0xfa, 0xad, 0xf9, 0x44, 0xf9, 0xac, 0xf8, + 0xb1, 0xf8, 0xbd, 0xf8, 0x8d, 0xf8, 0xee, 0xf8, 0x55, 0xf9, 0x49, 0xfa, + 0xcc, 0xfb, 0x24, 0xfd, 0x6b, 0xfe, 0xbb, 0x00, 0xac, 0x03, 0xee, 0x05, + 0xe8, 0x07, 0x18, 0x0a, 0x50, 0x0c, 0xdc, 0x0e, 0xda, 0x10, 0x68, 0x11, + 0x60, 0x11, 0xc7, 0x12, 0x25, 0x13, 0x09, 0x12, 0x05, 0x10, 0xa7, 0x0e, + 0x86, 0x0d, 0xd2, 0x0b, 0x23, 0x09, 0x30, 0x06, 0x0e, 0x04, 0x41, 0x02, + 0x75, 0x00, 0x23, 0xfe, 0x92, 0xfc, 0xb8, 0xfb, 0xde, 0xfa, 0x11, 0xfa, + 0x88, 0xf9, 0xa5, 0xf9, 0x50, 0xfa, 0xae, 0xfa, 0x02, 0xfb, 0x76, 0xfb, + 0xec, 0xfb, 0x5d, 0xfc, 0x3b, 0xfd, 0xbc, 0xfd, 0xd1, 0xfd, 0x9e, 0xfd, + 0x69, 0xfd, 0x72, 0xfd, 0xae, 0xfd, 0x8d, 0xfd, 0x28, 0xfd, 0xf1, 0xfc, + 0x28, 0xfd, 0x76, 0xfd, 0x81, 0xfd, 0xec, 0xfd, 0xde, 0xfe, 0xfd, 0xff, + 0xc5, 0x00, 0xb3, 0x01, 0xe1, 0x02, 0x1d, 0x04, 0x75, 0x05, 0xda, 0x06, + 0xbb, 0x07, 0xff, 0x07, 0x90, 0x08, 0xe1, 0x08, 0xc9, 0x08, 0xce, 0x08, + 0xb7, 0x07, 0xee, 0x05, 0xb9, 0x04, 0x1e, 0x03, 0x2a, 0x01, 0x47, 0xff, + 0x63, 0xfd, 0xc0, 0xfa, 0x8b, 0xf8, 0x61, 0xf6, 0x2b, 0xf4, 0x0c, 0xf3, + 0x52, 0xf1, 0x97, 0xef, 0xec, 0xed, 0x48, 0xec, 0x49, 0xeb, 0xe4, 0xea, + 0x47, 0xea, 0xc6, 0xe9, 0x5c, 0xe9, 0xc8, 0xe9, 0x6f, 0xeb, 0xdf, 0xed, + 0xa0, 0xef, 0x00, 0xf1, 0xc8, 0xf3, 0x5a, 0xf7, 0x9e, 0xfb, 0x75, 0xff, + 0x48, 0x02, 0x92, 0x05, 0xf4, 0x08, 0x52, 0x0b, 0xfc, 0x0d, 0xb5, 0x10, + 0x5b, 0x12, 0x09, 0x13, 0x18, 0x12, 0xe3, 0x10, 0xe0, 0x10, 0xcd, 0x10, + 0x87, 0x0f, 0xb2, 0x0c, 0x98, 0x09, 0x73, 0x07, 0x6e, 0x06, 0x44, 0x05, + 0x49, 0x03, 0xf1, 0x00, 0xba, 0xff, 0x49, 0xff, 0x7c, 0xfe, 0xba, 0xfd, + 0x75, 0xfd, 0x2c, 0xfd, 0x96, 0xfc, 0x58, 0xfc, 0x08, 0xfc, 0xc1, 0xfb, + 0xc2, 0xfb, 0xa0, 0xfa, 0x4b, 0xf9, 0xe3, 0xf8, 0xfa, 0xf8, 0x07, 0xf9, + 0x19, 0xf8, 0xe8, 0xf6, 0x99, 0xf6, 0x3f, 0xf7, 0x99, 0xf8, 0xfb, 0xf9, + 0xba, 0xfa, 0xa0, 0xfb, 0x64, 0xfd, 0x01, 0x00, 0xf9, 0x02, 0xdf, 0x05, + 0x55, 0x08, 0x52, 0x0a, 0x73, 0x0c, 0x6c, 0x0e, 0x8f, 0x10, 0x58, 0x12, + 0x40, 0x13, 0x9b, 0x13, 0x14, 0x13, 0xfa, 0x11, 0x43, 0x11, 0x0f, 0x10, + 0x69, 0x0e, 0x88, 0x0c, 0xb7, 0x09, 0xf0, 0x06, 0xe9, 0x04, 0xc9, 0x02, + 0xb0, 0x00, 0xf1, 0xfe, 0x17, 0xfd, 0xb8, 0xfb, 0xea, 0xfa, 0x30, 0xfa, + 0x6b, 0xf9, 0x65, 0xf9, 0xd4, 0xf9, 0x3a, 0xfa, 0x8d, 0xfa, 0xa1, 0xfa, + 0xd5, 0xfa, 0x69, 0xfb, 0xec, 0xfb, 0x7e, 0xfc, 0x6a, 0xfc, 0x17, 0xfc, + 0xe3, 0xfb, 0x99, 0xfb, 0xbe, 0xfb, 0xf9, 0xfb, 0xce, 0xfb, 0xa5, 0xfb, + 0xb4, 0xfb, 0xf9, 0xfb, 0xab, 0xfc, 0xe9, 0xfd, 0x0c, 0xff, 0x07, 0x00, + 0x0d, 0x01, 0x48, 0x02, 0x27, 0x04, 0x3c, 0x06, 0x77, 0x07, 0x68, 0x08, + 0x60, 0x09, 0x34, 0x0a, 0xbe, 0x0a, 0x0e, 0x0b, 0xf8, 0x0a, 0x34, 0x0a, + 0xc2, 0x08, 0x4a, 0x07, 0x89, 0x05, 0xd5, 0x03, 0xf0, 0x01, 0x6f, 0xff, + 0xf2, 0xfc, 0x31, 0xfa, 0xc6, 0xf7, 0xb5, 0xf5, 0xb9, 0xf3, 0xc4, 0xf1, + 0xde, 0xef, 0xf0, 0xed, 0xa4, 0xec, 0x7c, 0xeb, 0x64, 0xea, 0x34, 0xe9, + 0xaf, 0xe8, 0xc8, 0xe8, 0x6d, 0xe9, 0x7c, 0xea, 0x5d, 0xeb, 0x6e, 0xed, + 0x30, 0xef, 0xb1, 0xf1, 0xe4, 0xf4, 0x65, 0xf8, 0x38, 0xfc, 0x46, 0xff, + 0xf1, 0x01, 0xe9, 0x04, 0x9d, 0x08, 0x1b, 0x0c, 0x61, 0x0e, 0x98, 0x0f, + 0x7b, 0x10, 0x3e, 0x11, 0xbc, 0x11, 0x98, 0x11, 0xf5, 0x10, 0xe7, 0x0f, + 0x6b, 0x0e, 0xa3, 0x0c, 0xd8, 0x0a, 0x45, 0x09, 0xf6, 0x07, 0x90, 0x06, + 0x01, 0x05, 0x8a, 0x03, 0x66, 0x02, 0x8b, 0x01, 0xe3, 0x00, 0x12, 0x00, + 0x52, 0xff, 0xc4, 0xfe, 0x68, 0xfe, 0xb7, 0xfd, 0xa3, 0xfc, 0x8c, 0xfb, + 0xc5, 0xfa, 0x4e, 0xfa, 0xc1, 0xf9, 0xad, 0xf8, 0x21, 0xf7, 0x2b, 0xf6, + 0x07, 0xf6, 0x37, 0xf6, 0x6b, 0xf6, 0x8e, 0xf6, 0xd8, 0xf6, 0x7e, 0xf7, + 0xe6, 0xf8, 0xdc, 0xfa, 0x66, 0xfd, 0xf4, 0xff, 0x1f, 0x02, 0xe6, 0x03, + 0xfc, 0x05, 0xf7, 0x08, 0xff, 0x0b, 0x5d, 0x0e, 0x8a, 0x0f, 0x34, 0x10, + 0xe2, 0x10, 0xad, 0x11, 0x33, 0x12, 0xdd, 0x11, 0xdc, 0x10, 0x4b, 0x0f, + 0x91, 0x0d, 0xd9, 0x0b, 0x1d, 0x0a, 0x71, 0x08, 0x54, 0x06, 0x26, 0x04, + 0x4c, 0x02, 0x79, 0x00, 0xf8, 0xfe, 0x12, 0xfe, 0x1c, 0xfd, 0x6a, 0xfc, + 0xc6, 0xfb, 0x01, 0xfb, 0xee, 0xfa, 0x1c, 0xfb, 0x27, 0xfb, 0x46, 0xfb, + 0x3e, 0xfb, 0x1a, 0xfb, 0x33, 0xfb, 0x1d, 0xfb, 0xe3, 0xfa, 0xe1, 0xfa, + 0xb1, 0xfa, 0x50, 0xfa, 0x48, 0xfa, 0x00, 0xfa, 0xd6, 0xf9, 0x2d, 0xfa, + 0x74, 0xfa, 0x2e, 0xfb, 0xf4, 0xfb, 0xa3, 0xfc, 0xbc, 0xfd, 0x24, 0xff, + 0xb8, 0x00, 0x86, 0x02, 0xd8, 0x03, 0x5e, 0x05, 0x01, 0x07, 0x4f, 0x08, + 0x59, 0x09, 0x27, 0x0a, 0xd1, 0x0a, 0x34, 0x0b, 0x11, 0x0b, 0x21, 0x0a, + 0xdd, 0x08, 0xc2, 0x07, 0x79, 0x06, 0x81, 0x04, 0x50, 0x02, 0x1a, 0x00, + 0xbb, 0xfd, 0x33, 0xfb, 0x30, 0xf9, 0xe9, 0xf6, 0xaf, 0xf4, 0x1c, 0xf3, + 0xf6, 0xf0, 0xed, 0xee, 0x69, 0xed, 0xdc, 0xeb, 0x31, 0xeb, 0x98, 0xea, + 0x26, 0xe9, 0xd2, 0xe8, 0x6e, 0xe9, 0x59, 0xea, 0xf0, 0xeb, 0x4b, 0xed, + 0xad, 0xee, 0x18, 0xf1, 0x19, 0xf4, 0x4b, 0xf7, 0xc7, 0xfa, 0xef, 0xfd, + 0xe1, 0x00, 0xdf, 0x03, 0x66, 0x06, 0x5c, 0x09, 0x5d, 0x0c, 0x50, 0x0e, + 0x4a, 0x0f, 0x9e, 0x0f, 0x8b, 0x0f, 0xcc, 0x0f, 0x26, 0x10, 0xbe, 0x0f, + 0x5b, 0x0e, 0x92, 0x0c, 0xd9, 0x0a, 0x7d, 0x09, 0xb8, 0x08, 0x14, 0x08, + 0x00, 0x07, 0x44, 0x05, 0x97, 0x03, 0x9d, 0x02, 0x80, 0x02, 0x6f, 0x02, + 0xc9, 0x01, 0x75, 0x00, 0x43, 0xff, 0xb0, 0xfe, 0x3c, 0xfe, 0x84, 0xfd, + 0x87, 0xfc, 0x72, 0xfb, 0x55, 0xfa, 0x28, 0xf9, 0x20, 0xf8, 0x51, 0xf7, + 0xf3, 0xf6, 0xb7, 0xf6, 0x63, 0xf6, 0x32, 0xf6, 0x5f, 0xf6, 0x49, 0xf7, + 0x9a, 0xf8, 0x33, 0xfa, 0x0a, 0xfc, 0xb8, 0xfd, 0x8f, 0xff, 0xdd, 0x01, + 0x7b, 0x04, 0xe2, 0x06, 0x28, 0x09, 0xe7, 0x0a, 0x58, 0x0c, 0xff, 0x0d, + 0x2e, 0x0f, 0xcd, 0x0f, 0x3a, 0x10, 0x08, 0x10, 0x6b, 0x0f, 0x75, 0x0e, + 0x5a, 0x0d, 0x27, 0x0c, 0xb8, 0x0a, 0xf4, 0x08, 0xf9, 0x06, 0x2e, 0x05, + 0x93, 0x03, 0x6b, 0x02, 0x25, 0x01, 0xab, 0xff, 0x80, 0xfe, 0xa7, 0xfd, + 0x37, 0xfd, 0x13, 0xfd, 0xd0, 0xfc, 0x68, 0xfc, 0x37, 0xfc, 0x38, 0xfc, + 0x23, 0xfc, 0x1f, 0xfc, 0x0d, 0xfc, 0x09, 0xfc, 0xc8, 0xfb, 0x3a, 0xfb, + 0xa6, 0xfa, 0x6a, 0xfa, 0x62, 0xfa, 0x3f, 0xfa, 0xee, 0xf9, 0xb7, 0xf9, + 0xca, 0xf9, 0x2f, 0xfa, 0xd3, 0xfa, 0x9f, 0xfb, 0xce, 0xfc, 0x0d, 0xfe, + 0x31, 0xff, 0x7d, 0x00, 0x0e, 0x02, 0xbc, 0x03, 0x7c, 0x05, 0x0b, 0x07, + 0x3a, 0x08, 0x2c, 0x09, 0xd5, 0x09, 0x47, 0x0a, 0x92, 0x0a, 0x91, 0x0a, + 0xf3, 0x09, 0xbe, 0x08, 0x23, 0x07, 0x52, 0x05, 0xc2, 0x03, 0x2d, 0x02, + 0x21, 0x00, 0xb6, 0xfd, 0x2a, 0xfb, 0xc7, 0xf8, 0xce, 0xf6, 0x51, 0xf5, + 0x9c, 0xf3, 0xbe, 0xf1, 0x72, 0xef, 0xb8, 0xed, 0x9a, 0xec, 0x9b, 0xeb, + 0xe3, 0xea, 0xc8, 0xe9, 0xc3, 0xe9, 0x6e, 0xea, 0xe7, 0xea, 0xa9, 0xeb, + 0xd9, 0xec, 0x25, 0xef, 0xf9, 0xf1, 0x6f, 0xf4, 0xe3, 0xf6, 0xe0, 0xf9, + 0x42, 0xfd, 0x48, 0x00, 0xf8, 0x02, 0xc9, 0x05, 0xc4, 0x08, 0x49, 0x0b, + 0x6e, 0x0c, 0x0d, 0x0d, 0xfa, 0x0d, 0xc6, 0x0e, 0x79, 0x0f, 0x29, 0x0f, + 0xdd, 0x0d, 0xa9, 0x0c, 0xc2, 0x0b, 0xfb, 0x0a, 0x2a, 0x0a, 0x46, 0x09, + 0x17, 0x08, 0xe8, 0x06, 0xb6, 0x05, 0x08, 0x05, 0xb0, 0x04, 0x26, 0x04, + 0xa2, 0x03, 0xe1, 0x02, 0xe4, 0x01, 0x0e, 0x01, 0x61, 0x00, 0xe3, 0xff, + 0x30, 0xff, 0x11, 0xfe, 0x94, 0xfc, 0x30, 0xfb, 0x40, 0xfa, 0x69, 0xf9, + 0x98, 0xf8, 0xd2, 0xf7, 0x58, 0xf7, 0x91, 0xf6, 0x1a, 0xf6, 0x94, 0xf6, + 0x77, 0xf7, 0x95, 0xf8, 0xfe, 0xf9, 0xd1, 0xfa, 0xf9, 0xfb, 0x6d, 0xfe, + 0xda, 0x00, 0x2c, 0x03, 0x1d, 0x05, 0x7b, 0x06, 0x78, 0x08, 0xb0, 0x0a, + 0x52, 0x0c, 0x50, 0x0d, 0x8b, 0x0d, 0x2a, 0x0e, 0x99, 0x0e, 0x64, 0x0e, + 0xb6, 0x0d, 0x9a, 0x0c, 0xa9, 0x0b, 0x7c, 0x0a, 0xfb, 0x08, 0x9f, 0x07, + 0x40, 0x06, 0x82, 0x04, 0x0a, 0x03, 0xf5, 0x01, 0x17, 0x01, 0x14, 0x00, + 0x25, 0xff, 0x72, 0xfe, 0x11, 0xfe, 0xc0, 0xfd, 0x8a, 0xfd, 0x6f, 0xfd, + 0x58, 0xfd, 0x1a, 0xfd, 0xc4, 0xfc, 0x6a, 0xfc, 0x6e, 0xfc, 0xb8, 0xfc, + 0x3e, 0xfc, 0x3f, 0xfb, 0x8a, 0xfa, 0x68, 0xfa, 0x60, 0xfa, 0x78, 0xfa, + 0x3f, 0xfa, 0xa5, 0xf9, 0xb1, 0xf9, 0x47, 0xfa, 0x30, 0xfb, 0x41, 0xfc, + 0x55, 0xfd, 0x49, 0xfe, 0x52, 0xff, 0xb8, 0x00, 0x86, 0x02, 0x6e, 0x04, + 0xe3, 0x05, 0xfe, 0x06, 0xb5, 0x07, 0x75, 0x08, 0x4c, 0x09, 0xbc, 0x09, + 0xa3, 0x09, 0xfb, 0x08, 0xcb, 0x07, 0x33, 0x06, 0xde, 0x04, 0x88, 0x03, + 0xce, 0x01, 0xd1, 0xff, 0x5a, 0xfd, 0xd6, 0xfa, 0xea, 0xf8, 0x17, 0xf7, + 0x71, 0xf5, 0xa8, 0xf3, 0x90, 0xf1, 0x0c, 0xf0, 0x83, 0xee, 0x09, 0xed, + 0x27, 0xec, 0xac, 0xeb, 0x97, 0xeb, 0xcf, 0xeb, 0xea, 0xeb, 0x0e, 0xec, + 0x54, 0xed, 0x6c, 0xef, 0xaf, 0xf1, 0x05, 0xf4, 0xec, 0xf5, 0x68, 0xf8, + 0x62, 0xfb, 0x34, 0xfe, 0xf9, 0x00, 0xb8, 0x03, 0x11, 0x06, 0x2d, 0x08, + 0xc9, 0x09, 0x94, 0x0a, 0x77, 0x0b, 0xce, 0x0c, 0xa9, 0x0d, 0x1e, 0x0d, + 0xd2, 0x0b, 0x23, 0x0b, 0x2b, 0x0b, 0x03, 0x0b, 0x0e, 0x0a, 0xac, 0x08, + 0xa6, 0x07, 0x40, 0x07, 0xc9, 0x06, 0x23, 0x06, 0xab, 0x05, 0x73, 0x05, + 0x13, 0x05, 0x2a, 0x04, 0x1e, 0x03, 0xba, 0x02, 0xe9, 0x02, 0x76, 0x02, + 0x24, 0x01, 0x7d, 0xff, 0x08, 0xfe, 0x5e, 0xfd, 0xd3, 0xfc, 0xe2, 0xfb, + 0x99, 0xfa, 0x05, 0xf9, 0xe8, 0xf7, 0x87, 0xf7, 0xa0, 0xf7, 0xc9, 0xf7, + 0x01, 0xf8, 0x2d, 0xf8, 0xaf, 0xf8, 0xec, 0xf9, 0xca, 0xfb, 0xd0, 0xfd, + 0xb2, 0xff, 0x38, 0x01, 0xb3, 0x02, 0xcc, 0x04, 0x23, 0x07, 0x1a, 0x09, + 0x47, 0x0a, 0x32, 0x0b, 0x06, 0x0c, 0xd0, 0x0c, 0x4a, 0x0d, 0x31, 0x0d, + 0xad, 0x0c, 0xda, 0x0b, 0x1a, 0x0b, 0x36, 0x0a, 0x11, 0x09, 0xc0, 0x07, + 0x55, 0x06, 0x1e, 0x05, 0x23, 0x04, 0xd0, 0x02, 0xc0, 0x01, 0x3b, 0x01, + 0x9e, 0x00, 0x0d, 0x00, 0x50, 0xff, 0xd4, 0xfe, 0x01, 0xff, 0xfa, 0xfe, + 0x8c, 0xfe, 0x2a, 0xfe, 0xe3, 0xfd, 0x93, 0xfd, 0x67, 0xfd, 0xf2, 0xfc, + 0x48, 0xfc, 0xcf, 0xfb, 0x44, 0xfb, 0x9c, 0xfa, 0x18, 0xfa, 0xb5, 0xf9, + 0x7d, 0xf9, 0x6b, 0xf9, 0x71, 0xf9, 0xa7, 0xf9, 0x1c, 0xfa, 0xd2, 0xfa, + 0xd1, 0xfb, 0xfb, 0xfc, 0x55, 0xfe, 0x81, 0xff, 0xf1, 0x00, 0x75, 0x02, + 0xe7, 0x03, 0x53, 0x05, 0x7c, 0x06, 0x69, 0x07, 0x0e, 0x08, 0x6b, 0x08, + 0x89, 0x08, 0x92, 0x08, 0xd4, 0x07, 0xa6, 0x06, 0x6f, 0x05, 0x1b, 0x04, + 0x52, 0x02, 0xd8, 0x00, 0x1f, 0xff, 0x27, 0xfd, 0xf6, 0xfa, 0xc0, 0xf8, + 0x42, 0xf7, 0xdc, 0xf5, 0x86, 0xf4, 0x90, 0xf2, 0x99, 0xf0, 0x53, 0xef, + 0x63, 0xee, 0xb5, 0xed, 0x5e, 0xed, 0xf1, 0xec, 0xcf, 0xec, 0x3c, 0xed, + 0xd6, 0xed, 0xfd, 0xee, 0xa2, 0xf0, 0x5e, 0xf2, 0x79, 0xf4, 0xac, 0xf6, + 0x31, 0xf9, 0x78, 0xfb, 0xa1, 0xfd, 0x37, 0x00, 0xe0, 0x02, 0x84, 0x05, + 0x45, 0x07, 0x31, 0x08, 0xf5, 0x08, 0x40, 0x0a, 0x8a, 0x0b, 0xe5, 0x0b, + 0xad, 0x0b, 0x13, 0x0b, 0x6f, 0x0a, 0x0a, 0x0a, 0x94, 0x09, 0x3d, 0x09, + 0xb2, 0x08, 0xe8, 0x07, 0x50, 0x07, 0x4d, 0x06, 0xbd, 0x05, 0xf9, 0x05, + 0x10, 0x06, 0x94, 0x05, 0xda, 0x04, 0xe4, 0x03, 0x96, 0x03, 0xa6, 0x03, + 0x03, 0x03, 0x1e, 0x02, 0x3f, 0x01, 0x63, 0x00, 0x46, 0xff, 0xee, 0xfd, + 0x95, 0xfc, 0x15, 0xfc, 0xda, 0xfb, 0xd8, 0xfa, 0x4d, 0xf9, 0x3b, 0xf8, + 0x3a, 0xf8, 0x29, 0xf9, 0xed, 0xf9, 0x33, 0xfa, 0x80, 0xfa, 0x61, 0xfb, + 0xb0, 0xfc, 0x86, 0xfe, 0xb0, 0x00, 0x9d, 0x02, 0x1d, 0x04, 0x3a, 0x05, + 0x74, 0x06, 0x0f, 0x08, 0xc6, 0x09, 0x54, 0x0b, 0xe4, 0x0b, 0x76, 0x0b, + 0x0d, 0x0b, 0x00, 0x0b, 0xf6, 0x0a, 0xe9, 0x0a, 0x14, 0x0a, 0x4c, 0x08, + 0xe8, 0x06, 0xe7, 0x05, 0x02, 0x05, 0x3c, 0x04, 0x71, 0x03, 0x69, 0x02, + 0x7f, 0x01, 0xb8, 0x00, 0x25, 0x00, 0x26, 0x00, 0x25, 0x00, 0xf3, 0xff, + 0x8f, 0xff, 0x26, 0xff, 0x08, 0xff, 0xdb, 0xfe, 0x83, 0xfe, 0x35, 0xfe, + 0xbd, 0xfd, 0x25, 0xfd, 0x55, 0xfc, 0x82, 0xfb, 0xe7, 0xfa, 0x60, 0xfa, + 0xf9, 0xf9, 0x9b, 0xf9, 0x6e, 0xf9, 0x39, 0xf9, 0x11, 0xf9, 0x84, 0xf9, + 0x8b, 0xfa, 0x9f, 0xfb, 0x8f, 0xfc, 0x77, 0xfd, 0xae, 0xfe, 0x38, 0x00, + 0xa7, 0x01, 0x0f, 0x03, 0x72, 0x04, 0xa5, 0x05, 0x6a, 0x06, 0xa8, 0x06, + 0xef, 0x06, 0x27, 0x07, 0x15, 0x07, 0x6c, 0x06, 0x63, 0x05, 0xed, 0x03, + 0x84, 0x02, 0x1d, 0x01, 0xc7, 0xff, 0x5f, 0xfe, 0x5a, 0xfc, 0x52, 0xfa, + 0xba, 0xf8, 0x29, 0xf7, 0xe2, 0xf5, 0x75, 0xf4, 0xc7, 0xf2, 0x75, 0xf1, + 0x93, 0xf0, 0x6a, 0xef, 0x9a, 0xee, 0x4f, 0xee, 0xb4, 0xee, 0x79, 0xef, + 0x74, 0xef, 0xc9, 0xef, 0xed, 0xf0, 0x25, 0xf3, 0x7a, 0xf5, 0x49, 0xf7, + 0xde, 0xf8, 0x8f, 0xfa, 0x3a, 0xfd, 0xf4, 0xff, 0xe1, 0x01, 0xa8, 0x03, + 0x4e, 0x05, 0x9f, 0x06, 0xf1, 0x07, 0xc6, 0x08, 0x38, 0x09, 0xd0, 0x09, + 0x03, 0x0a, 0xbf, 0x09, 0x38, 0x09, 0xb0, 0x08, 0x86, 0x08, 0x81, 0x08, + 0xbc, 0x07, 0xdb, 0x06, 0x7b, 0x06, 0x75, 0x06, 0x87, 0x06, 0x25, 0x06, + 0x5e, 0x05, 0x0a, 0x05, 0x38, 0x05, 0x62, 0x05, 0x16, 0x05, 0x21, 0x04, + 0x66, 0x03, 0x12, 0x03, 0x8d, 0x02, 0xed, 0x01, 0xf3, 0x00, 0xca, 0xff, + 0xbf, 0xfe, 0x9d, 0xfd, 0xa3, 0xfc, 0xea, 0xfb, 0x78, 0xfb, 0x1d, 0xfb, + 0x52, 0xfa, 0x6d, 0xf9, 0x91, 0xf9, 0xaf, 0xfa, 0x9a, 0xfb, 0x5b, 0xfc, + 0xe0, 0xfc, 0x74, 0xfd, 0x1f, 0xff, 0x12, 0x01, 0xcd, 0x02, 0x45, 0x04, + 0x3f, 0x05, 0x31, 0x06, 0x66, 0x07, 0x8f, 0x08, 0x74, 0x09, 0x2d, 0x0a, + 0x31, 0x0a, 0xd5, 0x09, 0x85, 0x09, 0xee, 0x08, 0xcc, 0x08, 0x6b, 0x08, + 0x55, 0x07, 0x41, 0x06, 0x2b, 0x05, 0x4f, 0x04, 0xc5, 0x03, 0x51, 0x03, + 0x9e, 0x02, 0xec, 0x01, 0x56, 0x01, 0xf6, 0x00, 0xad, 0x00, 0x6f, 0x00, + 0x5b, 0x00, 0x26, 0x00, 0xa9, 0xff, 0x33, 0xff, 0xce, 0xfe, 0x63, 0xfe, + 0x0d, 0xfe, 0x68, 0xfd, 0xa0, 0xfc, 0x10, 0xfc, 0x73, 0xfb, 0xaa, 0xfa, + 0x09, 0xfa, 0xcb, 0xf9, 0xcf, 0xf9, 0xd0, 0xf9, 0xcd, 0xf9, 0xd9, 0xf9, + 0x4d, 0xfa, 0x3d, 0xfb, 0x71, 0xfc, 0xb3, 0xfd, 0xab, 0xfe, 0xa7, 0xff, + 0xc6, 0x00, 0x08, 0x02, 0x6c, 0x03, 0x8f, 0x04, 0x58, 0x05, 0xf5, 0x05, + 0x09, 0x06, 0xc8, 0x05, 0x86, 0x05, 0x76, 0x05, 0x20, 0x05, 0x0b, 0x04, + 0x8b, 0x02, 0xef, 0x00, 0xb5, 0xff, 0x9f, 0xfe, 0x65, 0xfd, 0x12, 0xfc, + 0x4c, 0xfa, 0x8a, 0xf8, 0x0f, 0xf7, 0x9d, 0xf5, 0xa7, 0xf4, 0xa3, 0xf3, + 0x60, 0xf2, 0x06, 0xf1, 0xe6, 0xef, 0x6a, 0xef, 0x90, 0xef, 0x00, 0xf0, + 0x66, 0xf0, 0x95, 0xf0, 0x04, 0xf1, 0x3e, 0xf2, 0x29, 0xf4, 0x7c, 0xf6, + 0x62, 0xf8, 0xf8, 0xf9, 0xa0, 0xfb, 0xf8, 0xfd, 0x3a, 0x00, 0x10, 0x02, + 0xf8, 0x03, 0x82, 0x05, 0x84, 0x06, 0x54, 0x07, 0xeb, 0x07, 0x6c, 0x08, + 0x19, 0x09, 0x3c, 0x09, 0xbc, 0x08, 0x12, 0x08, 0x98, 0x07, 0xa5, 0x07, + 0x96, 0x07, 0xec, 0x06, 0x38, 0x06, 0xd5, 0x05, 0xde, 0x05, 0xf6, 0x05, + 0xc4, 0x05, 0x4c, 0x05, 0x41, 0x05, 0x8c, 0x05, 0x30, 0x05, 0xbc, 0x04, + 0xac, 0x04, 0x71, 0x04, 0xd4, 0x03, 0x06, 0x03, 0x1e, 0x02, 0x6b, 0x01, + 0xdf, 0x00, 0xdb, 0xff, 0x74, 0xfe, 0x76, 0xfd, 0xd0, 0xfc, 0x45, 0xfc, + 0xae, 0xfb, 0x10, 0xfb, 0xbe, 0xfa, 0xb5, 0xfa, 0x30, 0xfb, 0xc7, 0xfb, + 0x68, 0xfc, 0x57, 0xfd, 0x53, 0xfe, 0x8f, 0xff, 0xbb, 0x00, 0xf9, 0x01, + 0x9d, 0x03, 0xf2, 0x04, 0xfb, 0x05, 0xa2, 0x06, 0x3c, 0x07, 0x45, 0x08, + 0xe8, 0x08, 0xe0, 0x08, 0xb9, 0x08, 0x7a, 0x08, 0x0a, 0x08, 0x6c, 0x07, + 0xd2, 0x06, 0x3c, 0x06, 0x9b, 0x05, 0xc0, 0x04, 0xbc, 0x03, 0x04, 0x03, + 0xa3, 0x02, 0x4e, 0x02, 0xe3, 0x01, 0x53, 0x01, 0xe7, 0x00, 0xc5, 0x00, + 0x9c, 0x00, 0x71, 0x00, 0x39, 0x00, 0xed, 0xff, 0xa1, 0xff, 0x27, 0xff, + 0x99, 0xfe, 0x2b, 0xfe, 0xb0, 0xfd, 0x18, 0xfd, 0x6e, 0xfc, 0x8e, 0xfb, + 0xdd, 0xfa, 0x84, 0xfa, 0x55, 0xfa, 0x21, 0xfa, 0xe6, 0xf9, 0xf5, 0xf9, + 0x51, 0xfa, 0xf0, 0xfa, 0xb9, 0xfb, 0xc2, 0xfc, 0xbf, 0xfd, 0xda, 0xfe, + 0xe8, 0xff, 0x16, 0x01, 0x91, 0x02, 0x9b, 0x03, 0x82, 0x04, 0x16, 0x05, + 0x77, 0x05, 0xc9, 0x05, 0xc9, 0x05, 0x88, 0x05, 0xe9, 0x04, 0x0e, 0x04, + 0x34, 0x03, 0xf0, 0x01, 0x98, 0x00, 0x5f, 0xff, 0x0a, 0xfe, 0x92, 0xfc, + 0x17, 0xfb, 0x92, 0xf9, 0x42, 0xf8, 0x17, 0xf7, 0xc9, 0xf5, 0x51, 0xf4, + 0x14, 0xf3, 0x4b, 0xf2, 0x49, 0xf1, 0x90, 0xf0, 0x35, 0xf0, 0x05, 0xf0, + 0x34, 0xf0, 0x8c, 0xf0, 0x07, 0xf1, 0xbf, 0xf1, 0x46, 0xf3, 0xe3, 0xf4, + 0x40, 0xf6, 0x14, 0xf8, 0xf7, 0xf9, 0x2d, 0xfc, 0xdf, 0xfd, 0x72, 0xff, + 0x88, 0x01, 0x68, 0x03, 0xde, 0x04, 0xcc, 0x05, 0x3e, 0x06, 0x0b, 0x07, + 0xff, 0x07, 0x93, 0x08, 0x4b, 0x08, 0xb3, 0x07, 0x91, 0x07, 0x9a, 0x07, + 0x6c, 0x07, 0xfc, 0x06, 0xa8, 0x06, 0x5c, 0x06, 0x4c, 0x06, 0x27, 0x06, + 0xd1, 0x05, 0xdb, 0x05, 0x21, 0x06, 0x18, 0x06, 0xbe, 0x05, 0x74, 0x05, + 0x66, 0x05, 0x66, 0x05, 0x3c, 0x05, 0x77, 0x04, 0x68, 0x03, 0x7e, 0x02, + 0x20, 0x02, 0xb0, 0x01, 0x6c, 0x00, 0x06, 0xff, 0xf3, 0xfd, 0x4c, 0xfd, + 0xda, 0xfc, 0x0d, 0xfc, 0x68, 0xfb, 0x45, 0xfb, 0x48, 0xfb, 0x4e, 0xfb, + 0x80, 0xfb, 0x3a, 0xfc, 0x74, 0xfd, 0x74, 0xfe, 0x31, 0xff, 0xf8, 0xff, + 0x4b, 0x01, 0xcf, 0x02, 0x34, 0x04, 0x47, 0x05, 0xb8, 0x05, 0x4f, 0x06, + 0x13, 0x07, 0xaf, 0x07, 0x25, 0x08, 0xf4, 0x07, 0x7e, 0x07, 0x34, 0x07, + 0xc9, 0x06, 0x49, 0x06, 0x08, 0x06, 0x61, 0x05, 0x6e, 0x04, 0xc5, 0x03, + 0x1b, 0x03, 0xf3, 0x02, 0xc8, 0x02, 0x4a, 0x02, 0xd2, 0x01, 0x56, 0x01, + 0x4c, 0x01, 0x74, 0x01, 0x5f, 0x01, 0xf4, 0x00, 0x5b, 0x00, 0xee, 0xff, + 0xa9, 0xff, 0x67, 0xff, 0xda, 0xfe, 0xef, 0xfd, 0x39, 0xfd, 0x72, 0xfc, + 0xb7, 0xfb, 0x39, 0xfb, 0xdb, 0xfa, 0x96, 0xfa, 0x12, 0xfa, 0xb0, 0xf9, + 0xdd, 0xf9, 0x72, 0xfa, 0x1f, 0xfb, 0xc9, 0xfb, 0x6f, 0xfc, 0x7c, 0xfd, + 0xac, 0xfe, 0xce, 0xff, 0x02, 0x01, 0x28, 0x02, 0x14, 0x03, 0x11, 0x04, + 0xb1, 0x04, 0xea, 0x04, 0x37, 0x05, 0x27, 0x05, 0xcf, 0x04, 0x59, 0x04, + 0x6f, 0x03, 0x8d, 0x02, 0x9e, 0x01, 0x3b, 0x00, 0xe9, 0xfe, 0x8e, 0xfd, + 0x6e, 0xfc, 0x3f, 0xfb, 0xd7, 0xf9, 0x65, 0xf8, 0x10, 0xf7, 0x13, 0xf6, + 0xfb, 0xf4, 0x17, 0xf4, 0xfc, 0xf2, 0x19, 0xf2, 0x83, 0xf1, 0x1c, 0xf1, + 0x19, 0xf1, 0x3c, 0xf1, 0x7d, 0xf1, 0xf8, 0xf1, 0x94, 0xf2, 0x8f, 0xf3, + 0x4e, 0xf5, 0x0c, 0xf7, 0x7d, 0xf8, 0xd5, 0xf9, 0x62, 0xfb, 0x79, 0xfd, + 0xb8, 0xff, 0x69, 0x01, 0x5f, 0x02, 0x7f, 0x03, 0xee, 0x04, 0xf6, 0x05, + 0xb9, 0x06, 0x10, 0x07, 0x44, 0x07, 0x48, 0x07, 0x3a, 0x07, 0x26, 0x07, + 0xf7, 0x06, 0xcb, 0x06, 0x81, 0x06, 0x26, 0x06, 0xd8, 0x05, 0xf9, 0x05, + 0x4f, 0x06, 0x35, 0x06, 0xdc, 0x05, 0xb6, 0x05, 0xfc, 0x05, 0x81, 0x06, + 0xb8, 0x06, 0x44, 0x06, 0x9e, 0x05, 0x3f, 0x05, 0x0e, 0x05, 0xdb, 0x04, + 0x10, 0x04, 0x11, 0x03, 0xd4, 0x01, 0xbf, 0x00, 0x11, 0x00, 0x3e, 0xff, + 0x54, 0xfe, 0x6d, 0xfd, 0x85, 0xfc, 0xf0, 0xfb, 0xb4, 0xfb, 0xb0, 0xfb, + 0xe2, 0xfb, 0x33, 0xfc, 0x8e, 0xfc, 0x28, 0xfd, 0x24, 0xfe, 0x30, 0xff, + 0x63, 0x00, 0x79, 0x01, 0x7a, 0x02, 0x89, 0x03, 0x90, 0x04, 0x9d, 0x05, + 0x67, 0x06, 0xd2, 0x06, 0x27, 0x07, 0x6f, 0x07, 0x7a, 0x07, 0x67, 0x07, + 0xfe, 0x06, 0x72, 0x06, 0xf4, 0x05, 0x80, 0x05, 0xdd, 0x04, 0x46, 0x04, + 0x92, 0x03, 0xda, 0x02, 0x8e, 0x02, 0x49, 0x02, 0x2d, 0x02, 0xc9, 0x01, + 0x3c, 0x01, 0x31, 0x01, 0x4e, 0x01, 0x4e, 0x01, 0x19, 0x01, 0xc8, 0x00, + 0x75, 0x00, 0x05, 0x00, 0xac, 0xff, 0x23, 0xff, 0x8f, 0xfe, 0xc5, 0xfd, + 0xf3, 0xfc, 0x3b, 0xfc, 0x70, 0xfb, 0xe3, 0xfa, 0x76, 0xfa, 0x11, 0xfa, + 0xd4, 0xf9, 0xc3, 0xf9, 0x13, 0xfa, 0x9e, 0xfa, 0x40, 0xfb, 0xfa, 0xfb, + 0x07, 0xfd, 0x40, 0xfe, 0x61, 0xff, 0x87, 0x00, 0x99, 0x01, 0xc9, 0x02, + 0xc7, 0x03, 0x5c, 0x04, 0xd1, 0x04, 0x10, 0x05, 0x0f, 0x05, 0xdf, 0x04, + 0x39, 0x04, 0x6f, 0x03, 0xc9, 0x02, 0xd5, 0x01, 0x71, 0x00, 0x4e, 0xff, + 0x0c, 0xfe, 0xc1, 0xfc, 0xad, 0xfb, 0x64, 0xfa, 0x18, 0xf9, 0x12, 0xf8, + 0xb5, 0xf6, 0x9c, 0xf5, 0x00, 0xf5, 0x04, 0xf4, 0x45, 0xf3, 0x79, 0xf2, + 0xe2, 0xf1, 0x0b, 0xf2, 0x24, 0xf2, 0x5f, 0xf2, 0xc5, 0xf2, 0x2f, 0xf3, + 0x63, 0xf4, 0x8b, 0xf5, 0xcc, 0xf6, 0x57, 0xf8, 0xcd, 0xf9, 0x50, 0xfb, + 0xd7, 0xfc, 0x30, 0xfe, 0xb3, 0xff, 0x6d, 0x01, 0xa8, 0x02, 0x7c, 0x03, + 0x08, 0x04, 0x8d, 0x04, 0x55, 0x05, 0x01, 0x06, 0x35, 0x06, 0x0d, 0x06, + 0xaf, 0x05, 0xaf, 0x05, 0x0b, 0x06, 0x20, 0x06, 0x04, 0x06, 0x23, 0x06, + 0x12, 0x06, 0x0f, 0x06, 0x4a, 0x06, 0xa1, 0x06, 0x03, 0x07, 0x20, 0x07, + 0xf3, 0x06, 0xd9, 0x06, 0xdb, 0x06, 0xda, 0x06, 0xb3, 0x06, 0x38, 0x06, + 0x72, 0x05, 0x9a, 0x04, 0xc0, 0x03, 0xfc, 0x02, 0x4f, 0x02, 0x3d, 0x01, + 0xfd, 0xff, 0xfc, 0xfe, 0x5a, 0xfe, 0xb1, 0xfd, 0x32, 0xfd, 0xb0, 0xfc, + 0x73, 0xfc, 0x7c, 0xfc, 0xa5, 0xfc, 0x06, 0xfd, 0xcd, 0xfd, 0xad, 0xfe, + 0x47, 0xff, 0xfb, 0xff, 0x2c, 0x01, 0x54, 0x02, 0x52, 0x03, 0x2f, 0x04, + 0xcf, 0x04, 0x69, 0x05, 0xf0, 0x05, 0x69, 0x06, 0xb9, 0x06, 0x9d, 0x06, + 0x40, 0x06, 0x21, 0x06, 0xad, 0x05, 0x44, 0x05, 0xd8, 0x04, 0x3c, 0x04, + 0xa2, 0x03, 0x10, 0x03, 0xa0, 0x02, 0x56, 0x02, 0x26, 0x02, 0xcc, 0x01, + 0x70, 0x01, 0x47, 0x01, 0x49, 0x01, 0x6e, 0x01, 0x50, 0x01, 0xf7, 0x00, + 0xba, 0x00, 0x85, 0x00, 0x49, 0x00, 0xed, 0xff, 0x4a, 0xff, 0xb0, 0xfe, + 0x0c, 0xfe, 0x4b, 0xfd, 0x96, 0xfc, 0x04, 0xfc, 0x78, 0xfb, 0xe7, 0xfa, + 0x6d, 0xfa, 0x3b, 0xfa, 0x4b, 0xfa, 0x77, 0xfa, 0xb5, 0xfa, 0x42, 0xfb, + 0x07, 0xfc, 0xeb, 0xfc, 0xeb, 0xfd, 0xe9, 0xfe, 0xed, 0xff, 0x09, 0x01, + 0x10, 0x02, 0xf5, 0x02, 0x87, 0x03, 0xe7, 0x03, 0x50, 0x04, 0x4f, 0x04, + 0x13, 0x04, 0xd7, 0x03, 0x45, 0x03, 0x7c, 0x02, 0x85, 0x01, 0x6c, 0x00, + 0x7d, 0xff, 0x80, 0xfe, 0x7b, 0xfd, 0x50, 0xfc, 0xbc, 0xfa, 0x9d, 0xf9, + 0xcd, 0xf8, 0xd1, 0xf7, 0xf9, 0xf6, 0x99, 0xf5, 0x8d, 0xf4, 0x00, 0xf4, + 0x59, 0xf3, 0x1a, 0xf3, 0xb9, 0xf2, 0xbe, 0xf2, 0x05, 0xf3, 0x28, 0xf3, + 0xa8, 0xf3, 0xac, 0xf4, 0x0d, 0xf6, 0x3b, 0xf7, 0x30, 0xf8, 0x4d, 0xf9, + 0xf4, 0xfa, 0xb1, 0xfc, 0x07, 0xfe, 0x33, 0xff, 0x71, 0x00, 0xa4, 0x01, + 0xaa, 0x02, 0x67, 0x03, 0xf7, 0x03, 0x91, 0x04, 0xfb, 0x04, 0x08, 0x05, + 0x1c, 0x05, 0x30, 0x05, 0x54, 0x05, 0x5a, 0x05, 0x40, 0x05, 0x3c, 0x05, + 0x52, 0x05, 0x92, 0x05, 0xb9, 0x05, 0xe5, 0x05, 0xfa, 0x05, 0x1b, 0x06, + 0x75, 0x06, 0xab, 0x06, 0xa5, 0x06, 0x7b, 0x06, 0x5c, 0x06, 0x49, 0x06, + 0xfe, 0x05, 0x62, 0x05, 0xc5, 0x04, 0x33, 0x04, 0x8a, 0x03, 0xa6, 0x02, + 0x9d, 0x01, 0xba, 0x00, 0x00, 0x00, 0x5f, 0xff, 0xa5, 0xfe, 0xcb, 0xfd, + 0x52, 0xfd, 0x3f, 0xfd, 0x67, 0xfd, 0x83, 0xfd, 0xa3, 0xfd, 0xf4, 0xfd, + 0xaa, 0xfe, 0x8a, 0xff, 0x42, 0x00, 0x25, 0x01, 0xff, 0x01, 0xd9, 0x02, + 0x9e, 0x03, 0x30, 0x04, 0xde, 0x04, 0x67, 0x05, 0xb0, 0x05, 0xd7, 0x05, + 0xbd, 0x05, 0x8a, 0x05, 0x4b, 0x05, 0xfd, 0x04, 0x7a, 0x04, 0x0f, 0x04, + 0x91, 0x03, 0x12, 0x03, 0xb3, 0x02, 0x47, 0x02, 0xea, 0x01, 0xdb, 0x01, + 0xc0, 0x01, 0x94, 0x01, 0x9c, 0x01, 0x81, 0x01, 0x81, 0x01, 0x88, 0x01, + 0x74, 0x01, 0x5c, 0x01, 0x2d, 0x01, 0xc0, 0x00, 0x49, 0x00, 0xc8, 0xff, + 0x36, 0xff, 0xa3, 0xfe, 0xf3, 0xfd, 0x32, 0xfd, 0x8f, 0xfc, 0xe2, 0xfb, + 0x55, 0xfb, 0xfc, 0xfa, 0xdb, 0xfa, 0xd7, 0xfa, 0xe0, 0xfa, 0x19, 0xfb, + 0x97, 0xfb, 0x49, 0xfc, 0x23, 0xfd, 0x16, 0xfe, 0x02, 0xff, 0xe3, 0xff, + 0xdd, 0x00, 0xd5, 0x01, 0x90, 0x02, 0x1d, 0x03, 0x9b, 0x03, 0xe2, 0x03, + 0xe3, 0x03, 0xa5, 0x03, 0x3e, 0x03, 0x93, 0x02, 0xe8, 0x01, 0x37, 0x01, + 0x43, 0x00, 0x22, 0xff, 0xea, 0xfd, 0xe5, 0xfc, 0x08, 0xfc, 0xff, 0xfa, + 0x03, 0xfa, 0xf3, 0xf8, 0xfe, 0xf7, 0x16, 0xf7, 0x43, 0xf6, 0x98, 0xf5, + 0xff, 0xf4, 0x8d, 0xf4, 0xd0, 0xf3, 0x86, 0xf3, 0x9e, 0xf3, 0xd1, 0xf3, + 0x1a, 0xf4, 0x64, 0xf4, 0xfe, 0xf4, 0xfa, 0xf5, 0x1a, 0xf7, 0x22, 0xf8, + 0x29, 0xf9, 0x5b, 0xfa, 0xf1, 0xfb, 0x5c, 0xfd, 0x78, 0xfe, 0x78, 0xff, + 0x82, 0x00, 0xa7, 0x01, 0x9b, 0x02, 0x3f, 0x03, 0xbf, 0x03, 0x3d, 0x04, + 0x69, 0x04, 0x77, 0x04, 0x9f, 0x04, 0xd4, 0x04, 0xff, 0x04, 0xfe, 0x04, + 0xc8, 0x04, 0xba, 0x04, 0xde, 0x04, 0x41, 0x05, 0x82, 0x05, 0x8a, 0x05, + 0x8c, 0x05, 0x96, 0x05, 0xbb, 0x05, 0x0a, 0x06, 0x31, 0x06, 0x19, 0x06, + 0xb7, 0x05, 0x52, 0x05, 0x0f, 0x05, 0xbd, 0x04, 0x30, 0x04, 0x77, 0x03, + 0xad, 0x02, 0xc5, 0x01, 0x18, 0x01, 0x86, 0x00, 0xd4, 0xff, 0x39, 0xff, + 0xaf, 0xfe, 0x45, 0xfe, 0x13, 0xfe, 0x1f, 0xfe, 0x4f, 0xfe, 0x9c, 0xfe, + 0xdc, 0xfe, 0x41, 0xff, 0xec, 0xff, 0xa6, 0x00, 0x71, 0x01, 0x2f, 0x02, + 0xbb, 0x02, 0x44, 0x03, 0xdc, 0x03, 0x64, 0x04, 0xcf, 0x04, 0x1e, 0x05, + 0x1d, 0x05, 0x07, 0x05, 0xf8, 0x04, 0xb4, 0x04, 0x89, 0x04, 0x4b, 0x04, + 0xf6, 0x03, 0x87, 0x03, 0xf6, 0x02, 0x9a, 0x02, 0x70, 0x02, 0x65, 0x02, + 0x28, 0x02, 0xd1, 0x01, 0x96, 0x01, 0x6f, 0x01, 0x5c, 0x01, 0x6d, 0x01, + 0x65, 0x01, 0x29, 0x01, 0xb0, 0x00, 0x63, 0x00, 0x3a, 0x00, 0xd4, 0xff, + 0x6a, 0xff, 0xdc, 0xfe, 0x5a, 0xfe, 0xd4, 0xfd, 0x3a, 0xfd, 0xb1, 0xfc, + 0x54, 0xfc, 0x0d, 0xfc, 0xd6, 0xfb, 0xae, 0xfb, 0x93, 0xfb, 0xab, 0xfb, + 0x10, 0xfc, 0x7e, 0xfc, 0x10, 0xfd, 0xb1, 0xfd, 0x6f, 0xfe, 0x2f, 0xff, + 0xe7, 0xff, 0xab, 0x00, 0x75, 0x01, 0x25, 0x02, 0xbd, 0x02, 0x27, 0x03, + 0x4e, 0x03, 0x5c, 0x03, 0x42, 0x03, 0x02, 0x03, 0xc1, 0x02, 0x23, 0x02, + 0x5b, 0x01, 0x8d, 0x00, 0xad, 0xff, 0xc9, 0xfe, 0x0f, 0xfe, 0x13, 0xfd, + 0x2a, 0xfc, 0x32, 0xfb, 0x49, 0xfa, 0x76, 0xf9, 0x9d, 0xf8, 0xe3, 0xf7, + 0x2f, 0xf7, 0x3f, 0xf6, 0x93, 0xf5, 0x11, 0xf5, 0x83, 0xf4, 0x67, 0xf4, + 0x45, 0xf4, 0x0c, 0xf4, 0x25, 0xf4, 0xa4, 0xf4, 0x25, 0xf5, 0x15, 0xf6, + 0xf2, 0xf6, 0xb7, 0xf7, 0xd9, 0xf8, 0x0c, 0xfa, 0x43, 0xfb, 0xc3, 0xfc, + 0xe8, 0xfd, 0xc8, 0xfe, 0xbc, 0xff, 0xad, 0x00, 0x9d, 0x01, 0x51, 0x02, + 0xcb, 0x02, 0x13, 0x03, 0x36, 0x03, 0x76, 0x03, 0x91, 0x03, 0xc6, 0x03, + 0xe3, 0x03, 0xd8, 0x03, 0xd7, 0x03, 0xeb, 0x03, 0x30, 0x04, 0x66, 0x04, + 0x95, 0x04, 0xcd, 0x04, 0xd8, 0x04, 0x00, 0x05, 0x56, 0x05, 0x68, 0x05, + 0x5d, 0x05, 0x50, 0x05, 0x2c, 0x05, 0x11, 0x05, 0xb3, 0x04, 0x31, 0x04, + 0xbb, 0x03, 0x4c, 0x03, 0xe5, 0x02, 0x42, 0x02, 0x81, 0x01, 0xe3, 0x00, + 0x84, 0x00, 0x31, 0x00, 0xf5, 0xff, 0xb2, 0xff, 0x8e, 0xff, 0x92, 0xff, + 0xa1, 0xff, 0xf9, 0xff, 0x77, 0x00, 0xd1, 0x00, 0x47, 0x01, 0xab, 0x01, + 0x09, 0x02, 0x88, 0x02, 0x14, 0x03, 0x85, 0x03, 0xd5, 0x03, 0xea, 0x03, + 0xec, 0x03, 0x11, 0x04, 0x1a, 0x04, 0x1c, 0x04, 0x0b, 0x04, 0xa3, 0x03, + 0x48, 0x03, 0x22, 0x03, 0xf4, 0x02, 0xd4, 0x02, 0x92, 0x02, 0x30, 0x02, + 0xf7, 0x01, 0xea, 0x01, 0xd4, 0x01, 0xd1, 0x01, 0x8f, 0x01, 0x53, 0x01, + 0x44, 0x01, 0x34, 0x01, 0x1b, 0x01, 0xd5, 0x00, 0x67, 0x00, 0x1f, 0x00, + 0xea, 0xff, 0x8e, 0xff, 0x1e, 0xff, 0xa0, 0xfe, 0x39, 0xfe, 0xd8, 0xfd, + 0x75, 0xfd, 0x1f, 0xfd, 0xfc, 0xfc, 0xdc, 0xfc, 0xa5, 0xfc, 0x8c, 0xfc, + 0xbc, 0xfc, 0x1d, 0xfd, 0x78, 0xfd, 0xd7, 0xfd, 0x45, 0xfe, 0xc5, 0xfe, + 0x6e, 0xff, 0x13, 0x00, 0xbd, 0x00, 0x3b, 0x01, 0xbf, 0x01, 0x33, 0x02, + 0x82, 0x02, 0xa0, 0x02, 0xb1, 0x02, 0xb2, 0x02, 0x82, 0x02, 0x24, 0x02, + 0x9c, 0x01, 0x36, 0x01, 0xc3, 0x00, 0x21, 0x00, 0x7a, 0xff, 0xe0, 0xfe, + 0x52, 0xfe, 0xb8, 0xfd, 0x0d, 0xfd, 0x61, 0xfc, 0xda, 0xfb, 0x3b, 0xfb, + 0x65, 0xfa, 0xa1, 0xf9, 0xde, 0xf8, 0x62, 0xf8, 0xa5, 0xf7, 0xbf, 0xf6, + 0xff, 0xf5, 0x35, 0xf5, 0xe7, 0xf4, 0xb9, 0xf4, 0x70, 0xf4, 0x4d, 0xf4, + 0x54, 0xf4, 0x97, 0xf4, 0x5a, 0xf5, 0x2c, 0xf6, 0x29, 0xf7, 0x19, 0xf8, + 0xfe, 0xf8, 0x3d, 0xfa, 0xb7, 0xfb, 0x23, 0xfd, 0x20, 0xfe, 0x1b, 0xff, + 0x1a, 0x00, 0x0d, 0x01, 0xe4, 0x01, 0x72, 0x02, 0xe0, 0x02, 0x3a, 0x03, + 0x5d, 0x03, 0x6b, 0x03, 0x70, 0x03, 0x99, 0x03, 0xad, 0x03, 0x98, 0x03, + 0x81, 0x03, 0x86, 0x03, 0xcf, 0x03, 0x11, 0x04, 0x29, 0x04, 0x37, 0x04, + 0x68, 0x04, 0xa3, 0x04, 0xeb, 0x04, 0xd9, 0x04, 0xbf, 0x04, 0xf5, 0x04, + 0xf4, 0x04, 0xa3, 0x04, 0x3c, 0x04, 0xea, 0x03, 0xbb, 0x03, 0x8a, 0x03, + 0xdd, 0x02, 0x4d, 0x02, 0xf4, 0x01, 0x82, 0x01, 0x27, 0x01, 0xd9, 0x00, + 0x88, 0x00, 0x81, 0x00, 0x6c, 0x00, 0x57, 0x00, 0x4d, 0x00, 0x9c, 0x00, + 0x02, 0x01, 0x50, 0x01, 0xba, 0x01, 0x01, 0x02, 0x58, 0x02, 0xd7, 0x02, + 0x40, 0x03, 0x94, 0x03, 0xf2, 0x03, 0x1b, 0x04, 0x0f, 0x04, 0x12, 0x04, + 0x10, 0x04, 0x0c, 0x04, 0xf8, 0x03, 0x93, 0x03, 0x4b, 0x03, 0xff, 0x02, + 0xb5, 0x02, 0x87, 0x02, 0x4d, 0x02, 0xf7, 0x01, 0xd6, 0x01, 0x9b, 0x01, + 0x60, 0x01, 0x46, 0x01, 0x30, 0x01, 0x24, 0x01, 0x05, 0x01, 0xbe, 0x00, + 0x76, 0x00, 0x63, 0x00, 0x3e, 0x00, 0x08, 0x00, 0xa7, 0xff, 0x5d, 0xff, + 0x16, 0xff, 0xae, 0xfe, 0x4e, 0xfe, 0x1a, 0xfe, 0x17, 0xfe, 0xec, 0xfd, + 0xa9, 0xfd, 0x81, 0xfd, 0x61, 0xfd, 0x9d, 0xfd, 0x00, 0xfe, 0x51, 0xfe, + 0x99, 0xfe, 0xc6, 0xfe, 0x16, 0xff, 0x8e, 0xff, 0x16, 0x00, 0xa9, 0x00, + 0x1b, 0x01, 0x5e, 0x01, 0x97, 0x01, 0xb8, 0x01, 0xb7, 0x01, 0xc0, 0x01, + 0xcb, 0x01, 0xab, 0x01, 0x5a, 0x01, 0xc8, 0x00, 0x57, 0x00, 0x1b, 0x00, + 0xd1, 0xff, 0x7f, 0xff, 0x1f, 0xff, 0x80, 0xfe, 0xd9, 0xfd, 0x65, 0xfd, + 0xf6, 0xfc, 0x87, 0xfc, 0x0e, 0xfc, 0x8e, 0xfb, 0xa7, 0xfa, 0xcc, 0xf9, + 0x44, 0xf9, 0xb5, 0xf8, 0x28, 0xf8, 0x9c, 0xf7, 0xf6, 0xf6, 0x1b, 0xf6, + 0xd0, 0xf5, 0x79, 0xf5, 0x77, 0xf5, 0x68, 0xf5, 0xb3, 0xf5, 0xe7, 0xf5, + 0x61, 0xf6, 0xbe, 0xf6, 0x74, 0xf7, 0xc2, 0xf8, 0xda, 0xf9, 0xec, 0xfa, + 0xc2, 0xfb, 0xa1, 0xfc, 0xa0, 0xfd, 0x06, 0xff, 0xed, 0xff, 0xb6, 0x00, + 0x43, 0x01, 0xb0, 0x01, 0x02, 0x02, 0x54, 0x02, 0xbf, 0x02, 0xbd, 0x02, + 0xbf, 0x02, 0xa2, 0x02, 0x8b, 0x02, 0x9c, 0x02, 0xbe, 0x02, 0xd3, 0x02, + 0xb4, 0x02, 0xb8, 0x02, 0x0b, 0x03, 0x7f, 0x03, 0xc5, 0x03, 0xd3, 0x03, + 0xbf, 0x03, 0x1f, 0x04, 0x8f, 0x04, 0xde, 0x04, 0xc0, 0x04, 0xa3, 0x04, + 0x67, 0x04, 0x3b, 0x04, 0x2b, 0x04, 0xf0, 0x03, 0x82, 0x03, 0x09, 0x03, + 0x97, 0x02, 0x21, 0x02, 0xa2, 0x01, 0x73, 0x01, 0x5a, 0x01, 0x14, 0x01, + 0xe9, 0x00, 0xd0, 0x00, 0xeb, 0x00, 0x31, 0x01, 0x9b, 0x01, 0xe4, 0x01, + 0x2e, 0x02, 0x8a, 0x02, 0xcc, 0x02, 0x3f, 0x03, 0xde, 0x03, 0xed, 0x03, + 0xde, 0x03, 0xcf, 0x03, 0xcb, 0x03, 0xf2, 0x03, 0xae, 0x03, 0x34, 0x03, + 0xbb, 0x02, 0x42, 0x02, 0xff, 0x01, 0xb9, 0x01, 0x70, 0x01, 0x07, 0x01, + 0xbc, 0x00, 0x8c, 0x00, 0x81, 0x00, 0x85, 0x00, 0x8d, 0x00, 0xcd, 0x00, + 0xdd, 0x00, 0xe0, 0x00, 0xc1, 0x00, 0xcb, 0x00, 0x02, 0x01, 0x2d, 0x01, + 0xe7, 0x00, 0xad, 0x00, 0x59, 0x00, 0x39, 0x00, 0x01, 0x00, 0x80, 0xff, + 0x29, 0xff, 0x0f, 0xff, 0x23, 0xff, 0xe4, 0xfe, 0x5e, 0xfe, 0x2a, 0xfe, + 0x49, 0xfe, 0xbf, 0xfe, 0x3c, 0xff, 0x58, 0xff, 0x6a, 0xff, 0x8a, 0xff, + 0xed, 0xff, 0x6d, 0x00, 0xe2, 0x00, 0x4c, 0x01, 0x7d, 0x01, 0x7a, 0x01, + 0x69, 0x01, 0x5e, 0x01, 0x86, 0x01, 0xa5, 0x01, 0x86, 0x01, 0x44, 0x01, + 0xbe, 0x00, 0x4f, 0x00, 0x15, 0x00, 0x0f, 0x00, 0xfe, 0xff, 0xaa, 0xff, + 0x73, 0xff, 0xd2, 0xfe, 0x88, 0xfe, 0x53, 0xfe, 0x46, 0xfe, 0x14, 0xfe, + 0xaf, 0xfd, 0x0a, 0xfd, 0x62, 0xfc, 0x20, 0xfc, 0xd7, 0xfb, 0x61, 0xfb, + 0xc8, 0xfa, 0xeb, 0xf9, 0x6d, 0xf9, 0x0c, 0xf9, 0xbc, 0xf8, 0x5e, 0xf8, + 0xda, 0xf7, 0x96, 0xf7, 0x76, 0xf7, 0x89, 0xf7, 0x95, 0xf7, 0x9d, 0xf7, + 0x07, 0xf8, 0x49, 0xf8, 0xb5, 0xf8, 0x64, 0xf9, 0xfb, 0xf9, 0xc5, 0xfa, + 0x7e, 0xfb, 0x27, 0xfc, 0xc5, 0xfc, 0x4c, 0xfd, 0x06, 0xfe, 0x9d, 0xfe, + 0x47, 0xff, 0xc5, 0xff, 0xe8, 0xff, 0x2c, 0x00, 0xa2, 0x00, 0x09, 0x01, + 0x3d, 0x01, 0x33, 0x01, 0x3b, 0x01, 0x79, 0x01, 0xaf, 0x01, 0xd0, 0x01, + 0xc4, 0x01, 0xef, 0x01, 0x42, 0x02, 0xa3, 0x02, 0xb1, 0x02, 0xba, 0x02, + 0xf3, 0x02, 0x2f, 0x03, 0x5a, 0x03, 0x85, 0x03, 0x9d, 0x03, 0x64, 0x03, + 0x3d, 0x03, 0x41, 0x03, 0x59, 0x03, 0x65, 0x03, 0x31, 0x03, 0xd1, 0x02, + 0x6e, 0x02, 0x80, 0x02, 0x8f, 0x02, 0x83, 0x02, 0x43, 0x02, 0x14, 0x02, + 0xeb, 0x01, 0xe9, 0x01, 0x0b, 0x02, 0x21, 0x02, 0x1e, 0x02, 0x1f, 0x02, + 0x16, 0x02, 0x2b, 0x02, 0x56, 0x02, 0x79, 0x02, 0x6f, 0x02, 0x62, 0x02, + 0x70, 0x02, 0x73, 0x02, 0x6c, 0x02, 0x64, 0x02, 0x52, 0x02, 0x41, 0x02, + 0x54, 0x02, 0x3a, 0x02, 0x37, 0x02, 0x3b, 0x02, 0x21, 0x02, 0x2f, 0x02, + 0x22, 0x02, 0x19, 0x02, 0x22, 0x02, 0x09, 0x02, 0xe5, 0x01, 0xe7, 0x01, + 0xc2, 0x01, 0xa7, 0x01, 0x97, 0x01, 0x7a, 0x01, 0x66, 0x01, 0x33, 0x01, + 0x12, 0x01, 0xe2, 0x00, 0xe4, 0x00, 0xd8, 0x00, 0x8e, 0x00, 0x6c, 0x00, + 0x73, 0x00, 0x71, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x47, 0x00, 0x1d, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x26, 0x00, 0x1d, 0x00, 0x0a, 0x00, 0xfa, 0xff, + 0x07, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x0b, 0x00, 0x37, 0x00, 0x62, 0x00, + 0x55, 0x00, 0x64, 0x00, 0x58, 0x00, 0x9e, 0x00, 0xbf, 0x00, 0xcd, 0x00, + 0xca, 0x00, 0xb0, 0x00, 0xc4, 0x00, 0x9f, 0x00, 0x88, 0x00, 0x81, 0x00, + 0x4f, 0x00, 0xe5, 0xff, 0x5f, 0xff, 0x04, 0xff, 0xd5, 0xfe, 0xab, 0xfe, + 0x70, 0xfe, 0xfa, 0xfd, 0x88, 0xfd, 0xb2, 0xfd, 0xb9, 0xfd, 0xa1, 0xfd, + 0x90, 0xfd, 0x5b, 0xfd, 0x5f, 0xfd, 0x0c, 0xfd, 0x23, 0xfd, 0xe8, 0xfc, + 0x87, 0xfc, 0x2b, 0xfc, 0xa4, 0xfb, 0x5e, 0xfb, 0x3c, 0xfb, 0xe6, 0xfa, + 0x58, 0xfa, 0x0b, 0xfa, 0xe5, 0xf9, 0xdb, 0xf9, 0xe0, 0xf9, 0xde, 0xf9, + 0x05, 0xfa, 0x54, 0xfa, 0x93, 0xfa, 0x06, 0xfb, 0x61, 0xfb, 0xad, 0xfb, + 0x00, 0xfc, 0x64, 0xfc, 0xc8, 0xfc, 0xd2, 0xfc, 0x02, 0xfd, 0x71, 0xfd, + 0xaf, 0xfd, 0xc0, 0xfd, 0xa2, 0xfd, 0x83, 0xfd, 0xaf, 0xfd, 0x1f, 0xfe, + 0x2f, 0xfe, 0x15, 0xfe, 0x36, 0xfe, 0x87, 0xfe, 0xea, 0xfe, 0x74, 0xff, + 0xd5, 0xff, 0x47, 0x00, 0x75, 0x00, 0xfd, 0x00, 0x8c, 0x01, 0xd1, 0x01, + 0x70, 0x02, 0x99, 0x02, 0x80, 0x02, 0x97, 0x02, 0xc4, 0x02, 0xda, 0x02, + 0xc9, 0x02, 0xa8, 0x02, 0x89, 0x02, 0x84, 0x02, 0x52, 0x02, 0x16, 0x02, + 0x28, 0x02, 0x42, 0x02, 0x3d, 0x02, 0x30, 0x02, 0x1f, 0x02, 0x2b, 0x02, + 0x56, 0x02, 0x67, 0x02, 0x6e, 0x02, 0x89, 0x02, 0xc9, 0x02, 0xc5, 0x02, + 0xa6, 0x02, 0xc4, 0x02, 0xc1, 0x02, 0xc7, 0x02, 0x98, 0x02, 0x86, 0x02, + 0x60, 0x02, 0x56, 0x02, 0x2b, 0x02, 0x0f, 0x02, 0xf3, 0x01, 0xd0, 0x01, + 0xd4, 0x01, 0xad, 0x01, 0x96, 0x01, 0xbc, 0x01, 0xad, 0x01, 0x9f, 0x01, + 0xc4, 0x01, 0xf7, 0x01, 0x1a, 0x02, 0x35, 0x02, 0x14, 0x02, 0x17, 0x02, + 0x28, 0x02, 0x1f, 0x02, 0x07, 0x02, 0xcf, 0x01, 0x91, 0x01, 0x5c, 0x01, + 0x45, 0x01, 0x09, 0x01, 0xd8, 0x00, 0xa1, 0x00, 0x80, 0x00, 0x60, 0x00, + 0x3b, 0x00, 0x22, 0x00, 0x12, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xfe, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, + 0xf8, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0xf8, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0xf7, 0xff, 0xf7, 0xff, + 0xf6, 0xff, 0xf3, 0xff, 0xf3, 0xff, 0xf3, 0xff, 0xf5, 0xff, 0xf5, 0xff, + 0xf5, 0xff, 0xf6, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0xfa, 0xff, 0xfa, 0xff, + 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfc, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, + 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xf8, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf8, 0xff, 0xf8, 0xff, + 0xf8, 0xff, 0xf8, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, + 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf8, 0xff, + 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, + 0xf9, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xfe, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, + 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x07, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, + 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +uint32_t right_channel_bin_len = 46390; +uint8_t left_channel_bin[] = { + 0x52, 0x49, 0x46, 0x46, 0x2a, 0xba, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, + 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0xc0, 0x5d, 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, + 0x64, 0x61, 0x74, 0x61, 0x06, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0xfb, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0xee, 0xff, 0xed, 0xff, + 0xec, 0xff, 0xed, 0xff, 0xec, 0xff, 0xed, 0xff, 0xef, 0xff, 0xf3, 0xff, + 0x01, 0x00, 0x04, 0x00, 0xe8, 0xff, 0xf6, 0xff, 0x08, 0x00, 0x06, 0x00, + 0x09, 0x00, 0x10, 0x00, 0x39, 0x00, 0x5c, 0x00, 0x6e, 0x00, 0x65, 0x00, + 0x6e, 0x00, 0x88, 0x00, 0x80, 0x00, 0x70, 0x00, 0x78, 0x00, 0xab, 0x00, + 0xa1, 0x00, 0xa9, 0x00, 0xab, 0x00, 0xe1, 0x00, 0x21, 0x01, 0x3c, 0x01, + 0x3a, 0x01, 0x3f, 0x01, 0x55, 0x01, 0x88, 0x01, 0xe4, 0x01, 0x02, 0x02, + 0xeb, 0x01, 0xef, 0x01, 0x1c, 0x02, 0x1a, 0x02, 0x3d, 0x02, 0x45, 0x02, + 0x3f, 0x02, 0x1e, 0x02, 0x1b, 0x02, 0x5d, 0x02, 0xb7, 0x02, 0x3c, 0x03, + 0x01, 0x03, 0x31, 0x03, 0x5e, 0x03, 0x47, 0x03, 0x8d, 0x03, 0xf2, 0x03, + 0xe4, 0x03, 0xc7, 0x03, 0x2d, 0x03, 0x32, 0x03, 0xba, 0x03, 0x3e, 0x03, + 0xb3, 0x02, 0x54, 0x02, 0x14, 0x02, 0xd5, 0x01, 0x4e, 0x01, 0xcc, 0x00, + 0xee, 0xff, 0xeb, 0xfe, 0x97, 0xfe, 0x08, 0xfe, 0x83, 0xfd, 0xe7, 0xfc, + 0x52, 0xfc, 0x0b, 0xfc, 0x78, 0xfc, 0xc0, 0xfb, 0xe2, 0xfa, 0x3a, 0xfb, + 0x57, 0xfb, 0x07, 0xfb, 0x9b, 0xfa, 0x09, 0xfa, 0x18, 0xfa, 0xee, 0xfa, + 0xb7, 0xfa, 0x1e, 0xfa, 0x4e, 0xf9, 0x39, 0xf9, 0x7d, 0xf9, 0x21, 0xfa, + 0xcb, 0xfa, 0x9e, 0xfa, 0xa1, 0xfa, 0x92, 0xfa, 0x52, 0xfb, 0x8e, 0xfb, + 0xa4, 0xfb, 0x5e, 0xfb, 0x03, 0xfc, 0x0c, 0xfd, 0xc3, 0xfd, 0xfe, 0xfd, + 0xda, 0xfd, 0x6e, 0xfe, 0x1d, 0xff, 0xf6, 0xff, 0x02, 0x00, 0xfc, 0xff, + 0x4b, 0x00, 0xcc, 0x00, 0x40, 0x01, 0x87, 0x01, 0xf0, 0x01, 0x2e, 0x02, + 0xf6, 0x02, 0x78, 0x03, 0xa4, 0x03, 0x3f, 0x04, 0x8f, 0x04, 0xdf, 0x04, + 0x11, 0x05, 0x97, 0x04, 0x05, 0x05, 0x57, 0x05, 0xae, 0x05, 0xb2, 0x05, + 0x84, 0x05, 0xc2, 0x05, 0x86, 0x05, 0x9f, 0x05, 0xfb, 0x05, 0x0e, 0x06, + 0x10, 0x06, 0xec, 0x05, 0xc4, 0x05, 0xc1, 0x05, 0xa1, 0x05, 0xa2, 0x06, + 0xba, 0x06, 0xbd, 0x05, 0xe9, 0x05, 0xf0, 0x05, 0x9a, 0x06, 0xfd, 0x06, + 0x45, 0x06, 0x3b, 0x06, 0x8d, 0x05, 0x69, 0x05, 0x8e, 0x05, 0x09, 0x05, + 0xbd, 0x04, 0x5f, 0x04, 0xcd, 0x03, 0xd7, 0x03, 0x74, 0x03, 0x81, 0x02, + 0x6e, 0x01, 0x21, 0x00, 0x1a, 0xff, 0xe3, 0xfe, 0x4b, 0xfe, 0x3f, 0xfd, + 0xc3, 0xfb, 0x0d, 0xfb, 0x8a, 0xf9, 0x15, 0xf8, 0x6a, 0xf7, 0x92, 0xf7, + 0xb3, 0xf7, 0xe6, 0xf7, 0xc3, 0xf6, 0xce, 0xf5, 0xc4, 0xf5, 0xe1, 0xf5, + 0xdd, 0xf5, 0x0e, 0xf5, 0xa4, 0xf4, 0xe5, 0xf4, 0xe9, 0xf4, 0x60, 0xf4, + 0xac, 0xf4, 0xba, 0xf4, 0xb2, 0xf5, 0xad, 0xf6, 0xf7, 0xf6, 0x4a, 0xf7, + 0x63, 0xf7, 0xad, 0xf7, 0xe4, 0xf8, 0x89, 0xf9, 0xc0, 0xf9, 0x80, 0xfa, + 0x93, 0xfb, 0xac, 0xfc, 0xae, 0xfd, 0x51, 0xfe, 0xf3, 0xfe, 0x91, 0x00, + 0x12, 0x02, 0x4a, 0x03, 0x60, 0x03, 0x84, 0x03, 0x6a, 0x04, 0xdd, 0x04, + 0xa3, 0x05, 0x45, 0x06, 0xeb, 0x06, 0xd6, 0x07, 0x74, 0x08, 0xaa, 0x08, + 0xdd, 0x08, 0x17, 0x09, 0xb8, 0x09, 0x27, 0x0a, 0x60, 0x0a, 0x7e, 0x0a, + 0xff, 0x0a, 0x18, 0x0b, 0x08, 0x0b, 0x3a, 0x0b, 0x97, 0x0b, 0xfe, 0x0b, + 0xd7, 0x0b, 0x1c, 0x0b, 0xc8, 0x0a, 0x85, 0x0a, 0x4f, 0x0a, 0x8c, 0x0a, + 0x4a, 0x0a, 0xc0, 0x09, 0x80, 0x09, 0xf5, 0x08, 0xc0, 0x08, 0xe4, 0x08, + 0x10, 0x08, 0x4a, 0x06, 0x89, 0x05, 0x51, 0x05, 0x7a, 0x04, 0xd6, 0x02, + 0x2a, 0x01, 0x5d, 0x00, 0x20, 0x00, 0xb6, 0xff, 0x24, 0xfe, 0xc6, 0xfa, + 0x8e, 0xf9, 0xfc, 0xf9, 0xe8, 0xf9, 0x67, 0xf8, 0x84, 0xf5, 0x67, 0xf5, + 0xc7, 0xf6, 0x4c, 0xf6, 0xb9, 0xf5, 0x47, 0xf4, 0x12, 0xf3, 0xa4, 0xf3, + 0xdd, 0xf3, 0x8f, 0xf3, 0x5f, 0xf2, 0x14, 0xf1, 0xa3, 0xf0, 0xb7, 0xf0, + 0xa1, 0xf1, 0x89, 0xf2, 0x7a, 0xf2, 0xa5, 0xf2, 0xea, 0xf2, 0xa1, 0xf3, + 0x5d, 0xf4, 0x01, 0xf5, 0x7a, 0xf5, 0x8a, 0xf5, 0x03, 0xf6, 0x4e, 0xf7, + 0xe7, 0xf8, 0x41, 0xf9, 0xa7, 0xf9, 0x0b, 0xfb, 0x03, 0xfd, 0x2f, 0xff, + 0x30, 0x00, 0xfd, 0x00, 0x2c, 0x01, 0xf8, 0x01, 0xa2, 0x03, 0xa6, 0x04, + 0x55, 0x05, 0xaa, 0x05, 0x00, 0x07, 0x3f, 0x08, 0xd0, 0x08, 0xb4, 0x09, + 0x30, 0x0a, 0xbc, 0x0a, 0xf0, 0x0b, 0x24, 0x0c, 0xe7, 0x0b, 0x00, 0x0c, + 0x7a, 0x0c, 0x30, 0x0d, 0xe2, 0x0c, 0x01, 0x0d, 0x4a, 0x0d, 0x9f, 0x0d, + 0xa8, 0x0d, 0x36, 0x0d, 0x0c, 0x0d, 0x97, 0x0c, 0xad, 0x0c, 0xce, 0x0c, + 0xe5, 0x0b, 0xb0, 0x0b, 0x59, 0x0b, 0xe7, 0x0a, 0xc0, 0x0a, 0x38, 0x0a, + 0xb0, 0x09, 0x08, 0x09, 0xbe, 0x08, 0x6d, 0x08, 0xf0, 0x06, 0xbf, 0x05, + 0xd7, 0x04, 0x0d, 0x05, 0x20, 0x04, 0xe4, 0x02, 0x00, 0x02, 0x35, 0x00, + 0xd0, 0xfd, 0x28, 0xfd, 0x2d, 0xfc, 0x24, 0xfa, 0xc7, 0xf8, 0xde, 0xf6, + 0x2c, 0xf6, 0x5d, 0xf6, 0x74, 0xf5, 0x3f, 0xf5, 0x33, 0xf4, 0xb4, 0xf2, + 0xf9, 0xf2, 0xe3, 0xf2, 0xd6, 0xf2, 0x04, 0xf2, 0xf9, 0xef, 0xf7, 0xee, + 0xc8, 0xef, 0x12, 0xf1, 0x74, 0xf0, 0xbf, 0xee, 0x3c, 0xf0, 0x79, 0xf1, + 0x40, 0xf1, 0x5c, 0xf1, 0xd9, 0xf1, 0xf3, 0xf2, 0xdf, 0xf3, 0xcf, 0xf3, + 0xcb, 0xf3, 0x90, 0xf4, 0x9f, 0xf5, 0x5c, 0xf7, 0x3c, 0xf9, 0x02, 0xfa, + 0x60, 0xfb, 0xcc, 0xfc, 0x7d, 0xfe, 0x11, 0x00, 0x3e, 0x01, 0x67, 0x02, + 0x33, 0x03, 0xbf, 0x04, 0x4a, 0x06, 0x2d, 0x07, 0x49, 0x08, 0x43, 0x09, + 0xb9, 0x0a, 0x54, 0x0c, 0x23, 0x0d, 0xc0, 0x0d, 0x6a, 0x0e, 0x0d, 0x0f, + 0x1c, 0x0f, 0x48, 0x0f, 0x62, 0x0f, 0xcb, 0x0e, 0xfb, 0x0e, 0x83, 0x0f, + 0x99, 0x0f, 0x48, 0x0f, 0x30, 0x0f, 0x28, 0x0f, 0x02, 0x0f, 0x6f, 0x0e, + 0xb5, 0x0d, 0x78, 0x0c, 0xd0, 0x0b, 0x34, 0x0b, 0xc1, 0x0a, 0x18, 0x0a, + 0x12, 0x09, 0x5b, 0x08, 0x8d, 0x07, 0x72, 0x06, 0x17, 0x05, 0xf9, 0x03, + 0xae, 0x03, 0xcf, 0x02, 0xd0, 0x00, 0xf5, 0xfe, 0x4c, 0xfe, 0xb3, 0xfd, + 0x1b, 0xfd, 0x63, 0xfb, 0x9a, 0xf7, 0x62, 0xf6, 0xd7, 0xf7, 0xc8, 0xf7, + 0x15, 0xf6, 0x6e, 0xf4, 0x22, 0xf3, 0x5f, 0xf3, 0xb8, 0xf3, 0xe3, 0xf2, + 0x15, 0xf2, 0x3c, 0xf2, 0x19, 0xf1, 0x8c, 0xf1, 0x98, 0xf1, 0x65, 0xef, + 0xfc, 0xef, 0x7b, 0xf0, 0x76, 0xf1, 0xac, 0xf2, 0x59, 0xf2, 0xb7, 0xf1, + 0x9e, 0xf2, 0xda, 0xf3, 0x33, 0xf4, 0xca, 0xf4, 0x9d, 0xf4, 0x16, 0xf5, + 0x21, 0xf6, 0x9e, 0xf7, 0xfd, 0xf7, 0xb8, 0xf8, 0x85, 0xfa, 0x31, 0xfc, + 0x01, 0xfe, 0x32, 0xff, 0x49, 0x00, 0x8e, 0x01, 0x75, 0x02, 0x74, 0x03, + 0xa8, 0x04, 0x59, 0x05, 0xaa, 0x06, 0xf9, 0x07, 0x16, 0x09, 0x55, 0x0a, + 0x5a, 0x0b, 0xa9, 0x0c, 0x2c, 0x0d, 0xee, 0x0d, 0x32, 0x0e, 0x64, 0x0e, + 0xa0, 0x0e, 0x40, 0x0e, 0xb2, 0x0e, 0x9e, 0x0e, 0xfa, 0x0d, 0xed, 0x0d, + 0x2e, 0x0e, 0xf5, 0x0e, 0xe1, 0x0e, 0xd1, 0x0d, 0xda, 0x0c, 0x96, 0x0c, + 0xa2, 0x0c, 0xd7, 0x0b, 0xaf, 0x0a, 0xdd, 0x09, 0x7e, 0x09, 0x19, 0x09, + 0x23, 0x08, 0x0d, 0x07, 0xb5, 0x06, 0xea, 0x06, 0x21, 0x06, 0x62, 0x04, + 0x92, 0x02, 0x6d, 0x01, 0xee, 0x00, 0x2b, 0x00, 0x62, 0xfe, 0x5a, 0xfc, + 0xeb, 0xfa, 0x63, 0xfa, 0xb5, 0xf9, 0xd0, 0xf7, 0xad, 0xf5, 0xaf, 0xf4, + 0x16, 0xf5, 0x35, 0xf5, 0xf6, 0xf3, 0xc7, 0xf2, 0xea, 0xf1, 0x5b, 0xf2, + 0xf7, 0xf2, 0x8c, 0xf3, 0xc3, 0xf1, 0x53, 0xef, 0xc9, 0xef, 0x79, 0xf0, + 0xc7, 0xf0, 0xbb, 0xf0, 0xfa, 0xef, 0x94, 0xef, 0xae, 0xf0, 0x3b, 0xf2, + 0x3e, 0xf3, 0xe9, 0xf2, 0x05, 0xf3, 0xc9, 0xf3, 0xa7, 0xf4, 0x79, 0xf4, + 0xe6, 0xf4, 0x56, 0xf6, 0xe7, 0xf7, 0x8c, 0xf9, 0xcd, 0xfa, 0x59, 0xfb, + 0x4d, 0xfd, 0xd8, 0xff, 0x8d, 0x01, 0x16, 0x02, 0xdf, 0x02, 0x3f, 0x04, + 0xf0, 0x05, 0x71, 0x07, 0xc6, 0x07, 0x1b, 0x09, 0xa0, 0x0a, 0xd1, 0x0b, + 0x15, 0x0d, 0x6b, 0x0d, 0x4d, 0x0e, 0x59, 0x0f, 0x33, 0x10, 0xe5, 0x0f, + 0x4d, 0x0f, 0x1e, 0x10, 0x0d, 0x11, 0x52, 0x11, 0x90, 0x11, 0xf1, 0x10, + 0xf2, 0x0f, 0x95, 0x0f, 0x45, 0x10, 0x25, 0x10, 0x78, 0x0e, 0xf8, 0x0c, + 0x90, 0x0c, 0x34, 0x0c, 0x80, 0x0b, 0x40, 0x0a, 0xee, 0x08, 0x5d, 0x08, + 0x2e, 0x08, 0x32, 0x07, 0x55, 0x05, 0xdc, 0x03, 0x14, 0x03, 0x6e, 0x02, + 0x5c, 0x00, 0x05, 0xfe, 0x32, 0xfc, 0xe6, 0xfb, 0x39, 0xfb, 0x73, 0xf9, + 0x14, 0xf7, 0xbe, 0xf4, 0x88, 0xf4, 0x5d, 0xf4, 0xfb, 0xf3, 0x1b, 0xf3, + 0xa8, 0xf1, 0x3b, 0xf2, 0x5c, 0xf2, 0x18, 0xf2, 0x2e, 0xf1, 0x97, 0xef, + 0xd2, 0xef, 0x8c, 0xf0, 0x3c, 0xef, 0xd8, 0xed, 0x69, 0xed, 0xc5, 0xee, + 0x19, 0xf0, 0x67, 0xf0, 0xa4, 0xef, 0x08, 0xf0, 0x46, 0xf1, 0x7b, 0xf2, + 0x83, 0xf2, 0x6e, 0xf2, 0x99, 0xf2, 0x60, 0xf4, 0xf2, 0xf5, 0xd2, 0xf5, + 0x34, 0xf6, 0xfc, 0xf7, 0x89, 0xfa, 0x07, 0xfd, 0x6e, 0xfe, 0xec, 0xfe, + 0xaa, 0xff, 0xb4, 0x00, 0xf7, 0x02, 0x54, 0x04, 0x49, 0x05, 0xe2, 0x05, + 0xdc, 0x06, 0xb3, 0x08, 0x46, 0x0a, 0xf6, 0x0b, 0x58, 0x0d, 0xff, 0x0d, + 0x86, 0x0f, 0x67, 0x10, 0x62, 0x10, 0xab, 0x0f, 0xdd, 0x0f, 0x00, 0x11, + 0x03, 0x12, 0x50, 0x12, 0xd7, 0x11, 0xb9, 0x11, 0x53, 0x12, 0x99, 0x12, + 0xd9, 0x12, 0x53, 0x11, 0x4a, 0x0f, 0x97, 0x0e, 0x47, 0x0e, 0x7b, 0x0d, + 0x07, 0x0c, 0xdd, 0x0a, 0xfe, 0x09, 0x9c, 0x09, 0x00, 0x09, 0x09, 0x08, + 0xfc, 0x06, 0xa6, 0x05, 0xdd, 0x03, 0xfd, 0x01, 0x55, 0x00, 0x0d, 0xff, + 0x05, 0xfe, 0x91, 0xfc, 0x46, 0xfb, 0x79, 0xf9, 0x92, 0xf7, 0x52, 0xf6, + 0xaa, 0xf4, 0xd8, 0xf3, 0x8d, 0xf3, 0xe6, 0xf2, 0xb4, 0xf1, 0xc5, 0xf0, + 0xc6, 0xf0, 0xd8, 0xf0, 0x1a, 0xf1, 0xc7, 0xf0, 0x47, 0xef, 0xf7, 0xee, + 0xc7, 0xee, 0x47, 0xee, 0x83, 0xee, 0x8a, 0xed, 0x7f, 0xee, 0x57, 0xef, + 0x94, 0xef, 0x4b, 0xf0, 0x5e, 0xf0, 0xc4, 0xf1, 0x7c, 0xf2, 0xbc, 0xf1, + 0x90, 0xf2, 0x1b, 0xf4, 0x00, 0xf5, 0x56, 0xf6, 0xa1, 0xf6, 0x54, 0xf7, + 0x66, 0xf9, 0x83, 0xfb, 0xfc, 0xfd, 0xb3, 0xff, 0xd0, 0xff, 0xe3, 0x00, + 0x1a, 0x03, 0xa6, 0x04, 0xba, 0x05, 0xaa, 0x06, 0x1f, 0x08, 0xa6, 0x09, + 0xae, 0x0a, 0xd1, 0x0b, 0xbb, 0x0d, 0x2e, 0x0f, 0xfc, 0x0f, 0x55, 0x10, + 0xb5, 0x10, 0x05, 0x11, 0xb8, 0x11, 0x6d, 0x12, 0x14, 0x12, 0xb1, 0x11, + 0x56, 0x11, 0xaf, 0x11, 0xe0, 0x12, 0x9a, 0x12, 0x3b, 0x11, 0x0f, 0x10, + 0xeb, 0x0f, 0xcb, 0x0f, 0x94, 0x0e, 0xce, 0x0c, 0x8a, 0x0b, 0x36, 0x0b, + 0xb8, 0x0a, 0xf9, 0x09, 0x35, 0x09, 0xbd, 0x07, 0xb8, 0x06, 0x45, 0x06, + 0xd4, 0x04, 0x19, 0x03, 0x0e, 0x01, 0x59, 0xff, 0x98, 0xfe, 0x4b, 0xfd, + 0x97, 0xfb, 0x85, 0xfa, 0x56, 0xf8, 0xc6, 0xf6, 0xe6, 0xf5, 0x5c, 0xf4, + 0xf2, 0xf2, 0x07, 0xf4, 0xb8, 0xf3, 0x79, 0xf1, 0x64, 0xf0, 0x2e, 0xef, + 0xf8, 0xef, 0x38, 0xf1, 0x86, 0xf0, 0xde, 0xee, 0x24, 0xed, 0x7d, 0xed, + 0xad, 0xee, 0x7c, 0xee, 0xb8, 0xed, 0x47, 0xed, 0xfa, 0xed, 0x36, 0xf0, + 0x1d, 0xf1, 0x47, 0xf0, 0xca, 0xef, 0xd8, 0xf0, 0x80, 0xf3, 0x71, 0xf4, + 0x77, 0xf4, 0x92, 0xf3, 0xe3, 0xf3, 0x52, 0xf7, 0xd6, 0xf9, 0x5b, 0xfb, + 0xe9, 0xfb, 0x63, 0xfc, 0x52, 0xff, 0xdf, 0x01, 0xaf, 0x03, 0x8c, 0x04, + 0xec, 0x03, 0xd6, 0x05, 0x6b, 0x08, 0x95, 0x0a, 0x20, 0x0c, 0x72, 0x0c, + 0xb4, 0x0d, 0x74, 0x0f, 0x08, 0x11, 0xc4, 0x11, 0x1a, 0x12, 0x4c, 0x12, + 0x79, 0x12, 0xf7, 0x12, 0x0a, 0x13, 0xa1, 0x12, 0xe6, 0x12, 0xed, 0x12, + 0x48, 0x13, 0x8a, 0x13, 0x10, 0x13, 0xcf, 0x12, 0xd2, 0x11, 0x97, 0x10, + 0xb8, 0x0f, 0xe2, 0x0e, 0xaf, 0x0d, 0x3a, 0x0c, 0x3e, 0x0c, 0x71, 0x0a, + 0x81, 0x08, 0x28, 0x08, 0xc3, 0x07, 0xc2, 0x06, 0x81, 0x04, 0x3a, 0x02, + 0x85, 0xff, 0x36, 0xfe, 0x15, 0xfd, 0x98, 0xfb, 0xab, 0xf9, 0xb5, 0xf8, + 0x8e, 0xf6, 0xfa, 0xf4, 0x85, 0xf3, 0x51, 0xf2, 0x59, 0xf1, 0x7e, 0xef, + 0x44, 0xef, 0xe3, 0xed, 0x0b, 0xee, 0xc2, 0xee, 0x7a, 0xee, 0xd3, 0xed, + 0x61, 0xed, 0x7f, 0xed, 0xb9, 0xee, 0x4e, 0xee, 0x7e, 0xec, 0xae, 0xeb, + 0xdd, 0xeb, 0x38, 0xed, 0x2e, 0xef, 0xef, 0xef, 0x21, 0xf0, 0x52, 0xf1, + 0x7a, 0xf2, 0x16, 0xf4, 0x2d, 0xf5, 0x7a, 0xf5, 0x0f, 0xf6, 0x8a, 0xf7, + 0xbb, 0xf8, 0x93, 0xf9, 0x43, 0xfb, 0x55, 0xfd, 0xfb, 0xfe, 0xa3, 0x00, + 0xe9, 0x02, 0x2f, 0x05, 0x8f, 0x06, 0x1f, 0x08, 0xe4, 0x08, 0xb4, 0x09, + 0x96, 0x0a, 0xbc, 0x0b, 0x64, 0x0d, 0x2d, 0x0f, 0x23, 0x10, 0x72, 0x10, + 0x7b, 0x11, 0xee, 0x11, 0x16, 0x13, 0x35, 0x14, 0xfc, 0x13, 0x4f, 0x13, + 0x10, 0x13, 0xe2, 0x12, 0x73, 0x12, 0x45, 0x12, 0x74, 0x12, 0x4d, 0x12, + 0x01, 0x12, 0xc3, 0x10, 0x5d, 0x0f, 0xfd, 0x0e, 0x74, 0x0e, 0x55, 0x0d, + 0x17, 0x0b, 0x72, 0x09, 0x01, 0x09, 0x8d, 0x08, 0x8a, 0x08, 0x29, 0x07, + 0x05, 0x05, 0xbf, 0x03, 0xc5, 0x02, 0x02, 0x02, 0x33, 0x00, 0x67, 0xfd, + 0x2b, 0xfb, 0x09, 0xfa, 0xbd, 0xf8, 0x7f, 0xf7, 0x7a, 0xf5, 0x62, 0xf2, + 0x65, 0xf0, 0x64, 0xef, 0x80, 0xef, 0x98, 0xef, 0xed, 0xed, 0x18, 0xec, + 0x43, 0xeb, 0xe7, 0xeb, 0xc9, 0xed, 0xed, 0xed, 0x2a, 0xec, 0x16, 0xea, + 0x8a, 0xea, 0xec, 0xec, 0x4b, 0xec, 0x45, 0xed, 0x2b, 0xec, 0x62, 0xeb, + 0xdb, 0xee, 0xcc, 0xef, 0x6b, 0xf1, 0x53, 0xf1, 0xac, 0xf1, 0x7e, 0xf3, + 0x9c, 0xf4, 0x04, 0xf6, 0x5b, 0xf7, 0xd6, 0xf8, 0xfc, 0xf9, 0xfa, 0xfa, + 0xe8, 0xfc, 0x92, 0xff, 0x52, 0x02, 0x2e, 0x04, 0x07, 0x05, 0xaf, 0x06, + 0x1d, 0x08, 0x94, 0x0a, 0x3b, 0x0c, 0x21, 0x0c, 0x65, 0x0d, 0x28, 0x0f, + 0xbe, 0x0f, 0x6b, 0x11, 0xf0, 0x11, 0xfe, 0x11, 0x04, 0x14, 0xf8, 0x14, + 0xdf, 0x14, 0xde, 0x14, 0x2c, 0x14, 0xdd, 0x13, 0xb8, 0x14, 0x01, 0x14, + 0xe0, 0x12, 0x03, 0x12, 0xb7, 0x11, 0xa0, 0x11, 0x60, 0x11, 0x14, 0x10, + 0x43, 0x0e, 0x6f, 0x0d, 0x85, 0x0c, 0x89, 0x0b, 0x2d, 0x0a, 0x61, 0x08, + 0xea, 0x07, 0x4c, 0x07, 0x14, 0x06, 0xe3, 0x04, 0x7d, 0x03, 0x37, 0x02, + 0x0f, 0x00, 0xc6, 0xff, 0xba, 0xfd, 0x61, 0xfb, 0x69, 0xfa, 0x4f, 0xf8, + 0x4e, 0xf8, 0x70, 0xf6, 0x6f, 0xf3, 0xc0, 0xf1, 0x47, 0xef, 0x03, 0xef, + 0x1e, 0xef, 0xa1, 0xed, 0x55, 0xec, 0x8c, 0xeb, 0xa4, 0xec, 0xe9, 0xec, + 0x89, 0xed, 0xb0, 0xed, 0x23, 0xed, 0xa5, 0xee, 0xaa, 0xef, 0x46, 0xee, + 0x94, 0xeb, 0x0a, 0xeb, 0xc7, 0xec, 0xed, 0xef, 0x33, 0xf1, 0xb8, 0xef, + 0xfe, 0xee, 0xf6, 0xf0, 0x2e, 0xf4, 0xac, 0xf6, 0x14, 0xf7, 0xa6, 0xf6, + 0x5d, 0xf7, 0xba, 0xf8, 0x9c, 0xfa, 0x9e, 0xfb, 0xd6, 0xfc, 0x83, 0xff, + 0x88, 0x01, 0x1f, 0x03, 0x78, 0x05, 0xe3, 0x06, 0x75, 0x09, 0x26, 0x0b, + 0x99, 0x0b, 0x1c, 0x0d, 0xfa, 0x0d, 0xc1, 0x0f, 0xc5, 0x10, 0x58, 0x11, + 0xdd, 0x11, 0x08, 0x13, 0x41, 0x15, 0x4e, 0x16, 0x56, 0x16, 0xd7, 0x15, + 0xc6, 0x15, 0xda, 0x15, 0x69, 0x14, 0x9f, 0x13, 0x1f, 0x14, 0x6b, 0x13, + 0xc3, 0x12, 0xbd, 0x11, 0x81, 0x10, 0xf5, 0x10, 0xbe, 0x10, 0x7a, 0x0f, + 0x15, 0x0d, 0x45, 0x0c, 0x50, 0x0b, 0xbe, 0x09, 0x9c, 0x08, 0xa5, 0x06, + 0x28, 0x05, 0xcb, 0x03, 0x92, 0x03, 0x3d, 0x02, 0x3e, 0xff, 0xe9, 0xfc, + 0x75, 0xfb, 0xbb, 0xfa, 0xf1, 0xf8, 0x5d, 0xf6, 0xb1, 0xf3, 0xaa, 0xf1, + 0xeb, 0xf0, 0x56, 0xef, 0xa7, 0xec, 0x60, 0xea, 0x00, 0xe9, 0xfc, 0xe9, + 0xe8, 0xee, 0x84, 0xec, 0x46, 0xe8, 0x58, 0xe7, 0x35, 0xe9, 0xa7, 0xef, + 0x9a, 0xf1, 0x71, 0xec, 0x51, 0xe8, 0xe5, 0xe8, 0x3d, 0xec, 0x40, 0xf0, + 0xfd, 0xee, 0xc9, 0xea, 0x54, 0xed, 0x90, 0xf1, 0x65, 0xf6, 0xc9, 0xf6, + 0x2e, 0xf3, 0xd1, 0xf4, 0xf8, 0xf7, 0x3d, 0xfb, 0x9d, 0xfc, 0xe9, 0xfa, + 0x9c, 0xfb, 0xae, 0xfe, 0x14, 0x02, 0x02, 0x05, 0x13, 0x05, 0xc6, 0x06, + 0xf9, 0x08, 0x45, 0x0b, 0xc4, 0x0c, 0xdf, 0x0c, 0x18, 0x0e, 0x61, 0x10, + 0x16, 0x11, 0x58, 0x11, 0xae, 0x10, 0x54, 0x12, 0x1d, 0x15, 0x39, 0x16, + 0xb0, 0x15, 0xb9, 0x14, 0x30, 0x15, 0x2d, 0x16, 0xc8, 0x15, 0xce, 0x14, + 0x3f, 0x13, 0x08, 0x12, 0x00, 0x12, 0x50, 0x11, 0xaa, 0x10, 0x7f, 0x10, + 0xa2, 0x0f, 0x2f, 0x0f, 0xb6, 0x0d, 0x39, 0x0c, 0x4e, 0x0b, 0xfe, 0x09, + 0x27, 0x09, 0x8a, 0x07, 0x7e, 0x05, 0x0b, 0x04, 0x90, 0x03, 0xf7, 0x02, + 0x34, 0x01, 0xca, 0xfe, 0x8d, 0xfd, 0x68, 0xfc, 0xb6, 0xfb, 0x25, 0xf9, + 0x10, 0xf6, 0x14, 0xf4, 0xf5, 0xf1, 0x6a, 0xf0, 0x31, 0xee, 0xe9, 0xeb, + 0x41, 0xea, 0xe8, 0xea, 0xd6, 0xea, 0xc4, 0xea, 0x24, 0xea, 0xaa, 0xe9, + 0x44, 0xeb, 0x84, 0xeb, 0xe7, 0xec, 0xc8, 0xed, 0xe5, 0xeb, 0xa1, 0xeb, + 0x0f, 0xeb, 0x06, 0xeb, 0xd2, 0xec, 0x8a, 0xee, 0x43, 0xef, 0xe1, 0xef, + 0x59, 0xf1, 0xdf, 0xf2, 0xaa, 0xf5, 0xe9, 0xf6, 0xa5, 0xf6, 0xc2, 0xf7, + 0x30, 0xf9, 0x1b, 0xfb, 0x08, 0xfd, 0x95, 0xfd, 0x22, 0xfe, 0x1d, 0x00, + 0x4c, 0x04, 0x76, 0x06, 0x67, 0x07, 0xcb, 0x08, 0x8b, 0x0a, 0x79, 0x0c, + 0x42, 0x0d, 0xfe, 0x0d, 0x99, 0x0e, 0xab, 0x0f, 0x43, 0x11, 0x6e, 0x11, + 0xb3, 0x10, 0xea, 0x12, 0x1f, 0x15, 0xb5, 0x15, 0xd3, 0x15, 0x8d, 0x14, + 0x2a, 0x15, 0xa1, 0x15, 0x11, 0x15, 0x54, 0x14, 0x35, 0x13, 0xb9, 0x12, + 0xec, 0x12, 0xcd, 0x12, 0x5b, 0x11, 0x8f, 0x10, 0xf5, 0x0f, 0x89, 0x0e, + 0x29, 0x0e, 0x13, 0x0d, 0xad, 0x0b, 0x6a, 0x0a, 0x3e, 0x09, 0xab, 0x07, + 0xc9, 0x05, 0xc9, 0x04, 0xc7, 0x03, 0x0a, 0x02, 0xa0, 0x01, 0xf1, 0xfe, + 0xe7, 0xfa, 0xff, 0xf9, 0xb2, 0xf8, 0x43, 0xf7, 0x7f, 0xf5, 0x1d, 0xf1, + 0xbc, 0xee, 0x4a, 0xed, 0x18, 0xec, 0x2f, 0xe9, 0xdb, 0xe8, 0x00, 0xe8, + 0xd1, 0xe8, 0xb7, 0xe9, 0x5f, 0xe7, 0x64, 0xe7, 0x65, 0xe8, 0xa7, 0xea, + 0xc2, 0xeb, 0xd2, 0xea, 0xfc, 0xe8, 0x76, 0xe8, 0x7a, 0xea, 0x65, 0xec, + 0x29, 0xed, 0x82, 0xed, 0x36, 0xee, 0xff, 0xef, 0xbb, 0xf2, 0xc8, 0xf4, + 0xe3, 0xf5, 0x3d, 0xf6, 0xe1, 0xf7, 0x25, 0xfb, 0x80, 0xfc, 0xc1, 0xfc, + 0x09, 0xfd, 0x0f, 0xff, 0xc0, 0x01, 0x3f, 0x05, 0xb4, 0x06, 0xa2, 0x07, + 0xc0, 0x08, 0xa1, 0x0b, 0xb7, 0x0d, 0xf6, 0x0f, 0x16, 0x10, 0xf8, 0x0e, + 0x42, 0x10, 0xb8, 0x11, 0xbe, 0x13, 0xbb, 0x14, 0x71, 0x14, 0x07, 0x15, + 0xfa, 0x15, 0x1f, 0x16, 0x0a, 0x16, 0xf6, 0x15, 0x3e, 0x17, 0x04, 0x17, + 0x1f, 0x15, 0x34, 0x13, 0x34, 0x12, 0xe8, 0x12, 0x9f, 0x12, 0x08, 0x12, + 0x85, 0x10, 0x28, 0x0e, 0xa4, 0x0d, 0x2b, 0x0d, 0x25, 0x0c, 0xc1, 0x0a, + 0xed, 0x08, 0xa9, 0x07, 0xab, 0x06, 0xed, 0x04, 0xbe, 0x02, 0x3d, 0x01, + 0x40, 0x00, 0x87, 0xfe, 0x9b, 0xfc, 0x5f, 0xfa, 0x73, 0xf7, 0x56, 0xf6, + 0xa5, 0xf5, 0x6c, 0xf3, 0x3b, 0xf0, 0xc1, 0xec, 0x53, 0xea, 0x3f, 0xea, + 0xfb, 0xe8, 0x1c, 0xe8, 0x79, 0xe7, 0xed, 0xe6, 0xf5, 0xe5, 0xde, 0xe6, + 0x47, 0xe9, 0x79, 0xeb, 0xff, 0xec, 0x14, 0xec, 0xf2, 0xe9, 0x25, 0xe9, + 0xa3, 0xea, 0xf3, 0xec, 0x36, 0xee, 0x28, 0xee, 0x8b, 0xee, 0xf2, 0xee, + 0x4f, 0xf2, 0x2d, 0xf5, 0x7e, 0xf7, 0x4c, 0xf9, 0x53, 0xfa, 0x02, 0xfc, + 0x3c, 0xfc, 0xf9, 0xfb, 0x98, 0xfe, 0x88, 0x00, 0xf5, 0x02, 0x04, 0x05, + 0x99, 0x05, 0x50, 0x07, 0xe3, 0x09, 0x62, 0x0d, 0xa0, 0x0e, 0xf4, 0x0e, + 0x9b, 0x0f, 0x1f, 0x11, 0x50, 0x12, 0x2b, 0x12, 0x6b, 0x11, 0xb6, 0x11, + 0xc2, 0x13, 0x45, 0x15, 0x8a, 0x15, 0x57, 0x15, 0x35, 0x15, 0x1c, 0x16, + 0x84, 0x16, 0x12, 0x15, 0xf0, 0x12, 0xf7, 0x11, 0x54, 0x12, 0x49, 0x12, + 0x78, 0x11, 0xd4, 0x0f, 0x4f, 0x0e, 0xcb, 0x0d, 0xc7, 0x0d, 0x35, 0x0d, + 0x3b, 0x0c, 0x73, 0x0b, 0x9c, 0x09, 0xe5, 0x06, 0x16, 0x05, 0xea, 0x03, + 0x68, 0x03, 0xa9, 0x02, 0x55, 0x00, 0x80, 0xfd, 0x20, 0xfb, 0xf6, 0xf8, + 0xff, 0xf8, 0xcd, 0xf7, 0x6a, 0xf5, 0x46, 0xf2, 0xcd, 0xee, 0x3e, 0xec, + 0x49, 0xea, 0xd4, 0xe8, 0x99, 0xe7, 0x82, 0xe5, 0xd9, 0xe5, 0x48, 0xe6, + 0x35, 0xe6, 0x30, 0xe8, 0xd4, 0xe7, 0xbf, 0xe8, 0xe4, 0xe9, 0xd7, 0xea, + 0x72, 0xeb, 0x6f, 0xea, 0x5b, 0xe9, 0xed, 0xe9, 0x74, 0xeb, 0xfa, 0xed, + 0xc4, 0xef, 0x91, 0xf0, 0x66, 0xf2, 0xa4, 0xf4, 0x07, 0xf7, 0xaf, 0xfb, + 0x2b, 0xfd, 0xf6, 0xfc, 0x9f, 0xfe, 0x65, 0xff, 0xcc, 0xff, 0x51, 0x02, + 0x3d, 0x04, 0x18, 0x06, 0xea, 0x08, 0x1c, 0x0a, 0x44, 0x0b, 0xdb, 0x0d, + 0x1b, 0x10, 0x76, 0x11, 0xcb, 0x12, 0x69, 0x12, 0xac, 0x11, 0x73, 0x12, + 0x1f, 0x13, 0x78, 0x13, 0x2b, 0x15, 0x08, 0x15, 0xd4, 0x14, 0xb1, 0x14, + 0xbe, 0x14, 0x15, 0x16, 0x19, 0x16, 0x0d, 0x14, 0xc1, 0x12, 0x9d, 0x11, + 0xaf, 0x11, 0xd3, 0x10, 0x15, 0x10, 0xd8, 0x0e, 0x75, 0x0d, 0xa3, 0x0d, + 0xeb, 0x0c, 0x90, 0x0b, 0x56, 0x0a, 0x34, 0x09, 0x6e, 0x08, 0x14, 0x07, + 0x87, 0x04, 0x27, 0x02, 0xed, 0x00, 0xcd, 0xff, 0x46, 0xfe, 0x7f, 0xfc, + 0xae, 0xf9, 0x13, 0xf7, 0x2f, 0xf7, 0xf1, 0xf5, 0x27, 0xf3, 0xe5, 0xef, + 0x2c, 0xec, 0x52, 0xea, 0x8f, 0xe9, 0x30, 0xe7, 0x56, 0xe5, 0x16, 0xe5, + 0x45, 0xe5, 0xbf, 0xe6, 0xf9, 0xe6, 0x96, 0xe6, 0x8e, 0xe8, 0x51, 0xec, + 0xed, 0xec, 0x1d, 0xeb, 0xdd, 0xe8, 0x4c, 0xe9, 0xfb, 0xec, 0x8f, 0xee, + 0x0b, 0xee, 0xca, 0xed, 0xfc, 0xef, 0x97, 0xf4, 0xc2, 0xf8, 0x21, 0xf9, + 0xb9, 0xf8, 0xe8, 0xfa, 0x0f, 0x00, 0x90, 0x03, 0x9a, 0x01, 0xfd, 0xff, + 0xeb, 0x00, 0xd4, 0x03, 0x8e, 0x07, 0xda, 0x08, 0xa0, 0x08, 0xc1, 0x0a, + 0xfc, 0x0d, 0x50, 0x10, 0x82, 0x12, 0x43, 0x12, 0xcf, 0x10, 0xdb, 0x11, + 0x80, 0x11, 0x41, 0x12, 0xe2, 0x12, 0x8d, 0x12, 0x2c, 0x13, 0xe6, 0x13, + 0x25, 0x14, 0x2d, 0x14, 0x7b, 0x14, 0xb2, 0x14, 0x29, 0x14, 0x60, 0x13, + 0xb7, 0x11, 0xf1, 0x10, 0x4d, 0x11, 0x57, 0x10, 0xe0, 0x0e, 0x3c, 0x0e, + 0x21, 0x0e, 0x23, 0x0d, 0x8c, 0x0c, 0xf8, 0x0b, 0x20, 0x0b, 0xf3, 0x09, + 0xd7, 0x07, 0xd8, 0x04, 0xf2, 0x02, 0x8b, 0x01, 0x94, 0xff, 0xa4, 0xfd, + 0xc3, 0xfa, 0x15, 0xf9, 0x9d, 0xf8, 0x51, 0xf7, 0x07, 0xf5, 0xd6, 0xf1, + 0x3f, 0xee, 0xce, 0xeb, 0x36, 0xe9, 0x51, 0xe6, 0x4c, 0xe4, 0x1e, 0xe4, + 0x56, 0xe2, 0x03, 0xe2, 0x40, 0xe3, 0xde, 0xe3, 0x29, 0xe7, 0x20, 0xeb, + 0xa4, 0xea, 0x51, 0xea, 0x99, 0xea, 0xba, 0xe9, 0x56, 0xec, 0x92, 0xed, + 0x11, 0xec, 0x0f, 0xee, 0x43, 0xf1, 0x96, 0xf3, 0x23, 0xf6, 0xd3, 0xf7, + 0xd9, 0xf9, 0x86, 0xfd, 0x31, 0x00, 0xd9, 0x01, 0xda, 0x03, 0xc7, 0x04, + 0x2f, 0x05, 0xb0, 0x05, 0x99, 0x06, 0xef, 0x08, 0x4e, 0x0c, 0x17, 0x0e, + 0x4e, 0x0f, 0xa9, 0x0f, 0x32, 0x10, 0xc0, 0x11, 0x42, 0x13, 0x10, 0x14, + 0xfa, 0x12, 0x9b, 0x11, 0x88, 0x10, 0xb3, 0x10, 0xb0, 0x11, 0xe4, 0x12, + 0x0c, 0x13, 0xcb, 0x12, 0xdb, 0x11, 0xd0, 0x11, 0x15, 0x13, 0xb9, 0x12, + 0x1c, 0x12, 0x2e, 0x11, 0x37, 0x10, 0x5f, 0x0f, 0x85, 0x0e, 0xe0, 0x0d, + 0x30, 0x0e, 0xff, 0x0d, 0xe4, 0x0d, 0x5a, 0x0c, 0x12, 0x0b, 0x09, 0x0a, + 0x2c, 0x09, 0x2b, 0x08, 0xac, 0x05, 0xe2, 0x02, 0x51, 0x00, 0x0f, 0xfe, + 0xb1, 0xfc, 0x1e, 0xfb, 0x95, 0xf8, 0xd4, 0xf5, 0x1d, 0xf3, 0xaf, 0xf0, + 0xaa, 0xed, 0x78, 0xea, 0x98, 0xe6, 0xa9, 0xe4, 0x0f, 0xe4, 0x41, 0xe3, + 0x98, 0xe3, 0xf5, 0xe1, 0xd2, 0xe2, 0x21, 0xe6, 0x2b, 0xe7, 0x71, 0xe8, + 0x8c, 0xe9, 0x4a, 0xea, 0xe6, 0xeb, 0xeb, 0xeb, 0xe8, 0xeb, 0xfb, 0xea, + 0xf0, 0xea, 0x6a, 0xed, 0x96, 0xef, 0xb5, 0xf4, 0xaf, 0xf7, 0x0c, 0xf9, + 0xd7, 0xfc, 0x87, 0xfd, 0x2f, 0x00, 0x6e, 0x02, 0x30, 0x03, 0x6c, 0x04, + 0xcf, 0x05, 0x9b, 0x05, 0xbc, 0x07, 0xae, 0x09, 0xc4, 0x0b, 0xd3, 0x0e, + 0x1e, 0x10, 0xc0, 0x11, 0x8f, 0x12, 0x2d, 0x12, 0x54, 0x13, 0xcf, 0x12, + 0x1a, 0x12, 0xee, 0x10, 0x70, 0x0f, 0x42, 0x10, 0xe7, 0x10, 0x99, 0x11, + 0x8a, 0x11, 0x26, 0x12, 0xb4, 0x12, 0x71, 0x13, 0xaa, 0x12, 0xd9, 0x11, + 0x19, 0x10, 0x4d, 0x10, 0x84, 0x10, 0xc1, 0x0f, 0x61, 0x0f, 0xc9, 0x0e, + 0xaf, 0x0e, 0x41, 0x0f, 0x66, 0x0f, 0xc7, 0x0e, 0x12, 0x0e, 0x1d, 0x0c, + 0xc3, 0x09, 0x93, 0x07, 0x5c, 0x06, 0x68, 0x04, 0x6e, 0x01, 0x6b, 0xfd, + 0x1d, 0xfa, 0x52, 0xfa, 0x39, 0xf8, 0x3e, 0xf5, 0x19, 0xf1, 0x19, 0xee, + 0x0d, 0xeb, 0x14, 0xe8, 0x4e, 0xe5, 0xc2, 0xe2, 0x9c, 0xe2, 0xfc, 0xe2, + 0x7f, 0xe2, 0x02, 0xe3, 0x41, 0xe4, 0x31, 0xe8, 0xeb, 0xea, 0x21, 0xeb, + 0xd0, 0xe9, 0xf5, 0xe8, 0xf7, 0xe9, 0x8b, 0xed, 0x94, 0xed, 0x61, 0xec, + 0x75, 0xed, 0x5c, 0xef, 0x27, 0xf4, 0xf2, 0xf6, 0xd2, 0xf8, 0x8f, 0xfb, + 0x6b, 0xfe, 0x1d, 0x01, 0x42, 0x02, 0x4c, 0x02, 0x7c, 0x03, 0x3f, 0x04, + 0xb6, 0x05, 0x0e, 0x07, 0xc9, 0x07, 0xef, 0x09, 0x6e, 0x0c, 0xd7, 0x0e, + 0x21, 0x10, 0xf1, 0x0f, 0x23, 0x10, 0x37, 0x10, 0xc6, 0x11, 0xcd, 0x10, + 0x3d, 0x0f, 0xf0, 0x0e, 0xda, 0x0e, 0x24, 0x0f, 0xb6, 0x0f, 0x30, 0x10, + 0x2d, 0x0f, 0x6d, 0x10, 0x60, 0x11, 0x04, 0x11, 0xa1, 0x10, 0xd9, 0x0f, + 0x0b, 0x10, 0x4e, 0x10, 0x6d, 0x10, 0xdc, 0x10, 0x96, 0x10, 0x9a, 0x10, + 0xfb, 0x11, 0x11, 0x12, 0xc7, 0x11, 0x0b, 0x11, 0x56, 0x0f, 0xa4, 0x0c, + 0x8d, 0x0a, 0x8a, 0x07, 0xaf, 0x04, 0xc4, 0x00, 0x7b, 0xfd, 0x25, 0xfb, + 0x97, 0xf8, 0x93, 0xf5, 0xe3, 0xf2, 0x2c, 0xef, 0xcc, 0xea, 0x98, 0xe6, + 0xb3, 0xe3, 0xea, 0xe2, 0x0b, 0xe3, 0xb6, 0xe2, 0x56, 0xe1, 0xfe, 0xdf, + 0xf6, 0xe1, 0x1c, 0xe5, 0x62, 0xe8, 0x4d, 0xe9, 0x4d, 0xe8, 0x4f, 0xe8, + 0x64, 0xe9, 0xcf, 0xeb, 0x17, 0xed, 0x13, 0xee, 0xcf, 0xec, 0x0b, 0xee, + 0xd0, 0xf2, 0xca, 0xf6, 0x9f, 0xf9, 0x6f, 0xfc, 0x14, 0xff, 0x46, 0x02, + 0x08, 0x04, 0x72, 0x02, 0x21, 0x04, 0x1d, 0x05, 0xb1, 0x06, 0xd4, 0x09, + 0x75, 0x09, 0x9a, 0x09, 0xe3, 0x0a, 0x12, 0x0d, 0x34, 0x0f, 0x26, 0x0f, + 0xe5, 0x0e, 0x59, 0x0f, 0xdc, 0x0f, 0x8d, 0x0e, 0x2c, 0x0c, 0xce, 0x0a, + 0x2b, 0x0b, 0x63, 0x0d, 0x5a, 0x0e, 0x93, 0x0d, 0x35, 0x0c, 0x60, 0x0d, + 0xa0, 0x0f, 0xbe, 0x10, 0xd8, 0x0e, 0xfa, 0x0c, 0x34, 0x0d, 0xa3, 0x0e, + 0x49, 0x0f, 0x98, 0x0e, 0xa2, 0x0d, 0x3b, 0x0f, 0xc5, 0x11, 0xcd, 0x12, + 0x45, 0x12, 0x70, 0x10, 0x08, 0x0f, 0x87, 0x0e, 0x17, 0x0d, 0x26, 0x0a, + 0x57, 0x05, 0xf5, 0xff, 0x1b, 0xfe, 0xa4, 0xfc, 0xef, 0xfa, 0x5f, 0xf6, + 0xf6, 0xf1, 0xae, 0xee, 0x0d, 0xea, 0x02, 0xe8, 0x03, 0xe6, 0x9d, 0xe5, + 0xd3, 0xe5, 0xf9, 0xe4, 0x04, 0xe5, 0x7e, 0xe6, 0x29, 0xe7, 0x51, 0xe9, + 0x73, 0xe9, 0x00, 0xeb, 0xad, 0xeb, 0xf8, 0xe8, 0x59, 0xe8, 0x07, 0xe8, + 0x23, 0xeb, 0x63, 0xef, 0x44, 0xf1, 0x52, 0xf1, 0xbe, 0xf2, 0xed, 0xf6, + 0x22, 0xfb, 0x2c, 0xff, 0xcf, 0xfe, 0xf6, 0xfe, 0x15, 0x01, 0xaf, 0x02, + 0xf1, 0x03, 0xe8, 0x04, 0x87, 0x04, 0x6e, 0x06, 0xb1, 0x08, 0x56, 0x09, + 0xfe, 0x0a, 0x71, 0x09, 0x2c, 0x0a, 0xb5, 0x0b, 0x37, 0x0c, 0x18, 0x0c, + 0xb5, 0x0a, 0x4e, 0x0a, 0x61, 0x0a, 0x72, 0x0a, 0x9e, 0x09, 0x15, 0x09, + 0x2c, 0x0a, 0x8b, 0x0c, 0x46, 0x0e, 0xfc, 0x0c, 0xed, 0x0a, 0xc8, 0x0a, + 0x01, 0x0e, 0x99, 0x0f, 0x2f, 0x0f, 0x97, 0x0c, 0x9d, 0x0c, 0x20, 0x0f, + 0xbb, 0x11, 0xbe, 0x12, 0x4b, 0x12, 0xe5, 0x11, 0x9b, 0x12, 0x7f, 0x13, + 0x56, 0x11, 0x84, 0x0c, 0xd1, 0x08, 0x6a, 0x08, 0xd9, 0x05, 0x72, 0x01, + 0xc5, 0xfc, 0x1f, 0xf9, 0xe9, 0xf9, 0xf5, 0xf6, 0xa0, 0xf0, 0x27, 0xeb, + 0xcf, 0xe5, 0x11, 0xe6, 0x27, 0xea, 0x4b, 0xe9, 0xc2, 0xe7, 0x49, 0xe7, + 0xd2, 0xe5, 0x7b, 0xe9, 0x65, 0xeb, 0xb1, 0xe8, 0xde, 0xe7, 0x33, 0xe9, + 0x1e, 0xea, 0x7e, 0xec, 0x60, 0xed, 0x21, 0xea, 0x25, 0xee, 0xad, 0xf1, + 0x27, 0xf5, 0x4b, 0xf9, 0xf1, 0xf9, 0xa6, 0xfc, 0x6a, 0x00, 0x3e, 0x00, + 0x9f, 0x01, 0x5e, 0x02, 0xac, 0x03, 0xa5, 0x05, 0x6d, 0x05, 0xb9, 0x04, + 0xfd, 0x05, 0xd3, 0x07, 0xcd, 0x08, 0xbf, 0x09, 0x34, 0x09, 0x42, 0x09, + 0xda, 0x07, 0x4f, 0x08, 0x35, 0x09, 0xd5, 0x08, 0x83, 0x08, 0xfe, 0x08, + 0xcc, 0x07, 0x5b, 0x07, 0x58, 0x07, 0x6f, 0x08, 0x83, 0x0a, 0xd1, 0x0a, + 0x20, 0x09, 0x1e, 0x0b, 0x1c, 0x0d, 0x16, 0x0d, 0x62, 0x0e, 0x71, 0x0e, + 0xa1, 0x0d, 0xdd, 0x0f, 0x69, 0x11, 0x4a, 0x14, 0x03, 0x15, 0xbc, 0x13, + 0xb2, 0x12, 0x15, 0x12, 0x9a, 0x10, 0x04, 0x0f, 0x0e, 0x0c, 0x0b, 0x06, + 0x3b, 0x02, 0x7f, 0xfe, 0x85, 0xfb, 0x4e, 0xf8, 0xc4, 0xf4, 0xe0, 0xed, + 0x09, 0xe8, 0x75, 0xe4, 0xb4, 0xe2, 0x62, 0xe5, 0x8c, 0xe8, 0x98, 0xe7, + 0xe3, 0xe5, 0x03, 0xe8, 0x9e, 0xea, 0xc6, 0xf0, 0xf6, 0xf2, 0x95, 0xf1, + 0xad, 0xef, 0x91, 0xf0, 0xbe, 0xf1, 0x58, 0xf4, 0x02, 0xf5, 0x1d, 0xf6, + 0xb0, 0xfa, 0xfa, 0xfe, 0x10, 0x04, 0x95, 0x06, 0x0f, 0x09, 0xf4, 0x0a, + 0xd6, 0x0b, 0xcb, 0x0b, 0x91, 0x09, 0xf6, 0x07, 0xc8, 0x06, 0xeb, 0x07, + 0xeb, 0x06, 0xb6, 0x03, 0xde, 0x01, 0x84, 0xff, 0x4d, 0x01, 0xc5, 0x02, + 0x03, 0x01, 0x2e, 0xfe, 0x1e, 0xfb, 0x01, 0xfa, 0xc1, 0xf9, 0xb1, 0xfa, + 0xd2, 0xf8, 0x03, 0xf8, 0x76, 0xf9, 0x25, 0xfb, 0x31, 0xfe, 0xa9, 0x01, + 0xea, 0x03, 0x19, 0x07, 0xe6, 0x08, 0xf9, 0x0a, 0x8c, 0x0c, 0x50, 0x0e, + 0x52, 0x10, 0xe4, 0x12, 0x0f, 0x15, 0xa1, 0x16, 0x19, 0x1a, 0xf2, 0x1b, + 0x3d, 0x1d, 0x2f, 0x1d, 0xd4, 0x19, 0xa5, 0x15, 0xad, 0x11, 0x2c, 0x0d, + 0x71, 0x08, 0x3e, 0x05, 0x7f, 0x01, 0xb4, 0xfb, 0xf3, 0xf6, 0x38, 0xed, + 0x46, 0xe8, 0x22, 0xe2, 0x9d, 0xdf, 0x01, 0xdd, 0x06, 0xdc, 0x08, 0xdc, + 0xe9, 0xdd, 0xe2, 0xe1, 0x7c, 0xe8, 0xf7, 0xee, 0xb5, 0xf4, 0x42, 0xf7, + 0xf9, 0xf7, 0x34, 0xfb, 0xd5, 0xfc, 0x9b, 0xff, 0xa8, 0x01, 0x5f, 0x02, + 0xe6, 0x02, 0x35, 0x05, 0xe2, 0x08, 0x42, 0x0e, 0xf1, 0x14, 0x1d, 0x17, + 0xd0, 0x16, 0x27, 0x13, 0x62, 0x0e, 0xe2, 0x08, 0xa5, 0x03, 0xc6, 0xfe, + 0x7f, 0xf9, 0x63, 0xf7, 0xe5, 0xf5, 0x23, 0xf5, 0xdb, 0xf3, 0xcf, 0xf2, + 0x45, 0xf1, 0x44, 0xf0, 0x36, 0xf0, 0x63, 0xee, 0xaf, 0xec, 0x50, 0xe8, + 0x4b, 0xe7, 0xa7, 0xe8, 0xff, 0xec, 0xff, 0xf3, 0xca, 0xf7, 0x01, 0x00, + 0x75, 0x07, 0xd9, 0x0e, 0x43, 0x15, 0x22, 0x19, 0x89, 0x1d, 0xa6, 0x20, + 0x44, 0x22, 0x45, 0x24, 0x5e, 0x26, 0x83, 0x29, 0x4a, 0x2b, 0xbc, 0x2b, + 0xba, 0x29, 0x84, 0x25, 0x57, 0x20, 0x6d, 0x18, 0x73, 0x11, 0xad, 0x08, + 0x4d, 0xfd, 0xa3, 0xf7, 0xa7, 0xf0, 0x98, 0xed, 0x85, 0xea, 0x54, 0xe4, + 0xa5, 0xdd, 0x29, 0xd4, 0x9d, 0xcb, 0xc2, 0xc4, 0x9f, 0xc5, 0x4c, 0xc8, + 0x69, 0xd0, 0x13, 0xd7, 0x36, 0xdd, 0x3d, 0xe9, 0x62, 0xf5, 0xf1, 0x02, + 0x07, 0x0c, 0x37, 0x11, 0x3f, 0x17, 0xb6, 0x1b, 0x73, 0x1f, 0x91, 0x20, + 0x45, 0x20, 0x61, 0x22, 0xcf, 0x23, 0x3f, 0x26, 0xa5, 0x26, 0x33, 0x27, + 0xd9, 0x1e, 0xb8, 0x15, 0x25, 0x0b, 0x14, 0xfe, 0xeb, 0xf3, 0x80, 0xec, + 0xdf, 0xe0, 0x6b, 0xd8, 0x45, 0xd6, 0x52, 0xd3, 0x55, 0xd7, 0x2d, 0xd8, + 0xab, 0xd5, 0x7b, 0xd7, 0x5c, 0xda, 0x76, 0xdf, 0xd4, 0xe3, 0xec, 0xe2, + 0x38, 0xe8, 0x94, 0xed, 0x00, 0xf8, 0xf0, 0x02, 0x62, 0x0b, 0x80, 0x16, + 0xfb, 0x1f, 0x9a, 0x28, 0xc0, 0x30, 0x64, 0x34, 0x0e, 0x32, 0x46, 0x33, + 0x8d, 0x33, 0x66, 0x35, 0xe8, 0x32, 0x50, 0x2f, 0x78, 0x2a, 0xfa, 0x26, + 0xc7, 0x20, 0xf3, 0x19, 0x30, 0x11, 0xb9, 0x09, 0x92, 0x02, 0xb1, 0xfa, + 0x80, 0xee, 0x49, 0xe3, 0xbe, 0xdd, 0x62, 0xd8, 0x21, 0xd5, 0xc3, 0xcc, + 0xf9, 0xc2, 0x3e, 0xb5, 0xdf, 0xb0, 0xb7, 0xae, 0x95, 0xb4, 0xa8, 0xc5, + 0x6f, 0xd4, 0x19, 0xe9, 0xa5, 0xfc, 0xc6, 0x10, 0x6d, 0x23, 0xfa, 0x32, + 0x5c, 0x3b, 0x69, 0x3d, 0xac, 0x3f, 0x62, 0x3b, 0x95, 0x39, 0xb9, 0x32, + 0xff, 0x2e, 0xb1, 0x2b, 0x60, 0x28, 0xb1, 0x23, 0x24, 0x1c, 0xef, 0x0f, + 0x29, 0xff, 0x3a, 0xef, 0x03, 0xdf, 0x7f, 0xd2, 0xab, 0xca, 0xf5, 0xc5, + 0x0f, 0xc3, 0xb0, 0xc3, 0xb8, 0xc4, 0x71, 0xc8, 0xb2, 0xcd, 0x24, 0xd3, + 0xdb, 0xdc, 0x59, 0xe5, 0xd0, 0xeb, 0xb8, 0xf1, 0x0a, 0xf8, 0xbb, 0x00, + 0x58, 0x0c, 0x3e, 0x17, 0x42, 0x1e, 0xdc, 0x25, 0x6d, 0x2b, 0xe9, 0x2f, + 0xa2, 0x33, 0xa6, 0x32, 0x54, 0x33, 0xa8, 0x31, 0x7d, 0x2d, 0xd7, 0x28, + 0xe7, 0x23, 0x8d, 0x1e, 0x00, 0x1b, 0x38, 0x16, 0x4c, 0x0d, 0xa9, 0x05, + 0xb6, 0xff, 0x2e, 0xfb, 0x75, 0xf5, 0x4e, 0xef, 0x68, 0xea, 0xf0, 0xe5, + 0x29, 0xe2, 0xa9, 0xdc, 0x44, 0xd6, 0xd8, 0xd0, 0x2e, 0xcc, 0x82, 0xc5, + 0xb6, 0xbe, 0x15, 0xb8, 0x98, 0xb8, 0xd2, 0xc4, 0x84, 0xd7, 0xc5, 0xeb, + 0xfa, 0xff, 0x15, 0x15, 0x7c, 0x28, 0x37, 0x3c, 0x60, 0x46, 0x79, 0x45, + 0x3c, 0x43, 0x37, 0x3e, 0xf5, 0x3a, 0xf3, 0x36, 0x24, 0x2d, 0xed, 0x24, + 0xcb, 0x1e, 0x3c, 0x19, 0x61, 0x0f, 0xbd, 0x03, 0x31, 0xf5, 0xb2, 0xe8, + 0x11, 0xdd, 0x58, 0xd3, 0x62, 0xcb, 0xe0, 0xc6, 0xc3, 0xc3, 0x00, 0xc2, + 0xd3, 0xc4, 0xb2, 0xc9, 0x2a, 0xd2, 0xe6, 0xd9, 0xf2, 0xe3, 0x75, 0xec, + 0x4a, 0xf6, 0xf8, 0xfe, 0x49, 0x06, 0x5c, 0x0c, 0xf2, 0x10, 0x6e, 0x18, + 0x24, 0x1f, 0x81, 0x25, 0xff, 0x28, 0xba, 0x2a, 0x67, 0x2c, 0xe1, 0x2d, + 0x97, 0x27, 0x14, 0x21, 0xf8, 0x1b, 0x53, 0x18, 0xdf, 0x19, 0x62, 0x16, + 0xe4, 0x11, 0x77, 0x0e, 0x61, 0x09, 0x89, 0x05, 0xed, 0x02, 0x7c, 0xfe, + 0x57, 0xf9, 0x48, 0xf7, 0xa9, 0xf2, 0xec, 0xed, 0xca, 0xe9, 0x51, 0xe5, + 0x0f, 0xe0, 0x99, 0xda, 0x12, 0xd3, 0xb0, 0xcb, 0x44, 0xc5, 0x46, 0xc0, + 0x91, 0xbd, 0xe9, 0xbf, 0x97, 0xcb, 0xa0, 0xdf, 0x56, 0xf9, 0x1e, 0x13, + 0x35, 0x22, 0xf2, 0x32, 0xd0, 0x3d, 0xc4, 0x45, 0x55, 0x49, 0x99, 0x43, + 0x34, 0x3d, 0x9b, 0x35, 0x06, 0x2f, 0xe1, 0x26, 0x5b, 0x23, 0x70, 0x19, + 0x44, 0x10, 0xf4, 0x04, 0x6d, 0xf7, 0x46, 0xe5, 0x9a, 0xd7, 0xf7, 0xcd, + 0xde, 0xc9, 0x45, 0xc6, 0x42, 0xc2, 0x13, 0xc4, 0x27, 0xc9, 0x87, 0xd3, + 0x06, 0xdc, 0x42, 0xe4, 0x0e, 0xed, 0xf7, 0xf5, 0xf9, 0xfd, 0xae, 0x05, + 0x7e, 0x0a, 0x1f, 0x0f, 0xad, 0x16, 0x55, 0x1c, 0xec, 0x20, 0xa3, 0x22, + 0x74, 0x21, 0x58, 0x21, 0x9f, 0x20, 0x02, 0x22, 0x59, 0x1e, 0xe9, 0x17, + 0x5f, 0x12, 0x5b, 0x0d, 0x47, 0x0d, 0xb2, 0x0d, 0xb6, 0x0d, 0xfc, 0x0c, + 0xde, 0x0c, 0x00, 0x0a, 0x6f, 0x04, 0x7e, 0x01, 0x66, 0xfd, 0xb6, 0xfa, + 0x36, 0xf7, 0xb0, 0xf0, 0x90, 0xeb, 0xf2, 0xe3, 0x9d, 0xdd, 0x85, 0xd9, + 0x15, 0xcf, 0x33, 0xc9, 0x0a, 0xc2, 0x5f, 0xbc, 0x26, 0xbc, 0x4b, 0xc5, + 0xdd, 0xd4, 0xe2, 0xf0, 0xfe, 0x0a, 0xd4, 0x1b, 0x16, 0x2d, 0xbc, 0x39, + 0xd1, 0x45, 0x70, 0x4a, 0xab, 0x46, 0x25, 0x3b, 0x47, 0x35, 0x8a, 0x30, + 0x54, 0x29, 0xd5, 0x1e, 0x34, 0x13, 0xa7, 0x0a, 0x02, 0x05, 0x83, 0xfc, + 0xde, 0xef, 0xd8, 0xe1, 0x61, 0xd6, 0xfb, 0xcb, 0x55, 0xc5, 0x52, 0xc3, + 0x99, 0xc5, 0x10, 0xcd, 0x65, 0xd7, 0xc6, 0xe3, 0xd5, 0xed, 0xb5, 0xf5, + 0x52, 0x00, 0x1e, 0x09, 0xe6, 0x0c, 0xae, 0x0d, 0x76, 0x0c, 0xf9, 0x0a, + 0x2e, 0x11, 0x9a, 0x17, 0x17, 0x1b, 0x71, 0x20, 0xd9, 0x22, 0x8d, 0x20, + 0xbd, 0x1a, 0x6e, 0x13, 0x8c, 0x0b, 0xe8, 0x08, 0x39, 0x07, 0x39, 0x06, + 0xbc, 0x08, 0x9b, 0x0b, 0x19, 0x10, 0x56, 0x12, 0x20, 0x12, 0x9e, 0x10, + 0xa9, 0x0b, 0x78, 0x05, 0x00, 0xff, 0xf6, 0xf6, 0xc9, 0xf0, 0x15, 0xe9, + 0xad, 0xe2, 0xa0, 0xdb, 0xcc, 0xd2, 0x03, 0xcc, 0x9d, 0xc4, 0x8a, 0xc2, + 0x60, 0xbd, 0x26, 0xbb, 0x26, 0xc2, 0xcd, 0xd5, 0x4b, 0xf0, 0x59, 0x0b, + 0xc8, 0x20, 0xe9, 0x32, 0xdc, 0x41, 0x5b, 0x47, 0x3f, 0x47, 0xc1, 0x42, + 0x30, 0x3e, 0x0d, 0x38, 0x81, 0x2d, 0xce, 0x22, 0x8e, 0x18, 0xd9, 0x11, + 0x94, 0x0a, 0x92, 0x03, 0xb6, 0xf6, 0x94, 0xe9, 0xe3, 0xdb, 0x78, 0xd2, + 0xf9, 0xcd, 0x19, 0xc9, 0x4e, 0xc7, 0x70, 0xcb, 0x3f, 0xd3, 0x24, 0xde, + 0x3b, 0xe9, 0x83, 0xf2, 0xfc, 0xfd, 0xa0, 0x0b, 0x60, 0x12, 0x53, 0x13, + 0x4c, 0x10, 0xd2, 0x10, 0x1f, 0x17, 0xfb, 0x19, 0x53, 0x1b, 0x51, 0x1a, + 0x21, 0x1b, 0x28, 0x19, 0x56, 0x15, 0xaf, 0x0e, 0x52, 0x05, 0x40, 0x01, + 0xe6, 0xff, 0x28, 0xff, 0x7c, 0x01, 0x81, 0x05, 0x90, 0x09, 0x1d, 0x12, + 0x40, 0x16, 0x51, 0x16, 0x81, 0x14, 0x24, 0x0f, 0x8b, 0x09, 0x5f, 0x02, + 0xa5, 0xf8, 0xc1, 0xef, 0x97, 0xe7, 0x83, 0xda, 0x4f, 0xd0, 0xb1, 0xc5, + 0xfa, 0xbd, 0x44, 0xb9, 0xdd, 0xb5, 0x5f, 0xb6, 0x9b, 0xc3, 0x7e, 0xda, + 0xda, 0xf7, 0x63, 0x13, 0x05, 0x26, 0xc1, 0x34, 0xd3, 0x3f, 0x02, 0x45, + 0x88, 0x46, 0x44, 0x42, 0x06, 0x3d, 0x67, 0x36, 0x4d, 0x2c, 0x93, 0x21, + 0x00, 0x16, 0x38, 0x0e, 0x03, 0x0b, 0x6b, 0x01, 0x11, 0xf1, 0x50, 0xe1, + 0x23, 0xd6, 0xf1, 0xcd, 0x1b, 0xcc, 0xe3, 0xc9, 0xcb, 0xc8, 0x3c, 0xd0, + 0xf6, 0xd9, 0x44, 0xe7, 0x2a, 0xf4, 0x65, 0xfe, 0x4f, 0x09, 0x45, 0x12, + 0x33, 0x16, 0xa5, 0x15, 0x57, 0x15, 0x83, 0x14, 0xd5, 0x16, 0xd1, 0x18, + 0x0a, 0x14, 0xf1, 0x12, 0xdf, 0x0f, 0x3d, 0x0c, 0xca, 0x09, 0x0c, 0x05, + 0x70, 0xfe, 0x26, 0xfa, 0xfa, 0xf9, 0x92, 0xfb, 0x88, 0x01, 0xfd, 0x08, + 0x67, 0x12, 0x56, 0x18, 0x44, 0x1a, 0xfa, 0x19, 0xaa, 0x16, 0x15, 0x11, + 0x00, 0x0c, 0x89, 0x05, 0x26, 0xfd, 0x2e, 0xf3, 0x01, 0xe5, 0xd2, 0xd6, + 0xe1, 0xcb, 0x76, 0xc1, 0x7c, 0xb6, 0xb2, 0xae, 0xb6, 0xaf, 0xc0, 0xbc, + 0x10, 0xd4, 0x4a, 0xf0, 0x21, 0x08, 0xdb, 0x19, 0xb4, 0x27, 0xbe, 0x34, + 0x17, 0x40, 0x22, 0x42, 0x17, 0x42, 0x34, 0x3d, 0x03, 0x36, 0x27, 0x2e, + 0x39, 0x24, 0xba, 0x1b, 0x19, 0x18, 0x0b, 0x12, 0x1e, 0x04, 0x34, 0xf2, + 0xf5, 0xe2, 0x19, 0xda, 0xe7, 0xd4, 0x30, 0xd1, 0x98, 0xce, 0x56, 0xd1, + 0x76, 0xd6, 0xf3, 0xde, 0x42, 0xe9, 0x55, 0xf3, 0x50, 0xfe, 0x35, 0x09, + 0x69, 0x0f, 0x05, 0x13, 0xd5, 0x14, 0xab, 0x17, 0x03, 0x1a, 0x75, 0x1a, + 0xf3, 0x16, 0x53, 0x11, 0x6f, 0x0c, 0xce, 0x09, 0xcf, 0x05, 0x5e, 0xff, + 0x47, 0xf9, 0x8b, 0xf4, 0xe7, 0xf3, 0x62, 0xf5, 0x39, 0xf9, 0x2c, 0x00, + 0x37, 0x0d, 0x52, 0x16, 0x6f, 0x1a, 0x6f, 0x1d, 0x64, 0x1c, 0x1d, 0x19, + 0xe4, 0x16, 0xbc, 0x11, 0x6f, 0x09, 0x2b, 0x01, 0x6e, 0xf3, 0x09, 0xe5, + 0xda, 0xd5, 0x23, 0xc7, 0xc9, 0xbd, 0x99, 0xb5, 0x14, 0xaf, 0x4a, 0xb2, + 0x4f, 0xbf, 0x82, 0xd7, 0x5c, 0xf4, 0x46, 0x0d, 0x93, 0x1c, 0xc0, 0x2b, + 0xe5, 0x37, 0xc8, 0x38, 0x85, 0x39, 0x39, 0x3b, 0xe5, 0x38, 0x1a, 0x35, + 0x41, 0x2f, 0xed, 0x24, 0xab, 0x1c, 0x59, 0x16, 0xe6, 0x0a, 0xee, 0xfb, + 0x97, 0xed, 0x9e, 0xe0, 0x8a, 0xd8, 0x03, 0xd4, 0x92, 0xd2, 0xfc, 0xd4, + 0xc2, 0xd7, 0x04, 0xe0, 0x5e, 0xe8, 0x11, 0xf0, 0x19, 0xf9, 0xb3, 0x01, + 0x3f, 0x0b, 0xd6, 0x10, 0x9a, 0x12, 0x4b, 0x15, 0x42, 0x15, 0x69, 0x16, + 0x44, 0x13, 0xd9, 0x0d, 0x26, 0x0b, 0x1f, 0x06, 0x13, 0xff, 0x09, 0xfb, + 0x6b, 0xf8, 0x71, 0xf6, 0x95, 0xf5, 0x88, 0xf6, 0x12, 0xf9, 0xbf, 0xff, + 0x9f, 0x08, 0x6d, 0x12, 0x4a, 0x1b, 0xef, 0x20, 0xac, 0x22, 0x06, 0x21, + 0x4a, 0x1b, 0x82, 0x14, 0x17, 0x0d, 0xe7, 0x02, 0x8c, 0xf6, 0x7d, 0xe6, + 0x7b, 0xd6, 0x7f, 0xc8, 0x04, 0xbb, 0x32, 0xb1, 0xe1, 0xac, 0xe0, 0xaf, + 0x3f, 0xc0, 0x79, 0xda, 0x08, 0xf4, 0x07, 0x0b, 0xa2, 0x1a, 0x31, 0x28, + 0x62, 0x34, 0x48, 0x39, 0xde, 0x3b, 0x58, 0x3a, 0xc1, 0x37, 0x22, 0x31, + 0xcf, 0x2d, 0xa5, 0x23, 0x6b, 0x1c, 0xb5, 0x11, 0xe6, 0x05, 0x71, 0xfb, + 0x92, 0xe9, 0x67, 0xdc, 0xe2, 0xd1, 0x0e, 0xd0, 0xf5, 0xd1, 0xe8, 0xd6, + 0x80, 0xde, 0xb4, 0xe6, 0x54, 0xf0, 0x6d, 0xfa, 0x1a, 0x02, 0x56, 0x06, + 0x52, 0x0b, 0x12, 0x10, 0xfc, 0x12, 0x2a, 0x14, 0xe5, 0x12, 0x3a, 0x11, + 0x96, 0x10, 0xad, 0x0d, 0x71, 0x07, 0xe0, 0x00, 0x9c, 0xfc, 0x6a, 0xf7, + 0x77, 0xf5, 0x45, 0xf5, 0xf4, 0xf5, 0x87, 0xf8, 0x85, 0xfd, 0x71, 0x04, + 0x64, 0x0b, 0x63, 0x16, 0xff, 0x1c, 0x5f, 0x1f, 0x6f, 0x20, 0x71, 0x1d, + 0x73, 0x1b, 0x45, 0x12, 0xd4, 0x09, 0x6a, 0xfe, 0xcb, 0xed, 0x8f, 0xdc, + 0xd0, 0xcc, 0xa4, 0xbd, 0xe6, 0xb5, 0x32, 0xb0, 0x4c, 0xb3, 0xea, 0xbb, + 0xe1, 0xd0, 0xb2, 0xee, 0x3e, 0x09, 0x3e, 0x1c, 0xf4, 0x25, 0x54, 0x2f, + 0x0b, 0x33, 0xb0, 0x39, 0x16, 0x3a, 0x72, 0x36, 0x12, 0x33, 0xbb, 0x2c, + 0x21, 0x24, 0x3d, 0x1a, 0xd9, 0x10, 0x09, 0x07, 0x2f, 0xfc, 0x88, 0xef, + 0x90, 0xe0, 0x3c, 0xd4, 0x4b, 0xcd, 0xd3, 0xd1, 0x2f, 0xdb, 0xb1, 0xe2, + 0xc1, 0xea, 0x8a, 0xf3, 0x5d, 0xfd, 0x68, 0x06, 0x23, 0x09, 0xa4, 0x0b, + 0x7d, 0x10, 0x50, 0x15, 0x8e, 0x15, 0xfc, 0x11, 0xea, 0x0d, 0x74, 0x0d, + 0x88, 0x0b, 0x07, 0x08, 0x7d, 0x00, 0xf6, 0xf9, 0xef, 0xf2, 0x2d, 0xf2, + 0xce, 0xf4, 0x94, 0xf4, 0xe1, 0xf7, 0x5e, 0xfd, 0x20, 0x04, 0xe8, 0x0d, + 0x1e, 0x15, 0xc4, 0x1a, 0xd6, 0x1f, 0x7a, 0x20, 0xfc, 0x1c, 0x72, 0x1d, + 0x78, 0x16, 0x80, 0x0d, 0x24, 0x03, 0x87, 0xef, 0xc6, 0xde, 0x64, 0xcc, + 0x62, 0xbf, 0x2a, 0xb6, 0x7c, 0xaf, 0xc9, 0xb0, 0xbe, 0xbb, 0xe0, 0xd1, + 0x9d, 0xed, 0x1c, 0x06, 0x3f, 0x18, 0x6b, 0x22, 0x32, 0x2d, 0xf7, 0x32, + 0x51, 0x36, 0xf4, 0x3b, 0x87, 0x39, 0xcf, 0x33, 0xa6, 0x2b, 0x20, 0x22, + 0x7d, 0x1c, 0xbe, 0x13, 0xba, 0x09, 0x73, 0xfb, 0x96, 0xec, 0x06, 0xdd, + 0x22, 0xd6, 0x9a, 0xd3, 0x8d, 0xda, 0x0b, 0xe1, 0xc8, 0xe6, 0x78, 0xeb, + 0xa6, 0xf1, 0x68, 0xf7, 0x34, 0x02, 0x52, 0x0a, 0x21, 0x0e, 0x65, 0x13, + 0xcf, 0x13, 0xea, 0x12, 0xce, 0x11, 0x27, 0x0e, 0xd1, 0x0b, 0x82, 0x0a, + 0x38, 0x05, 0x0e, 0xff, 0x1e, 0xf7, 0xc4, 0xf2, 0x23, 0xf2, 0x7c, 0xf4, + 0x43, 0xf7, 0xc7, 0xfa, 0x5e, 0xff, 0x89, 0x04, 0xab, 0x0d, 0xef, 0x14, + 0x26, 0x1d, 0x4d, 0x21, 0x0b, 0x21, 0xc6, 0x1c, 0x54, 0x16, 0x12, 0x0f, + 0xd6, 0x06, 0xab, 0xf9, 0xe2, 0xe7, 0x37, 0xd8, 0x46, 0xc9, 0xc4, 0xbe, + 0x3c, 0xb6, 0x8e, 0xb2, 0xb9, 0xb6, 0x41, 0xc8, 0x13, 0xe0, 0xd4, 0xf8, + 0x7b, 0x0e, 0xe1, 0x1c, 0x7d, 0x23, 0x07, 0x2c, 0x3a, 0x2f, 0x15, 0x32, + 0xd3, 0x30, 0xc1, 0x2f, 0x44, 0x2c, 0x64, 0x27, 0xc7, 0x20, 0x04, 0x18, + 0xb3, 0x10, 0x20, 0x05, 0x09, 0xfa, 0x86, 0xee, 0x9f, 0xe1, 0xee, 0xda, + 0x6f, 0xd9, 0x7c, 0xdd, 0x19, 0xe6, 0xb5, 0xf0, 0x1e, 0xf6, 0x21, 0xfb, + 0xba, 0xfe, 0x68, 0x01, 0x45, 0x07, 0x5e, 0x09, 0xbb, 0x0c, 0x61, 0x0c, + 0xda, 0x0c, 0xac, 0x0e, 0x3e, 0x0d, 0xb1, 0x09, 0x03, 0x05, 0xe9, 0xfe, + 0xcb, 0xf9, 0x21, 0xf6, 0xc3, 0xf2, 0x6f, 0xf2, 0xbf, 0xf5, 0x56, 0xfa, + 0x85, 0x00, 0x88, 0x07, 0x3a, 0x0d, 0x78, 0x15, 0xfd, 0x1b, 0x5c, 0x20, + 0x30, 0x21, 0x79, 0x1d, 0xce, 0x19, 0x84, 0x13, 0x1e, 0x0a, 0x0c, 0xfe, + 0x89, 0xed, 0x63, 0xd9, 0x5f, 0xca, 0x4a, 0xbd, 0xc9, 0xb5, 0x59, 0xb3, + 0xbb, 0xb8, 0x68, 0xc4, 0xfa, 0xdb, 0x7c, 0xf3, 0x11, 0x05, 0xc6, 0x17, + 0x18, 0x21, 0x47, 0x2f, 0x1a, 0x31, 0x7f, 0x30, 0xd8, 0x31, 0xb6, 0x30, + 0xd2, 0x2d, 0xe0, 0x27, 0x12, 0x21, 0x58, 0x19, 0x25, 0x11, 0x06, 0x08, + 0x84, 0xf7, 0xad, 0xe9, 0xe5, 0xdb, 0xb0, 0xd8, 0x15, 0xdc, 0x07, 0xe0, + 0x10, 0xe8, 0x9e, 0xef, 0xc6, 0xf7, 0xef, 0xff, 0xab, 0x05, 0xd8, 0x0a, + 0xbf, 0x0e, 0x0d, 0x11, 0x32, 0x10, 0xb1, 0x10, 0xc0, 0x0f, 0x81, 0x0d, + 0xe2, 0x0c, 0xaf, 0x07, 0x2a, 0x04, 0x2d, 0xfe, 0x29, 0xf7, 0x9b, 0xf2, + 0x1d, 0xf0, 0x00, 0xef, 0xbe, 0xf2, 0x4a, 0xf5, 0x6a, 0xf9, 0x9d, 0x01, + 0x6e, 0x0a, 0x44, 0x11, 0x35, 0x1a, 0x52, 0x1e, 0xa5, 0x1e, 0xf4, 0x1c, + 0x36, 0x18, 0xd3, 0x10, 0xa7, 0x09, 0x3b, 0xfa, 0x47, 0xeb, 0xa8, 0xdd, + 0x85, 0xcd, 0x45, 0xc4, 0x04, 0xbc, 0x7b, 0xb8, 0x3b, 0xbf, 0x26, 0xcb, + 0x2e, 0xe1, 0x54, 0xf7, 0xf8, 0x07, 0x0b, 0x18, 0x1f, 0x1f, 0xd0, 0x24, + 0xbf, 0x2a, 0x2e, 0x2d, 0x89, 0x2e, 0x55, 0x2d, 0xa2, 0x26, 0x49, 0x21, + 0x63, 0x1e, 0x3e, 0x17, 0x0b, 0x11, 0xf6, 0x05, 0x71, 0xf8, 0x95, 0xed, + 0x3c, 0xe6, 0x97, 0xe2, 0xbe, 0xe3, 0xf3, 0xe5, 0xae, 0xed, 0x09, 0xf7, + 0x73, 0xfc, 0x14, 0x02, 0xbf, 0x09, 0x06, 0x0b, 0xab, 0x0d, 0x4d, 0x0f, + 0x59, 0x0e, 0x99, 0x0d, 0x11, 0x0c, 0xa6, 0x08, 0x0d, 0x06, 0x7d, 0x02, + 0xeb, 0xfd, 0xd5, 0xfa, 0x6b, 0xf7, 0x0a, 0xf4, 0x6e, 0xf1, 0x7d, 0xef, + 0xfa, 0xf0, 0x1a, 0xf7, 0xf7, 0xfa, 0x20, 0x01, 0x60, 0x09, 0x59, 0x12, + 0xff, 0x16, 0x46, 0x1d, 0x81, 0x1c, 0x27, 0x1a, 0x26, 0x12, 0x42, 0x07, + 0xbd, 0xf9, 0x07, 0xf1, 0xb7, 0xe6, 0x9c, 0xd9, 0x29, 0xce, 0xc8, 0xc7, + 0x8f, 0xc1, 0x04, 0xc4, 0xb4, 0xd0, 0xc0, 0xe0, 0x9c, 0xf3, 0xb1, 0xff, + 0x64, 0x0b, 0x5c, 0x15, 0xf5, 0x1b, 0x82, 0x20, 0x1b, 0x2a, 0x9e, 0x28, + 0xd5, 0x2a, 0xb9, 0x28, 0xb9, 0x21, 0xc1, 0x1a, 0x27, 0x14, 0x4d, 0x0d, + 0x1f, 0x07, 0x9f, 0x01, 0x7f, 0xf6, 0x8b, 0xee, 0xaf, 0xe8, 0x15, 0xe7, + 0xd2, 0xec, 0x70, 0xf1, 0xff, 0xf5, 0xf1, 0xfb, 0x4a, 0xff, 0x0e, 0x02, + 0xf5, 0x05, 0xfc, 0x05, 0xf2, 0x0a, 0xf4, 0x0d, 0x57, 0x0e, 0x81, 0x0c, + 0xfb, 0x0a, 0xe8, 0x06, 0x6d, 0x03, 0x6e, 0xff, 0x8f, 0xfb, 0x77, 0xf8, + 0x8f, 0xf3, 0x48, 0xee, 0x89, 0xee, 0x36, 0xf0, 0x17, 0xf5, 0xe0, 0xfc, + 0x53, 0x02, 0xde, 0x07, 0x75, 0x0e, 0xce, 0x12, 0xaf, 0x16, 0xc0, 0x16, + 0x8a, 0x14, 0xd6, 0x12, 0x2a, 0x0a, 0xe7, 0x00, 0x03, 0xf7, 0x6c, 0xe9, + 0x69, 0xdc, 0x08, 0xd1, 0xd8, 0xc5, 0xf8, 0xc3, 0x6d, 0xc8, 0x71, 0xd6, + 0xb5, 0xe7, 0x0b, 0xf3, 0xd1, 0xfd, 0x55, 0x07, 0xd3, 0x0d, 0x57, 0x18, + 0x10, 0x19, 0xea, 0x1d, 0x23, 0x23, 0x62, 0x25, 0x34, 0x28, 0xb5, 0x23, + 0x48, 0x20, 0x6d, 0x1b, 0xc5, 0x13, 0xd1, 0x0a, 0xc9, 0x02, 0xfb, 0xfa, + 0x67, 0xf2, 0xc2, 0xed, 0x64, 0xea, 0x29, 0xed, 0x8a, 0xf0, 0xe8, 0xf3, + 0x95, 0xf8, 0x87, 0xfd, 0x1b, 0x02, 0x1f, 0x07, 0xd0, 0x0a, 0xb3, 0x0d, + 0x2c, 0x0f, 0x34, 0x0e, 0x7c, 0x0b, 0xc1, 0x0b, 0xfe, 0x09, 0x7a, 0x08, + 0xd9, 0x04, 0x31, 0xff, 0x4d, 0xf9, 0x23, 0xf3, 0x06, 0xef, 0x26, 0xec, + 0x46, 0xee, 0x18, 0xf0, 0xea, 0xf3, 0x0f, 0xfb, 0xa7, 0x01, 0x96, 0x07, + 0xcb, 0x0b, 0x39, 0x0f, 0x19, 0x12, 0x1e, 0x12, 0x1c, 0x0d, 0xfc, 0x07, + 0xb0, 0xff, 0x84, 0xf6, 0x35, 0xea, 0x44, 0xdc, 0x9f, 0xcf, 0xbf, 0xc8, + 0xcc, 0xcb, 0x41, 0xd5, 0x4c, 0xe0, 0x77, 0xee, 0xb4, 0xfa, 0x2e, 0x07, + 0xc7, 0x0f, 0x82, 0x15, 0x64, 0x16, 0xb9, 0x19, 0xaa, 0x1c, 0x51, 0x1b, + 0x74, 0x1f, 0x76, 0x1d, 0x52, 0x1c, 0x47, 0x1a, 0x1b, 0x14, 0xec, 0x0e, + 0xe9, 0x05, 0xb6, 0xfc, 0x48, 0xf7, 0x42, 0xf2, 0xcb, 0xee, 0x38, 0xee, + 0x03, 0xef, 0xcb, 0xee, 0x42, 0xf5, 0x83, 0xf9, 0xed, 0xff, 0x16, 0x08, + 0x18, 0x0d, 0x4b, 0x0f, 0x87, 0x13, 0x4f, 0x12, 0x72, 0x10, 0xf6, 0x12, + 0x3e, 0x10, 0x1a, 0x0f, 0xcb, 0x0a, 0x85, 0x03, 0x3d, 0xfd, 0xc9, 0xf8, + 0x81, 0xf3, 0xab, 0xf1, 0xe5, 0xef, 0xe3, 0xee, 0x96, 0xf1, 0xb7, 0xf4, + 0x6d, 0xf9, 0xd6, 0x01, 0x6f, 0x06, 0xdd, 0x0a, 0xc1, 0x0c, 0xd7, 0x0b, + 0xd8, 0x08, 0xdf, 0x03, 0x27, 0xfe, 0x5b, 0xf7, 0x7e, 0xef, 0x49, 0xe6, + 0x6a, 0xdf, 0xe3, 0xd8, 0xd8, 0xd5, 0xa3, 0xda, 0x57, 0xe3, 0x59, 0xea, + 0x4a, 0xf3, 0xc0, 0xfa, 0x49, 0x01, 0x40, 0x09, 0x31, 0x11, 0x20, 0x16, + 0xce, 0x17, 0x79, 0x19, 0x14, 0x1c, 0x5c, 0x1c, 0x1a, 0x1b, 0xfe, 0x15, + 0xcb, 0x13, 0x74, 0x12, 0x5b, 0x0e, 0xeb, 0x08, 0x79, 0x01, 0x6e, 0xfb, + 0x1f, 0xf7, 0x31, 0xf4, 0x0d, 0xf3, 0x58, 0xf3, 0xb5, 0xf6, 0xff, 0xf5, + 0x25, 0xf9, 0x82, 0xfb, 0x38, 0xff, 0xb0, 0x03, 0x83, 0x08, 0xfb, 0x0c, + 0x94, 0x11, 0x40, 0x14, 0x00, 0x14, 0x3b, 0x11, 0x3e, 0x0c, 0x17, 0x0a, + 0xfd, 0x05, 0x31, 0x01, 0x97, 0xfb, 0xdb, 0xf5, 0xc7, 0xf1, 0x0e, 0xf1, + 0x94, 0xf1, 0x2b, 0xf5, 0x99, 0xf9, 0x68, 0xfa, 0xf0, 0xfb, 0x3b, 0xfe, + 0xb7, 0x00, 0xa0, 0x03, 0x64, 0x06, 0x92, 0x05, 0xe5, 0x03, 0xbf, 0xfd, + 0x81, 0xf9, 0xde, 0xf0, 0xb2, 0xe7, 0x36, 0xdf, 0xa8, 0xd6, 0x0a, 0xd3, + 0x1d, 0xd9, 0x4d, 0xe2, 0x6d, 0xed, 0x82, 0xf5, 0xf0, 0xfb, 0x30, 0x03, + 0x16, 0x0a, 0x12, 0x0f, 0x2f, 0x13, 0x54, 0x17, 0x51, 0x17, 0xfe, 0x1d, + 0x22, 0x22, 0x7f, 0x21, 0xcb, 0x21, 0x4b, 0x1d, 0x79, 0x15, 0xd3, 0x0d, + 0xa6, 0x06, 0x12, 0xff, 0xc6, 0xfb, 0xef, 0xf6, 0x4d, 0xf3, 0x1d, 0xf2, + 0xf8, 0xef, 0x5d, 0xf2, 0xcc, 0xf6, 0xff, 0xf9, 0xd7, 0xfc, 0x82, 0x00, + 0xb2, 0x02, 0x04, 0x07, 0x0b, 0x0d, 0x55, 0x0f, 0x43, 0x11, 0x83, 0x12, + 0x19, 0x0d, 0x77, 0x0a, 0xf3, 0x05, 0xd1, 0x02, 0x48, 0xff, 0x59, 0xf9, + 0xd4, 0xf3, 0x73, 0xf0, 0x20, 0xf2, 0x46, 0xf4, 0x2b, 0xf8, 0x90, 0xfb, + 0xa4, 0xfc, 0x2b, 0xfe, 0x16, 0x03, 0xb0, 0x07, 0x2d, 0x0b, 0xee, 0x08, + 0xdd, 0x08, 0xc9, 0x06, 0x91, 0xff, 0xc1, 0xfa, 0x1e, 0xf1, 0x3d, 0xeb, + 0x39, 0xe4, 0x0d, 0xdf, 0x75, 0xd8, 0x1d, 0xd7, 0x25, 0xd7, 0x03, 0xde, + 0xb4, 0xe8, 0x24, 0xf1, 0x10, 0xfb, 0x9c, 0x06, 0x52, 0x0b, 0x8e, 0x12, + 0xa8, 0x16, 0xc5, 0x1b, 0x89, 0x20, 0xb8, 0x21, 0x03, 0x21, 0x51, 0x1d, + 0xc8, 0x17, 0x63, 0x14, 0x7f, 0x12, 0xa8, 0x0d, 0xa9, 0x09, 0x9e, 0x02, + 0x9b, 0xfa, 0xfb, 0xf6, 0x1b, 0xf2, 0x6d, 0xef, 0x15, 0xf1, 0x80, 0xf3, + 0x3f, 0xf6, 0xb6, 0xfc, 0x25, 0x00, 0x86, 0x05, 0x78, 0x0a, 0x4b, 0x0e, + 0x2d, 0x11, 0x02, 0x11, 0x49, 0x0f, 0x8d, 0x0d, 0x37, 0x08, 0x81, 0x03, + 0x15, 0xff, 0x92, 0xf8, 0xa2, 0xf5, 0x0a, 0xf3, 0x6f, 0xef, 0x19, 0xee, + 0xa9, 0xf1, 0xf2, 0xf3, 0x44, 0xfc, 0x01, 0x02, 0x32, 0x05, 0x34, 0x08, + 0xaf, 0x08, 0xc2, 0x07, 0x8a, 0x0b, 0xdc, 0x0a, 0x36, 0x08, 0xc4, 0x04, + 0xb8, 0xff, 0xc4, 0xfa, 0x8b, 0xf5, 0xbb, 0xef, 0x25, 0xe8, 0xdc, 0xde, + 0x56, 0xd9, 0x4f, 0xd4, 0xc4, 0xd8, 0xee, 0xdf, 0xc4, 0xe9, 0x1b, 0xf5, + 0xb5, 0xfe, 0xc5, 0x05, 0x33, 0x09, 0xbb, 0x0a, 0x88, 0x0d, 0xb7, 0x0d, + 0xcc, 0x12, 0xf3, 0x1a, 0xbc, 0x1a, 0xf2, 0x1a, 0x12, 0x1b, 0x96, 0x17, + 0x2c, 0x16, 0x94, 0x11, 0xb1, 0x0a, 0xf2, 0x04, 0x84, 0x01, 0xff, 0xff, + 0xa0, 0xfe, 0x6c, 0xfb, 0x59, 0xf8, 0x5a, 0xf8, 0xd0, 0xf8, 0xba, 0xfd, + 0x4d, 0x02, 0x66, 0x06, 0x81, 0x09, 0xc0, 0x08, 0x3f, 0x08, 0xd2, 0x06, + 0xed, 0x01, 0x77, 0x00, 0xec, 0xfd, 0x18, 0xfa, 0x1d, 0xf6, 0x6f, 0xf3, + 0xb3, 0xf0, 0x90, 0xf1, 0x31, 0xf2, 0x27, 0xf4, 0x5b, 0xf8, 0xb6, 0xfb, + 0xf0, 0x00, 0x1e, 0x07, 0x03, 0x08, 0x09, 0x09, 0x10, 0x0b, 0xf9, 0x0b, + 0x12, 0x0f, 0x56, 0x0f, 0xa0, 0x0b, 0xc9, 0x06, 0x4a, 0x02, 0x3b, 0xfc, + 0x26, 0xfa, 0x84, 0xf1, 0x71, 0xe9, 0x94, 0xe3, 0xaf, 0xdf, 0x7f, 0xe0, + 0xb0, 0xe1, 0x12, 0xe0, 0x24, 0xe4, 0x73, 0xea, 0x3c, 0xf1, 0x3e, 0xfa, + 0x87, 0x01, 0x8d, 0x08, 0x6a, 0x0f, 0x05, 0x14, 0x80, 0x15, 0x53, 0x1a, + 0xc0, 0x1b, 0x23, 0x19, 0x9a, 0x16, 0x43, 0x14, 0x4f, 0x11, 0xdd, 0x0d, + 0x7a, 0x0b, 0xde, 0x06, 0xdc, 0x02, 0x0a, 0x01, 0xcd, 0xfe, 0xb6, 0xfe, + 0xf5, 0xfb, 0x9c, 0xfc, 0x38, 0xfe, 0xc5, 0xfe, 0x56, 0xfd, 0xd2, 0xfd, + 0x1b, 0xff, 0xb4, 0x01, 0xd9, 0x05, 0x0c, 0x06, 0xac, 0x07, 0x4f, 0x07, + 0xdb, 0x03, 0xed, 0xff, 0xdd, 0xfb, 0xef, 0xf7, 0xbc, 0xf5, 0xfc, 0xf3, + 0x71, 0xf3, 0x33, 0xf5, 0x98, 0xf6, 0x84, 0xf7, 0x98, 0xf9, 0x74, 0xfb, + 0xc4, 0x01, 0x81, 0x06, 0xc0, 0x09, 0xd3, 0x0b, 0x32, 0x0a, 0x21, 0x0a, + 0xb6, 0x0a, 0x28, 0x0a, 0xb5, 0x08, 0x20, 0x06, 0x61, 0x00, 0xcc, 0xfc, + 0x9d, 0xf6, 0x91, 0xf1, 0xb1, 0xe9, 0x48, 0xe0, 0xaf, 0xda, 0xae, 0xda, + 0xa6, 0xde, 0xeb, 0xe2, 0x6c, 0xea, 0x90, 0xf1, 0x0a, 0xf9, 0x46, 0x01, + 0x51, 0x08, 0xb0, 0x0e, 0x31, 0x14, 0x14, 0x15, 0x2d, 0x15, 0x5c, 0x14, + 0x4f, 0x15, 0xb1, 0x15, 0xb3, 0x15, 0x87, 0x15, 0x58, 0x13, 0x72, 0x12, + 0x61, 0x0d, 0x1f, 0x06, 0x64, 0xfe, 0xd5, 0xf9, 0x1c, 0xf6, 0x5b, 0xf7, + 0x29, 0xf4, 0x97, 0xf3, 0x6b, 0xfa, 0xaa, 0xff, 0x63, 0x03, 0x80, 0x06, + 0x4c, 0x07, 0x4b, 0x07, 0x08, 0x0a, 0xee, 0x05, 0xd9, 0x03, 0xaf, 0x01, + 0xba, 0xfc, 0xcd, 0xf9, 0x55, 0xf7, 0x0b, 0xf4, 0x18, 0xf5, 0x8f, 0xf5, + 0x34, 0xf7, 0x1d, 0xf6, 0x4f, 0xf7, 0xe1, 0xf8, 0x00, 0xfc, 0xcf, 0x02, + 0xf7, 0x07, 0xda, 0x0b, 0xd3, 0x0e, 0xa6, 0x0f, 0x1e, 0x0e, 0xa1, 0x0e, + 0xd0, 0x0c, 0x0f, 0x08, 0x03, 0x05, 0x7c, 0x01, 0xee, 0xfe, 0xec, 0xfc, + 0x1c, 0xf7, 0x85, 0xf3, 0x01, 0xee, 0xe9, 0xe9, 0x61, 0xe9, 0x30, 0xe9, + 0x52, 0xe7, 0xea, 0xea, 0x49, 0xeb, 0x0c, 0xed, 0x93, 0xf1, 0x37, 0xf6, + 0x15, 0xfe, 0x70, 0x06, 0xbf, 0x0a, 0xf1, 0x0c, 0x43, 0x12, 0x1a, 0x15, + 0x78, 0x19, 0x94, 0x19, 0x2b, 0x1a, 0x1a, 0x18, 0x35, 0x11, 0xa0, 0x09, + 0xa2, 0x06, 0x4c, 0x09, 0xa4, 0x09, 0xda, 0x09, 0xd7, 0x05, 0x67, 0xf9, + 0x98, 0xf2, 0x7f, 0xf1, 0x9c, 0xf3, 0x31, 0xf9, 0x05, 0xfb, 0x2f, 0xfb, + 0xb0, 0xf9, 0x08, 0xf8, 0x6b, 0xf9, 0xe3, 0xfc, 0xb9, 0xff, 0xf0, 0x03, + 0x11, 0x04, 0xa8, 0xfc, 0xb4, 0xf5, 0xaf, 0xf1, 0x40, 0xf2, 0x51, 0xf8, + 0x1f, 0xfd, 0x6f, 0x00, 0xd1, 0x03, 0x54, 0x04, 0x4a, 0x05, 0x1b, 0x07, + 0x3f, 0x06, 0x86, 0x04, 0x50, 0x04, 0xb3, 0x03, 0x99, 0x03, 0x08, 0x05, + 0x22, 0x09, 0x84, 0x0a, 0x79, 0x0a, 0xeb, 0x09, 0xca, 0x06, 0x93, 0x02, + 0x56, 0xff, 0x96, 0xfc, 0x1c, 0xf6, 0x39, 0xf3, 0x64, 0xec, 0x7e, 0xe8, + 0x87, 0xe2, 0xd0, 0xe4, 0x29, 0xe7, 0x4b, 0xef, 0x09, 0xf2, 0x88, 0xf4, + 0xb2, 0xf9, 0x3b, 0xfe, 0xb6, 0x04, 0x15, 0x0a, 0x6c, 0x0e, 0x32, 0x0f, + 0xea, 0x15, 0xd9, 0x16, 0x37, 0x19, 0xf5, 0x17, 0x06, 0x15, 0xc0, 0x0e, + 0xe5, 0x09, 0x2f, 0x07, 0x0e, 0x00, 0x2b, 0xfd, 0x5a, 0xfa, 0xf8, 0xf9, + 0x20, 0xfd, 0xb8, 0x01, 0x04, 0x03, 0x9b, 0xfe, 0x38, 0xf9, 0x35, 0xf7, + 0x96, 0xf9, 0xdb, 0xfc, 0x6d, 0xff, 0x78, 0xfc, 0x6d, 0xfc, 0xa7, 0xfd, + 0xe0, 0x01, 0x99, 0x02, 0xcd, 0x04, 0xdf, 0x00, 0x85, 0xfc, 0xb3, 0xf9, + 0x72, 0xf7, 0x53, 0xf5, 0x30, 0xf6, 0x05, 0xfa, 0xd7, 0xfd, 0xc3, 0xfe, + 0xf0, 0x00, 0x29, 0x03, 0x2b, 0x03, 0xce, 0x05, 0x74, 0x08, 0x0b, 0x0a, + 0xc0, 0x0a, 0x36, 0x0d, 0x8d, 0x0d, 0x6f, 0x0d, 0x5e, 0x0d, 0x5d, 0x09, + 0x47, 0x07, 0xd2, 0x07, 0x2d, 0x02, 0x5c, 0xfa, 0x76, 0xf1, 0x2d, 0xe9, + 0x52, 0xe7, 0x61, 0xe7, 0x5c, 0xe9, 0x0a, 0xeb, 0xd7, 0xeb, 0xfa, 0xef, + 0xd6, 0xf6, 0xe6, 0xfe, 0x83, 0x03, 0x7d, 0x08, 0xa3, 0x0a, 0x0a, 0x0d, + 0xe9, 0x0d, 0xbf, 0x0c, 0x60, 0x10, 0xf6, 0x11, 0xe7, 0x12, 0x94, 0x0e, + 0x3c, 0x07, 0x6f, 0x02, 0x72, 0x03, 0x90, 0x02, 0x83, 0x05, 0xff, 0x04, + 0x2d, 0x04, 0x4b, 0x01, 0xa6, 0xf7, 0x93, 0xef, 0x13, 0xef, 0x26, 0xfb, + 0xb3, 0x03, 0x08, 0x05, 0xc8, 0x00, 0x20, 0xf9, 0xcb, 0xf6, 0xa9, 0xfd, + 0x37, 0x03, 0x1a, 0x06, 0x0f, 0x04, 0x97, 0x00, 0xa7, 0xfb, 0xa5, 0xf7, + 0x34, 0xf8, 0x51, 0xfa, 0x60, 0xfd, 0x9c, 0xff, 0x06, 0xfe, 0x0c, 0xfb, + 0xb6, 0xf8, 0x17, 0xf9, 0x03, 0xfe, 0xb5, 0x03, 0x78, 0x08, 0x35, 0x0b, + 0x6b, 0x0c, 0x69, 0x0c, 0x11, 0x0c, 0x2e, 0x0f, 0xd1, 0x0d, 0x10, 0x0e, + 0x23, 0x0c, 0xe0, 0x09, 0x9f, 0x05, 0x67, 0x02, 0x4e, 0xfe, 0x26, 0xfa, + 0x29, 0xf9, 0x6c, 0xf8, 0xa0, 0xf5, 0xbd, 0xf1, 0xeb, 0xec, 0x01, 0xec, + 0x93, 0xee, 0x47, 0xf4, 0x0d, 0xfa, 0xe9, 0xfc, 0xb1, 0xff, 0x8c, 0x01, + 0x9a, 0x03, 0x6e, 0x04, 0x19, 0x04, 0x6a, 0x07, 0x07, 0x08, 0x10, 0x09, + 0x69, 0x0b, 0xb0, 0x0a, 0x85, 0x0a, 0x82, 0x0a, 0x39, 0x09, 0xc0, 0x05, + 0x67, 0x00, 0xea, 0xfa, 0xae, 0xf6, 0x0e, 0xf8, 0x01, 0xfd, 0x91, 0xff, + 0x3e, 0x01, 0x81, 0x02, 0x17, 0x02, 0x90, 0xff, 0xee, 0xfb, 0x1a, 0xf8, + 0x52, 0xf6, 0x7d, 0xf7, 0x0c, 0xfb, 0x25, 0xfd, 0xb6, 0xff, 0x54, 0x02, + 0xaf, 0x05, 0xc9, 0x04, 0x1f, 0x02, 0x96, 0xfe, 0x47, 0xfa, 0x82, 0xf7, + 0x86, 0xf8, 0x04, 0xfb, 0x4e, 0xfa, 0x0e, 0xfb, 0xe0, 0xfd, 0x70, 0x02, + 0xb8, 0x07, 0xe0, 0x0b, 0xee, 0x0b, 0xcd, 0x08, 0x74, 0x08, 0x5a, 0x08, + 0x0b, 0x09, 0xe3, 0x08, 0x54, 0x09, 0x02, 0x08, 0xe8, 0x06, 0x76, 0x06, + 0x44, 0x05, 0xa9, 0x02, 0xc4, 0x00, 0xf5, 0xfd, 0xbe, 0xfb, 0x5f, 0xfa, + 0x6f, 0xf9, 0x26, 0xf7, 0x23, 0xf6, 0x94, 0xf7, 0x9c, 0xf9, 0x5c, 0xfc, + 0x6d, 0xff, 0xa9, 0x01, 0x22, 0x02, 0x7a, 0x04, 0x4b, 0x04, 0x87, 0x04, + 0x2d, 0x05, 0xbd, 0x03, 0xa2, 0x04, 0x7c, 0x04, 0x1c, 0x04, 0x95, 0x04, + 0x90, 0x03, 0x14, 0x01, 0x38, 0x02, 0x2b, 0x00, 0x8b, 0xfe, 0x93, 0xfe, + 0x5c, 0xfe, 0x33, 0xff, 0x12, 0xff, 0x8c, 0xfe, 0x4b, 0xfb, 0xd4, 0xfb, + 0x00, 0xfc, 0x94, 0xf8, 0x3e, 0xf8, 0x6a, 0xfb, 0x0a, 0xfe, 0xa4, 0xfe, + 0x96, 0x00, 0x22, 0x00, 0x0c, 0xfb, 0x39, 0xf9, 0x5b, 0xfa, 0xda, 0xfc, + 0xa2, 0xfe, 0xae, 0x00, 0x06, 0x01, 0x3d, 0x01, 0xef, 0x00, 0x35, 0x00, + 0x6f, 0xfe, 0x94, 0x00, 0xf1, 0x03, 0x79, 0x04, 0xfe, 0x05, 0xb2, 0x04, + 0x77, 0x05, 0xf7, 0x05, 0xa6, 0x07, 0xd0, 0x08, 0x64, 0x08, 0xf0, 0x08, + 0xd0, 0x06, 0xaf, 0x04, 0x44, 0x04, 0x8f, 0x03, 0x38, 0x01, 0x01, 0xff, + 0x4b, 0xfe, 0xc5, 0xfe, 0x57, 0x00, 0xe7, 0x02, 0x82, 0x02, 0xc8, 0x00, + 0x49, 0x03, 0xb5, 0x04, 0x40, 0x03, 0xdb, 0x01, 0x09, 0xff, 0xc9, 0xfd, + 0x71, 0xfb, 0x35, 0xfe, 0x4e, 0xff, 0x07, 0xff, 0xce, 0xfe, 0xb2, 0xfd, + 0xc9, 0xfd, 0xd4, 0xff, 0x10, 0x01, 0x60, 0xff, 0x99, 0xfe, 0xe9, 0xfe, + 0xe5, 0xfe, 0x89, 0xff, 0xe4, 0xff, 0xa7, 0xff, 0xc3, 0x00, 0x03, 0x01, + 0xed, 0x01, 0x8d, 0x00, 0xf9, 0xfc, 0x05, 0xfa, 0x20, 0xf9, 0x39, 0xfa, + 0x3e, 0xfa, 0x3a, 0xfb, 0x2b, 0xfe, 0xed, 0xff, 0x13, 0x00, 0x57, 0xfe, + 0x69, 0xfa, 0x1a, 0xf7, 0x03, 0xf8, 0x4a, 0xf9, 0xb5, 0xfa, 0x0d, 0xfd, + 0x0f, 0xff, 0x0a, 0x01, 0x5c, 0x04, 0x28, 0x06, 0xb8, 0x06, 0x90, 0x04, + 0x88, 0x04, 0x7c, 0x05, 0x4e, 0x04, 0x4c, 0x06, 0xa2, 0x06, 0x58, 0x04, + 0x41, 0x03, 0xed, 0x03, 0xeb, 0x03, 0xe5, 0x03, 0x44, 0x04, 0x46, 0x04, + 0x81, 0x04, 0x6e, 0x03, 0xa1, 0x01, 0x48, 0x01, 0x10, 0x02, 0xde, 0x02, + 0x85, 0x04, 0x67, 0x05, 0x4b, 0x05, 0x68, 0x04, 0x65, 0x03, 0x39, 0x02, + 0xd5, 0x01, 0x31, 0x03, 0x51, 0x03, 0x45, 0x02, 0x57, 0x02, 0xb4, 0x00, + 0x10, 0xff, 0xb2, 0xfc, 0x62, 0xfc, 0x79, 0xfb, 0x1d, 0xfc, 0x81, 0xfc, + 0xda, 0xfc, 0x53, 0xfc, 0xd3, 0xfa, 0x12, 0xfb, 0x3c, 0xfa, 0x5c, 0xfa, + 0x67, 0xfd, 0xab, 0xfe, 0x1c, 0xff, 0x18, 0x01, 0xd5, 0x01, 0x7a, 0x01, + 0x5b, 0x01, 0x33, 0xfe, 0xd4, 0xfc, 0x6a, 0xfd, 0x14, 0xfe, 0xb7, 0xfe, + 0x25, 0xfe, 0x41, 0xfc, 0x28, 0xfa, 0xbd, 0xfa, 0x02, 0xf9, 0xce, 0xf8, + 0x30, 0xf8, 0x21, 0xfa, 0x24, 0xfc, 0xe6, 0xfb, 0x4e, 0xfc, 0x19, 0xfe, + 0x8b, 0xfe, 0xe8, 0xff, 0x71, 0x01, 0xae, 0x02, 0x66, 0x03, 0x8f, 0x03, + 0x71, 0x03, 0xfd, 0x03, 0x4b, 0x04, 0x70, 0x06, 0xcc, 0x05, 0x60, 0x04, + 0xf0, 0x02, 0xdb, 0x01, 0x77, 0xff, 0x05, 0x00, 0x6b, 0xff, 0xcc, 0xff, + 0x36, 0x01, 0x57, 0x01, 0x2c, 0x02, 0x17, 0x02, 0x27, 0x01, 0xbf, 0x01, + 0x1a, 0x03, 0x71, 0x01, 0x6e, 0x02, 0x32, 0x03, 0x68, 0x03, 0x1d, 0x05, + 0x9c, 0x05, 0x20, 0x06, 0xfe, 0x05, 0xe1, 0x05, 0x1e, 0x04, 0x05, 0x02, + 0x6a, 0x02, 0x8d, 0x00, 0xe0, 0xfe, 0x93, 0xfd, 0x53, 0xfc, 0xc1, 0xfa, + 0x04, 0xfb, 0xb4, 0xfb, 0x5e, 0xfc, 0xc3, 0xfc, 0x5c, 0xfd, 0x58, 0xfd, + 0xfe, 0xfd, 0xda, 0xff, 0x68, 0x00, 0xfa, 0xff, 0x85, 0x00, 0x7a, 0x00, + 0x14, 0x00, 0x84, 0x00, 0x3d, 0x01, 0x36, 0x00, 0x72, 0xfd, 0x72, 0xfb, + 0x4b, 0xf9, 0x28, 0xf9, 0x28, 0xfa, 0x33, 0xfa, 0x82, 0xf6, 0x9b, 0xf7, + 0x06, 0xfa, 0xc4, 0xfd, 0x7d, 0xfe, 0xb7, 0xfe, 0xf5, 0xff, 0xcb, 0xfe, + 0x1e, 0xfe, 0x7f, 0xfe, 0xbc, 0xfd, 0x9c, 0xfe, 0x92, 0x00, 0xe3, 0x00, + 0x3c, 0x02, 0x7b, 0xff, 0x11, 0xfe, 0x5e, 0xff, 0x93, 0xff, 0xbe, 0xfe, + 0x41, 0x00, 0x88, 0xfd, 0x2c, 0xfd, 0xc7, 0xfe, 0xb0, 0x00, 0x00, 0x02, + 0x33, 0x02, 0x55, 0x01, 0xa7, 0x00, 0x39, 0xff, 0x81, 0x00, 0x17, 0x00, + 0x83, 0x00, 0x7c, 0x02, 0x64, 0x03, 0xe3, 0x01, 0x14, 0x01, 0x1a, 0x03, + 0x99, 0x03, 0x90, 0x02, 0xa2, 0x02, 0xaf, 0x00, 0x75, 0x00, 0x26, 0xff, + 0x9b, 0xfe, 0x4e, 0xfa, 0xd0, 0xfd, 0x4b, 0xff, 0x58, 0xff, 0x8d, 0x00, + 0xbe, 0x01, 0x97, 0x02, 0x9c, 0x00, 0x5b, 0x01, 0xbe, 0xff, 0xe6, 0xfe, + 0x4e, 0xff, 0xfe, 0x00, 0x23, 0x02, 0xa0, 0x02, 0xc1, 0x01, 0x7a, 0x01, + 0x09, 0x00, 0x30, 0xff, 0xf1, 0xfd, 0x40, 0xfe, 0xbe, 0xfc, 0x0e, 0xfb, + 0xb2, 0xf9, 0x71, 0xfb, 0x32, 0xfb, 0xe5, 0xfc, 0x07, 0xfe, 0x98, 0xfe, + 0x95, 0xfe, 0x13, 0xff, 0xea, 0xfe, 0x6e, 0xfe, 0x87, 0xff, 0x9f, 0xff, + 0xd0, 0x00, 0x09, 0x01, 0xe6, 0x00, 0x64, 0x00, 0xcc, 0xff, 0x8f, 0xfe, + 0x88, 0xfd, 0x46, 0xff, 0x35, 0xfe, 0x8f, 0xfd, 0xbe, 0xfd, 0x06, 0xfe, + 0x39, 0xff, 0x07, 0x01, 0x1f, 0x01, 0xc8, 0x00, 0x6c, 0xff, 0x79, 0xff, + 0x2e, 0x00, 0x80, 0xff, 0xa5, 0xfd, 0x6c, 0xff, 0x09, 0x00, 0x4c, 0x00, + 0xa5, 0xff, 0x23, 0xfe, 0xd9, 0xfd, 0xd1, 0xfd, 0xe1, 0xfe, 0x46, 0x00, + 0x8c, 0xff, 0x2f, 0x00, 0x6b, 0x01, 0xf7, 0x00, 0x9e, 0x01, 0xb3, 0x01, + 0x01, 0xff, 0x80, 0x00, 0x03, 0x01, 0x50, 0x02, 0xa5, 0x02, 0xcc, 0x00, + 0x36, 0x01, 0x5a, 0x00, 0xd0, 0xff, 0x78, 0xfe, 0x77, 0xfe, 0x35, 0xff, + 0xe0, 0xff, 0x9e, 0xff, 0x78, 0xff, 0x7a, 0xff, 0x92, 0x01, 0x33, 0x00, + 0x93, 0x01, 0x30, 0x00, 0x8c, 0xfe, 0x38, 0xfe, 0x0d, 0xff, 0x0f, 0xff, + 0xe1, 0xfe, 0x8e, 0xff, 0xa7, 0xff, 0xfb, 0xfe, 0x86, 0xfe, 0x2c, 0xff, + 0xa1, 0xfd, 0x58, 0xfd, 0xb4, 0xfd, 0x3c, 0xfe, 0x24, 0xfc, 0xa3, 0xfd, + 0x29, 0x01, 0x77, 0x00, 0x29, 0x00, 0xe6, 0xff, 0xc1, 0xff, 0x5c, 0x00, + 0xd9, 0xff, 0x6d, 0xff, 0xa5, 0x00, 0xb2, 0xfe, 0x4e, 0xff, 0xe3, 0xff, + 0xb6, 0xff, 0x75, 0xfe, 0x1d, 0x00, 0x23, 0x00, 0x92, 0xfe, 0x7f, 0xff, + 0xc1, 0xff, 0xd4, 0xfc, 0x61, 0xff, 0xc7, 0x01, 0x6d, 0xff, 0xc5, 0xff, + 0xa6, 0x00, 0xf7, 0xff, 0x55, 0xff, 0xc2, 0xfe, 0x50, 0xfe, 0x57, 0xff, + 0xe8, 0xfe, 0x82, 0x01, 0x58, 0x00, 0xd4, 0x00, 0x5c, 0x00, 0xc6, 0xff, + 0xe0, 0x01, 0xa3, 0xff, 0x2a, 0x00, 0x86, 0xff, 0x0c, 0x01, 0x80, 0x00, + 0x58, 0x00, 0x04, 0xfe, 0xf0, 0xff, 0x29, 0x01, 0x1b, 0x01, 0xc8, 0xfd, + 0xbb, 0xff, 0xdb, 0x00, 0xf7, 0xff, 0x08, 0x01, 0xb6, 0x01, 0xa4, 0x00, + 0x17, 0x01, 0x83, 0x01, 0x06, 0x03, 0xaa, 0x00, 0xf6, 0xff, 0x12, 0xff, + 0xc6, 0xff, 0xcd, 0xfd, 0x40, 0xfe, 0xdd, 0xfe, 0xe0, 0xfd, 0x09, 0xff, + 0x8e, 0xfe, 0x6f, 0x00, 0x57, 0xff, 0x7e, 0xff, 0xeb, 0xfe, 0x9e, 0x00, + 0x33, 0x00, 0xf2, 0xff, 0xfc, 0xfe, 0xe8, 0xff, 0xb0, 0xfd, 0x64, 0x02, + 0xda, 0x01, 0x8c, 0x01, 0x5d, 0xff, 0xb5, 0xfc, 0xbf, 0xfd, 0xa5, 0xff, + 0x8f, 0xff, 0x90, 0xff, 0x9a, 0xfe, 0x75, 0xff, 0x62, 0xff, 0x0c, 0x00, + 0x55, 0xff, 0x92, 0xff, 0xd7, 0xfe, 0xa3, 0xff, 0x0b, 0x00, 0xeb, 0x00, + 0xd7, 0xfe, 0xe4, 0x00, 0x4f, 0x01, 0xdc, 0x02, 0xae, 0x02, 0xdf, 0x02, + 0xae, 0xff, 0xd8, 0x00, 0x7a, 0x01, 0x5c, 0x02, 0x6f, 0x04, 0xb8, 0x01, + 0xfc, 0xff, 0x1c, 0x01, 0x60, 0xff, 0x91, 0x01, 0x21, 0x01, 0xc0, 0xff, + 0x21, 0x00, 0x0c, 0x05, 0xb3, 0x04, 0x36, 0x05, 0x55, 0x03, 0x01, 0x00, + 0xa7, 0x00, 0xc0, 0xfe, 0xd4, 0xff, 0xe7, 0x00, 0xfe, 0x02, 0xf5, 0x01, + 0xb7, 0x00, 0x35, 0xff, 0x54, 0xff, 0x64, 0x00, 0x80, 0xff, 0x29, 0x00, + 0xfd, 0x02, 0x69, 0x00, 0xcc, 0xff, 0xd0, 0x03, 0x60, 0x01, 0x70, 0xff, + 0xce, 0xfe, 0x50, 0xff, 0xdd, 0x00, 0xa1, 0x00, 0x20, 0xfe, 0xcc, 0xfb, + 0xb5, 0xff, 0xa2, 0xff, 0x63, 0x01, 0xe1, 0xfc, 0xd3, 0xfd, 0xd9, 0xfd, + 0x94, 0xfd, 0xff, 0xfe, 0xc4, 0xfe, 0x75, 0x00, 0xa4, 0xff, 0xe5, 0xfc, + 0x80, 0x00, 0xd4, 0xff, 0xb5, 0x00, 0x04, 0x00, 0x15, 0x00, 0x1e, 0xff, + 0xc0, 0xfe, 0x7b, 0xfe, 0xc1, 0x01, 0xb2, 0x00, 0xef, 0x01, 0x61, 0x00, + 0x56, 0x01, 0xe2, 0xff, 0x0c, 0xff, 0xb2, 0x01, 0xa5, 0xff, 0xf2, 0xff, + 0x15, 0x02, 0xa7, 0x01, 0xaf, 0x02, 0x94, 0x00, 0x40, 0x01, 0x04, 0x01, + 0x6e, 0x00, 0x10, 0x01, 0xa1, 0xff, 0x74, 0x02, 0xfe, 0x01, 0x39, 0x02, + 0xc0, 0x01, 0xe3, 0x01, 0x2c, 0x01, 0xcb, 0x01, 0x09, 0x00, 0x32, 0x01, + 0xd2, 0xff, 0x5b, 0xff, 0xd6, 0xfe, 0x5e, 0x00, 0x67, 0x01, 0x39, 0xff, + 0x80, 0x00, 0x6f, 0x01, 0x48, 0xfe, 0x33, 0x02, 0x98, 0x01, 0xe0, 0xfd, + 0xd3, 0x00, 0xeb, 0x00, 0x1e, 0x00, 0xf7, 0x01, 0x65, 0x01, 0x83, 0xff, + 0x33, 0x03, 0x95, 0x01, 0xf2, 0x01, 0x70, 0x01, 0x87, 0x00, 0x17, 0x00, + 0x59, 0xfe, 0x65, 0x01, 0x7c, 0xfe, 0xf3, 0xfe, 0xc0, 0x00, 0x3c, 0x00, + 0xe9, 0xff, 0x23, 0xff, 0xf8, 0xfe, 0x29, 0xfe, 0xef, 0xfe, 0x2a, 0xff, + 0x46, 0xfe, 0xb2, 0xff, 0x40, 0x00, 0x3e, 0xff, 0x60, 0xff, 0xd2, 0xff, + 0x8d, 0xff, 0x91, 0xff, 0x1a, 0xff, 0x1d, 0xfe, 0x0e, 0x01, 0xb4, 0xfe, + 0x1b, 0xff, 0xa1, 0xff, 0xb7, 0xfe, 0x4b, 0xff, 0xfc, 0xff, 0xa0, 0xfe, + 0xa5, 0xff, 0x98, 0xfe, 0xd4, 0xff, 0xb4, 0xff, 0xcc, 0x00, 0xa6, 0x02, + 0x0b, 0x01, 0xfb, 0xff, 0xce, 0x02, 0x41, 0x01, 0xb6, 0x01, 0xbe, 0x00, + 0x17, 0x03, 0x6c, 0x01, 0xae, 0xff, 0xc5, 0xff, 0x92, 0x01, 0xa8, 0xfe, + 0x18, 0xff, 0xdb, 0xfd, 0x30, 0x00, 0x29, 0x00, 0x06, 0x01, 0x3f, 0x01, + 0xed, 0x01, 0xc4, 0x01, 0xe1, 0xfe, 0x1f, 0x03, 0x66, 0x00, 0x86, 0x01, + 0xa8, 0x00, 0x34, 0x02, 0x71, 0xfe, 0x71, 0x00, 0x8c, 0xff, 0x0c, 0x01, + 0x87, 0x00, 0x78, 0x01, 0xb7, 0x01, 0x81, 0x01, 0xa1, 0xff, 0x39, 0x00, + 0xe6, 0xff, 0xd2, 0x03, 0x4e, 0x01, 0x3f, 0x00, 0xc4, 0x02, 0xc3, 0x00, + 0xed, 0xff, 0x42, 0x01, 0x59, 0x00, 0x77, 0xff, 0xc9, 0xfe, 0xb4, 0xff, + 0x70, 0xff, 0x29, 0x00, 0x86, 0xff, 0x36, 0x00, 0xa9, 0xfe, 0x5f, 0xff, + 0xa3, 0xff, 0xab, 0xfe, 0xbb, 0xff, 0x78, 0x03, 0x4b, 0x00, 0xab, 0x00, + 0x60, 0x00, 0xcb, 0xfc, 0x98, 0xfd, 0x85, 0xfd, 0x42, 0xff, 0xc6, 0xfd, + 0xf4, 0x00, 0x86, 0x00, 0xa4, 0xff, 0xce, 0xfe, 0x29, 0xff, 0x54, 0xff, + 0xd4, 0x01, 0x0b, 0x00, 0x06, 0x00, 0xf6, 0xff, 0xaf, 0xff, 0x54, 0x00, + 0x7e, 0x00, 0x60, 0x01, 0x2d, 0xff, 0x03, 0x01, 0x00, 0x00, 0xf1, 0xfd, + 0x9f, 0x00, 0x6e, 0x00, 0x84, 0x00, 0xed, 0xff, 0x32, 0x01, 0xd4, 0x01, + 0x52, 0x00, 0x55, 0x00, 0xaf, 0x03, 0xaa, 0x00, 0x4a, 0x01, 0x39, 0x02, + 0xc5, 0xff, 0xf0, 0xfd, 0x39, 0xff, 0x4b, 0xff, 0x16, 0xff, 0x6c, 0xfe, + 0x63, 0x00, 0xef, 0x01, 0xeb, 0x00, 0xea, 0x01, 0x81, 0xfc, 0x64, 0x02, + 0xa4, 0x00, 0x23, 0x00, 0x4c, 0x01, 0x37, 0x00, 0x9f, 0x00, 0xfa, 0xff, + 0xf7, 0x00, 0x0f, 0x00, 0x7a, 0xff, 0xbd, 0xfe, 0x5f, 0x00, 0x5d, 0x00, + 0x35, 0xfe, 0x99, 0xff, 0x07, 0x00, 0x3d, 0x01, 0x00, 0x00, 0xe2, 0x00, + 0xe5, 0x01, 0xd5, 0xff, 0x9f, 0xff, 0x57, 0x00, 0x90, 0xff, 0xea, 0xfe, + 0xd3, 0x00, 0x3e, 0x01, 0xac, 0x01, 0x6f, 0x01, 0xad, 0xff, 0x12, 0x01, + 0x06, 0x00, 0x74, 0xfe, 0xa1, 0xfe, 0xc1, 0xff, 0xff, 0xfe, 0xc4, 0x00, + 0xc2, 0xff, 0x0e, 0xff, 0x96, 0x00, 0x68, 0xff, 0x2e, 0xff, 0xa8, 0xfe, + 0xd5, 0xff, 0xe8, 0xfe, 0xf7, 0xfe, 0x3b, 0xff, 0xd8, 0xfe, 0x79, 0x00, + 0xc5, 0x00, 0x4b, 0xff, 0x2a, 0x00, 0xde, 0xfe, 0xfa, 0xfe, 0xab, 0xfc, + 0xd3, 0x01, 0x5c, 0xff, 0x07, 0x00, 0xd2, 0xfe, 0xee, 0xfb, 0x8f, 0x01, + 0x51, 0x00, 0x75, 0xff, 0xde, 0x01, 0xb1, 0x01, 0x56, 0x00, 0xc8, 0xff, + 0x4f, 0x02, 0x46, 0x00, 0x95, 0x00, 0x70, 0x01, 0x81, 0x01, 0xa9, 0x01, + 0x5f, 0x00, 0x13, 0x01, 0xcb, 0x00, 0x1b, 0x01, 0xb7, 0xff, 0xbf, 0x01, + 0x59, 0xfe, 0x69, 0x00, 0xdd, 0x00, 0x18, 0xff, 0x29, 0x00, 0x2e, 0x01, + 0x2f, 0x00, 0x8b, 0xfe, 0x2e, 0xff, 0x24, 0x01, 0x41, 0xff, 0x66, 0xfe, + 0x5e, 0xfd, 0x2e, 0xff, 0x83, 0xff, 0x44, 0x00, 0x84, 0x00, 0xcd, 0xff, + 0x21, 0x00, 0x74, 0xff, 0x66, 0xfd, 0xaf, 0xff, 0xce, 0xfe, 0x28, 0xff, + 0xb3, 0x02, 0xa0, 0x01, 0x42, 0x01, 0xdc, 0x01, 0xb1, 0xff, 0x2c, 0x00, + 0xf9, 0xff, 0x15, 0x00, 0x13, 0x00, 0xcd, 0xff, 0xf6, 0xfe, 0xce, 0xfe, + 0xa8, 0xfe, 0x89, 0xff, 0x53, 0xff, 0x40, 0xfd, 0x46, 0x00, 0x12, 0x00, + 0x6a, 0x00, 0x4b, 0xff, 0x41, 0x00, 0x8e, 0xfe, 0xe2, 0xff, 0x18, 0xfe, + 0x05, 0xfe, 0xa4, 0xfe, 0x48, 0xff, 0xed, 0xfe, 0xc6, 0xfd, 0x9e, 0xfd, + 0x11, 0xfe, 0xb0, 0xfe, 0xde, 0xff, 0x68, 0xff, 0x10, 0x00, 0x64, 0xff, + 0xed, 0xfe, 0x94, 0x01, 0x07, 0x02, 0x89, 0x01, 0x7d, 0x01, 0xc2, 0xff, + 0x1b, 0x01, 0xab, 0xfe, 0xfc, 0x00, 0x5a, 0x00, 0x3d, 0x01, 0x68, 0xff, + 0x06, 0x01, 0x51, 0xff, 0x7a, 0x00, 0x15, 0x01, 0x18, 0xff, 0x84, 0xfe, + 0x57, 0xff, 0xf8, 0x01, 0x1e, 0x01, 0x52, 0x00, 0x73, 0xff, 0xef, 0xfe, + 0x2a, 0x01, 0x30, 0xff, 0x9a, 0xff, 0x11, 0xff, 0x3d, 0xfe, 0x98, 0xff, + 0x20, 0xfe, 0x9b, 0xff, 0x57, 0x01, 0x5c, 0x01, 0xf2, 0xfc, 0xac, 0xff, + 0x9e, 0x00, 0xb2, 0xfe, 0x7f, 0x00, 0x54, 0xff, 0xe1, 0xff, 0x04, 0xff, + 0xdc, 0x01, 0xa5, 0x00, 0x47, 0xff, 0xfb, 0x00, 0x96, 0x00, 0x05, 0x00, + 0x56, 0x02, 0x1d, 0x00, 0xe2, 0xfe, 0xd0, 0xff, 0x5d, 0xfd, 0x49, 0xff, + 0xda, 0xfe, 0x61, 0x00, 0x43, 0xff, 0x33, 0xff, 0xe6, 0xfd, 0x98, 0x00, + 0x45, 0x00, 0x6b, 0x00, 0xf9, 0xff, 0xd8, 0xff, 0x4b, 0xff, 0x10, 0x01, + 0xd3, 0xfe, 0x52, 0xfe, 0x6e, 0xff, 0x6e, 0x01, 0xaa, 0xff, 0x1d, 0xfe, + 0x05, 0x01, 0x4f, 0x00, 0x7e, 0xff, 0x50, 0x00, 0x86, 0x00, 0x31, 0x00, + 0x3e, 0x00, 0x8d, 0x03, 0x80, 0x00, 0x0b, 0x01, 0xb3, 0xfe, 0xf7, 0xff, + 0xe5, 0xfe, 0xc8, 0xff, 0xf8, 0xff, 0xc0, 0xff, 0x52, 0x00, 0x1f, 0x00, + 0x7b, 0x00, 0x4c, 0x00, 0xb2, 0xfe, 0x1d, 0xff, 0xd9, 0xff, 0xf6, 0x00, + 0x93, 0xff, 0xe9, 0x00, 0x57, 0x00, 0x84, 0x00, 0x96, 0x00, 0x66, 0xff, + 0xe3, 0xfe, 0xa3, 0xfe, 0xb9, 0xff, 0x02, 0xff, 0xff, 0xfd, 0x3d, 0x00, + 0x7a, 0xff, 0xff, 0xfd, 0xd4, 0xff, 0x2e, 0xfe, 0x1e, 0xff, 0x6a, 0x01, + 0xdf, 0xff, 0xb6, 0x00, 0x82, 0x02, 0x45, 0x00, 0x4d, 0x00, 0xe0, 0x00, + 0x5b, 0x01, 0x98, 0xff, 0x06, 0x01, 0x00, 0x00, 0xfa, 0x00, 0xcc, 0xff, + 0x07, 0x01, 0xf8, 0xff, 0x0e, 0x00, 0x85, 0x01, 0x42, 0xff, 0xa8, 0x00, + 0xa5, 0xff, 0x61, 0x00, 0x91, 0xff, 0x3c, 0x00, 0x40, 0x01, 0x94, 0xfe, + 0xfd, 0xff, 0x2e, 0xff, 0xfb, 0xff, 0x0b, 0x00, 0x73, 0xff, 0xb8, 0xfe, + 0xc7, 0xfe, 0xcf, 0xfd, 0xa2, 0xff, 0xcd, 0xfd, 0x32, 0xff, 0x79, 0x00, + 0x9f, 0xfe, 0xdc, 0xff, 0x73, 0xff, 0xec, 0xfd, 0x40, 0x00, 0xa0, 0xff, + 0xf6, 0xfe, 0x5c, 0x01, 0x39, 0x00, 0x41, 0xff, 0x6c, 0x00, 0xb6, 0x01, + 0x0b, 0x00, 0x4f, 0x02, 0xef, 0x00, 0xbd, 0x00, 0x27, 0x01, 0x2e, 0x00, + 0x4c, 0x01, 0x5a, 0xff, 0x96, 0x01, 0xcf, 0xff, 0x6c, 0x01, 0x01, 0x00, + 0x97, 0x01, 0xb0, 0xfe, 0x8c, 0xff, 0xd3, 0xff, 0x95, 0xff, 0xc5, 0xfd, + 0x41, 0x00, 0x0c, 0xff, 0xf9, 0xfe, 0x2b, 0x00, 0xec, 0xfd, 0xea, 0x00, + 0x56, 0xff, 0xc7, 0xff, 0x33, 0x00, 0x2b, 0x00, 0x4d, 0xfd, 0xd1, 0xfe, + 0x9d, 0xff, 0xd4, 0xff, 0x9d, 0xff, 0xd9, 0x00, 0x0b, 0x01, 0x12, 0x01, + 0xfa, 0x01, 0xc8, 0x00, 0xae, 0x00, 0x68, 0xff, 0x5b, 0x03, 0x58, 0xfe, + 0xc7, 0x02, 0xb2, 0x01, 0xab, 0xfe, 0xc1, 0x00, 0x79, 0x00, 0xb8, 0xff, + 0x9f, 0x00, 0xd6, 0xfe, 0x24, 0xff, 0xaf, 0xfe, 0x5a, 0xff, 0x90, 0x00, + 0x49, 0xfb, 0x3e, 0x01, 0x53, 0xfd, 0xd2, 0x00, 0xb1, 0xfe, 0xcb, 0xff, + 0x5c, 0x00, 0x97, 0x00, 0x0a, 0xff, 0xc5, 0xff, 0xed, 0xfe, 0xe2, 0xfe, + 0x06, 0xff, 0x99, 0xff, 0x0a, 0x00, 0x4c, 0x00, 0xad, 0x01, 0xd9, 0xff, + 0xe6, 0x00, 0x98, 0x01, 0x37, 0x00, 0xcf, 0x00, 0x5e, 0xff, 0x91, 0x03, + 0x90, 0xff, 0x16, 0x01, 0x61, 0x00, 0xe8, 0xfd, 0x54, 0x01, 0xec, 0xff, + 0x58, 0x00, 0xd9, 0xff, 0xf1, 0xfe, 0x7e, 0xff, 0x7f, 0xff, 0x33, 0xff, + 0x09, 0xff, 0xff, 0xff, 0x66, 0xff, 0x4d, 0xff, 0x07, 0x01, 0x7c, 0xfe, + 0xd1, 0x00, 0x42, 0x02, 0xeb, 0xfe, 0xe6, 0xff, 0x14, 0x00, 0xe0, 0xfd, + 0x6d, 0x01, 0x26, 0xff, 0x13, 0x00, 0xb6, 0xff, 0xce, 0x00, 0xe4, 0xff, + 0x8a, 0x01, 0x37, 0x00, 0x11, 0x00, 0xa5, 0xfd, 0xd5, 0x00, 0xfa, 0x01, + 0xf4, 0xff, 0x40, 0x01, 0xd5, 0x00, 0x41, 0xff, 0xc7, 0xfe, 0xe9, 0xff, + 0xfa, 0xfe, 0x28, 0x01, 0xbc, 0x01, 0x9f, 0xff, 0x31, 0x02, 0x68, 0xff, + 0x1e, 0x00, 0x4f, 0xff, 0xe7, 0xfe, 0x53, 0xfe, 0x89, 0x00, 0xe9, 0xff, + 0x9f, 0xff, 0x38, 0xff, 0x9e, 0x00, 0x39, 0x00, 0x9b, 0xff, 0xb3, 0xff, + 0xa3, 0x00, 0x7f, 0x02, 0xf1, 0xfd, 0xa6, 0xff, 0xeb, 0x00, 0xf0, 0x00, + 0x33, 0x01, 0xd0, 0x03, 0xec, 0xff, 0xd9, 0x01, 0x4a, 0xff, 0x46, 0x01, + 0xbd, 0xfe, 0x7a, 0x00, 0xbf, 0x00, 0x76, 0xff, 0x93, 0xff, 0x06, 0x01, + 0x5f, 0x00, 0xf8, 0x00, 0x2c, 0x01, 0x32, 0x01, 0x0a, 0xff, 0xc6, 0x00, + 0x24, 0xff, 0x2f, 0xfe, 0xab, 0xfe, 0x6b, 0xfe, 0xe7, 0xfe, 0xb8, 0x00, + 0xa9, 0xff, 0x8c, 0xfe, 0x49, 0x00, 0x21, 0xff, 0xdc, 0xfe, 0x0a, 0xff, + 0x4f, 0x00, 0x71, 0xff, 0xc8, 0x00, 0x8a, 0xfe, 0xd7, 0x00, 0x21, 0x00, + 0xca, 0x00, 0x3d, 0x00, 0xf4, 0x00, 0x71, 0x00, 0x44, 0x00, 0x87, 0xff, + 0xa5, 0x01, 0x06, 0x00, 0xe2, 0xfe, 0xac, 0x00, 0x48, 0xff, 0x70, 0x00, + 0xfd, 0x00, 0x8c, 0x00, 0xb9, 0x01, 0xe8, 0x01, 0x5b, 0x01, 0xc2, 0xff, + 0x86, 0x00, 0x45, 0xff, 0xdd, 0xff, 0x04, 0x00, 0x45, 0x00, 0x9e, 0x00, + 0x94, 0xff, 0x9e, 0xff, 0x45, 0xff, 0x72, 0xff, 0xba, 0xfe, 0xa7, 0xff, + 0x7e, 0xff, 0xbd, 0xff, 0xe7, 0xfe, 0x56, 0x00, 0xea, 0x00, 0x04, 0xff, + 0x75, 0x00, 0x7c, 0xff, 0xcf, 0xff, 0xda, 0x00, 0xb6, 0xff, 0xf6, 0x00, + 0x1d, 0xff, 0x10, 0xff, 0x28, 0x00, 0x16, 0xff, 0xf1, 0xff, 0xa5, 0xff, + 0xe5, 0x00, 0x4f, 0xfe, 0x9b, 0x01, 0x53, 0x01, 0x19, 0xff, 0xcc, 0x00, + 0x66, 0xfe, 0xb5, 0x00, 0xdc, 0xfe, 0x21, 0x00, 0x82, 0x00, 0x85, 0x00, + 0x55, 0x00, 0xe6, 0xff, 0xf9, 0xff, 0xf5, 0xff, 0xab, 0x00, 0xaa, 0xfd, + 0x00, 0x00, 0xbf, 0xff, 0xb4, 0x00, 0xf1, 0xfe, 0xfb, 0xff, 0x8d, 0x00, + 0x17, 0xff, 0x73, 0xff, 0x94, 0xfe, 0x9d, 0x02, 0x91, 0xfe, 0xd8, 0x00, + 0x9b, 0x00, 0x18, 0x00, 0xb8, 0x00, 0x29, 0x00, 0xb7, 0x00, 0x59, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x4a, 0xff, 0xfc, 0xff, 0x7c, 0xfe, 0x6a, 0xff, + 0xa2, 0xff, 0x79, 0xff, 0xf7, 0x00, 0xb2, 0xff, 0x54, 0xfe, 0xa8, 0x00, + 0xfa, 0xfc, 0xfa, 0xff, 0x6d, 0x01, 0x45, 0xff, 0x61, 0x01, 0x23, 0x00, + 0x3d, 0xff, 0x03, 0x00, 0x4c, 0xff, 0xd1, 0xff, 0xe8, 0xfe, 0xc2, 0xff, + 0x90, 0x00, 0x64, 0xff, 0x5d, 0xff, 0x89, 0xfe, 0x9b, 0x00, 0xfc, 0xfe, + 0xea, 0x00, 0xf3, 0xfe, 0x16, 0x02, 0x1c, 0x01, 0x0c, 0x03, 0x25, 0x01, + 0xbb, 0x01, 0xaa, 0xff, 0xa4, 0x01, 0xfc, 0x00, 0xf1, 0xff, 0x70, 0xff, + 0xcf, 0x00, 0xb8, 0x00, 0x6e, 0x00, 0x45, 0xff, 0xf8, 0xff, 0xd8, 0xff, + 0x2e, 0x00, 0x91, 0xff, 0xe2, 0xfe, 0xf0, 0xff, 0xcb, 0xff, 0xbc, 0xff, + 0x93, 0xff, 0x93, 0xfe, 0x26, 0xfe, 0xcf, 0xfe, 0x2b, 0xfe, 0x7b, 0x01, + 0xb2, 0xfe, 0x2d, 0x02, 0xf4, 0xfd, 0x8f, 0x01, 0x4b, 0xff, 0x86, 0x02, + 0x99, 0xff, 0xa6, 0xff, 0x0b, 0xff, 0xfc, 0xfe, 0x20, 0x01, 0x1a, 0xff, + 0x93, 0x00, 0xaf, 0x01, 0x30, 0x00, 0x2b, 0x01, 0x52, 0x01, 0xfc, 0xfd, + 0xe5, 0x01, 0xbc, 0xff, 0xf8, 0xfe, 0x7b, 0x00, 0xf5, 0xff, 0x90, 0xfe, + 0x27, 0x01, 0xf7, 0xfb, 0x63, 0xff, 0x08, 0x02, 0xbb, 0xfd, 0xa5, 0x00, + 0x6f, 0x00, 0x0a, 0xff, 0xa2, 0xff, 0x28, 0xff, 0x96, 0x00, 0x1b, 0xff, + 0x1c, 0x01, 0x1b, 0xff, 0xee, 0x02, 0xf3, 0xfe, 0xdc, 0x01, 0x9b, 0xfe, + 0xcc, 0x01, 0x23, 0xff, 0x7a, 0xfe, 0x94, 0x01, 0x66, 0xff, 0x62, 0x00, + 0xd0, 0x00, 0xb0, 0x00, 0x83, 0x01, 0x0f, 0x00, 0x6a, 0x00, 0x1f, 0x01, + 0xe8, 0xff, 0x54, 0x01, 0x04, 0xff, 0x23, 0xfc, 0x4e, 0xfe, 0x59, 0x04, + 0xdf, 0xfb, 0x48, 0x01, 0x1a, 0x00, 0xb1, 0x01, 0x68, 0xff, 0xf5, 0x00, + 0x0e, 0xff, 0x79, 0x00, 0x22, 0xff, 0x8d, 0xff, 0xd3, 0xff, 0xed, 0x01, + 0x27, 0x01, 0x72, 0x00, 0x52, 0x01, 0x2b, 0x00, 0x33, 0x00, 0x90, 0x00, + 0xbb, 0x00, 0xdb, 0xff, 0x3b, 0xfe, 0xbe, 0x00, 0x8f, 0x00, 0xf3, 0x02, + 0xa9, 0xff, 0xb0, 0x00, 0x5e, 0xff, 0xa9, 0xff, 0x2f, 0x01, 0x32, 0xfe, + 0x64, 0xff, 0xf2, 0xfd, 0xb8, 0xff, 0x85, 0xff, 0xaf, 0xff, 0x6f, 0xfd, + 0x04, 0x01, 0x39, 0xfe, 0x9a, 0xfe, 0x9b, 0xfe, 0x2c, 0xfc, 0xdd, 0xfd, + 0xe7, 0xfe, 0x04, 0xff, 0x84, 0xfd, 0xf5, 0x00, 0x3c, 0x03, 0x6d, 0xff, + 0xce, 0x01, 0x8a, 0xff, 0x2d, 0x02, 0x58, 0xff, 0xc9, 0x00, 0xba, 0x00, + 0x49, 0x00, 0x03, 0x02, 0xfa, 0xff, 0xba, 0x00, 0x16, 0x02, 0x7c, 0xff, + 0x8b, 0x00, 0x3f, 0x00, 0xd2, 0xff, 0x6d, 0xfb, 0xa2, 0x00, 0xf5, 0xfd, + 0xda, 0xff, 0xbb, 0xff, 0x23, 0xff, 0x5b, 0xfe, 0x11, 0xff, 0xdc, 0x00, + 0x44, 0x00, 0x86, 0xff, 0x12, 0xff, 0x62, 0xff, 0xea, 0xfe, 0xad, 0xff, + 0x1d, 0x00, 0xce, 0xff, 0x93, 0xff, 0x26, 0x01, 0x85, 0x00, 0x97, 0x01, + 0x5c, 0x00, 0x32, 0x00, 0x1b, 0x00, 0x5b, 0x00, 0x3d, 0xff, 0xe7, 0x00, + 0x2d, 0x00, 0x47, 0x00, 0x0b, 0xff, 0x25, 0x04, 0x01, 0x00, 0x56, 0x00, + 0xe0, 0xff, 0x12, 0x00, 0x4e, 0xfe, 0x4d, 0x00, 0x32, 0xff, 0x71, 0x00, + 0x96, 0xff, 0x4b, 0x01, 0x6c, 0x01, 0x9b, 0xfd, 0xdf, 0x00, 0x2e, 0x00, + 0x9f, 0xfb, 0xaf, 0xfe, 0xd5, 0xff, 0xa9, 0x01, 0x44, 0xfe, 0xc5, 0x02, + 0x1c, 0xff, 0x21, 0x03, 0x99, 0x00, 0x97, 0xfd, 0xd9, 0xff, 0xc5, 0xff, + 0x0d, 0xff, 0x20, 0x02, 0x07, 0x02, 0x71, 0xff, 0x29, 0x01, 0x37, 0xff, + 0x76, 0x01, 0x80, 0x01, 0x62, 0xff, 0x53, 0xfd, 0xc6, 0x00, 0x6f, 0xfc, + 0xe3, 0xff, 0xa5, 0xff, 0x95, 0xff, 0x50, 0xfe, 0x4a, 0x03, 0x56, 0xfe, + 0xfa, 0xfe, 0x36, 0x00, 0xda, 0x02, 0xc7, 0xfd, 0xaa, 0xff, 0x33, 0xfd, + 0x65, 0xfe, 0xc6, 0xff, 0x91, 0xff, 0x25, 0xff, 0xf4, 0xfe, 0xc3, 0x01, + 0x3d, 0xff, 0xd8, 0x00, 0x6a, 0x01, 0x96, 0x01, 0x8c, 0xff, 0xe4, 0xff, + 0xa9, 0x01, 0x09, 0x01, 0x67, 0x02, 0xfa, 0x01, 0xa0, 0x04, 0x4a, 0x00, + 0x16, 0xff, 0xc1, 0x01, 0x4f, 0xff, 0x5e, 0xff, 0x89, 0xfe, 0x8e, 0x01, + 0x23, 0xff, 0x5f, 0xfc, 0x0f, 0x01, 0x4c, 0x00, 0x47, 0xfe, 0xe4, 0xfd, + 0xfe, 0xff, 0x82, 0xfd, 0x99, 0xff, 0x3b, 0xff, 0x85, 0xfd, 0x32, 0xff, + 0xce, 0xfe, 0x80, 0x00, 0x22, 0x00, 0x74, 0xff, 0x24, 0x00, 0xe4, 0xff, + 0x50, 0x00, 0x48, 0xff, 0xc8, 0xfe, 0x5b, 0x00, 0x21, 0x00, 0x37, 0x01, + 0xe7, 0x00, 0x88, 0x02, 0xb0, 0xff, 0xaf, 0x00, 0x04, 0x01, 0x6e, 0x01, + 0x72, 0xfd, 0xbe, 0x00, 0xea, 0x01, 0xac, 0xff, 0x87, 0xfc, 0x3f, 0x02, + 0xdb, 0x01, 0x7b, 0xff, 0xe8, 0xff, 0xe4, 0xff, 0xd2, 0xfd, 0xb5, 0xff, + 0x2d, 0x02, 0x2b, 0x00, 0x63, 0xfe, 0x49, 0x01, 0xb5, 0xfe, 0xdc, 0xff, + 0x83, 0x00, 0xdb, 0x01, 0xaf, 0xfd, 0x6b, 0xff, 0xef, 0xff, 0x81, 0xfc, + 0x8b, 0x02, 0x18, 0xff, 0x44, 0x00, 0x67, 0xfe, 0x7a, 0x00, 0x00, 0x02, + 0xbe, 0xfc, 0x35, 0x02, 0x86, 0xff, 0x62, 0xff, 0x21, 0x00, 0xbc, 0xfe, + 0x10, 0x00, 0xf7, 0x00, 0x1e, 0x01, 0x46, 0x01, 0x9b, 0x01, 0xa2, 0xff, + 0x5b, 0x00, 0xec, 0x00, 0x37, 0x00, 0xc9, 0xfc, 0xdc, 0xfe, 0x54, 0xff, + 0xb8, 0xff, 0xde, 0xff, 0xf3, 0x00, 0xe3, 0x00, 0xf4, 0xfe, 0x3a, 0x00, + 0x75, 0x00, 0xd6, 0xfe, 0x68, 0xff, 0x7d, 0x01, 0x0c, 0x03, 0xbd, 0xff, + 0x27, 0x01, 0x21, 0x04, 0x99, 0x00, 0x37, 0x03, 0x93, 0xfe, 0x61, 0x01, + 0xd4, 0x02, 0x05, 0x01, 0x85, 0x01, 0x69, 0xfe, 0x5a, 0xff, 0x3e, 0xff, + 0x31, 0x00, 0xcb, 0x01, 0x73, 0xff, 0x53, 0xfe, 0xee, 0xff, 0x81, 0xfa, + 0x90, 0x00, 0x60, 0xfe, 0xcb, 0xff, 0xf8, 0xfe, 0xdf, 0xfc, 0xca, 0xff, + 0xb4, 0xff, 0x0d, 0xfe, 0x7e, 0xff, 0xcc, 0xff, 0xfc, 0xfd, 0xf6, 0xfc, + 0x18, 0x00, 0x85, 0xfe, 0x81, 0xff, 0x97, 0x00, 0xce, 0xfe, 0xd4, 0xff, + 0x36, 0x02, 0xfd, 0xff, 0x61, 0x01, 0x76, 0xfe, 0x99, 0xff, 0x62, 0x00, + 0x6f, 0x00, 0xa6, 0x00, 0x48, 0x00, 0xc2, 0x00, 0x9c, 0xfe, 0xae, 0xfd, + 0x4f, 0x02, 0xf7, 0x02, 0x0f, 0x00, 0xc6, 0x00, 0x13, 0x00, 0x11, 0x02, + 0x6f, 0x01, 0x6c, 0x00, 0x58, 0x01, 0xde, 0xfd, 0x00, 0x00, 0x2f, 0x01, + 0x4a, 0xfe, 0xa1, 0x00, 0x05, 0x00, 0x83, 0x00, 0xd9, 0xfd, 0xc5, 0xff, + 0xdb, 0xfe, 0x75, 0x00, 0xa4, 0xff, 0xbe, 0xff, 0xc2, 0xff, 0x41, 0x03, + 0xea, 0x01, 0x70, 0xfe, 0xa4, 0x02, 0xba, 0xff, 0x0a, 0xff, 0xc7, 0xff, + 0xa6, 0x00, 0x2b, 0x02, 0x38, 0x00, 0x5d, 0xfd, 0xfc, 0x00, 0xd9, 0x01, + 0x86, 0xff, 0xe8, 0x00, 0x4c, 0x00, 0x2a, 0x00, 0x80, 0x01, 0xcd, 0x00, + 0x86, 0xff, 0x6a, 0x00, 0x81, 0xff, 0xd9, 0x01, 0x09, 0x02, 0xe6, 0xff, + 0x62, 0xfe, 0xd0, 0xff, 0x44, 0xff, 0x3e, 0x00, 0xf2, 0xff, 0xe3, 0xff, + 0xfb, 0xff, 0x17, 0xff, 0x10, 0x01, 0x54, 0x01, 0x0d, 0x00, 0xce, 0x00, + 0x8d, 0xff, 0x0f, 0xff, 0xb1, 0x00, 0x32, 0x00, 0x4b, 0xff, 0x41, 0x02, + 0x98, 0x00, 0xd5, 0xff, 0x83, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x15, 0xff, + 0xa6, 0xff, 0x6d, 0xfd, 0x91, 0xfe, 0xdd, 0x00, 0x8d, 0xff, 0x88, 0xfe, + 0x7d, 0x00, 0x98, 0x00, 0x4e, 0xff, 0x4f, 0x01, 0x93, 0x00, 0xe3, 0x00, + 0xb0, 0x00, 0x56, 0xff, 0xd7, 0xff, 0x48, 0xff, 0xce, 0xff, 0x42, 0x01, + 0x11, 0x01, 0xe5, 0x00, 0xfa, 0xff, 0x3f, 0x00, 0x5d, 0x00, 0x19, 0x01, + 0x85, 0x00, 0x7c, 0xfe, 0x23, 0x00, 0xdd, 0xfb, 0xf2, 0xff, 0xe9, 0x01, + 0xec, 0x01, 0xad, 0xff, 0xc7, 0xff, 0xa1, 0xff, 0x8f, 0x00, 0x10, 0x02, + 0x31, 0xff, 0x93, 0xff, 0x02, 0x02, 0x15, 0x01, 0x17, 0x00, 0xf1, 0x01, + 0x74, 0xff, 0xa4, 0x00, 0x20, 0xfe, 0x96, 0xff, 0x2a, 0x01, 0x2f, 0x00, + 0x11, 0xff, 0x1f, 0x00, 0xe1, 0x00, 0x1c, 0xff, 0xf7, 0xff, 0x66, 0x00, + 0x50, 0x00, 0xf3, 0x00, 0xb8, 0x00, 0xce, 0xff, 0xcc, 0x00, 0xe4, 0x00, + 0xc3, 0x02, 0xcb, 0x00, 0xfb, 0xff, 0x11, 0x01, 0x61, 0x00, 0x33, 0x01, + 0x79, 0x00, 0x4a, 0x00, 0x58, 0x00, 0x7e, 0xff, 0xb8, 0xff, 0x22, 0xff, + 0xed, 0xff, 0x71, 0x00, 0x1d, 0x00, 0xd7, 0xff, 0x18, 0x01, 0x5c, 0x00, + 0x85, 0xff, 0x1d, 0x01, 0x6b, 0xff, 0xe9, 0xff, 0xf1, 0x00, 0x26, 0x00, + 0x68, 0x00, 0xaf, 0x00, 0x21, 0x01, 0xf4, 0x00, 0x0b, 0x01, 0x06, 0x00, + 0x75, 0x01, 0xc6, 0x00, 0xaa, 0xff, 0x9f, 0x00, 0x5c, 0x00, 0x92, 0xff, + 0x9d, 0x00, 0xeb, 0x00, 0x26, 0xff, 0xbe, 0x00, 0xdf, 0x00, 0x2b, 0x00, + 0x21, 0xff, 0x8a, 0x00, 0xf9, 0xff, 0x31, 0x01, 0xb6, 0x00, 0xab, 0xff, + 0x99, 0x00, 0x23, 0x01, 0x85, 0x01, 0x18, 0x01, 0x6e, 0x00, 0xe1, 0xff, + 0x8c, 0xff, 0xf6, 0x00, 0x2f, 0x00, 0xe1, 0x00, 0x7a, 0x00, 0xf4, 0xff, + 0x15, 0x00, 0x9b, 0x00, 0xf6, 0x00, 0xf3, 0x00, 0x08, 0xff, 0x43, 0x00, + 0x91, 0x00, 0x45, 0x00, 0x67, 0x00, 0x00, 0x00, 0x9e, 0xff, 0xbc, 0x00, + 0x0e, 0x01, 0x6a, 0x00, 0x72, 0x00, 0x69, 0x00, 0xa0, 0x00, 0xbf, 0x00, + 0x7c, 0x00, 0x49, 0xff, 0xf9, 0xff, 0x71, 0x00, 0x71, 0x00, 0xfc, 0xff, + 0xa1, 0x00, 0xd1, 0x00, 0xcb, 0xff, 0xb6, 0x00, 0x87, 0x01, 0x22, 0x00, + 0x25, 0x02, 0xa1, 0x00, 0xbb, 0x00, 0x12, 0x01, 0x4e, 0x01, 0x5c, 0x01, + 0x7c, 0x01, 0x21, 0x00, 0x1a, 0x00, 0x7d, 0x00, 0x81, 0x00, 0x8b, 0x00, + 0x46, 0x00, 0xbb, 0x00, 0x8d, 0x00, 0xb1, 0x00, 0xfa, 0x00, 0x5c, 0x01, + 0x9d, 0x00, 0x01, 0x00, 0x17, 0x00, 0xf8, 0xff, 0xf6, 0x00, 0x8b, 0x00, + 0x5c, 0x00, 0x67, 0x00, 0xdf, 0xff, 0x3c, 0x00, 0x74, 0x00, 0x32, 0x00, + 0x61, 0x00, 0x3b, 0x00, 0x5f, 0x00, 0x9b, 0x00, 0x2f, 0x00, 0x65, 0x00, + 0xf4, 0x00, 0xbb, 0xff, 0xd5, 0xff, 0x85, 0x00, 0x90, 0x00, 0x1b, 0x00, + 0x79, 0x00, 0x04, 0x00, 0x03, 0x00, 0xdb, 0x00, 0x08, 0x01, 0xa5, 0x00, + 0x9a, 0x00, 0x68, 0x00, 0x25, 0x00, 0xcd, 0x00, 0x78, 0x00, 0x9b, 0x00, + 0xa0, 0x00, 0xc3, 0xff, 0x21, 0xff, 0x06, 0x00, 0x48, 0x00, 0x32, 0x00, + 0xa3, 0x00, 0xb5, 0x00, 0x97, 0x00, 0xc4, 0x00, 0xa4, 0x00, 0xd2, 0xff, + 0xff, 0xff, 0xbe, 0x00, 0x66, 0x00, 0x9a, 0x00, 0x99, 0x01, 0xc9, 0x00, + 0xb2, 0xff, 0xa3, 0x00, 0x63, 0x00, 0x5d, 0x00, 0xc1, 0x00, 0x9e, 0x00, + 0x4a, 0x00, 0xc0, 0x00, 0xdb, 0x00, 0xd3, 0x00, 0xe7, 0x00, 0xd2, 0x00, + 0xa7, 0x00, 0x72, 0x00, 0xb9, 0x00, 0x88, 0x00, 0xb0, 0x00, 0xa1, 0x00, + 0x86, 0x00, 0x73, 0x00, 0x96, 0x00, 0x57, 0x01, 0x00, 0x01, 0xa8, 0x00, + 0x9e, 0x00, 0x8a, 0x00, 0x34, 0x00, 0x5c, 0x00, 0xf8, 0x00, 0xa3, 0x00, + 0x93, 0x00, 0x59, 0x00, 0xac, 0xff, 0xc3, 0xff, 0x3d, 0x00, 0xfa, 0xff, + 0x2b, 0x00, 0xfd, 0xff, 0x1e, 0x00, 0x60, 0x00, 0x29, 0x00, 0x36, 0x00, + 0x4a, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x5d, 0x00, 0x60, 0x00, 0x38, 0x00, + 0x57, 0x00, 0x63, 0x00, 0x4d, 0x00, 0x30, 0x00, 0x39, 0x00, 0x8b, 0x00, + 0x1d, 0x00, 0x28, 0x00, 0x51, 0x00, 0x27, 0x00, 0x57, 0x00, 0x44, 0x00, + 0x2c, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x3c, 0x00, 0x09, 0x00, 0x23, 0x00, + 0x3c, 0x00, 0x41, 0x00, 0x3a, 0x00, 0x18, 0x00, 0xfd, 0xff, 0x59, 0x00, + 0x68, 0x00, 0x31, 0x00, 0x58, 0x00, 0x2b, 0x00, 0x25, 0x00, 0x2a, 0x00, + 0x37, 0x00, 0x10, 0x00, 0x18, 0x00, 0x40, 0x00, 0xf2, 0xff, 0x2b, 0x00, + 0x2b, 0x00, 0x35, 0x00, 0x2c, 0x00, 0x3b, 0x00, 0x41, 0x00, 0x26, 0x00, + 0x4c, 0x00, 0x60, 0x00, 0x62, 0x00, 0x6d, 0x00, 0x5c, 0x00, 0x3e, 0x00, + 0x64, 0x00, 0x6e, 0x00, 0x7d, 0x00, 0x74, 0x00, 0x53, 0x00, 0x70, 0x00, + 0x6d, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x5f, 0x00, 0x71, 0x00, + 0x87, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x5b, 0x00, 0x4a, 0x00, 0x6f, 0x00, + 0x6b, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x62, 0x00, + 0x68, 0x00, 0x52, 0x00, 0x3a, 0x00, 0x35, 0x00, 0x38, 0x00, 0x35, 0x00, + 0x1f, 0x00, 0x25, 0x00, 0x4a, 0x00, 0x56, 0x00, 0x3b, 0x00, 0x14, 0x00, + 0x06, 0x00, 0x16, 0x00, 0xfb, 0xff, 0x1d, 0x00, 0x32, 0x00, 0x12, 0x00, + 0x15, 0x00, 0x27, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x18, 0x00, 0x21, 0x00, + 0x27, 0x00, 0x1d, 0x00, 0x24, 0x00, 0x26, 0x00, 0x31, 0x00, 0x2f, 0x00, + 0x32, 0x00, 0x23, 0x00, 0x0d, 0x00, 0x22, 0x00, 0x2b, 0x00, 0x48, 0x00, + 0x50, 0x00, 0x47, 0x00, 0x30, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x24, 0x00, + 0x39, 0x00, 0x47, 0x00, 0x35, 0x00, 0x32, 0x00, 0x3d, 0x00, 0x32, 0x00, + 0x42, 0x00, 0x28, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2a, 0x00, 0x26, 0x00, + 0x2e, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x35, 0x00, 0x26, 0x00, 0x10, 0x00, + 0x1f, 0x00, 0x20, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x36, 0x00, 0x30, 0x00, + 0x1a, 0x00, 0x23, 0x00, 0x25, 0x00, 0x22, 0x00, 0x2a, 0x00, 0x36, 0x00, + 0x31, 0x00, 0x30, 0x00, 0x38, 0x00, 0x33, 0x00, 0x3d, 0x00, 0x3c, 0x00, + 0x34, 0x00, 0x2d, 0x00, 0x09, 0x00, 0x16, 0x00, 0x33, 0x00, 0x2b, 0x00, + 0x2c, 0x00, 0x2a, 0x00, 0x27, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x21, 0x00, 0x21, 0x00, 0x16, 0x00, 0x16, 0x00, + 0x1a, 0x00, 0x1a, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x12, 0x00, 0x14, 0x00, + 0x11, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x10, 0x00, + 0x0d, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, + 0x09, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0xff, + 0xfd, 0xff, 0x03, 0x00, 0xf7, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x15, 0x00, + 0x16, 0x00, 0x0c, 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfe, 0xff, 0x01, 0x00, + 0x09, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, + 0xfd, 0xff, 0x01, 0x00, 0xff, 0xff, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0xff, 0xfc, 0xff, + 0xf9, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0x03, 0x00, 0x06, 0x00, + 0xfb, 0xff, 0xf9, 0xff, 0xfd, 0xff, 0x01, 0x00, 0xf8, 0xff, 0xf8, 0xff, + 0x01, 0x00, 0x08, 0x00, 0x08, 0x00, 0xfb, 0xff, 0xf4, 0xff, 0xfa, 0xff, + 0xfe, 0xff, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xfa, 0xff, 0xfc, 0xff, + 0xfb, 0xff, 0xfc, 0xff, 0xf7, 0xff, 0xfb, 0xff, 0xfe, 0xff, 0x00, 0x00, + 0x00, 0x00, 0xf3, 0xff, 0xf5, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0xff, 0xff, + 0x03, 0x00, 0xff, 0xff, 0xf8, 0xff, 0xf6, 0xff, 0xf9, 0xff, 0xf7, 0xff, + 0xfa, 0xff, 0xf4, 0xff, 0xf3, 0xff, 0xf4, 0xff, 0xf5, 0xff, 0xf1, 0xff, + 0xfa, 0xff, 0xf4, 0xff, 0xee, 0xff, 0xf0, 0xff, 0xf3, 0xff, 0xf3, 0xff, + 0xee, 0xff, 0xeb, 0xff, 0xf0, 0xff, 0xf4, 0xff, 0xee, 0xff, 0xea, 0xff, + 0xef, 0xff, 0xf1, 0xff, 0xf2, 0xff, 0xf2, 0xff, 0xf3, 0xff, 0xf3, 0xff, + 0xf1, 0xff, 0xf0, 0xff, 0xf3, 0xff, 0xf1, 0xff, 0xf9, 0xff, 0xfe, 0xff, + 0xf6, 0xff, 0xf2, 0xff, 0xeb, 0xff, 0xf1, 0xff, 0xfa, 0xff, 0x00, 0x00, + 0xfd, 0xff, 0xf8, 0xff, 0xf7, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0xfd, 0xff, 0xfc, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xff, 0xff, 0x00, 0x00, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0xfe, 0xff, 0xfe, 0xff, + 0xfb, 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfa, 0xff, + 0xf8, 0xff, 0xf4, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xf4, 0xff, 0xf4, 0xff, + 0xf3, 0xff, 0xed, 0xff, 0xed, 0xff, 0xf2, 0xff, 0xf1, 0xff, 0xee, 0xff, + 0xef, 0xff, 0xf0, 0xff, 0xee, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xf0, 0xff, 0xee, 0xff, 0xee, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xee, 0xff, 0xf1, 0xff, 0xf3, 0xff, 0xf2, 0xff, 0xf0, 0xff, 0xf2, 0xff, + 0xf3, 0xff, 0xf4, 0xff, 0xf4, 0xff, 0xf3, 0xff, 0xf1, 0xff, 0xf0, 0xff, + 0xf1, 0xff, 0xf3, 0xff, 0xf2, 0xff, 0xf1, 0xff, 0xf1, 0xff, 0xf2, 0xff, + 0xf4, 0xff, 0xf2, 0xff, 0xf2, 0xff, 0xf7, 0xff, 0xf5, 0xff, 0xf5, 0xff, + 0xf5, 0xff, 0xfa, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf9, 0xff, 0xfa, 0xff, + 0xfc, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0x01, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, + 0x11, 0x00, 0x16, 0x00, 0x1d, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x54, 0x00, + 0x6d, 0x00, 0xa3, 0x00, 0x19, 0x01, 0xdb, 0x01, 0x79, 0x03, 0x53, 0x05, + 0x09, 0x05, 0x4a, 0x02, 0x9d, 0xff, 0x8a, 0xfe, 0xe7, 0xff, 0x66, 0x01, + 0x8d, 0x00, 0xc2, 0xff, 0x06, 0xfe, 0x3d, 0xff, 0xe2, 0x00, 0x85, 0xff, + 0x47, 0x01, 0xc9, 0x00, 0xc6, 0xfe, 0xcc, 0xfd, 0x45, 0xfe, 0x2c, 0x01, + 0x60, 0x01, 0x41, 0x01, 0x20, 0x00, 0xb0, 0xfd, 0xad, 0xfd, 0x00, 0x00, + 0x32, 0x00, 0xaf, 0xff, 0x28, 0x00, 0x14, 0xff, 0x4b, 0xfe, 0x46, 0x00, + 0xa8, 0x00, 0xcf, 0xff, 0x71, 0x00, 0xc3, 0xfe, 0xa6, 0xfe, 0xeb, 0xff, + 0xfe, 0xff, 0x06, 0x00, 0xfb, 0xff, 0xe1, 0xff, 0xaf, 0xff, 0x51, 0x01, + 0xba, 0x01, 0x73, 0x00, 0x1d, 0x00, 0xf1, 0xff, 0x35, 0x00, 0x79, 0x00, + 0x88, 0x00, 0x05, 0x00, 0x89, 0x00, 0xfa, 0xff, 0xf8, 0xff, 0x00, 0x00, + 0x58, 0x00, 0xed, 0xff, 0xb1, 0x00, 0xea, 0xff, 0x3e, 0xff, 0x36, 0x00, + 0x43, 0x00, 0x00, 0x01, 0xb9, 0x01, 0xd1, 0x00, 0x79, 0x00, 0x64, 0x00, + 0xb5, 0x00, 0x7e, 0x00, 0xad, 0x00, 0x9f, 0x01, 0x79, 0x01, 0xc6, 0x00, + 0x5e, 0xff, 0x68, 0xff, 0x60, 0xff, 0x51, 0xff, 0xd9, 0xfe, 0x99, 0xff, + 0x12, 0x01, 0x7c, 0x00, 0x7f, 0xff, 0x36, 0x00, 0x6c, 0xff, 0x52, 0xfe, + 0xe4, 0xff, 0x5f, 0x01, 0x0e, 0x01, 0x78, 0x00, 0xa1, 0xfe, 0x29, 0xff, + 0xa2, 0xff, 0x6b, 0x00, 0x12, 0x01, 0x9d, 0xff, 0x55, 0xfe, 0x38, 0xff, + 0x16, 0xff, 0x18, 0xff, 0x5f, 0x01, 0x10, 0x01, 0x29, 0xff, 0x51, 0xff, + 0x7b, 0xff, 0x8e, 0x00, 0x8e, 0x00, 0xc0, 0xff, 0xe1, 0xff, 0x0f, 0x00, + 0xa3, 0x00, 0x92, 0x00, 0xe7, 0xff, 0x26, 0xff, 0x5e, 0x00, 0xe5, 0x00, + 0xbd, 0xff, 0xf7, 0xff, 0x85, 0x00, 0x78, 0xff, 0xf6, 0xfe, 0x26, 0x00, + 0x03, 0x00, 0x57, 0xff, 0x75, 0x00, 0x87, 0x00, 0xdc, 0xff, 0x18, 0x00, + 0x8a, 0xff, 0x31, 0xfe, 0x90, 0xff, 0x8b, 0x00, 0xbd, 0x00, 0x9b, 0x00, + 0x25, 0x00, 0xd7, 0xfe, 0xf1, 0xfd, 0x26, 0x02, 0xb8, 0x03, 0xf3, 0xfe, + 0xe8, 0xfd, 0x0f, 0x00, 0x04, 0xff, 0xba, 0xff, 0x7e, 0x00, 0xf3, 0xff, + 0x26, 0x00, 0xb4, 0xff, 0x1e, 0xff, 0x96, 0xff, 0xa1, 0xff, 0x54, 0x00, + 0x4c, 0x00, 0x0b, 0xfd, 0x0b, 0xff, 0x0a, 0x03, 0x9b, 0x00, 0x29, 0xff, + 0x1a, 0x01, 0x52, 0x00, 0x5f, 0xfe, 0x8f, 0xff, 0x11, 0x01, 0x18, 0x00, + 0x50, 0xff, 0xed, 0xff, 0x0b, 0x00, 0xa4, 0x00, 0xc6, 0xff, 0x05, 0xff, + 0x98, 0x01, 0x01, 0x01, 0x99, 0xfd, 0x42, 0xff, 0x41, 0x02, 0x5a, 0x00, + 0x0c, 0x00, 0x4e, 0x01, 0x4f, 0x00, 0x76, 0xff, 0x79, 0x00, 0xa1, 0x00, + 0xca, 0x00, 0xa4, 0xff, 0x4b, 0x00, 0x51, 0x00, 0xf8, 0xfe, 0x1e, 0x00, + 0x51, 0x00, 0xe9, 0xfe, 0xed, 0xfe, 0xe7, 0xff, 0x4d, 0x00, 0xca, 0x00, + 0x54, 0x01, 0xea, 0xff, 0x65, 0xfd, 0xf0, 0xfd, 0x09, 0x01, 0xda, 0x02, + 0x03, 0x00, 0x35, 0xfd, 0xc2, 0xfe, 0x8e, 0xff, 0xf7, 0x00, 0xdb, 0x01, + 0x85, 0xff, 0x9e, 0xfd, 0xcd, 0xfd, 0xdb, 0xff, 0x66, 0x01, 0x4f, 0x01, + 0x97, 0xff, 0x66, 0xfd, 0xf6, 0xfe, 0xe1, 0x01, 0x4e, 0x02, 0x1c, 0xff, + 0xcd, 0xfd, 0x99, 0xff, 0x81, 0xff, 0x3e, 0x00, 0x90, 0x01, 0xdf, 0xff, + 0x4e, 0xff, 0x3e, 0x01, 0x14, 0x00, 0x0e, 0x00, 0x05, 0xff, 0x45, 0xfe, + 0xfa, 0x00, 0xc1, 0x02, 0x1e, 0xff, 0xa3, 0xfd, 0xb6, 0xff, 0x4c, 0x02, + 0xa9, 0x01, 0x01, 0xff, 0xe5, 0xff, 0x81, 0xff, 0xd6, 0xff, 0x9f, 0x01, + 0x94, 0x01, 0xb6, 0xff, 0xd8, 0xfe, 0xc4, 0xfe, 0x34, 0x00, 0xac, 0x01, + 0x7a, 0x02, 0x4b, 0x00, 0xfe, 0xfd, 0x4d, 0xfe, 0x24, 0x00, 0x1c, 0x01, + 0x74, 0x00, 0xd9, 0x00, 0x60, 0x00, 0xd1, 0xfd, 0x6a, 0xfd, 0x44, 0x01, + 0xd1, 0x01, 0x45, 0xfd, 0x67, 0x00, 0xaa, 0x01, 0xa5, 0xfd, 0xf0, 0xfe, + 0x35, 0x04, 0xd6, 0xff, 0x2e, 0xfd, 0xb9, 0x01, 0xbd, 0xfe, 0xb2, 0xfc, + 0x0b, 0x03, 0x50, 0x03, 0xfa, 0xfc, 0xc8, 0xfd, 0xcf, 0xfc, 0x99, 0xff, + 0xe6, 0xff, 0x87, 0x02, 0x93, 0x02, 0xe5, 0xfe, 0xaf, 0xfd, 0xb4, 0xfe, + 0xda, 0xff, 0x04, 0x00, 0x4f, 0x03, 0xfa, 0x01, 0x59, 0xfe, 0x1c, 0xfd, + 0x1f, 0x01, 0x70, 0x01, 0xf5, 0xfe, 0x6f, 0x00, 0xed, 0x01, 0x10, 0xff, + 0x96, 0xfe, 0x1c, 0x02, 0x8d, 0x02, 0xa3, 0xfc, 0x2d, 0xfe, 0x92, 0x04, + 0xa5, 0xfd, 0x12, 0xfc, 0x6b, 0x06, 0xad, 0x01, 0x89, 0xf8, 0xdc, 0x01, + 0x81, 0x04, 0x17, 0xfd, 0x9c, 0x00, 0x63, 0x02, 0x38, 0x01, 0x26, 0xfb, + 0x16, 0xfb, 0x9c, 0x04, 0x46, 0x04, 0xf6, 0xfe, 0xc2, 0xfd, 0xbe, 0xfe, + 0xc5, 0xfd, 0xd3, 0x00, 0xcb, 0x02, 0x6c, 0xff, 0x2b, 0xfe, 0x9b, 0x01, + 0xb1, 0xff, 0x00, 0xfe, 0x76, 0x00, 0xc2, 0x03, 0x43, 0xff, 0x33, 0xfc, + 0xfd, 0xfe, 0x25, 0x01, 0xa4, 0x01, 0xf9, 0xff, 0x30, 0x00, 0xc6, 0x01, + 0x2f, 0xfe, 0xde, 0xfc, 0x17, 0x02, 0xb4, 0x03, 0x6b, 0xfe, 0x51, 0xff, + 0x9c, 0x00, 0x76, 0xff, 0x87, 0xfd, 0x58, 0x00, 0x39, 0x05, 0xc8, 0xfe, + 0x1f, 0xfd, 0x00, 0x01, 0xb8, 0x00, 0x1d, 0xfa, 0x67, 0x01, 0x40, 0x09, + 0xf3, 0xfd, 0x28, 0xfc, 0xa3, 0x00, 0x7c, 0xff, 0xfb, 0x00, 0x1d, 0x01, + 0x5d, 0xff, 0xe0, 0xfb, 0x93, 0xff, 0x49, 0x05, 0x31, 0x01, 0xad, 0xfe, + 0xc4, 0xfe, 0x57, 0x00, 0xc1, 0x00, 0xd1, 0xfe, 0xfb, 0x00, 0x18, 0x01, + 0x8b, 0xfe, 0xbe, 0xff, 0x94, 0x00, 0x25, 0x00, 0x3b, 0xff, 0x22, 0xff, + 0xa9, 0x01, 0x26, 0x01, 0xff, 0xfe, 0x7a, 0xff, 0x03, 0xfd, 0x8c, 0x00, + 0x85, 0x04, 0xce, 0xfe, 0x43, 0xfe, 0x4e, 0x04, 0x3d, 0xfe, 0x91, 0xf9, + 0xa2, 0x02, 0x9c, 0x06, 0x23, 0x01, 0xc1, 0xf9, 0x9f, 0xfc, 0xb9, 0x02, + 0x61, 0x00, 0x0f, 0x01, 0x70, 0x02, 0x2f, 0xfe, 0xeb, 0xfe, 0x36, 0x01, + 0xc2, 0xff, 0x07, 0xff, 0xcb, 0xff, 0x64, 0x01, 0x68, 0x00, 0x41, 0x01, + 0x8c, 0xff, 0xeb, 0xfd, 0xd9, 0xff, 0x9d, 0x00, 0xad, 0xff, 0x7f, 0x02, + 0x98, 0x01, 0x3a, 0xfc, 0xac, 0xfe, 0x62, 0x01, 0x59, 0xff, 0x6d, 0xfe, + 0x5b, 0xfd, 0x1f, 0x02, 0x40, 0x06, 0x1a, 0xff, 0x5c, 0xf9, 0x6b, 0x00, + 0x5f, 0x04, 0x6f, 0xfa, 0xab, 0xff, 0xff, 0x0a, 0xe8, 0xfe, 0x44, 0xf9, + 0x44, 0x01, 0x0a, 0xfc, 0x80, 0xfe, 0xbe, 0x08, 0xd3, 0x02, 0x5d, 0xfb, + 0x89, 0xff, 0x7a, 0xfd, 0xff, 0xff, 0x53, 0x02, 0x3b, 0x03, 0xaa, 0xfe, + 0xa3, 0xfb, 0x4f, 0x02, 0xea, 0x02, 0x2e, 0xfd, 0xbb, 0x00, 0x2a, 0x02, + 0xe6, 0xfc, 0x5a, 0x01, 0x34, 0x05, 0xe8, 0x00, 0x5a, 0xfd, 0x4c, 0xfe, + 0x34, 0xfd, 0xae, 0x02, 0xfa, 0x05, 0x93, 0xfe, 0x2e, 0xfd, 0x90, 0xfc, + 0x1e, 0xfe, 0x3a, 0x05, 0x0e, 0x06, 0x67, 0xfd, 0x60, 0x00, 0x29, 0x01, + 0x44, 0xfa, 0x70, 0xfd, 0x15, 0x07, 0x69, 0x04, 0x3b, 0xfc, 0xed, 0xfe, + 0x32, 0x00, 0x21, 0xfd, 0xc5, 0x00, 0xc2, 0x02, 0xc7, 0x01, 0x9a, 0xfe, + 0x62, 0xfe, 0xe7, 0xfe, 0x24, 0xff, 0xd6, 0x02, 0x61, 0x07, 0xa8, 0x00, + 0xf3, 0xf7, 0x38, 0xf9, 0xf1, 0x04, 0x2c, 0x0a, 0x62, 0xff, 0x08, 0xfe, + 0x2f, 0xfc, 0x2c, 0xf7, 0xd4, 0x04, 0xe9, 0x08, 0x4e, 0xfb, 0xcc, 0xf9, + 0xde, 0x04, 0x6f, 0x01, 0x93, 0xfc, 0x5a, 0x05, 0x00, 0x04, 0x29, 0xf6, + 0xe9, 0xfb, 0x01, 0x07, 0xc0, 0x03, 0xe7, 0x02, 0x14, 0xfe, 0xcd, 0xfe, + 0xe6, 0xfd, 0x15, 0xfe, 0x20, 0x03, 0x9e, 0x01, 0xa6, 0x00, 0x30, 0x00, + 0xb4, 0xfe, 0x63, 0xff, 0x8e, 0x02, 0xdb, 0xfe, 0x4f, 0xfe, 0x31, 0x03, + 0x93, 0x00, 0x5a, 0x01, 0x84, 0xfe, 0x49, 0x00, 0xae, 0x00, 0x82, 0xfd, + 0xa7, 0x01, 0x54, 0x03, 0x35, 0xfd, 0xee, 0xfc, 0x2f, 0x00, 0x4c, 0x03, + 0x0b, 0x02, 0xa6, 0xfd, 0x6c, 0xfc, 0x5c, 0x04, 0x1d, 0x03, 0xf5, 0xfc, + 0xa6, 0x00, 0x3e, 0x00, 0xc3, 0xfb, 0xb9, 0x01, 0x4e, 0x04, 0xb1, 0x01, + 0x4e, 0xfe, 0x45, 0xfe, 0xe3, 0xfe, 0xd4, 0xfe, 0x42, 0x01, 0x64, 0x05, + 0x9d, 0x00, 0xe1, 0xfc, 0xf5, 0xfd, 0xa4, 0xff, 0x91, 0x00, 0x90, 0x01, + 0xba, 0x00, 0xbd, 0x00, 0xad, 0x00, 0x68, 0xfe, 0x72, 0xff, 0xa0, 0x00, + 0x9d, 0x00, 0x43, 0x01, 0xb0, 0xff, 0x34, 0xfd, 0x6e, 0x00, 0x2d, 0xff, + 0xc2, 0x02, 0xe9, 0x02, 0x83, 0xfb, 0x70, 0xff, 0x75, 0x01, 0xd3, 0xfd, + 0x12, 0xff, 0xeb, 0x04, 0x78, 0x00, 0xcb, 0xfd, 0xf5, 0xfe, 0x1b, 0xfe, + 0x95, 0x00, 0x8c, 0x00, 0x60, 0x03, 0x07, 0x02, 0x72, 0xfd, 0x10, 0xfd, + 0x09, 0xff, 0x23, 0x00, 0xd4, 0x00, 0x11, 0x04, 0xea, 0x01, 0x9b, 0xfb, + 0x39, 0xff, 0x0e, 0x02, 0x98, 0xfd, 0x1b, 0xfe, 0xa3, 0x04, 0x88, 0x01, + 0xe1, 0xfb, 0x3a, 0x00, 0x63, 0x02, 0xce, 0xfe, 0xae, 0x00, 0x8f, 0x02, + 0x95, 0xfe, 0x33, 0xfc, 0x1e, 0x00, 0xbf, 0x02, 0x0b, 0x01, 0x2b, 0x01, + 0x09, 0x01, 0x81, 0xfe, 0xe4, 0xfd, 0x93, 0xff, 0xe6, 0x01, 0x63, 0x00, + 0x61, 0x01, 0xe5, 0xfd, 0xc2, 0xfd, 0x0d, 0x04, 0x32, 0x05, 0x61, 0xfd, + 0x1d, 0xfb, 0x43, 0x02, 0xb3, 0x00, 0x97, 0xfe, 0xec, 0x02, 0x35, 0x01, + 0x18, 0xfd, 0x74, 0xfe, 0xb7, 0x02, 0xdb, 0x02, 0x40, 0xff, 0xea, 0xfd, + 0xcc, 0xfe, 0xdb, 0xfe, 0xf2, 0xff, 0xc2, 0x00, 0x19, 0x03, 0x1f, 0x04, + 0xe7, 0xfc, 0x3f, 0xfd, 0x79, 0x02, 0x8f, 0xff, 0x98, 0xfc, 0x02, 0x02, + 0xc7, 0x02, 0xfa, 0xff, 0x88, 0x01, 0x1c, 0xfe, 0xac, 0xfb, 0x4f, 0xff, + 0x35, 0x01, 0xbc, 0x02, 0x87, 0x00, 0xfe, 0xfd, 0xc1, 0xff, 0x40, 0x00, + 0x11, 0x00, 0x6a, 0xff, 0x12, 0x00, 0x5a, 0x02, 0x7b, 0x01, 0x8b, 0xfd, + 0xf2, 0xfd, 0xe6, 0x00, 0x9b, 0x00, 0xc2, 0xfc, 0x1c, 0x01, 0xdf, 0x01, + 0x30, 0xff, 0x3f, 0x03, 0x6e, 0x00, 0x32, 0xfd, 0x2a, 0xfc, 0x4f, 0xff, + 0x35, 0x04, 0x83, 0x05, 0xe0, 0x00, 0x6e, 0xfa, 0x02, 0xfc, 0xae, 0x01, + 0x3c, 0x03, 0xd9, 0x01, 0x36, 0x02, 0xb1, 0xff, 0x17, 0xfb, 0x3c, 0xfd, + 0xfb, 0x02, 0x8a, 0x02, 0x07, 0x02, 0xb7, 0xfe, 0x56, 0xfd, 0x87, 0xfe, + 0x49, 0x02, 0xf9, 0x02, 0x73, 0xff, 0x30, 0xfe, 0x9a, 0xff, 0xed, 0xff, + 0xc6, 0xff, 0xd9, 0x03, 0xca, 0x00, 0x63, 0xfb, 0xff, 0xfd, 0x5c, 0x01, + 0xa9, 0x00, 0x12, 0x03, 0x5d, 0x01, 0x89, 0xfb, 0x66, 0xfe, 0xf4, 0x01, + 0x7c, 0x00, 0x3a, 0x02, 0xd0, 0xff, 0x44, 0xfc, 0xf3, 0xff, 0x1d, 0x03, + 0x8d, 0x00, 0x38, 0xff, 0x1f, 0x00, 0xa4, 0xfd, 0x95, 0xfd, 0x2b, 0x03, + 0xf1, 0x04, 0x9c, 0xfa, 0xab, 0xfe, 0x58, 0x06, 0xde, 0xfb, 0x8a, 0xfc, + 0xd9, 0x05, 0x25, 0xff, 0x30, 0xfa, 0x1d, 0x00, 0x84, 0x04, 0x2b, 0x00, + 0x70, 0xff, 0x6e, 0x02, 0x2a, 0xfc, 0x1d, 0xfd, 0x35, 0x06, 0xe6, 0x01, + 0x72, 0xfe, 0xaf, 0x00, 0x1e, 0xfc, 0x45, 0xfb, 0x9b, 0x03, 0x36, 0x04, + 0xd5, 0xff, 0xb1, 0x00, 0x5e, 0xfc, 0x97, 0xfc, 0xa7, 0xff, 0x6e, 0x01, + 0x65, 0x03, 0x78, 0x01, 0x70, 0xfd, 0xbe, 0xff, 0x0d, 0xff, 0xfc, 0xfe, + 0x1d, 0x02, 0x5e, 0x01, 0xab, 0xfd, 0x33, 0xff, 0x7e, 0x00, 0x6c, 0xfd, + 0x82, 0x00, 0xe6, 0x02, 0xa1, 0xff, 0xc3, 0x03, 0x43, 0xff, 0x58, 0xf7, + 0xdc, 0xfe, 0xb7, 0x08, 0xda, 0x03, 0x5b, 0xfb, 0x24, 0xfa, 0x79, 0xff, + 0x46, 0x01, 0xad, 0x02, 0xde, 0x05, 0xc4, 0xfc, 0x67, 0xf9, 0xb6, 0x00, + 0x27, 0x03, 0xd4, 0xff, 0xc1, 0x01, 0x84, 0x03, 0x28, 0xfc, 0xc6, 0xf9, + 0x04, 0x02, 0xee, 0x03, 0xd9, 0x01, 0x92, 0xfd, 0xed, 0xfc, 0xb5, 0x02, + 0x4a, 0x01, 0x82, 0xfe, 0x35, 0x00, 0xa3, 0xfd, 0x05, 0x00, 0x19, 0x02, + 0x5e, 0x01, 0x2d, 0xff, 0x30, 0xfe, 0x55, 0x01, 0x7a, 0x01, 0xc4, 0xfe, + 0xd9, 0xff, 0x1d, 0x01, 0xb5, 0xff, 0xb6, 0xfe, 0xa2, 0xfd, 0xe8, 0x01, + 0xb7, 0x04, 0x02, 0xfa, 0x7f, 0xfd, 0x94, 0x05, 0x0a, 0xff, 0xad, 0xfc, + 0x2d, 0x02, 0x75, 0x02, 0xcd, 0xfb, 0x5d, 0x00, 0xb9, 0x02, 0xa3, 0xfd, + 0xdb, 0xfe, 0x76, 0xff, 0xf4, 0x02, 0xa6, 0xff, 0xe9, 0xfc, 0xe7, 0x02, + 0x00, 0x00, 0xae, 0xfa, 0xff, 0x02, 0xfb, 0x02, 0x12, 0xfd, 0x21, 0x02, + 0x6e, 0xff, 0xc6, 0xf9, 0xc1, 0x02, 0xa8, 0x04, 0x55, 0xff, 0xf2, 0x01, + 0x7a, 0xfd, 0x91, 0xf7, 0x76, 0x00, 0x89, 0x0b, 0x69, 0x03, 0xe5, 0xf8, + 0x84, 0xfb, 0x1c, 0x00, 0x5e, 0x00, 0x57, 0x04, 0xbb, 0x04, 0x54, 0xfc, + 0xef, 0xf5, 0x20, 0xfe, 0xf9, 0x0a, 0x87, 0x05, 0x9d, 0xfe, 0x51, 0xfd, + 0xc3, 0xf9, 0x10, 0xfa, 0x2f, 0x05, 0x6d, 0x08, 0x78, 0x00, 0x0f, 0xfd, + 0xdb, 0xfa, 0x0b, 0xfc, 0x49, 0x02, 0xd3, 0x06, 0xe2, 0xfc, 0x75, 0xfc, + 0xca, 0x04, 0xce, 0x00, 0x6f, 0xfb, 0x46, 0x00, 0x3f, 0xfd, 0x89, 0xfe, + 0xf5, 0x05, 0xa4, 0x05, 0xd0, 0xfd, 0x82, 0xf9, 0xbb, 0xfe, 0x76, 0x02, + 0x7b, 0xff, 0x46, 0x02, 0x43, 0x01, 0x23, 0x04, 0x8b, 0xfd, 0x55, 0xf4, + 0x01, 0x02, 0xf5, 0x07, 0x07, 0xfd, 0x6a, 0xff, 0xa4, 0x05, 0x0b, 0xfe, + 0x59, 0xfa, 0xd9, 0xff, 0x84, 0x03, 0x3b, 0xfe, 0xef, 0xfe, 0x8b, 0x00, + 0x70, 0x00, 0x06, 0x03, 0x0d, 0x03, 0x9e, 0xfb, 0xc1, 0xfb, 0x73, 0x03, + 0x19, 0x01, 0x7d, 0xfc, 0x25, 0x02, 0x9c, 0x03, 0xea, 0xfb, 0xd2, 0xfc, + 0x2c, 0x04, 0xc0, 0x01, 0x3c, 0xfe, 0x9c, 0x00, 0xd0, 0x00, 0x0d, 0xfe, + 0xc5, 0xfd, 0x12, 0x01, 0xd9, 0xfe, 0x2d, 0xfe, 0xd2, 0x04, 0x6f, 0x03, + 0x71, 0xfd, 0x1d, 0xfe, 0xa6, 0x03, 0x89, 0xfe, 0x8f, 0xf7, 0x9e, 0x03, + 0x25, 0x07, 0xdf, 0xfb, 0xd7, 0xff, 0xe7, 0x04, 0x68, 0xfc, 0xe7, 0xf8, + 0x97, 0x01, 0x7c, 0x0a, 0xe8, 0x05, 0xdd, 0xfa, 0xf0, 0xf5, 0x23, 0xfe, + 0x54, 0x08, 0xc3, 0x02, 0x24, 0xfd, 0xe1, 0x01, 0xc4, 0x01, 0xd5, 0xfc, + 0xae, 0xf9, 0x89, 0x02, 0x6b, 0x06, 0xd2, 0x00, 0x34, 0xfb, 0xc0, 0xfd, + 0xc0, 0x02, 0x24, 0xfe, 0xea, 0xfb, 0x60, 0x09, 0x8f, 0x07, 0x7c, 0xf9, + 0x0d, 0xfa, 0x37, 0x00, 0x44, 0xfd, 0x8d, 0x03, 0x26, 0x09, 0x51, 0xfd, + 0x5b, 0xf6, 0xdf, 0x01, 0xd6, 0x04, 0xc6, 0xfe, 0x28, 0x00, 0x80, 0x00, + 0x1c, 0x01, 0xdb, 0xfe, 0x8b, 0xff, 0xae, 0xff, 0x39, 0x01, 0x5c, 0x01, + 0x1d, 0x02, 0x46, 0xfd, 0x66, 0xfb, 0xbe, 0x04, 0xe5, 0x04, 0x57, 0xfe, + 0xde, 0xff, 0x98, 0xfc, 0x86, 0xfb, 0x81, 0x02, 0x4a, 0x04, 0xe1, 0xfe, + 0x73, 0xfd, 0x81, 0x04, 0x82, 0x03, 0x4c, 0xf8, 0xb0, 0xfd, 0x01, 0x05, + 0xbb, 0x00, 0xd9, 0xff, 0x3e, 0x02, 0xc8, 0xfd, 0x8f, 0xfc, 0x27, 0x02, + 0x5a, 0xff, 0xc7, 0xfc, 0xd0, 0x05, 0xc3, 0x04, 0x94, 0xfc, 0x83, 0x00, + 0x0a, 0x01, 0x3d, 0xf9, 0x77, 0xfd, 0xe0, 0x06, 0x85, 0x03, 0x03, 0xfd, + 0x2c, 0x05, 0x95, 0x00, 0x59, 0xf6, 0x59, 0xfd, 0x6b, 0x09, 0xc4, 0x02, + 0x4d, 0xfd, 0x0b, 0x01, 0xe6, 0xfd, 0xdf, 0xfa, 0xce, 0x01, 0x68, 0x04, + 0x05, 0x02, 0x39, 0x03, 0x2c, 0xfd, 0x19, 0xf8, 0x84, 0xfd, 0xe5, 0x04, + 0xd1, 0x09, 0x95, 0xfd, 0x6e, 0xf8, 0xa0, 0x03, 0x98, 0xff, 0xa6, 0xf9, + 0xcf, 0x06, 0xc2, 0x08, 0x1f, 0xfc, 0x2f, 0xf7, 0xbd, 0xfd, 0x15, 0x00, + 0xc9, 0x05, 0x51, 0x06, 0x23, 0xf8, 0x27, 0xfb, 0x1e, 0x07, 0x8c, 0x01, + 0xfd, 0x02, 0x5c, 0x02, 0x68, 0xf6, 0xcd, 0xfd, 0x84, 0x05, 0xd1, 0xff, + 0xf8, 0xfd, 0x85, 0x03, 0x08, 0x05, 0x14, 0xff, 0xe2, 0xf5, 0x66, 0xfd, + 0xd4, 0x08, 0x18, 0x0e, 0x3d, 0xfe, 0x50, 0xf5, 0xff, 0xf9, 0x81, 0xfc, + 0xa9, 0xfe, 0x44, 0x08, 0xee, 0x09, 0xfc, 0xf9, 0xd7, 0xf8, 0x5b, 0x00, + 0x34, 0x01, 0x8a, 0x01, 0xd1, 0x04, 0x96, 0x00, 0x7c, 0xfa, 0x5e, 0xfd, + 0x5b, 0xff, 0xe9, 0x02, 0x25, 0x08, 0x46, 0x01, 0x95, 0xfc, 0xb0, 0xfd, + 0x08, 0xff, 0x84, 0xff, 0xe9, 0xff, 0xb2, 0x02, 0xb9, 0xff, 0x9d, 0x00, + 0x4d, 0xfe, 0x23, 0xff, 0xe2, 0x02, 0x05, 0x02, 0xdd, 0xff, 0x5c, 0xfe, + 0x60, 0xfe, 0x5c, 0xff, 0xac, 0x02, 0x0a, 0x05, 0x7e, 0x01, 0xda, 0xf8, + 0x86, 0xfb, 0x81, 0x07, 0x50, 0x02, 0x2d, 0xfd, 0xd3, 0xfd, 0xe2, 0xfd, + 0xde, 0x04, 0xb6, 0x02, 0xf2, 0xfc, 0x73, 0x02, 0xb1, 0xfc, 0xcc, 0xf7, + 0xe2, 0x05, 0xd7, 0x0b, 0xa6, 0xff, 0x58, 0xf7, 0x78, 0xff, 0xcd, 0x02, + 0xc3, 0xfc, 0x14, 0x03, 0xbe, 0x07, 0x21, 0xfc, 0xbb, 0xf4, 0xdf, 0xfe, + 0x0a, 0x08, 0x18, 0x05, 0x0b, 0xff, 0x4b, 0xfe, 0xf2, 0xfd, 0xb8, 0xff, + 0xfd, 0xfd, 0x7c, 0xfd, 0x48, 0x04, 0x54, 0x05, 0x32, 0xfe, 0x73, 0xfc, + 0xcb, 0x02, 0x97, 0xfe, 0x5d, 0xfc, 0x70, 0x03, 0x78, 0x03, 0x3a, 0xfe, + 0x49, 0xfe, 0xa6, 0xfe, 0x6c, 0x02, 0xae, 0x05, 0x19, 0xf9, 0xf8, 0xf8, + 0xc2, 0xff, 0x21, 0x02, 0x44, 0x0a, 0xe7, 0x03, 0x6e, 0xf8, 0x48, 0xfb, + 0xfb, 0xff, 0x86, 0x01, 0x18, 0x00, 0xbd, 0x01, 0xc5, 0x05, 0xcc, 0x03, + 0x8c, 0xfa, 0x64, 0xf8, 0x07, 0x02, 0xa1, 0x01, 0x91, 0x01, 0x5a, 0x04, + 0x77, 0x01, 0xf2, 0xfa, 0x73, 0xfc, 0xec, 0x01, 0xcf, 0x01, 0xa3, 0xfd, + 0x64, 0x00, 0xf3, 0x07, 0x4b, 0x03, 0xdc, 0xf7, 0x56, 0xfa, 0xd3, 0x01, + 0x93, 0x01, 0xcb, 0x02, 0xcb, 0x00, 0x25, 0xfe, 0x67, 0x05, 0x95, 0xff, + 0xdc, 0xf7, 0xac, 0x00, 0xb5, 0x01, 0x47, 0xff, 0x78, 0x03, 0x26, 0xff, + 0x94, 0xfb, 0x10, 0x00, 0xd0, 0x01, 0x70, 0x02, 0x5d, 0x00, 0xc8, 0x02, + 0xdb, 0xfd, 0x36, 0xf8, 0x91, 0xfd, 0x3b, 0x08, 0x5b, 0x04, 0x62, 0xff, + 0xfc, 0xfb, 0x89, 0xfc, 0x34, 0x01, 0xc1, 0x00, 0x16, 0xfe, 0x08, 0x01, + 0xef, 0x03, 0x47, 0xfe, 0x2f, 0x00, 0x13, 0xfe, 0x91, 0xfe, 0xbe, 0x01, + 0x0e, 0x01, 0xbb, 0x01, 0x3b, 0xff, 0x2a, 0xfd, 0xb7, 0xfe, 0x14, 0xfe, + 0x46, 0x02, 0xb1, 0x04, 0x0e, 0x03, 0xe8, 0xfb, 0x8b, 0xfb, 0xa3, 0x01, + 0x47, 0x03, 0x79, 0x02, 0x78, 0xfb, 0xca, 0xfd, 0x28, 0x04, 0xcb, 0xf8, + 0x62, 0x01, 0x65, 0x0c, 0xca, 0x00, 0xb9, 0xfb, 0xec, 0xfd, 0x99, 0xf9, + 0x22, 0xf9, 0x7a, 0x07, 0x9d, 0x08, 0x9c, 0x00, 0xb4, 0xfb, 0xcb, 0xfd, + 0xfa, 0xf9, 0x37, 0xfd, 0x68, 0x0b, 0x44, 0x08, 0x86, 0xf5, 0xcf, 0xf5, + 0x4b, 0x03, 0x3a, 0x02, 0xa5, 0x03, 0xd0, 0x07, 0xbf, 0xfe, 0x95, 0xf5, + 0x77, 0xfa, 0x2a, 0x07, 0x22, 0x0a, 0x3b, 0xfe, 0xa3, 0xfa, 0x71, 0xfe, + 0xfb, 0x03, 0x0f, 0xff, 0x5b, 0xfd, 0x4c, 0x03, 0x08, 0x04, 0x3c, 0xfd, + 0xfd, 0xf6, 0x6f, 0xf8, 0x7c, 0x0a, 0x47, 0x0d, 0xa8, 0xfa, 0xb5, 0xf4, + 0x32, 0x00, 0x1d, 0x08, 0x63, 0x01, 0xee, 0xf9, 0x33, 0x03, 0x93, 0xfb, + 0x67, 0xfb, 0xf9, 0x02, 0x15, 0x01, 0x7d, 0x05, 0xb5, 0x03, 0x4e, 0xf9, + 0xfb, 0xf7, 0xc3, 0xfd, 0x05, 0xff, 0xc6, 0x07, 0x3b, 0x04, 0x83, 0xfb, + 0x34, 0xfc, 0x61, 0xfe, 0x17, 0x00, 0x3a, 0x08, 0x4b, 0x02, 0xf1, 0xf7, + 0x34, 0xff, 0xc2, 0x03, 0x65, 0xff, 0x3b, 0x01, 0x6f, 0x00, 0x59, 0xfd, + 0x4f, 0x00, 0x02, 0xfc, 0x23, 0xfb, 0x20, 0x02, 0xa3, 0x07, 0xd7, 0x03, + 0x51, 0xfb, 0xa6, 0xf9, 0x7d, 0xfa, 0x85, 0x01, 0x49, 0x09, 0x25, 0x06, + 0xb6, 0xf9, 0xa6, 0xfa, 0x61, 0x02, 0xf8, 0xfe, 0xb0, 0xfe, 0xa6, 0x05, + 0x76, 0x03, 0x19, 0xfd, 0xb2, 0xf8, 0xb7, 0xfb, 0x58, 0x03, 0x0b, 0x06, + 0xf3, 0x02, 0xb4, 0xfd, 0xfa, 0xfd, 0x87, 0xff, 0x60, 0xfc, 0x49, 0x03, + 0x86, 0x05, 0x01, 0x00, 0x43, 0xfd, 0xae, 0xfc, 0x3d, 0xfa, 0x29, 0x03, + 0x45, 0x09, 0x32, 0x05, 0x8d, 0xfc, 0x77, 0xec, 0x5c, 0xf8, 0xff, 0x1b, + 0x9c, 0x08, 0x40, 0xed, 0x8b, 0xfa, 0x6b, 0x05, 0x97, 0xfa, 0xd6, 0xfc, + 0xff, 0x06, 0x28, 0x06, 0x74, 0xfd, 0xdb, 0xfb, 0xc5, 0xfe, 0x12, 0xfe, + 0x4c, 0xfe, 0x20, 0x04, 0x29, 0x00, 0x89, 0x02, 0x78, 0x03, 0x35, 0xfc, + 0x6f, 0xf6, 0x70, 0xfe, 0x55, 0x0a, 0xea, 0x01, 0x9a, 0xfb, 0xcd, 0xfd, + 0xf3, 0xfc, 0x86, 0xfc, 0x2b, 0x01, 0x73, 0x01, 0xe0, 0x04, 0x44, 0x02, + 0x33, 0xfb, 0x90, 0xf3, 0x88, 0xfd, 0x5a, 0x0d, 0xf1, 0x0d, 0x00, 0x00, + 0xfd, 0xf6, 0xca, 0xf6, 0x85, 0xfb, 0x2b, 0x03, 0x30, 0x0d, 0xe0, 0x05, + 0xe1, 0x03, 0xa8, 0xf6, 0xd8, 0xf2, 0x6b, 0xff, 0xe6, 0x08, 0xae, 0x09, + 0xf5, 0x01, 0x51, 0xfe, 0xb8, 0xf7, 0x1a, 0xf2, 0xe9, 0xfe, 0xab, 0x15, + 0x75, 0x08, 0xa4, 0xf7, 0xad, 0xf7, 0x4a, 0xfc, 0xd3, 0x00, 0x10, 0xfe, + 0xc7, 0x05, 0x6a, 0x0c, 0x1e, 0xf9, 0x9a, 0xef, 0x9a, 0x03, 0xf2, 0x03, + 0xe8, 0x03, 0x3c, 0x03, 0xb2, 0xf6, 0x56, 0xfa, 0x29, 0x07, 0x56, 0xfd, + 0x13, 0xf9, 0x8e, 0x04, 0x6a, 0x07, 0xb5, 0xfb, 0x73, 0xf8, 0x0b, 0x01, + 0x83, 0x03, 0xf8, 0x00, 0xee, 0xfc, 0x62, 0xfd, 0xe4, 0x07, 0x88, 0x00, + 0x71, 0xf7, 0x81, 0x06, 0x04, 0x04, 0xeb, 0xf9, 0x91, 0x0c, 0x61, 0x02, + 0x36, 0xea, 0xcb, 0xfe, 0xc7, 0x13, 0xe7, 0xff, 0xc2, 0xf9, 0x9f, 0xfc, + 0x8b, 0xfc, 0x9b, 0xfe, 0xbf, 0x03, 0x29, 0x03, 0x04, 0xfe, 0x62, 0x03, + 0x68, 0x01, 0x4e, 0x00, 0xf9, 0xfd, 0xaf, 0x03, 0x8e, 0x06, 0x9f, 0xf6, + 0xd0, 0xf6, 0x04, 0x02, 0xb4, 0x02, 0xe3, 0x08, 0x99, 0x01, 0x53, 0xf8, + 0xec, 0xf9, 0x99, 0xf9, 0xda, 0x00, 0xf8, 0x07, 0x96, 0x03, 0x6b, 0x01, + 0xbc, 0xfa, 0x62, 0xf9, 0x40, 0x00, 0x5e, 0x01, 0x27, 0x04, 0x88, 0x09, + 0xed, 0xfd, 0x77, 0xf8, 0x95, 0xff, 0xbd, 0xff, 0xa2, 0x00, 0x94, 0x07, + 0x33, 0x01, 0x6b, 0x00, 0x5d, 0xfa, 0xe2, 0xfb, 0xf1, 0x00, 0x26, 0x06, + 0xee, 0x02, 0xa5, 0xfc, 0x9e, 0xf8, 0x84, 0xfe, 0xf6, 0x03, 0x14, 0x04, + 0xa0, 0x06, 0xfe, 0xf6, 0xe0, 0xf6, 0x49, 0x05, 0x3f, 0x05, 0x85, 0x03, + 0x93, 0xfd, 0x41, 0xfd, 0xa7, 0xfc, 0x8c, 0x02, 0xe2, 0x04, 0x41, 0x05, + 0x55, 0xff, 0x7b, 0xf8, 0xa7, 0xfe, 0xbe, 0x06, 0xaf, 0xf7, 0x81, 0xf9, + 0x3d, 0x0b, 0x0f, 0x0c, 0xe0, 0xfc, 0x62, 0xf1, 0xcb, 0xfa, 0xe0, 0x08, + 0xc8, 0x01, 0x5e, 0xfc, 0x16, 0x06, 0x6c, 0x00, 0xfe, 0xec, 0x42, 0x07, + 0xf1, 0x11, 0x18, 0xfd, 0xbe, 0xff, 0x72, 0xf9, 0x6b, 0xf4, 0x89, 0x05, + 0x0a, 0x0c, 0x0f, 0xfd, 0x6d, 0xff, 0xb2, 0xf6, 0xce, 0xfa, 0x8e, 0x05, + 0x09, 0x04, 0xb3, 0xfd, 0xef, 0x08, 0x08, 0xff, 0x0e, 0xef, 0x17, 0xf9, + 0x0c, 0x0b, 0x88, 0x02, 0xc7, 0xfc, 0x75, 0x04, 0x18, 0x08, 0x13, 0x01, + 0x63, 0xf3, 0x54, 0xfe, 0x29, 0x08, 0x67, 0x01, 0xfe, 0x05, 0xd3, 0x09, + 0xca, 0xfd, 0x42, 0xf7, 0xb1, 0xef, 0xcb, 0xff, 0xc3, 0x14, 0x23, 0x04, + 0x37, 0xec, 0xc0, 0xfe, 0x3f, 0x0e, 0x28, 0xfa, 0xb4, 0xfb, 0x6d, 0x0a, + 0xc9, 0x02, 0x50, 0xee, 0xad, 0xfb, 0xca, 0x07, 0x6e, 0x07, 0xe9, 0xff, + 0xa1, 0xff, 0xec, 0xff, 0x9e, 0xfe, 0x1e, 0xfd, 0xe5, 0x03, 0x79, 0x09, + 0x50, 0x06, 0x32, 0xf5, 0x3a, 0xf3, 0x3c, 0x05, 0x14, 0x01, 0xf8, 0x05, + 0x58, 0x07, 0x3c, 0xf1, 0xe1, 0xf6, 0x26, 0x0a, 0xb4, 0x02, 0xcf, 0xfd, + 0x8a, 0x06, 0x6b, 0xfe, 0xbd, 0xf5, 0x4a, 0x08, 0xeb, 0x07, 0x8a, 0x0c, + 0xf8, 0x01, 0xdd, 0xee, 0x72, 0xfa, 0x0d, 0x05, 0x77, 0x05, 0xe0, 0x02, + 0xb2, 0x02, 0x57, 0x00, 0x22, 0xf9, 0xf4, 0xf5, 0x02, 0x05, 0xef, 0x04, + 0x0b, 0xf6, 0x63, 0xf8, 0xbf, 0x09, 0xff, 0x08, 0xb1, 0xfe, 0xb5, 0xf8, + 0xaf, 0xf4, 0x3e, 0x00, 0xe5, 0x0b, 0x6e, 0x07, 0xd7, 0x07, 0x28, 0xfc, + 0xfe, 0xf3, 0xd7, 0xf9, 0x66, 0x01, 0xa2, 0x08, 0x50, 0x0a, 0x72, 0x0a, + 0xde, 0xf7, 0xaa, 0xf3, 0xd8, 0x00, 0x02, 0x03, 0xea, 0xfe, 0x24, 0x01, + 0x40, 0x05, 0x07, 0x07, 0x65, 0xfb, 0x32, 0xf7, 0x0c, 0x01, 0xb3, 0x06, + 0xc4, 0xfe, 0x05, 0xfb, 0xd7, 0x02, 0x01, 0x0d, 0x39, 0xff, 0x05, 0xef, + 0x68, 0xfa, 0x68, 0x04, 0x24, 0x06, 0x1e, 0x08, 0x41, 0xf6, 0x34, 0xf6, + 0x07, 0x0c, 0x4e, 0x02, 0xbd, 0xfa, 0xd4, 0x05, 0x26, 0xfc, 0x62, 0xf5, + 0x84, 0x0d, 0x20, 0x0a, 0xb8, 0x04, 0x57, 0xff, 0x25, 0xe7, 0x6a, 0xfa, + 0x1b, 0x1a, 0x6d, 0x03, 0xff, 0xf5, 0x28, 0x04, 0xd5, 0xf7, 0x66, 0xf5, + 0xfe, 0x09, 0xc2, 0x0b, 0x37, 0xf9, 0xfa, 0xf6, 0x44, 0xfb, 0x16, 0x0f, + 0x61, 0x03, 0x3f, 0xf5, 0x5c, 0xf5, 0x44, 0x03, 0xba, 0x12, 0x78, 0x06, + 0x83, 0xfd, 0x49, 0x02, 0x8d, 0xf6, 0x3a, 0xf4, 0xe0, 0x09, 0x9c, 0x01, + 0x98, 0xfb, 0xbf, 0x0e, 0xdc, 0xff, 0xfe, 0xee, 0xa9, 0x08, 0xed, 0xfc, + 0xa6, 0xf9, 0x4c, 0x09, 0x97, 0x0a, 0xf7, 0x00, 0x05, 0xf1, 0xd7, 0xee, + 0x3b, 0x04, 0x97, 0x1c, 0xdd, 0x04, 0x32, 0xeb, 0x34, 0x08, 0x70, 0x0a, + 0xec, 0xf2, 0xba, 0xf9, 0x4b, 0x11, 0xed, 0x0c, 0xa8, 0xef, 0xed, 0xec, + 0x78, 0x0b, 0xcb, 0x14, 0x9c, 0xfe, 0xb9, 0xfe, 0xd6, 0xf8, 0x5c, 0xe5, + 0xa8, 0xf6, 0x6e, 0x1f, 0xbe, 0x0e, 0x18, 0xf1, 0x97, 0xfb, 0x66, 0xfe, + 0x50, 0xf7, 0x4b, 0x02, 0x2b, 0x11, 0x4e, 0x09, 0xf5, 0xf6, 0x6a, 0xf9, + 0xef, 0x03, 0x79, 0x01, 0x0c, 0xfb, 0x9b, 0x06, 0x14, 0xf9, 0xe7, 0xe5, + 0x76, 0x12, 0x07, 0x1e, 0x4a, 0xf5, 0x55, 0xed, 0x8a, 0xfc, 0x02, 0x03, + 0x68, 0x00, 0x03, 0x05, 0x63, 0x0b, 0xeb, 0xfb, 0x31, 0xe8, 0x18, 0x04, + 0x33, 0x1f, 0x7c, 0xf9, 0x0f, 0xed, 0x80, 0x11, 0x3c, 0x0c, 0xd3, 0xf1, + 0x76, 0xf5, 0xaf, 0x0f, 0x48, 0x0a, 0xe4, 0xf1, 0xde, 0xf9, 0x03, 0x05, + 0x28, 0xfe, 0x66, 0x01, 0xec, 0x03, 0x0c, 0xf8, 0x5c, 0xfb, 0x57, 0x13, + 0x1d, 0x00, 0x24, 0xef, 0x1a, 0x02, 0x24, 0x07, 0xc8, 0xf9, 0x33, 0xfa, + 0x4e, 0x03, 0x50, 0x0b, 0xca, 0x0a, 0xb8, 0xf9, 0xeb, 0xf1, 0x84, 0x00, + 0xa1, 0x08, 0x23, 0xf3, 0x1d, 0xf9, 0xd1, 0x16, 0xfd, 0x10, 0xff, 0xf2, + 0xd6, 0xed, 0xa0, 0xfa, 0xbb, 0x00, 0x24, 0x05, 0x90, 0x0a, 0x84, 0x05, + 0x3e, 0x02, 0xd0, 0xf7, 0xbc, 0xfa, 0xf6, 0x03, 0xe4, 0x02, 0xbc, 0xfc, + 0xcb, 0x04, 0x1a, 0x03, 0x6d, 0x01, 0x02, 0x03, 0xa2, 0x04, 0xa9, 0xfd, + 0x5e, 0xf5, 0x4b, 0xfe, 0xa9, 0x09, 0x33, 0x09, 0x29, 0xf5, 0x48, 0xf8, + 0x1d, 0x0f, 0x7c, 0xfd, 0x33, 0xf3, 0x87, 0xff, 0x44, 0x03, 0x7b, 0x03, + 0x80, 0x06, 0x7c, 0xf8, 0xea, 0xf4, 0xfc, 0x06, 0xa4, 0x04, 0xa9, 0xfb, + 0xa2, 0x02, 0xa6, 0x05, 0xa3, 0x00, 0xf9, 0xf3, 0x60, 0x00, 0x6e, 0x06, + 0x97, 0xfd, 0x20, 0x06, 0x19, 0x03, 0x7a, 0xfb, 0x80, 0x08, 0x40, 0xfc, + 0x25, 0xef, 0x7e, 0x03, 0x95, 0x03, 0xb9, 0xf8, 0x71, 0x0f, 0xb0, 0x06, + 0x9b, 0xf3, 0x30, 0xf9, 0x19, 0xfd, 0x4e, 0xff, 0xd8, 0x05, 0x40, 0x07, + 0x14, 0x03, 0x1d, 0xfc, 0x5b, 0xf7, 0x5d, 0xfd, 0x16, 0x06, 0xc5, 0xfc, + 0xd5, 0xf5, 0xfc, 0x0f, 0x24, 0x10, 0x22, 0xf8, 0x09, 0xf9, 0xa4, 0x04, + 0xa9, 0xff, 0x8e, 0xff, 0xef, 0x04, 0x29, 0xff, 0x5d, 0xf8, 0x4e, 0x04, + 0x50, 0x04, 0x72, 0x03, 0x24, 0xf4, 0x0c, 0xf9, 0xa6, 0x08, 0x91, 0x06, + 0xd1, 0xfe, 0x6f, 0xfe, 0x1e, 0xf7, 0x1c, 0x05, 0x9c, 0x00, 0x9d, 0xf5, + 0x5c, 0x07, 0x34, 0x0b, 0x97, 0xf4, 0x8b, 0xf5, 0xf7, 0x04, 0x14, 0x0b, + 0xf5, 0x05, 0x0f, 0xf6, 0xca, 0xf3, 0xa0, 0x01, 0xde, 0x05, 0x69, 0xfb, + 0xb7, 0x09, 0x31, 0x06, 0xca, 0xfa, 0xd3, 0xfd, 0x6e, 0x02, 0x06, 0xf8, + 0x09, 0xfd, 0xb5, 0x06, 0x1e, 0x00, 0x0c, 0x08, 0xf8, 0x0a, 0x54, 0xfe, + 0x15, 0xf5, 0x00, 0xfa, 0x06, 0x02, 0x67, 0x0e, 0x0a, 0x04, 0x0d, 0xff, + 0x8f, 0xf7, 0x01, 0xef, 0xb2, 0xfc, 0xab, 0x0a, 0x79, 0x03, 0xc5, 0x07, + 0x10, 0x04, 0x94, 0xeb, 0xcc, 0xee, 0x41, 0x09, 0x94, 0x0e, 0x81, 0x06, + 0x0b, 0xfd, 0x30, 0xef, 0x2c, 0xf7, 0xea, 0x0b, 0xa5, 0x05, 0x1d, 0x00, + 0x3a, 0x0a, 0x69, 0xf7, 0x69, 0xef, 0x14, 0x0d, 0x3b, 0x03, 0x1c, 0xf7, + 0xfb, 0x02, 0x52, 0x01, 0xa4, 0x03, 0x3a, 0xff, 0x22, 0x02, 0xc4, 0x04, + 0x4c, 0xf8, 0x29, 0xfc, 0xff, 0x02, 0x31, 0x02, 0x69, 0x01, 0x68, 0xf8, + 0xe9, 0xfc, 0xec, 0x0a, 0x53, 0x02, 0x36, 0xf6, 0xf3, 0x02, 0xcd, 0x05, + 0x62, 0x00, 0xda, 0xf6, 0x08, 0xf8, 0xc4, 0x07, 0xe9, 0x0c, 0xde, 0xf7, + 0x20, 0xf0, 0xdb, 0x05, 0x4f, 0x01, 0xac, 0x00, 0x21, 0x0b, 0xb1, 0xf9, + 0x89, 0xf6, 0x6b, 0x0d, 0x71, 0x03, 0x9e, 0xf1, 0x45, 0xfc, 0xf7, 0x09, + 0x5c, 0xf9, 0xae, 0xf6, 0xd9, 0x05, 0xce, 0x07, 0x20, 0x05, 0xd7, 0xfe, + 0xf1, 0xf0, 0x54, 0xfb, 0x9e, 0x0a, 0xce, 0x02, 0x5d, 0xfa, 0x81, 0x07, + 0x33, 0x0f, 0x94, 0xf2, 0xb7, 0xf1, 0x64, 0x08, 0xbd, 0x0b, 0xa4, 0xfc, + 0x60, 0x02, 0xd6, 0xfc, 0xb9, 0xf5, 0x08, 0xfb, 0x2b, 0x08, 0x3e, 0x09, + 0xb0, 0xf3, 0x18, 0xf2, 0x66, 0x11, 0xb5, 0x09, 0xc4, 0xf3, 0x83, 0x01, + 0x56, 0x0a, 0x56, 0xf5, 0xab, 0xf9, 0xca, 0x0c, 0xcd, 0xf8, 0x9b, 0xe0, + 0x70, 0x05, 0xf2, 0x1f, 0xdd, 0x08, 0xf7, 0x01, 0xe3, 0xe7, 0x9f, 0xe5, + 0x86, 0x0a, 0xb1, 0x1b, 0x9d, 0x06, 0x44, 0xf4, 0x7d, 0xf6, 0xd1, 0xf7, + 0xfe, 0xff, 0x56, 0x09, 0x68, 0x12, 0xb4, 0xfe, 0x6f, 0xf7, 0xd3, 0xf4, + 0x06, 0xf5, 0x35, 0x07, 0xba, 0x11, 0xd6, 0x02, 0xb3, 0xfc, 0x8c, 0xfe, + 0x67, 0xfb, 0x0c, 0xf7, 0xa0, 0x03, 0xa5, 0x12, 0x31, 0xfd, 0xab, 0xf5, + 0x54, 0x03, 0x61, 0x00, 0xcd, 0xf5, 0x96, 0xfa, 0x8c, 0x0c, 0x35, 0x02, + 0x60, 0xfa, 0x9b, 0x03, 0x18, 0xfd, 0x75, 0xfa, 0x3a, 0xff, 0x02, 0x00, + 0xf2, 0xf6, 0x32, 0x04, 0xbe, 0x12, 0x8d, 0xff, 0x3f, 0xef, 0xf8, 0xf5, + 0xad, 0x08, 0x20, 0x04, 0xed, 0xff, 0xe7, 0x01, 0x9e, 0x01, 0x3c, 0xf2, + 0xd7, 0xf4, 0xee, 0x06, 0x43, 0x0b, 0x24, 0x0e, 0xda, 0x00, 0xfc, 0xed, + 0x07, 0xf6, 0xf6, 0x07, 0x22, 0x09, 0x94, 0x09, 0xc5, 0xff, 0xaf, 0xf2, + 0x5c, 0xfa, 0x21, 0x06, 0x22, 0xfd, 0x78, 0x0a, 0xb0, 0x11, 0x22, 0xf4, + 0xf5, 0xe6, 0xdb, 0x05, 0x13, 0x05, 0xc4, 0xeb, 0x1e, 0x0c, 0xd6, 0x14, + 0xe8, 0xef, 0x9e, 0xef, 0xe9, 0x0a, 0xdf, 0x0d, 0x7a, 0xfc, 0x46, 0xfc, + 0x5f, 0xf9, 0x2e, 0x01, 0xf5, 0x01, 0x85, 0xff, 0xfa, 0xfd, 0xa3, 0x04, + 0x03, 0x11, 0xfd, 0xf9, 0x05, 0xe8, 0x2a, 0x03, 0x3d, 0x0e, 0x7b, 0x06, + 0x2e, 0xfa, 0xc9, 0x00, 0x7d, 0x00, 0x0b, 0xfe, 0x6f, 0x05, 0xde, 0x05, + 0x3a, 0xf8, 0x48, 0xfd, 0x73, 0xf9, 0x27, 0xf3, 0x80, 0xfc, 0x26, 0x08, + 0x0d, 0x10, 0x91, 0x01, 0xcb, 0xed, 0x2f, 0xf3, 0x8f, 0x02, 0x6a, 0x00, + 0x99, 0x06, 0x59, 0x0d, 0x01, 0xf4, 0xac, 0xeb, 0x8f, 0x07, 0x9b, 0x08, + 0x46, 0xf3, 0xdd, 0xf8, 0x74, 0x14, 0x36, 0x0b, 0x65, 0xf3, 0x86, 0xf5, + 0x9f, 0x1e, 0x1c, 0x0e, 0xa2, 0xef, 0x0c, 0xf5, 0xb3, 0xf8, 0xfd, 0x02, + 0x5f, 0x13, 0x4c, 0x09, 0x9f, 0xf7, 0x42, 0x00, 0x9e, 0xfd, 0x58, 0xed, + 0x77, 0x02, 0x86, 0x15, 0x37, 0x05, 0x92, 0xf7, 0x61, 0x04, 0x97, 0xfa, + 0x47, 0xe9, 0xeb, 0x04, 0x48, 0x0d, 0xc8, 0xfb, 0x9b, 0xff, 0x28, 0x02, + 0xd4, 0xfc, 0xef, 0x00, 0xf2, 0x01, 0x2c, 0xfc, 0x2c, 0xfa, 0xbe, 0xfd, + 0xb4, 0xf4, 0x94, 0xff, 0x9f, 0xfe, 0x3f, 0x03, 0x5a, 0x09, 0x42, 0x06, + 0x4a, 0x00, 0xe5, 0xf8, 0x41, 0xf0, 0xaf, 0xf4, 0x2d, 0x0d, 0x40, 0x11, + 0xf6, 0xfe, 0x4e, 0xf5, 0x79, 0xfa, 0xfd, 0xfd, 0x8e, 0x0d, 0x43, 0x11, + 0x8a, 0xfa, 0x81, 0xf9, 0x96, 0xfd, 0x90, 0x01, 0x20, 0x02, 0xeb, 0x02, + 0x00, 0x05, 0xa8, 0xfb, 0x14, 0xf6, 0x32, 0x00, 0x51, 0x08, 0x4c, 0x0d, + 0x94, 0x00, 0xf8, 0xff, 0x32, 0xfa, 0xa3, 0xf5, 0xe9, 0x01, 0x2a, 0x0f, + 0x38, 0x06, 0xda, 0xf9, 0xd9, 0xfa, 0xa7, 0xf0, 0x33, 0x07, 0x4b, 0x0e, + 0x77, 0xf8, 0x78, 0xf7, 0x3f, 0x04, 0x29, 0xfb, 0x8a, 0xfa, 0x61, 0x04, + 0x08, 0x03, 0x64, 0x06, 0x6f, 0x01, 0x61, 0xf2, 0x2f, 0xf7, 0xb5, 0x02, + 0x39, 0x05, 0x6d, 0xfb, 0xc0, 0xfd, 0x0d, 0x07, 0xc2, 0x01, 0x8c, 0xf5, + 0x73, 0x02, 0x53, 0x06, 0x4a, 0x0f, 0x0a, 0x01, 0x25, 0xf6, 0x07, 0x03, + 0x87, 0x02, 0x6e, 0xf5, 0x14, 0x01, 0x98, 0x0f, 0x18, 0x06, 0x3a, 0xf8, + 0xe9, 0x01, 0xde, 0xfe, 0xc5, 0xf8, 0xc8, 0xfc, 0x1a, 0x04, 0xd6, 0x04, + 0x29, 0xf9, 0xd4, 0xfa, 0x56, 0x0c, 0x3e, 0x04, 0x71, 0xf5, 0x88, 0xfb, + 0x33, 0x04, 0x21, 0x09, 0xd2, 0x02, 0xb2, 0xfc, 0x14, 0xfd, 0xef, 0xfb, + 0x70, 0xf9, 0x14, 0x09, 0x6b, 0x07, 0x02, 0xfe, 0xe2, 0xfc, 0x29, 0x00, + 0x97, 0xf6, 0x0f, 0xfc, 0x71, 0x04, 0xd4, 0x07, 0x21, 0x03, 0xd4, 0xfa, + 0x8e, 0xfa, 0x2c, 0x07, 0x8e, 0x01, 0x2b, 0x07, 0x43, 0x03, 0x83, 0xf3, + 0x5a, 0xfa, 0x82, 0xfe, 0x99, 0x00, 0x58, 0x0b, 0xcb, 0x07, 0x1b, 0xfb, + 0x5e, 0xfa, 0x91, 0x03, 0x48, 0x02, 0xed, 0x01, 0x45, 0x02, 0x26, 0xf1, + 0x60, 0xf1, 0xad, 0x04, 0xc2, 0x08, 0x23, 0x08, 0x09, 0x03, 0x45, 0x06, + 0xff, 0x01, 0x24, 0xfc, 0x07, 0x00, 0xb8, 0xfd, 0x2d, 0xff, 0x3d, 0xfc, + 0x99, 0xfe, 0x4a, 0x05, 0x52, 0x08, 0xbd, 0xfd, 0x13, 0xf4, 0x9e, 0xf1, + 0x91, 0x03, 0x6a, 0x10, 0x7b, 0x09, 0x9e, 0xfb, 0x25, 0xfd, 0xdc, 0xf7, + 0x4d, 0xf6, 0x88, 0x00, 0xb9, 0x0a, 0x00, 0x0b, 0x9e, 0x08, 0xfd, 0xf4, + 0x6f, 0xf4, 0x27, 0x02, 0x82, 0x0b, 0x69, 0x06, 0x57, 0xfe, 0xb7, 0xfa, + 0xd1, 0xf9, 0x63, 0xfc, 0x53, 0x02, 0xa7, 0xff, 0xbc, 0xfd, 0x82, 0x06, + 0x55, 0x01, 0x3b, 0xfd, 0x8e, 0x02, 0x2a, 0x07, 0x91, 0xfd, 0x5e, 0x00, + 0x2e, 0x07, 0x87, 0xfe, 0xb9, 0xfa, 0x05, 0x09, 0x02, 0x08, 0x97, 0xff, + 0x36, 0x00, 0x76, 0x08, 0xd3, 0x00, 0x6b, 0xfe, 0xc4, 0xfe, 0x11, 0xfb, + 0xfe, 0xf6, 0x1c, 0x03, 0x32, 0x06, 0xf1, 0xf9, 0x89, 0xf7, 0x8c, 0xfe, + 0x13, 0x01, 0xe4, 0xfa, 0xd0, 0xfb, 0x0b, 0xff, 0x34, 0x04, 0xa7, 0x00, + 0xb4, 0xfa, 0x12, 0xfc, 0xe8, 0xfe, 0xc7, 0xfb, 0x59, 0x01, 0xc6, 0x04, + 0x45, 0x01, 0x7d, 0xfa, 0x5e, 0x03, 0xc7, 0x07, 0xd8, 0xfc, 0x5c, 0xfe, + 0xd8, 0xfd, 0x41, 0xf5, 0x5b, 0xfb, 0x92, 0x06, 0x91, 0x06, 0x38, 0x06, + 0x96, 0x01, 0x4e, 0x03, 0x1b, 0x03, 0xbb, 0x00, 0xb5, 0xfd, 0x89, 0x01, + 0x64, 0x07, 0xb4, 0x04, 0x9f, 0x05, 0xee, 0x00, 0xf7, 0xf4, 0x25, 0xff, + 0x35, 0x05, 0xa8, 0xfd, 0x40, 0x01, 0xca, 0x09, 0xb0, 0x05, 0xf6, 0xf9, + 0xb0, 0xfe, 0xd2, 0xfd, 0x0b, 0xf7, 0xee, 0xf8, 0xd1, 0x03, 0xab, 0x03, + 0x0a, 0xf8, 0xf5, 0xfb, 0xa9, 0x02, 0xa0, 0xfe, 0x5d, 0xfe, 0x23, 0xff, + 0x6e, 0x03, 0x7d, 0xfd, 0x40, 0xfd, 0xb1, 0x03, 0xfb, 0xfe, 0x68, 0xff, + 0x6a, 0xfd, 0x9e, 0x06, 0x53, 0x05, 0xca, 0x05, 0x5e, 0x05, 0x41, 0xfd, + 0xb2, 0xff, 0x3e, 0x01, 0x1b, 0xff, 0x0c, 0x01, 0x40, 0x05, 0x4e, 0xfb, + 0x86, 0xfd, 0x69, 0x04, 0xf6, 0x01, 0x2b, 0x0e, 0x3f, 0x05, 0x0f, 0xf2, + 0x92, 0xf5, 0x65, 0xff, 0x6b, 0x03, 0x69, 0x0d, 0x90, 0x02, 0x67, 0xf3, + 0x8a, 0xfb, 0x95, 0x04, 0x8e, 0xff, 0x8b, 0xff, 0xc4, 0x07, 0x60, 0x05, + 0xce, 0xfa, 0x73, 0xf3, 0x5c, 0xfa, 0xdf, 0x01, 0x48, 0x02, 0xc7, 0x05, + 0xdd, 0x01, 0x16, 0xfe, 0xc2, 0xf9, 0x7e, 0xfb, 0xa2, 0x04, 0xad, 0x07, + 0xaa, 0x05, 0x30, 0x07, 0xe1, 0x02, 0xfe, 0xf8, 0x04, 0xfb, 0x92, 0x02, + 0x00, 0x07, 0x90, 0x04, 0xf6, 0x03, 0xda, 0xfb, 0x0c, 0xf8, 0xc0, 0xfd, + 0xa3, 0x04, 0xfd, 0x01, 0xe2, 0xf8, 0x7e, 0xf7, 0xf1, 0x00, 0x10, 0xfb, + 0x9f, 0xfc, 0xbe, 0x04, 0x98, 0x05, 0xd0, 0xfe, 0x4d, 0xff, 0xb8, 0x00, + 0x03, 0x01, 0x54, 0x02, 0x99, 0x00, 0xe9, 0xfc, 0x1f, 0xfb, 0x39, 0x03, + 0x7a, 0x06, 0xab, 0x06, 0x4d, 0x04, 0x0a, 0x01, 0x53, 0xfa, 0x96, 0xf6, + 0xcd, 0xfd, 0x96, 0x05, 0x6b, 0x05, 0x0c, 0xff, 0xa5, 0x01, 0x00, 0x04, + 0x17, 0xfd, 0x21, 0xfa, 0x68, 0x03, 0xcd, 0x01, 0x48, 0xfb, 0xc1, 0xf9, + 0x4c, 0x00, 0xd2, 0x06, 0xe1, 0x02, 0x94, 0x05, 0x0a, 0x05, 0xa3, 0xf8, + 0x7b, 0xf9, 0x9b, 0xff, 0x7c, 0x05, 0x6f, 0x05, 0x1d, 0x02, 0x01, 0x08, + 0x8f, 0x00, 0xb3, 0xf7, 0x60, 0xfa, 0xde, 0x06, 0x05, 0x09, 0x26, 0x09, + 0x02, 0x02, 0x19, 0x04, 0x88, 0x01, 0x5d, 0xf8, 0x3a, 0xfa, 0x38, 0xfe, + 0x25, 0xff, 0x47, 0x03, 0xeb, 0x04, 0x30, 0x00, 0x3d, 0x00, 0x1d, 0xf7, + 0x0b, 0xfd, 0xd1, 0x00, 0xc8, 0x00, 0xf6, 0xfe, 0xde, 0xfe, 0x0c, 0x00, + 0x87, 0xfc, 0x7f, 0xf6, 0x34, 0xff, 0x9a, 0x07, 0xec, 0x02, 0x9c, 0x04, + 0x5f, 0x02, 0x65, 0xfd, 0xef, 0xff, 0xce, 0x03, 0x19, 0x03, 0x56, 0x06, + 0x49, 0x04, 0x3f, 0xff, 0x7e, 0xfe, 0x98, 0x01, 0x43, 0x04, 0x39, 0x04, + 0xca, 0x00, 0x98, 0x01, 0x30, 0xff, 0x43, 0x01, 0x32, 0xfd, 0x54, 0xfb, + 0x35, 0xfe, 0x99, 0x01, 0xfb, 0xff, 0x91, 0xfd, 0x88, 0xff, 0x51, 0x00, + 0x98, 0x01, 0x2b, 0x00, 0xb6, 0xfc, 0xf0, 0xf9, 0x5a, 0xfa, 0x24, 0xfe, + 0xd9, 0x01, 0x59, 0xfe, 0x21, 0xfe, 0x44, 0x02, 0x14, 0x00, 0x75, 0x00, + 0xd7, 0x01, 0xee, 0xff, 0x0f, 0xfd, 0x32, 0xfc, 0xf7, 0xfe, 0x3e, 0x01, + 0x92, 0x03, 0xd1, 0x02, 0x01, 0x01, 0x81, 0x00, 0x75, 0x01, 0x96, 0x01, + 0x92, 0x00, 0x43, 0xff, 0xfb, 0xff, 0x1e, 0x02, 0x8d, 0x02, 0xa6, 0x01, + 0x8a, 0x02, 0x4a, 0x01, 0x50, 0xfe, 0x23, 0xff, 0xe7, 0x02, 0x01, 0x03, + 0x22, 0x03, 0x97, 0x02, 0x78, 0x00, 0xd2, 0x00, 0xb0, 0xfe, 0xec, 0xfb, + 0xd9, 0xfe, 0x02, 0x02, 0x74, 0x04, 0x9f, 0x05, 0xea, 0x01, 0xf7, 0xfc, + 0xc9, 0xfd, 0x47, 0xff, 0x25, 0x00, 0xfb, 0x03, 0x74, 0xfe, 0xa3, 0xfe, + 0x36, 0x00, 0xca, 0x00, 0xdb, 0x03, 0xf9, 0x04, 0x09, 0x06, 0x1b, 0x03, + 0xd8, 0x01, 0x31, 0xfe, 0x15, 0xfd, 0x77, 0xfd, 0xa0, 0x01, 0xfe, 0x00, + 0xa5, 0xff, 0x01, 0xfe, 0xc6, 0x00, 0x79, 0x02, 0x8a, 0x00, 0x70, 0xff, + 0x1b, 0xfd, 0x8c, 0xfc, 0xc0, 0xfd, 0x1e, 0x02, 0x08, 0x04, 0x4c, 0x02, + 0x2f, 0x00, 0xd0, 0xfe, 0x6f, 0xff, 0xc4, 0x00, 0x08, 0x04, 0xd3, 0x02, + 0x72, 0x01, 0x86, 0xfe, 0x9c, 0xfc, 0x13, 0xfd, 0x86, 0xfd, 0x89, 0xfe, + 0xe0, 0xff, 0x90, 0x00, 0x18, 0xfe, 0xae, 0xfc, 0xe9, 0xfc, 0x9b, 0xfd, + 0xa8, 0xfd, 0x7c, 0xfb, 0x1c, 0xfa, 0x1c, 0xfa, 0x87, 0xf8, 0x70, 0xfc, + 0x69, 0x00, 0x7b, 0x01, 0x7c, 0xff, 0xf0, 0xfd, 0xd5, 0xfd, 0x58, 0xfc, + 0x10, 0xfd, 0x49, 0xfb, 0x28, 0xfb, 0x5b, 0xfb, 0xbc, 0xfc, 0xcd, 0xff, + 0x00, 0x00, 0x26, 0x00, 0x3b, 0xfe, 0x76, 0xfe, 0x07, 0xfe, 0xa1, 0xfe, + 0x4e, 0xfd, 0x07, 0xff, 0x98, 0xfe, 0x0b, 0x00, 0x51, 0x02, 0xc7, 0x02, + 0x2b, 0x03, 0x69, 0x01, 0x09, 0xfe, 0x5d, 0xfc, 0x68, 0xff, 0x9c, 0x00, + 0x39, 0x01, 0xe2, 0x07, 0x29, 0x09, 0x7a, 0x07, 0x40, 0x06, 0x68, 0x00, + 0x51, 0xfd, 0x0d, 0xfe, 0x6f, 0xfd, 0x1d, 0x02, 0x7b, 0x07, 0x76, 0x10, + 0xb1, 0x10, 0xf6, 0x09, 0x31, 0x03, 0x09, 0xff, 0x0d, 0x00, 0x21, 0x02, + 0x48, 0x07, 0xbb, 0x08, 0xfd, 0x06, 0xc7, 0x03, 0xa1, 0x04, 0x93, 0x03, + 0xad, 0x04, 0x63, 0x06, 0x4b, 0x07, 0xb1, 0x05, 0xff, 0x02, 0x52, 0xff, + 0xd8, 0xfb, 0xb2, 0xfa, 0x17, 0xfe, 0x2f, 0x02, 0x39, 0x04, 0xc3, 0x04, + 0xf6, 0x03, 0xe6, 0x00, 0xe0, 0xfe, 0xce, 0xfd, 0xd2, 0xfe, 0x61, 0xfe, + 0x81, 0xfe, 0x9a, 0xfd, 0x9c, 0xfd, 0x25, 0xfd, 0x92, 0xfd, 0x37, 0xfe, + 0xf7, 0xfe, 0x46, 0xff, 0xa3, 0xfd, 0xc3, 0xf9, 0xeb, 0xf6, 0xa4, 0xf3, + 0x8d, 0xf3, 0xa2, 0xf6, 0x61, 0xf9, 0x6f, 0xfb, 0x61, 0xfb, 0xfb, 0xfb, + 0x5f, 0xfc, 0x63, 0xfa, 0xcf, 0xf7, 0x7a, 0xf5, 0x1c, 0xf3, 0x2f, 0xf1, + 0x23, 0xf2, 0xc6, 0xf5, 0xb0, 0xf7, 0xc7, 0xfa, 0x66, 0xfb, 0xec, 0xfa, + 0xe7, 0xfc, 0x34, 0xfe, 0xb3, 0xfb, 0x19, 0xf9, 0x42, 0xf7, 0x38, 0xf8, + 0x10, 0xf9, 0x67, 0xfe, 0x4c, 0xff, 0x4a, 0x00, 0x28, 0x00, 0x7d, 0x00, + 0x7f, 0xfd, 0x2c, 0xfe, 0xc7, 0xff, 0xdf, 0x01, 0x86, 0x02, 0x9e, 0x03, + 0xb2, 0x03, 0x7d, 0x0b, 0xde, 0x12, 0xcf, 0x13, 0xdf, 0x13, 0xce, 0x0c, + 0x39, 0x06, 0x3b, 0x03, 0x7b, 0x02, 0xd5, 0x02, 0x3d, 0x08, 0x30, 0x0b, + 0x37, 0x0b, 0x55, 0x0b, 0xa9, 0x0a, 0xa7, 0x08, 0x28, 0x09, 0x2c, 0x07, + 0x65, 0x05, 0x9e, 0x05, 0xa8, 0x05, 0xcf, 0x07, 0x62, 0x09, 0xd3, 0x0b, + 0x9e, 0x0b, 0x7f, 0x08, 0xa8, 0x06, 0xf3, 0x05, 0x1d, 0x06, 0xf4, 0x05, + 0xf5, 0x07, 0xd2, 0x06, 0xcc, 0x04, 0x16, 0x07, 0xd7, 0x06, 0xae, 0x04, + 0x5a, 0x04, 0xfa, 0x00, 0xb7, 0xff, 0xa5, 0xfd, 0x9d, 0xfb, 0x02, 0xfc, + 0x34, 0xfc, 0x9e, 0xfc, 0x98, 0x00, 0xfa, 0x01, 0x86, 0xff, 0x2f, 0xfd, + 0xe5, 0xfa, 0xd4, 0xf6, 0x69, 0xf6, 0xe9, 0xf6, 0xa0, 0xf6, 0x77, 0xf2, + 0x3e, 0xf1, 0x9e, 0xee, 0xc4, 0xee, 0xb4, 0xee, 0x98, 0xef, 0x5a, 0xf0, + 0xe5, 0xee, 0xa0, 0xee, 0xfb, 0xef, 0x03, 0xf3, 0x6e, 0xf2, 0x97, 0xf1, + 0x6e, 0xf0, 0xf8, 0xef, 0xd1, 0xf0, 0x26, 0xf6, 0x30, 0xfb, 0x5e, 0xff, + 0x48, 0xfd, 0x67, 0xf9, 0x6f, 0xf5, 0x72, 0xf6, 0x7d, 0xf9, 0x25, 0xfe, + 0x02, 0x02, 0x75, 0x02, 0xad, 0x08, 0xed, 0x06, 0x98, 0x03, 0xc2, 0x00, + 0x07, 0xff, 0x1c, 0xfc, 0x53, 0xff, 0xce, 0x00, 0x61, 0x00, 0x9f, 0x01, + 0x0e, 0x00, 0xab, 0x00, 0xd6, 0xff, 0x56, 0x01, 0x55, 0x04, 0xd3, 0x07, + 0xcd, 0x09, 0x4c, 0x08, 0xd5, 0x02, 0x23, 0x06, 0xaf, 0x0a, 0xc7, 0x0e, + 0xfd, 0x12, 0xe1, 0x13, 0x7a, 0x13, 0x43, 0x13, 0x4f, 0x10, 0xc7, 0x0c, + 0x37, 0x0c, 0xde, 0x0b, 0xd6, 0x0a, 0xb9, 0x0c, 0x8d, 0x0d, 0xab, 0x0c, + 0xcd, 0x0b, 0x9e, 0x0a, 0x70, 0x08, 0x39, 0x06, 0x5f, 0x05, 0x0a, 0x05, + 0x58, 0x06, 0xd7, 0x06, 0x6f, 0x08, 0x2c, 0x09, 0x28, 0x0a, 0x39, 0x0b, + 0xfd, 0x09, 0xf9, 0x07, 0x51, 0x04, 0x91, 0x01, 0xf5, 0xff, 0x43, 0x01, + 0xb3, 0x01, 0xf5, 0xff, 0xde, 0xfc, 0x14, 0xfb, 0x6b, 0xf9, 0x74, 0xfa, + 0x09, 0xfa, 0xf2, 0xf5, 0x77, 0xf1, 0xfd, 0xeb, 0x43, 0xea, 0xe2, 0xe8, + 0x95, 0xea, 0xb7, 0xed, 0x89, 0xf2, 0x34, 0xf5, 0x0c, 0xf5, 0x50, 0xf3, + 0xc5, 0xed, 0xf5, 0xe7, 0x92, 0xe6, 0xb1, 0xe9, 0x1c, 0xee, 0xff, 0xf4, + 0x19, 0xf7, 0x14, 0xf5, 0xb8, 0xef, 0x2c, 0xf1, 0x48, 0xf5, 0xcc, 0xf9, + 0xb8, 0x01, 0x32, 0x01, 0xc6, 0xfb, 0xc1, 0xf5, 0xb1, 0xf0, 0xf8, 0xf1, + 0x47, 0xf8, 0xdb, 0x01, 0x98, 0x06, 0x0b, 0x07, 0xa4, 0x04, 0xd9, 0xff, + 0x35, 0xff, 0xc9, 0xfa, 0xc4, 0xfd, 0x1b, 0xff, 0xdc, 0xfc, 0x84, 0xfc, + 0x14, 0xfb, 0x8c, 0xfa, 0x89, 0x00, 0xf6, 0x04, 0xe7, 0x05, 0xaa, 0x06, + 0x04, 0x05, 0x37, 0x05, 0x99, 0x05, 0x65, 0x06, 0x04, 0x04, 0x88, 0x07, + 0x11, 0x08, 0x2d, 0x0f, 0x26, 0x15, 0x81, 0x18, 0x54, 0x19, 0x2d, 0x16, + 0x87, 0x13, 0x42, 0x11, 0x21, 0x10, 0xbc, 0x10, 0xd8, 0x11, 0xe3, 0x11, + 0x4b, 0x0d, 0x88, 0x0c, 0x00, 0x0d, 0x8a, 0x0d, 0x61, 0x10, 0x02, 0x10, + 0x48, 0x0f, 0x4c, 0x0b, 0xa4, 0x09, 0xe6, 0x05, 0x95, 0x04, 0x61, 0x03, + 0xc3, 0x04, 0x5f, 0x06, 0xb3, 0x07, 0x3c, 0x09, 0x36, 0x09, 0x22, 0x06, + 0x38, 0x02, 0x31, 0xfd, 0xf7, 0xfa, 0x9f, 0xfa, 0x21, 0xfb, 0xf3, 0xfa, + 0xf8, 0xf8, 0x48, 0xf7, 0x4f, 0xf5, 0x01, 0xf4, 0x2a, 0xf2, 0x7b, 0xf2, + 0x4f, 0xf1, 0x35, 0xee, 0xff, 0xea, 0xf2, 0xe8, 0xb9, 0xe6, 0xd4, 0xe9, + 0x31, 0xeb, 0x6d, 0xed, 0x37, 0xea, 0x9c, 0xe6, 0x99, 0xe8, 0x2e, 0xea, + 0x1d, 0xf2, 0x9f, 0xf6, 0x70, 0xfa, 0x93, 0xf5, 0x6f, 0xf3, 0xa8, 0xf1, + 0x20, 0xf6, 0x18, 0xff, 0x2d, 0x01, 0x18, 0x02, 0xb1, 0xfe, 0x96, 0xfa, + 0xc8, 0xfa, 0x13, 0xfb, 0xeb, 0xfc, 0x7d, 0x00, 0x2d, 0xfd, 0x6f, 0xfd, + 0xb3, 0xfb, 0x2c, 0xfa, 0xd8, 0xfa, 0x78, 0xf9, 0x73, 0xf6, 0x86, 0xf7, + 0x54, 0xf8, 0xbc, 0xfa, 0x50, 0xfe, 0xd9, 0xfd, 0x27, 0xff, 0x38, 0xff, + 0x41, 0x00, 0xc1, 0x00, 0xed, 0x03, 0xf1, 0x00, 0x26, 0x04, 0x3a, 0x08, + 0x7a, 0x0a, 0xbb, 0x0d, 0x74, 0x0f, 0xa8, 0x0e, 0xb6, 0x0d, 0x90, 0x0e, + 0xb4, 0x0e, 0x82, 0x11, 0x2f, 0x15, 0xe9, 0x17, 0xdb, 0x17, 0xf5, 0x17, + 0xaf, 0x12, 0x69, 0x12, 0x08, 0x11, 0x50, 0x12, 0x4e, 0x14, 0xe5, 0x13, + 0x16, 0x13, 0x8a, 0x0e, 0xa9, 0x0d, 0xae, 0x08, 0x0f, 0x0a, 0x49, 0x0c, + 0xf3, 0x0d, 0xcf, 0x0f, 0xfa, 0x0c, 0x46, 0x09, 0xc8, 0x04, 0xdf, 0x01, + 0xd4, 0xff, 0x1d, 0x00, 0xb0, 0x01, 0x7a, 0x01, 0x7f, 0x03, 0xf9, 0x00, + 0xb0, 0xff, 0x85, 0xfc, 0x69, 0xf7, 0xe5, 0xf9, 0x6f, 0xf7, 0x33, 0xf9, + 0xb0, 0xf7, 0xc7, 0xf3, 0x0b, 0xf0, 0xf6, 0xeb, 0x44, 0xed, 0xef, 0xed, + 0x7f, 0xef, 0x5a, 0xed, 0x66, 0xe8, 0x1d, 0xe3, 0x5b, 0xdc, 0xab, 0xdd, + 0xc9, 0xe2, 0x0b, 0xe8, 0x05, 0xf0, 0xbf, 0xf1, 0x34, 0xf2, 0x76, 0xf1, + 0x43, 0xf7, 0x53, 0xfb, 0xda, 0xf6, 0x60, 0x00, 0x5f, 0xfd, 0x71, 0x00, + 0xe6, 0x03, 0x2f, 0x02, 0x85, 0xff, 0x4d, 0xfb, 0xe3, 0xfa, 0xfb, 0xf6, + 0xea, 0xfa, 0xe1, 0xf8, 0x8d, 0xfb, 0xcf, 0xfb, 0x36, 0xfb, 0x2a, 0xf8, + 0xab, 0xf5, 0xeb, 0xf3, 0x7c, 0xf6, 0xc0, 0xf8, 0x1d, 0xfb, 0x0c, 0xfc, + 0xce, 0xf7, 0x63, 0xfd, 0xc4, 0x00, 0x63, 0x02, 0xe8, 0x03, 0x5d, 0x03, + 0x71, 0x02, 0xb3, 0x05, 0xe2, 0x08, 0x70, 0x09, 0x59, 0x0c, 0x72, 0x0d, + 0xc4, 0x0b, 0x76, 0x0d, 0xfd, 0x0e, 0xd4, 0x0f, 0x7a, 0x13, 0xe7, 0x16, + 0xf7, 0x17, 0xbd, 0x18, 0x78, 0x19, 0x72, 0x17, 0xf6, 0x15, 0xec, 0x16, + 0xbb, 0x16, 0x72, 0x18, 0x04, 0x18, 0xde, 0x15, 0x45, 0x13, 0xf4, 0x10, + 0x75, 0x0d, 0xea, 0x0b, 0x74, 0x09, 0x3a, 0x07, 0x5f, 0x09, 0x1d, 0x0a, + 0x04, 0x0b, 0x3d, 0x0a, 0xae, 0x07, 0x91, 0x03, 0x1d, 0x01, 0xb2, 0x00, + 0x60, 0xff, 0x95, 0x00, 0x80, 0x00, 0x43, 0xfd, 0x51, 0xfc, 0xe6, 0xf9, + 0xdc, 0xfb, 0x41, 0xfd, 0xc8, 0xfc, 0xa6, 0xfc, 0xc7, 0xf7, 0x8d, 0xf5, + 0x6c, 0xef, 0x72, 0xeb, 0x30, 0xe6, 0x7a, 0xe3, 0x07, 0xe1, 0x42, 0xe0, + 0x10, 0xe1, 0xdb, 0xe1, 0x03, 0xe5, 0xc8, 0xe7, 0x19, 0xeb, 0x38, 0xec, + 0x71, 0xee, 0xa3, 0xf0, 0xb2, 0xf7, 0xa3, 0xf8, 0x92, 0xfd, 0x40, 0xfd, + 0x4f, 0xfc, 0xe2, 0xfd, 0xda, 0xff, 0x0c, 0x03, 0x2b, 0x02, 0xc2, 0xff, + 0x76, 0xf9, 0x37, 0xf8, 0x5e, 0xf7, 0xe8, 0xfa, 0x51, 0xfa, 0x07, 0xf8, + 0xff, 0xf4, 0xd0, 0xf2, 0xee, 0xef, 0x08, 0xf1, 0x44, 0xf6, 0x89, 0xf7, + 0xb7, 0xf9, 0xeb, 0xfa, 0x55, 0xfb, 0xf3, 0xfc, 0x6e, 0x03, 0xf9, 0x06, + 0x58, 0x08, 0x72, 0x07, 0x06, 0x04, 0xdf, 0x02, 0xbe, 0x05, 0xc1, 0x08, + 0xcf, 0x0d, 0x7b, 0x0d, 0x05, 0x0e, 0xaa, 0x0a, 0xae, 0x09, 0x83, 0x08, + 0xd5, 0x0a, 0x02, 0x11, 0xca, 0x17, 0x89, 0x1b, 0x30, 0x1a, 0xa9, 0x19, + 0x06, 0x17, 0x42, 0x17, 0xa6, 0x17, 0x28, 0x17, 0x95, 0x19, 0xbe, 0x1a, + 0x74, 0x19, 0xc0, 0x17, 0x3d, 0x11, 0x66, 0x0c, 0x2e, 0x0b, 0x8f, 0x0c, + 0x08, 0x0d, 0x06, 0x0f, 0x2b, 0x0c, 0x8f, 0x08, 0xc1, 0x06, 0xc8, 0x04, + 0xfd, 0x02, 0x23, 0x02, 0xee, 0xfd, 0x98, 0xfc, 0x6e, 0xfc, 0xfc, 0xfc, + 0x8a, 0xff, 0xb1, 0x03, 0x87, 0x04, 0xc5, 0x04, 0x1e, 0x00, 0x00, 0xfc, + 0x26, 0xf9, 0x6d, 0xf7, 0x2b, 0xf3, 0x3b, 0xf0, 0x0d, 0xea, 0x9d, 0xe7, + 0x19, 0xe6, 0x00, 0xe4, 0xab, 0xe3, 0x43, 0xdf, 0x35, 0xdd, 0x33, 0xdd, + 0x7c, 0xdf, 0x62, 0xe3, 0x89, 0xe6, 0x74, 0xeb, 0xe0, 0xf1, 0x09, 0xf7, + 0xdc, 0xfb, 0x95, 0xff, 0x9e, 0x02, 0x66, 0x05, 0xe0, 0x07, 0xaa, 0x04, + 0x89, 0x05, 0xed, 0x00, 0x8e, 0xff, 0x4f, 0x01, 0x6d, 0xfe, 0xb4, 0xf9, + 0x37, 0xf5, 0xa7, 0xee, 0xa2, 0xec, 0x33, 0xee, 0x9d, 0xec, 0x9d, 0xeb, + 0x7e, 0xec, 0xac, 0xeb, 0xb8, 0xf1, 0xad, 0xf9, 0x64, 0xfb, 0xfd, 0xff, + 0x49, 0x03, 0xca, 0xff, 0x78, 0x04, 0x04, 0x06, 0x39, 0x07, 0xad, 0x0c, + 0xca, 0x0b, 0xf1, 0x09, 0xb8, 0x09, 0xb7, 0x0a, 0x22, 0x09, 0xd6, 0x09, + 0x31, 0x07, 0x60, 0x07, 0x9f, 0x0a, 0x07, 0x0f, 0x14, 0x12, 0x04, 0x14, + 0x44, 0x13, 0xe4, 0x11, 0x7f, 0x13, 0x35, 0x15, 0xa4, 0x18, 0x77, 0x1a, + 0x97, 0x1b, 0x71, 0x1a, 0x07, 0x19, 0xbc, 0x18, 0x76, 0x17, 0x3a, 0x17, + 0x81, 0x15, 0xfd, 0x13, 0xb3, 0x10, 0x0b, 0x0e, 0x08, 0x0c, 0xa5, 0x09, + 0xc0, 0x07, 0x11, 0x05, 0x9d, 0x03, 0x17, 0x02, 0x8a, 0x01, 0xad, 0x01, + 0x17, 0x01, 0xc8, 0x00, 0x2a, 0x00, 0xac, 0xff, 0xb9, 0x01, 0x9c, 0x02, + 0xea, 0x03, 0x13, 0x03, 0x7e, 0x02, 0x20, 0x02, 0xb0, 0x00, 0x4f, 0xfe, + 0xe2, 0xfa, 0x05, 0xf5, 0xb5, 0xf0, 0xfc, 0xec, 0x42, 0xe8, 0x5e, 0xe4, + 0xb8, 0xde, 0x10, 0xd9, 0x7c, 0xd4, 0xad, 0xd3, 0x48, 0xd4, 0x3c, 0xd6, + 0xbe, 0xdc, 0xea, 0xe1, 0x54, 0xec, 0x5e, 0xf6, 0xf8, 0xff, 0x39, 0x03, + 0x35, 0x05, 0x20, 0x05, 0x69, 0x07, 0x2f, 0x0b, 0x31, 0x0c, 0x7b, 0x0c, + 0xef, 0x09, 0x60, 0x07, 0xf3, 0x01, 0xad, 0xfd, 0x16, 0xf8, 0xef, 0xf2, + 0xf0, 0xed, 0x4b, 0xe9, 0xf1, 0xe5, 0xf3, 0xe4, 0x8a, 0xe4, 0x7c, 0xe9, + 0x23, 0xed, 0xf3, 0xf2, 0xeb, 0xf9, 0x8c, 0xfd, 0x1c, 0x02, 0x6b, 0x06, + 0x87, 0x08, 0x72, 0x09, 0x5a, 0x0a, 0x97, 0x08, 0x57, 0x08, 0xe6, 0x06, + 0x49, 0x06, 0x75, 0x05, 0x98, 0x06, 0x7c, 0x05, 0x59, 0x06, 0xb2, 0x06, + 0xf6, 0x05, 0x3f, 0x07, 0x4f, 0x07, 0xa2, 0x08, 0x73, 0x0b, 0xdf, 0x0e, + 0x26, 0x12, 0xda, 0x14, 0xf9, 0x15, 0xc0, 0x18, 0xff, 0x1b, 0x56, 0x1f, + 0xb7, 0x21, 0x6d, 0x21, 0x40, 0x1e, 0x53, 0x1b, 0x60, 0x17, 0xce, 0x12, + 0xde, 0x0f, 0x31, 0x0e, 0xdb, 0x0c, 0xbf, 0x0c, 0x30, 0x0a, 0xda, 0x06, + 0xa2, 0x03, 0x2b, 0x00, 0x5c, 0xfd, 0x27, 0xfd, 0x43, 0xfd, 0xe1, 0xfe, + 0x09, 0x01, 0x2f, 0x03, 0x76, 0x03, 0x10, 0x04, 0x86, 0x03, 0x53, 0x03, + 0x0f, 0x05, 0xcc, 0x04, 0xb4, 0x04, 0xec, 0x03, 0xfe, 0xff, 0x15, 0xfe, + 0xa8, 0xfa, 0x08, 0xf6, 0xd0, 0xf2, 0xdb, 0xee, 0x74, 0xea, 0x99, 0xe5, + 0xd9, 0xe0, 0x12, 0xdd, 0x15, 0xdc, 0x95, 0xd9, 0xe2, 0xd6, 0x94, 0xd3, + 0xd9, 0xd2, 0x4e, 0xd8, 0x57, 0xdf, 0x8a, 0xe8, 0xf1, 0xf4, 0xba, 0xfe, + 0xef, 0x05, 0xea, 0x0c, 0xbd, 0x0f, 0x67, 0x12, 0x05, 0x13, 0xd9, 0x0f, + 0x06, 0x08, 0x9b, 0x03, 0xa6, 0xfc, 0xaf, 0xf9, 0x9a, 0xf6, 0xc8, 0xf2, + 0xd0, 0xf1, 0xb1, 0xf0, 0x4c, 0xed, 0xad, 0xeb, 0x00, 0xec, 0xe7, 0xeb, + 0xc5, 0xee, 0xd7, 0xf1, 0xd6, 0xf3, 0xfd, 0xf6, 0x6d, 0xfc, 0x89, 0x00, + 0xbb, 0x04, 0x22, 0x09, 0xce, 0x0b, 0x20, 0x0e, 0x1f, 0x0f, 0xb8, 0x0c, + 0x1c, 0x0a, 0x4c, 0x07, 0x08, 0x04, 0x8c, 0x01, 0x3d, 0x00, 0x16, 0xfe, + 0x6d, 0xfe, 0x24, 0x00, 0x2b, 0x02, 0x2d, 0x04, 0xa5, 0x04, 0x6a, 0x06, + 0x7c, 0x0b, 0x45, 0x11, 0xa1, 0x17, 0xe1, 0x1c, 0x81, 0x20, 0xd7, 0x21, + 0x40, 0x23, 0xb1, 0x23, 0x30, 0x23, 0x0e, 0x22, 0x06, 0x1f, 0x1d, 0x1a, + 0x71, 0x14, 0x22, 0x0f, 0xbd, 0x0b, 0xf1, 0x08, 0xdc, 0x07, 0x91, 0x05, + 0x57, 0x03, 0xe5, 0xff, 0x95, 0xfd, 0xba, 0xfb, 0xc9, 0xfa, 0x16, 0xfb, + 0xc8, 0xfc, 0x64, 0xff, 0xda, 0x01, 0x37, 0x04, 0x90, 0x06, 0xe8, 0x07, + 0xfd, 0x08, 0x11, 0x09, 0x82, 0x07, 0x49, 0x05, 0x53, 0x03, 0xc7, 0xff, + 0xf1, 0xfc, 0x3a, 0xfa, 0x9c, 0xf5, 0x7a, 0xf2, 0xf3, 0xef, 0x50, 0xed, + 0x66, 0xec, 0x31, 0xea, 0xbf, 0xe4, 0x6b, 0xdf, 0x4b, 0xd9, 0x32, 0xd3, + 0x26, 0xd1, 0x71, 0xd0, 0x0d, 0xd4, 0x0d, 0xdb, 0x13, 0xe2, 0x0e, 0xea, + 0x73, 0xf3, 0x0f, 0xff, 0x06, 0x0a, 0x58, 0x12, 0x3b, 0x15, 0xb6, 0x14, + 0xf1, 0x13, 0x34, 0x11, 0xfd, 0x0a, 0x32, 0x04, 0xf4, 0xfb, 0x01, 0xf6, + 0x5b, 0xf2, 0xb3, 0xf0, 0x11, 0xf0, 0x24, 0xef, 0x21, 0xee, 0xe1, 0xeb, + 0x52, 0xeb, 0xa8, 0xee, 0xfe, 0xef, 0x34, 0xf2, 0xb5, 0xf4, 0x86, 0xf8, + 0x6e, 0xfe, 0x9c, 0x04, 0x3c, 0x09, 0xc4, 0x0c, 0x49, 0x0f, 0x95, 0x0f, + 0x78, 0x0e, 0x26, 0x0d, 0x0a, 0x0b, 0xd3, 0x07, 0x42, 0x01, 0xa5, 0xfb, + 0x13, 0xf9, 0xf9, 0xf7, 0x7c, 0xfa, 0x33, 0xfc, 0xb0, 0xfe, 0x13, 0x02, + 0x2b, 0x06, 0x29, 0x0a, 0xbd, 0x0d, 0xe2, 0x11, 0x0f, 0x19, 0x23, 0x1e, + 0xcb, 0x22, 0xa3, 0x25, 0x06, 0x25, 0xc1, 0x23, 0x5e, 0x22, 0x11, 0x1f, + 0x7a, 0x1b, 0xd3, 0x18, 0x9d, 0x14, 0xa9, 0x0e, 0x89, 0x08, 0xc2, 0x02, + 0xdd, 0xff, 0x04, 0xff, 0x9f, 0xfe, 0x79, 0xfe, 0x08, 0xfe, 0x4f, 0xfd, + 0x4c, 0xfd, 0x4d, 0xfe, 0xcf, 0xff, 0x56, 0x02, 0x3b, 0x05, 0x29, 0x06, + 0xa5, 0x07, 0x60, 0x08, 0x7f, 0x08, 0xda, 0x08, 0x4e, 0x09, 0x56, 0x07, + 0xba, 0x05, 0xe4, 0x03, 0xed, 0x00, 0x49, 0xfe, 0xc0, 0xf8, 0x42, 0xf2, + 0x39, 0xef, 0x9d, 0xee, 0x6d, 0xf0, 0x68, 0xf1, 0x41, 0xf2, 0x15, 0xed, + 0x41, 0xe7, 0x59, 0xe1, 0x80, 0xd5, 0x63, 0xd1, 0x2e, 0xcf, 0xd7, 0xce, + 0x9d, 0xd1, 0xaa, 0xd8, 0x32, 0xdd, 0xdd, 0xe8, 0x24, 0xf7, 0x72, 0x02, + 0x3a, 0x11, 0x95, 0x1a, 0x4c, 0x1b, 0xfc, 0x1d, 0x7e, 0x1b, 0x77, 0x15, + 0xeb, 0x0f, 0xe3, 0x08, 0x32, 0xfe, 0xab, 0xf5, 0x6d, 0xec, 0x88, 0xe7, + 0x62, 0xe5, 0x8b, 0xe5, 0x5b, 0xe7, 0x45, 0xe8, 0xcf, 0xea, 0xc9, 0xed, + 0x94, 0xf2, 0xcf, 0xf6, 0xa6, 0xfd, 0x79, 0x01, 0x1b, 0x06, 0x1b, 0x0b, + 0x2b, 0x0e, 0x9c, 0x10, 0xcc, 0x10, 0x46, 0x0f, 0x0b, 0x0f, 0x47, 0x0e, + 0xfa, 0x0a, 0xf3, 0x05, 0x9d, 0xfd, 0x91, 0xf6, 0xa6, 0xf4, 0x75, 0xf5, + 0xd5, 0xf8, 0x58, 0xfc, 0x56, 0x00, 0xb9, 0x03, 0x8e, 0x08, 0xdf, 0x0c, + 0x90, 0x11, 0x50, 0x16, 0xe2, 0x1a, 0xd6, 0x1d, 0xe6, 0x1f, 0xff, 0x20, + 0x9b, 0x21, 0x99, 0x20, 0xb0, 0x1e, 0x24, 0x1b, 0x29, 0x18, 0xad, 0x14, + 0x8e, 0x0f, 0x66, 0x0a, 0x91, 0x04, 0xb8, 0xff, 0x0a, 0xfd, 0x49, 0xfc, + 0xfa, 0xfa, 0x59, 0xfb, 0x60, 0xfc, 0x14, 0xfe, 0x20, 0x02, 0x5f, 0x06, + 0x58, 0x09, 0x78, 0x0a, 0x02, 0x0a, 0x69, 0x09, 0x2e, 0x09, 0x00, 0x09, + 0xba, 0x08, 0xf2, 0x07, 0xbf, 0x06, 0xf1, 0x04, 0x77, 0x02, 0x1f, 0x00, + 0x08, 0xfe, 0x0f, 0xfb, 0x73, 0xf8, 0x3b, 0xf5, 0xda, 0xf2, 0xc5, 0xef, + 0x4a, 0xf1, 0x3b, 0xf2, 0x80, 0xf4, 0xcd, 0xf2, 0x28, 0xf0, 0xaa, 0xeb, + 0x15, 0xe8, 0x56, 0xe5, 0xa2, 0xe2, 0x57, 0xdd, 0xcf, 0xd4, 0xcb, 0xcb, + 0xc6, 0xc7, 0xf5, 0xcc, 0x6d, 0xda, 0x80, 0xed, 0x9e, 0xfe, 0x27, 0x0e, + 0x0f, 0x19, 0xf2, 0x22, 0x51, 0x26, 0xc5, 0x25, 0xc1, 0x1d, 0x36, 0x13, + 0xa8, 0x08, 0xed, 0xfd, 0x92, 0xf4, 0x1a, 0xed, 0xf1, 0xe7, 0x25, 0xe5, + 0x96, 0xe5, 0x56, 0xe7, 0x53, 0xea, 0x75, 0xed, 0x6e, 0xf0, 0x73, 0xf4, + 0x8b, 0xf7, 0x12, 0xf9, 0x6e, 0xfc, 0x7e, 0xff, 0x0e, 0x04, 0x5c, 0x0a, + 0x9f, 0x0e, 0x5b, 0x11, 0x26, 0x13, 0xc9, 0x13, 0x73, 0x12, 0x59, 0x10, + 0x9c, 0x0a, 0x6e, 0x04, 0x4f, 0xfe, 0x98, 0xf8, 0xdb, 0xf4, 0xb5, 0xf3, + 0xa3, 0xf3, 0x71, 0xf7, 0xa6, 0xfc, 0xe0, 0x01, 0x8a, 0x08, 0xd3, 0x0e, + 0xda, 0x13, 0x5b, 0x18, 0x1b, 0x1b, 0x25, 0x1d, 0x2c, 0x1f, 0x2d, 0x20, + 0xb3, 0x1f, 0xb3, 0x1d, 0xd0, 0x1a, 0x84, 0x17, 0xd6, 0x13, 0x8b, 0x0e, + 0x3b, 0x09, 0x75, 0x04, 0x55, 0x00, 0x6d, 0xfd, 0x84, 0xfb, 0x21, 0xfb, + 0xa1, 0xfc, 0x61, 0xff, 0xab, 0x01, 0xed, 0x03, 0xbe, 0x05, 0x04, 0x08, + 0x36, 0x0a, 0x01, 0x0c, 0xeb, 0x0c, 0xb5, 0x0c, 0xe3, 0x09, 0x26, 0x07, + 0x62, 0x04, 0xaf, 0x02, 0x2d, 0x02, 0xd1, 0x01, 0xcf, 0x00, 0x2e, 0x00, + 0x4e, 0xff, 0x9b, 0xff, 0xd3, 0xff, 0x72, 0xfe, 0xfb, 0xfb, 0x5b, 0xf7, + 0xd9, 0xf1, 0x98, 0xed, 0xff, 0xec, 0x7d, 0xee, 0x7f, 0xf1, 0xbf, 0xf2, + 0x44, 0xf1, 0xd1, 0xeb, 0xf9, 0xe8, 0x16, 0xe2, 0x52, 0xda, 0x4b, 0xd1, + 0x74, 0xc7, 0xd3, 0xc2, 0x30, 0xc6, 0x7b, 0xd2, 0x39, 0xe6, 0x66, 0x00, + 0x28, 0x17, 0x7f, 0x27, 0x46, 0x30, 0x18, 0x31, 0xbb, 0x2c, 0x96, 0x25, + 0x02, 0x1b, 0xe8, 0x0d, 0x6d, 0xfd, 0xbd, 0xec, 0xa8, 0xdf, 0x72, 0xd9, + 0x02, 0xd9, 0x9c, 0xdb, 0x8c, 0xe0, 0xc4, 0xe6, 0x13, 0xed, 0x2c, 0xf3, + 0xed, 0xf8, 0xc4, 0xfd, 0x29, 0x02, 0x71, 0x06, 0xc6, 0x08, 0xd0, 0x0a, + 0xda, 0x0c, 0xff, 0x0e, 0x37, 0x11, 0x3b, 0x13, 0x16, 0x13, 0xb7, 0x11, + 0x94, 0x0e, 0x7c, 0x09, 0xd7, 0x03, 0xde, 0xfc, 0x13, 0xf7, 0xb0, 0xf2, + 0xf6, 0xf0, 0xdd, 0xf0, 0xde, 0xf4, 0x58, 0xfa, 0x68, 0x00, 0x92, 0x07, + 0x84, 0x0e, 0x01, 0x15, 0x2a, 0x1c, 0xcb, 0x20, 0x92, 0x22, 0xf5, 0x21, + 0x93, 0x1f, 0x85, 0x1c, 0x79, 0x19, 0x80, 0x15, 0x72, 0x10, 0xd4, 0x0b, + 0xdd, 0x06, 0xe9, 0x03, 0xea, 0x01, 0x54, 0x00, 0xea, 0xfe, 0xe4, 0xfc, + 0x0c, 0xfc, 0xe8, 0xfc, 0xe5, 0xff, 0x07, 0x03, 0xe8, 0x05, 0x9e, 0x07, + 0x50, 0x09, 0x31, 0x0c, 0x79, 0x0e, 0x6c, 0x0f, 0x5f, 0x0e, 0xe2, 0x0b, + 0x49, 0x0a, 0x06, 0x08, 0xb8, 0x05, 0x45, 0x03, 0x90, 0x00, 0xaa, 0xfe, + 0x3f, 0xfe, 0x6f, 0xfe, 0x58, 0xfe, 0x59, 0xfd, 0x81, 0xfc, 0xe0, 0xfa, + 0x8a, 0xf9, 0x53, 0xf8, 0x38, 0xf6, 0x3c, 0xf2, 0x2d, 0xf0, 0xb6, 0xee, + 0x02, 0xf0, 0x03, 0xf2, 0x97, 0xf3, 0x12, 0xf1, 0xd6, 0xec, 0x9f, 0xe6, + 0x4e, 0xdf, 0xc5, 0xd5, 0xb2, 0xca, 0x47, 0xc2, 0xa4, 0xbf, 0x15, 0xca, + 0x7d, 0xdb, 0xa0, 0xf6, 0xfd, 0x10, 0x70, 0x25, 0xfe, 0x2f, 0xa9, 0x32, + 0x62, 0x2f, 0xdb, 0x28, 0x93, 0x1e, 0xed, 0x10, 0x69, 0x01, 0x19, 0xf0, + 0x92, 0xdf, 0xec, 0xd5, 0x61, 0xd3, 0xc0, 0xd6, 0xf4, 0xde, 0xf1, 0xe6, + 0xa8, 0xf0, 0xbc, 0xf9, 0x7a, 0x00, 0x6e, 0x03, 0xda, 0x05, 0x74, 0x07, + 0x65, 0x08, 0xf3, 0x08, 0x2f, 0x08, 0xfa, 0x09, 0x67, 0x0b, 0x34, 0x0d, + 0x43, 0x0e, 0x6a, 0x0e, 0x45, 0x0e, 0xc4, 0x0d, 0x2c, 0x08, 0x1e, 0x01, + 0xa6, 0xfa, 0x63, 0xf5, 0x1b, 0xf3, 0xe8, 0xf2, 0xb4, 0xf3, 0xa9, 0xf7, + 0xd8, 0xfd, 0x52, 0x05, 0xa5, 0x0d, 0xb1, 0x15, 0xd8, 0x1b, 0x30, 0x20, + 0x4c, 0x22, 0xff, 0x20, 0xbe, 0x1e, 0x02, 0x1b, 0x20, 0x16, 0xdc, 0x11, + 0x61, 0x0d, 0xdc, 0x08, 0xcc, 0x05, 0x6d, 0x02, 0x4d, 0x00, 0x07, 0xff, + 0xbb, 0xfe, 0x6b, 0xfe, 0xdd, 0xfe, 0xd4, 0xff, 0x36, 0x01, 0x54, 0x03, + 0x42, 0x05, 0xd4, 0x06, 0xce, 0x08, 0x00, 0x0b, 0xc6, 0x0c, 0x42, 0x0e, + 0x91, 0x0e, 0x32, 0x0c, 0xc9, 0x09, 0x19, 0x07, 0x6b, 0x05, 0x0a, 0x05, + 0x39, 0x05, 0x5d, 0x03, 0x6b, 0x01, 0x07, 0xff, 0xbb, 0xfd, 0xeb, 0xfd, + 0x66, 0xfe, 0x08, 0xfe, 0xa4, 0xfc, 0x03, 0xfb, 0x20, 0xf8, 0xd3, 0xf5, + 0x6c, 0xf3, 0x6f, 0xf0, 0xcf, 0xee, 0x27, 0xee, 0x98, 0xee, 0x78, 0xf0, + 0x81, 0xf1, 0x7e, 0xf1, 0xfa, 0xef, 0x74, 0xec, 0x63, 0xe6, 0x07, 0xde, + 0x56, 0xd3, 0xb6, 0xc9, 0x58, 0xc4, 0x55, 0xc7, 0x92, 0xd4, 0x73, 0xeb, + 0x1b, 0x05, 0x5b, 0x1a, 0x66, 0x29, 0x9c, 0x30, 0x8a, 0x32, 0x49, 0x2d, + 0x4f, 0x26, 0x60, 0x18, 0x9d, 0x06, 0xa3, 0xf3, 0xc8, 0xe0, 0x75, 0xd4, + 0x9e, 0xd0, 0x7f, 0xd3, 0x6f, 0xda, 0xf7, 0xe4, 0x40, 0xef, 0x3a, 0xf9, + 0x7b, 0x02, 0x1f, 0x09, 0x0b, 0x0c, 0x9e, 0x0d, 0x0e, 0x0d, 0xb9, 0x0a, + 0xc8, 0x08, 0x7e, 0x06, 0x02, 0x04, 0x25, 0x05, 0xdc, 0x06, 0xdf, 0x09, + 0xf1, 0x0c, 0x8d, 0x0d, 0xdc, 0x0a, 0xca, 0x06, 0x42, 0x01, 0x5a, 0xfc, + 0xb6, 0xf9, 0x99, 0xf6, 0x54, 0xf5, 0x2c, 0xf7, 0x61, 0xfb, 0x54, 0x02, + 0x26, 0x0b, 0x1c, 0x13, 0x63, 0x1a, 0xb5, 0x20, 0x48, 0x22, 0xcf, 0x21, + 0xe1, 0x1f, 0x4b, 0x1a, 0xe2, 0x14, 0xde, 0x0e, 0x7f, 0x08, 0xca, 0x03, + 0xaf, 0x00, 0x8a, 0xfd, 0xe7, 0xfb, 0x83, 0xfc, 0x1e, 0xfd, 0x8e, 0xff, + 0xc6, 0x02, 0x4e, 0x04, 0x5b, 0x06, 0x26, 0x08, 0x39, 0x08, 0x62, 0x08, + 0xc6, 0x08, 0x0f, 0x09, 0x62, 0x0a, 0x51, 0x0b, 0x20, 0x0b, 0xf0, 0x0a, + 0xbc, 0x09, 0x3b, 0x08, 0xca, 0x06, 0x42, 0x05, 0x04, 0x03, 0x35, 0x01, + 0x4f, 0xff, 0x3c, 0xfe, 0xde, 0xfd, 0x1f, 0xfe, 0x58, 0xfe, 0xf6, 0xfe, + 0x10, 0xff, 0xc4, 0xfe, 0x68, 0xfe, 0x76, 0xfd, 0x4d, 0xfb, 0x45, 0xf7, + 0x03, 0xf2, 0x73, 0xec, 0xd0, 0xe9, 0xd2, 0xea, 0xbb, 0xee, 0x80, 0xf2, + 0xdf, 0xf3, 0x81, 0xf1, 0x3d, 0xed, 0x51, 0xe7, 0x2a, 0xe1, 0x1c, 0xdc, + 0x12, 0xd4, 0xb8, 0xcc, 0x06, 0xc8, 0x5b, 0xca, 0xc1, 0xd8, 0x52, 0xf1, + 0xf1, 0x0b, 0x88, 0x21, 0xfd, 0x2d, 0x55, 0x30, 0xb3, 0x2e, 0x8e, 0x2b, + 0xba, 0x24, 0xf6, 0x18, 0xda, 0x07, 0x34, 0xf3, 0x4c, 0xe0, 0xec, 0xd4, + 0xa9, 0xcf, 0xfe, 0xd2, 0x3d, 0xdb, 0x22, 0xe5, 0xaa, 0xf0, 0xa1, 0xfb, + 0x07, 0x04, 0xa9, 0x0a, 0xa5, 0x0e, 0x61, 0x0e, 0x9a, 0x0c, 0x9b, 0x0a, + 0x56, 0x07, 0xe1, 0x04, 0x53, 0x04, 0xf4, 0x03, 0x8c, 0x06, 0x29, 0x0b, + 0x33, 0x0f, 0x2a, 0x11, 0x5b, 0x10, 0x1c, 0x0b, 0xa8, 0x04, 0xf3, 0xfe, + 0xe6, 0xf9, 0x0b, 0xf7, 0x53, 0xf6, 0xd9, 0xf6, 0x59, 0xfa, 0x45, 0x01, + 0x82, 0x09, 0x60, 0x12, 0x3b, 0x1a, 0x81, 0x1f, 0x97, 0x21, 0xbd, 0x21, + 0xe8, 0x1e, 0x9a, 0x19, 0x37, 0x13, 0x42, 0x0c, 0xee, 0x05, 0x05, 0x01, + 0x72, 0xfd, 0xc3, 0xfa, 0x3a, 0xfa, 0xfb, 0xfa, 0x24, 0xfd, 0x08, 0x00, + 0xf0, 0x02, 0x73, 0x04, 0xbb, 0x05, 0x58, 0x06, 0x79, 0x07, 0xe7, 0x08, + 0x9b, 0x09, 0x9c, 0x09, 0x7d, 0x0a, 0xa6, 0x0a, 0x3a, 0x0b, 0x09, 0x0b, + 0x94, 0x09, 0xa8, 0x07, 0x8a, 0x05, 0x7a, 0x03, 0xf8, 0x01, 0x1d, 0x00, + 0x6a, 0xfe, 0xd8, 0xfc, 0xf6, 0xfb, 0x80, 0xfc, 0x8c, 0xfd, 0x21, 0xfe, + 0x40, 0xfe, 0x7b, 0xfd, 0x1b, 0xfc, 0xb6, 0xfa, 0x2a, 0xfa, 0x8a, 0xf8, + 0x4c, 0xf6, 0xa3, 0xf3, 0x45, 0xef, 0xf4, 0xec, 0x3a, 0xee, 0xeb, 0xf0, + 0x28, 0xf4, 0x9c, 0xf4, 0x56, 0xf1, 0xbb, 0xeb, 0x1e, 0xe6, 0x94, 0xdf, + 0x4a, 0xd9, 0x62, 0xd2, 0xe9, 0xcd, 0xcf, 0xce, 0x36, 0xd8, 0x49, 0xe9, + 0xad, 0xfd, 0x19, 0x11, 0x2d, 0x1f, 0x47, 0x28, 0xdf, 0x2b, 0x83, 0x2c, + 0x98, 0x27, 0xe1, 0x1e, 0x7e, 0x10, 0xd8, 0xff, 0xba, 0xee, 0x3e, 0xe1, + 0x1f, 0xd9, 0x3b, 0xd7, 0xe5, 0xd9, 0xce, 0xdf, 0x17, 0xe8, 0xae, 0xf1, + 0x2f, 0xfb, 0x12, 0x04, 0xf0, 0x09, 0x26, 0x0d, 0xe3, 0x0d, 0xfe, 0x0c, + 0x19, 0x0b, 0xc3, 0x08, 0x28, 0x07, 0x5e, 0x06, 0x26, 0x08, 0xb8, 0x0a, + 0xb1, 0x0d, 0x4d, 0x0f, 0xec, 0x0e, 0xd6, 0x0c, 0x0e, 0x09, 0x35, 0x04, + 0x11, 0xff, 0xc0, 0xfa, 0x91, 0xf7, 0xe4, 0xf6, 0xd6, 0xf8, 0x14, 0xfd, + 0x8d, 0x04, 0xf7, 0x0c, 0x71, 0x14, 0x3f, 0x1a, 0x26, 0x1e, 0xbc, 0x1e, + 0x81, 0x1d, 0xf5, 0x19, 0x07, 0x14, 0x33, 0x0e, 0xd7, 0x08, 0xc0, 0x03, + 0xd6, 0xff, 0x14, 0xfd, 0x07, 0xfb, 0x4f, 0xfb, 0x1d, 0xfd, 0xc1, 0xfe, + 0x13, 0x01, 0xe2, 0x02, 0xa4, 0x03, 0xdc, 0x04, 0xae, 0x06, 0xba, 0x07, + 0x5a, 0x08, 0xb3, 0x08, 0x77, 0x07, 0x45, 0x08, 0x25, 0x0a, 0x2f, 0x0b, + 0xae, 0x0b, 0x46, 0x09, 0x4e, 0x05, 0x5a, 0x02, 0x0e, 0x01, 0xb0, 0x00, + 0x96, 0x00, 0x59, 0xff, 0xad, 0xfd, 0xc7, 0xfc, 0x61, 0xfc, 0xa2, 0xfd, + 0x5b, 0xfe, 0x36, 0xfe, 0x1e, 0xfe, 0x6e, 0xfc, 0x20, 0xfb, 0x61, 0xfa, + 0x5a, 0xf8, 0xaf, 0xf6, 0x60, 0xf4, 0x1a, 0xf2, 0x70, 0xf0, 0x61, 0xf1, + 0x30, 0xf3, 0xc9, 0xf4, 0xb9, 0xf5, 0x27, 0xf3, 0x78, 0xee, 0xc0, 0xe8, + 0x3d, 0xe1, 0x16, 0xda, 0x0a, 0xd3, 0xeb, 0xce, 0x25, 0xcf, 0x54, 0xd6, + 0x51, 0xe3, 0x21, 0xf5, 0xfe, 0x07, 0xe3, 0x18, 0xb9, 0x25, 0x06, 0x2d, + 0xa5, 0x2e, 0x36, 0x2a, 0x33, 0x21, 0x3b, 0x13, 0x8e, 0x03, 0x1c, 0xf4, + 0x50, 0xe6, 0x54, 0xdc, 0x19, 0xd8, 0x6e, 0xd8, 0xdf, 0xdd, 0x01, 0xe7, + 0x1e, 0xf0, 0x68, 0xf9, 0x99, 0x02, 0x51, 0x08, 0xf1, 0x0b, 0x4e, 0x0d, + 0x00, 0x0c, 0x3b, 0x0a, 0x2e, 0x09, 0xb4, 0x07, 0xff, 0x06, 0xb4, 0x07, + 0x43, 0x09, 0x31, 0x0c, 0xb0, 0x0f, 0xcd, 0x10, 0xc2, 0x0f, 0xc8, 0x0b, + 0xce, 0x05, 0xa5, 0xff, 0xfe, 0xfa, 0xba, 0xf7, 0x00, 0xf7, 0x39, 0xf8, + 0xb2, 0xfb, 0x86, 0x01, 0xf9, 0x08, 0xf3, 0x10, 0x2e, 0x18, 0x80, 0x1d, + 0xe4, 0x1f, 0x48, 0x1f, 0x00, 0x1c, 0x9b, 0x16, 0x62, 0x10, 0xff, 0x09, + 0x0a, 0x04, 0x75, 0xff, 0xc2, 0xfb, 0x20, 0xfa, 0x53, 0xfa, 0xb0, 0xfb, + 0x91, 0xfd, 0xe8, 0xff, 0x95, 0x01, 0xb1, 0x02, 0x25, 0x04, 0x9a, 0x05, + 0xdb, 0x06, 0xd9, 0x07, 0x62, 0x08, 0x47, 0x08, 0x16, 0x09, 0xfa, 0x09, + 0xe6, 0x0a, 0xb1, 0x0a, 0xc6, 0x09, 0xb0, 0x07, 0x4c, 0x05, 0x30, 0x03, + 0xc4, 0x00, 0x76, 0xfe, 0x03, 0xfd, 0xde, 0xfb, 0xd8, 0xfb, 0x46, 0xfc, + 0xba, 0xfc, 0xe7, 0xfd, 0x32, 0xfe, 0x1c, 0xfe, 0xdb, 0xfd, 0x5d, 0xfd, + 0x69, 0xfc, 0xc2, 0xfb, 0xc9, 0xf9, 0x63, 0xf7, 0xda, 0xf4, 0x43, 0xf3, + 0x6c, 0xf2, 0x86, 0xf3, 0x32, 0xf4, 0x14, 0xf3, 0x9a, 0xf1, 0x7f, 0xec, + 0x2a, 0xe9, 0x9a, 0xe5, 0xd0, 0xe1, 0x47, 0xdd, 0x9d, 0xd7, 0xb5, 0xd2, + 0x57, 0xd1, 0x98, 0xd7, 0x22, 0xe4, 0x61, 0xf7, 0x0c, 0x0b, 0x33, 0x1b, + 0xb5, 0x25, 0x1c, 0x29, 0x6c, 0x29, 0x59, 0x25, 0x4f, 0x1e, 0x9b, 0x12, + 0x1a, 0x03, 0x4b, 0xf3, 0xc7, 0xe4, 0xd7, 0xdb, 0x84, 0xd8, 0x43, 0xdb, + 0xfb, 0xe1, 0x70, 0xeb, 0x65, 0xf4, 0x28, 0xfc, 0x0e, 0x03, 0x16, 0x08, + 0xeb, 0x0a, 0x8c, 0x0c, 0xea, 0x0b, 0x28, 0x0a, 0xa9, 0x08, 0x7b, 0x06, + 0x97, 0x05, 0xac, 0x07, 0x29, 0x0b, 0xd4, 0x0e, 0x04, 0x11, 0xc6, 0x10, + 0x06, 0x0e, 0xfa, 0x09, 0xac, 0x05, 0x64, 0x01, 0xb0, 0xfd, 0xad, 0xf9, + 0xc1, 0xf6, 0x65, 0xf6, 0xd8, 0xf9, 0xdb, 0x00, 0xf0, 0x09, 0xcd, 0x11, + 0xdb, 0x17, 0x5a, 0x1b, 0x55, 0x1d, 0x79, 0x1d, 0xb1, 0x1b, 0x08, 0x17, + 0x68, 0x10, 0x2e, 0x0a, 0xa3, 0x03, 0xd6, 0xfe, 0xec, 0xfb, 0xa0, 0xfa, + 0x42, 0xfa, 0xe3, 0xfb, 0xfe, 0xfd, 0x53, 0x00, 0x5e, 0x02, 0x44, 0x03, + 0x9a, 0x03, 0xf7, 0x03, 0x3e, 0x04, 0xc8, 0x04, 0xf9, 0x04, 0xca, 0x04, + 0x77, 0x05, 0x68, 0x06, 0xda, 0x07, 0xcc, 0x09, 0xa2, 0x0a, 0x3b, 0x0a, + 0x5c, 0x08, 0x16, 0x06, 0x49, 0x03, 0xbc, 0x00, 0x7d, 0xfe, 0x61, 0xfd, + 0x5f, 0xfc, 0x38, 0xfc, 0x61, 0xfc, 0x78, 0xfc, 0xaf, 0xfc, 0x58, 0xfd, + 0x5e, 0xfe, 0x9e, 0xfe, 0x6a, 0xfe, 0x6e, 0xfd, 0xc1, 0xfb, 0x5c, 0xfa, + 0x9a, 0xf8, 0xfe, 0xf6, 0x90, 0xf4, 0x90, 0xf2, 0xa9, 0xf1, 0xc6, 0xf1, + 0x68, 0xf2, 0x41, 0xf2, 0xb5, 0xef, 0x13, 0xec, 0xeb, 0xe6, 0xd0, 0xe1, + 0xa2, 0xdc, 0x97, 0xd7, 0x20, 0xd3, 0x6e, 0xd1, 0x5c, 0xd6, 0xee, 0xe2, + 0xac, 0xf5, 0x26, 0x09, 0xf6, 0x18, 0x68, 0x23, 0x4b, 0x28, 0x3d, 0x2a, + 0xcb, 0x28, 0x7c, 0x22, 0x53, 0x16, 0x09, 0x06, 0xa7, 0xf4, 0x75, 0xe6, + 0x3a, 0xde, 0xa7, 0xda, 0xe2, 0xdb, 0xfe, 0xdf, 0x57, 0xe7, 0x9c, 0xf0, + 0x9a, 0xfa, 0x72, 0x03, 0x67, 0x0a, 0x4f, 0x0e, 0xa5, 0x0f, 0x38, 0x0e, + 0x6f, 0x0b, 0x44, 0x08, 0xcf, 0x06, 0x9e, 0x06, 0x64, 0x08, 0x03, 0x0b, + 0x5d, 0x0e, 0x6f, 0x0e, 0x4c, 0x0e, 0x1c, 0x0d, 0x36, 0x0a, 0x5e, 0x07, + 0xf7, 0x02, 0x2b, 0xfd, 0xf1, 0xf8, 0x42, 0xf7, 0xa0, 0xf7, 0x6c, 0xfb, + 0x6f, 0x01, 0xb3, 0x07, 0xbd, 0x0e, 0xfa, 0x13, 0x37, 0x17, 0xa7, 0x19, + 0x90, 0x1a, 0x9b, 0x19, 0xc0, 0x16, 0x17, 0x11, 0x8e, 0x0a, 0xc3, 0x04, + 0x02, 0x00, 0xa9, 0xfd, 0xd9, 0xfc, 0x3c, 0xfc, 0x27, 0xfc, 0xbe, 0xfc, + 0x4d, 0xfd, 0x50, 0xff, 0xc7, 0x01, 0x27, 0x03, 0xdb, 0x03, 0x4e, 0x04, + 0x47, 0x03, 0x94, 0x03, 0x84, 0x04, 0x28, 0x05, 0x5d, 0x06, 0xb4, 0x06, + 0x86, 0x06, 0x99, 0x06, 0x9e, 0x06, 0x07, 0x06, 0x68, 0x06, 0x52, 0x06, + 0xf9, 0x04, 0x6b, 0x02, 0xed, 0xff, 0xa7, 0xfd, 0x62, 0xfc, 0x1a, 0xfc, + 0x1b, 0xfc, 0x36, 0xfc, 0xe8, 0xfc, 0xfd, 0xfc, 0xae, 0xfc, 0x59, 0xfd, + 0xee, 0xfd, 0x4a, 0xfe, 0xbb, 0xfe, 0x72, 0xfd, 0xa3, 0xfa, 0x50, 0xf7, + 0x84, 0xf4, 0x45, 0xf1, 0xc1, 0xf1, 0xb1, 0xf1, 0x93, 0xf1, 0x91, 0xee, + 0x28, 0xec, 0x5b, 0xe8, 0x21, 0xe4, 0x75, 0xe1, 0x23, 0xdb, 0x3c, 0xd6, + 0x00, 0xd3, 0x4c, 0xd5, 0x1d, 0xdc, 0xe0, 0xeb, 0x97, 0xfd, 0x92, 0x0f, + 0x29, 0x1e, 0x05, 0x27, 0xf5, 0x2a, 0x06, 0x2c, 0x6f, 0x28, 0xd3, 0x1f, + 0xbd, 0x12, 0x6d, 0x01, 0x1d, 0xf0, 0xa5, 0xe2, 0x14, 0xda, 0x1b, 0xd8, + 0xc0, 0xdb, 0x89, 0xe2, 0xcd, 0xeb, 0x63, 0xf5, 0x3d, 0xfd, 0x4f, 0x04, + 0x66, 0x0a, 0x18, 0x0e, 0xb9, 0x0f, 0xb2, 0x0e, 0xc0, 0x0a, 0xf0, 0x07, + 0x81, 0x07, 0x53, 0x08, 0xf5, 0x0a, 0xed, 0x0d, 0x8d, 0x0e, 0x8a, 0x0e, + 0xc1, 0x0d, 0x68, 0x0b, 0x55, 0x08, 0xaa, 0x04, 0xbf, 0xff, 0xda, 0xfa, + 0x3b, 0xf7, 0xa8, 0xf5, 0x06, 0xf7, 0x91, 0xfb, 0xf5, 0x01, 0xeb, 0x08, + 0xb5, 0x0f, 0x69, 0x15, 0x8e, 0x19, 0x6d, 0x1b, 0x4d, 0x1a, 0x9f, 0x16, + 0x27, 0x12, 0xa3, 0x0d, 0xca, 0x09, 0x04, 0x05, 0xd4, 0xff, 0xbc, 0xfb, + 0x80, 0xf9, 0x6b, 0xfa, 0x0b, 0xfc, 0xd4, 0xfd, 0xe1, 0xfe, 0x03, 0xff, + 0x89, 0xff, 0x2d, 0x00, 0x51, 0x01, 0x77, 0x02, 0xc4, 0x02, 0xd9, 0x02, + 0x13, 0x03, 0xb7, 0x03, 0xe4, 0x05, 0x10, 0x08, 0x60, 0x09, 0xc3, 0x09, + 0xcc, 0x08, 0xf4, 0x07, 0x85, 0x06, 0x6c, 0x05, 0xfd, 0x02, 0xe9, 0x00, + 0x67, 0xff, 0xa8, 0xfe, 0xd7, 0xfe, 0x51, 0xff, 0x99, 0xff, 0x44, 0xff, + 0x36, 0xff, 0x14, 0xff, 0x3a, 0xff, 0xb5, 0xfe, 0x28, 0xfe, 0x14, 0xfd, + 0x9a, 0xfc, 0x4f, 0xfc, 0xe0, 0xfb, 0xca, 0xf9, 0xe1, 0xf7, 0x9c, 0xf5, + 0x0b, 0xf4, 0xdb, 0xf3, 0x8c, 0xf3, 0x3e, 0xf2, 0xdb, 0xef, 0x1d, 0xec, + 0x74, 0xe8, 0xf9, 0xe4, 0x76, 0xe1, 0xdd, 0xdc, 0xd5, 0xd7, 0xe9, 0xd4, + 0x51, 0xd6, 0x78, 0xde, 0x10, 0xee, 0xc2, 0xff, 0xd7, 0x10, 0x77, 0x1d, + 0x9a, 0x24, 0xd8, 0x28, 0x62, 0x2a, 0x6d, 0x27, 0xd1, 0x1e, 0xfd, 0x11, + 0x98, 0x01, 0x18, 0xf0, 0x79, 0xe3, 0x8e, 0xdc, 0x79, 0xda, 0xcc, 0xdc, + 0xaf, 0xe2, 0xf3, 0xe8, 0xad, 0xf1, 0xcd, 0xfb, 0x0f, 0x04, 0x9f, 0x0a, + 0x89, 0x0e, 0x22, 0x0e, 0x38, 0x0b, 0x5a, 0x09, 0x4a, 0x07, 0x25, 0x07, + 0x5e, 0x08, 0x8d, 0x09, 0x85, 0x0a, 0x85, 0x0c, 0xda, 0x0d, 0xb2, 0x0d, + 0xca, 0x0c, 0x52, 0x0a, 0x6f, 0x06, 0xfe, 0x01, 0x70, 0xfc, 0x7c, 0xf7, + 0xb9, 0xf5, 0xa0, 0xf6, 0xea, 0xf8, 0xb1, 0xfe, 0x8d, 0x05, 0x70, 0x0c, + 0xc0, 0x12, 0x7c, 0x16, 0x76, 0x18, 0x76, 0x19, 0x83, 0x18, 0xd8, 0x14, + 0x8a, 0x0f, 0xb5, 0x09, 0x3f, 0x04, 0x52, 0x00, 0x59, 0xfd, 0x2f, 0xfb, + 0x25, 0xfa, 0x33, 0xfa, 0x02, 0xfb, 0x30, 0xfd, 0xbc, 0xff, 0x7d, 0x01, + 0x63, 0x02, 0x27, 0x02, 0x69, 0x01, 0x4d, 0x02, 0x62, 0x03, 0x5e, 0x03, + 0x06, 0x04, 0x25, 0x04, 0xfb, 0x04, 0x6b, 0x07, 0x1f, 0x0a, 0xe7, 0x0b, + 0x98, 0x0c, 0xfe, 0x0a, 0xc8, 0x07, 0x8e, 0x05, 0x65, 0x04, 0x82, 0x03, + 0xf1, 0x02, 0x28, 0x01, 0xd8, 0xfe, 0x81, 0xfd, 0xf4, 0xfc, 0x11, 0xfe, + 0x8a, 0xff, 0x86, 0x00, 0xd8, 0x00, 0xcf, 0x00, 0xdd, 0x00, 0xc8, 0x00, + 0xb0, 0x00, 0xea, 0xfe, 0x96, 0xfc, 0x95, 0xf8, 0x52, 0xf5, 0x15, 0xf2, + 0xd3, 0xf0, 0xae, 0xf0, 0x64, 0xf1, 0x1e, 0xf0, 0x60, 0xee, 0x86, 0xeb, + 0x2b, 0xe8, 0xd7, 0xe6, 0xe8, 0xe2, 0xf5, 0xdd, 0xdd, 0xd8, 0xd6, 0xd4, + 0x3a, 0xd6, 0x96, 0xdf, 0x94, 0xef, 0xcb, 0x02, 0x5b, 0x14, 0xe4, 0x20, + 0x95, 0x27, 0x16, 0x2a, 0x44, 0x29, 0x6b, 0x26, 0x22, 0x1e, 0xca, 0x0f, + 0xab, 0xfe, 0x2e, 0xed, 0xc7, 0xde, 0xe2, 0xd6, 0x6c, 0xd6, 0x5b, 0xdb, + 0xc3, 0xe2, 0x2c, 0xea, 0x04, 0xf1, 0x8a, 0xf9, 0x39, 0x02, 0x77, 0x09, + 0xb2, 0x0d, 0x28, 0x0e, 0x3e, 0x0c, 0x3f, 0x09, 0xab, 0x06, 0xbe, 0x05, + 0x2e, 0x07, 0xd7, 0x09, 0x7b, 0x0c, 0x5b, 0x0e, 0xf0, 0x0e, 0xdd, 0x0d, + 0x0f, 0x0c, 0x59, 0x09, 0x4e, 0x05, 0x96, 0x01, 0x5a, 0xfd, 0xaa, 0xf7, + 0x02, 0xf4, 0x1c, 0xf4, 0xc5, 0xf7, 0xd8, 0xfe, 0x2b, 0x06, 0x3c, 0x0c, + 0x1b, 0x11, 0x6d, 0x16, 0x7d, 0x18, 0xdf, 0x18, 0xa3, 0x17, 0xf8, 0x14, + 0x0c, 0x11, 0x5c, 0x0c, 0x42, 0x06, 0xd4, 0x00, 0x04, 0xfd, 0xe3, 0xfa, + 0x44, 0xfa, 0xa5, 0xfa, 0xbf, 0xfb, 0x5a, 0xfc, 0xcb, 0xfc, 0xc9, 0xfd, + 0x6e, 0xff, 0xdc, 0x00, 0xb5, 0x02, 0x45, 0x03, 0xf9, 0x03, 0xb8, 0x04, + 0xfc, 0x05, 0xf0, 0x06, 0xac, 0x09, 0x2c, 0x0c, 0x37, 0x0d, 0x81, 0x0d, + 0x28, 0x0c, 0x61, 0x0a, 0x92, 0x09, 0x61, 0x08, 0xef, 0x06, 0xc0, 0x04, + 0xc6, 0x01, 0xce, 0xff, 0xb9, 0xfe, 0x60, 0xfe, 0xe3, 0xfe, 0x69, 0xff, + 0xc6, 0xff, 0x3d, 0x00, 0x87, 0x00, 0xf2, 0x00, 0xfc, 0x01, 0x30, 0x01, + 0x50, 0x00, 0xd9, 0xfd, 0x03, 0xfc, 0x44, 0xfa, 0x1e, 0xf8, 0xb7, 0xf4, + 0x06, 0xf3, 0xef, 0xf1, 0xe2, 0xf1, 0x63, 0xf1, 0xbd, 0xee, 0x22, 0xec, + 0xdc, 0xe6, 0xa7, 0xe5, 0x5a, 0xe0, 0xba, 0xdc, 0x3b, 0xd8, 0xa1, 0xd3, + 0xa1, 0xd5, 0xf9, 0xdd, 0xca, 0xeb, 0x8f, 0xfd, 0xe6, 0x0c, 0x3b, 0x18, + 0x15, 0x20, 0x83, 0x27, 0xfe, 0x29, 0x71, 0x29, 0x3f, 0x21, 0x8c, 0x11, + 0x6f, 0x01, 0x45, 0xf2, 0x88, 0xe6, 0x83, 0xdf, 0x07, 0xdb, 0xec, 0xd8, + 0xf3, 0xdb, 0x51, 0xe2, 0x83, 0xea, 0x91, 0xf4, 0x02, 0xfd, 0xcb, 0x03, + 0xa2, 0x08, 0xb4, 0x09, 0x8d, 0x0a, 0x3e, 0x09, 0x06, 0x09, 0x92, 0x08, + 0x4f, 0x08, 0x35, 0x09, 0x4d, 0x0b, 0x2a, 0x0d, 0xde, 0x0e, 0xe7, 0x0e, + 0xed, 0x0d, 0x25, 0x0c, 0xcf, 0x09, 0x88, 0x06, 0xd7, 0x01, 0xc2, 0xfc, + 0x13, 0xf9, 0x29, 0xf7, 0x62, 0xf8, 0x69, 0xfb, 0xdc, 0xff, 0x2b, 0x04, + 0x54, 0x09, 0x24, 0x0f, 0xc8, 0x13, 0xfd, 0x16, 0xaf, 0x17, 0x50, 0x15, + 0x10, 0x12, 0x7e, 0x0e, 0x2e, 0x0b, 0xe9, 0x07, 0x3e, 0x05, 0x0c, 0x01, + 0xf3, 0xfd, 0x45, 0xfc, 0x27, 0xfc, 0xfa, 0xfc, 0x6e, 0xfe, 0xc1, 0xfe, + 0x0d, 0xff, 0xda, 0xfe, 0x11, 0xff, 0x0b, 0x00, 0xc1, 0x01, 0x00, 0x04, + 0xab, 0x05, 0xdb, 0x06, 0x26, 0x08, 0xf4, 0x09, 0xcf, 0x0b, 0xde, 0x0d, + 0xc5, 0x0e, 0x87, 0x0e, 0x99, 0x0d, 0x2a, 0x0c, 0x81, 0x0a, 0x87, 0x08, + 0x45, 0x06, 0x1b, 0x04, 0xca, 0x01, 0x40, 0x00, 0x91, 0xff, 0x7f, 0xfe, + 0x4a, 0xfe, 0x1a, 0xfe, 0x01, 0xfe, 0x0c, 0xff, 0x7e, 0xff, 0x3b, 0x00, + 0x40, 0x00, 0xb4, 0xff, 0x7f, 0xff, 0x83, 0xfe, 0xb9, 0xfc, 0xd2, 0xf9, + 0x0a, 0xf6, 0xc6, 0xf2, 0xab, 0xf1, 0xdd, 0xef, 0xde, 0xee, 0xec, 0xec, + 0x3b, 0xe9, 0x7a, 0xe7, 0xdf, 0xe4, 0xb0, 0xe1, 0xd6, 0xde, 0x96, 0xda, + 0x87, 0xd6, 0xdc, 0xd5, 0xa6, 0xdb, 0xe6, 0xe6, 0x98, 0xf7, 0x03, 0x07, + 0x34, 0x11, 0xd7, 0x18, 0x2d, 0x1d, 0xf7, 0x20, 0x79, 0x23, 0xcc, 0x20, + 0x92, 0x16, 0xb6, 0x08, 0xd3, 0xf8, 0x18, 0xed, 0x8e, 0xe6, 0x54, 0xe3, + 0x45, 0xe1, 0x69, 0xe1, 0x23, 0xe3, 0x33, 0xe8, 0xc2, 0xef, 0xe4, 0xf7, + 0x26, 0xfe, 0xde, 0x02, 0x8f, 0x04, 0x14, 0x05, 0x4a, 0x05, 0xe5, 0x04, + 0x4f, 0x05, 0xd3, 0x06, 0x8b, 0x08, 0x07, 0x0b, 0x08, 0x0d, 0x72, 0x0e, + 0x4c, 0x10, 0xce, 0x11, 0xbd, 0x11, 0x2e, 0x11, 0x94, 0x0d, 0x96, 0x08, + 0x5e, 0x03, 0x76, 0xff, 0x3c, 0xfc, 0xed, 0xfa, 0x71, 0xfb, 0xe4, 0xfc, + 0x6f, 0x00, 0x29, 0x04, 0x8d, 0x07, 0x63, 0x0b, 0x26, 0x0f, 0x6b, 0x11, + 0xb2, 0x12, 0x09, 0x12, 0xcb, 0x0f, 0x42, 0x0d, 0xd0, 0x0a, 0xd7, 0x07, + 0x8d, 0x05, 0x67, 0x03, 0xe6, 0x00, 0x9d, 0xff, 0xc3, 0xfe, 0xa1, 0xfe, + 0xa4, 0xff, 0x7b, 0x00, 0xc6, 0x00, 0x29, 0x01, 0xe6, 0x00, 0x59, 0x00, + 0x8c, 0x01, 0xa6, 0x02, 0x3d, 0x04, 0xa1, 0x05, 0x8a, 0x06, 0x67, 0x07, + 0x8d, 0x09, 0x61, 0x0b, 0x59, 0x0d, 0xac, 0x0e, 0x90, 0x0e, 0x9c, 0x0e, + 0x82, 0x0d, 0xbc, 0x0b, 0x15, 0x0a, 0xa3, 0x07, 0x89, 0x05, 0x55, 0x03, + 0x24, 0x01, 0xa3, 0xff, 0x9a, 0xfe, 0xfc, 0xfd, 0x6b, 0xfd, 0x82, 0xfd, + 0xf0, 0xfd, 0xa3, 0xfe, 0x09, 0x00, 0x9c, 0xff, 0x6d, 0xfe, 0xe9, 0xfc, + 0xdf, 0xfb, 0x8c, 0xf8, 0x51, 0xf6, 0x61, 0xf3, 0x0b, 0xf1, 0x8b, 0xf0, + 0x30, 0xee, 0x38, 0xec, 0xd7, 0xe8, 0x9e, 0xe6, 0xfa, 0xe3, 0x58, 0xe1, + 0xfd, 0xde, 0x46, 0xd9, 0x73, 0xd6, 0xe9, 0xd6, 0xee, 0xdc, 0x09, 0xe9, + 0x3e, 0xf6, 0x15, 0x01, 0x4b, 0x09, 0x6b, 0x11, 0x5a, 0x18, 0x61, 0x1e, + 0x40, 0x20, 0xa7, 0x1b, 0x4c, 0x12, 0xef, 0x07, 0xc5, 0xfc, 0x7e, 0xf4, + 0x55, 0xee, 0x7d, 0xe9, 0xd4, 0xe6, 0x56, 0xe6, 0x9f, 0xe7, 0x68, 0xeb, + 0x40, 0xf0, 0xcb, 0xf5, 0xe4, 0xfa, 0xa1, 0xfe, 0x50, 0x00, 0xfe, 0xff, + 0x25, 0x00, 0x67, 0x00, 0x0e, 0x03, 0x75, 0x05, 0x24, 0x08, 0x0c, 0x0a, + 0xa1, 0x0c, 0x19, 0x0f, 0x0f, 0x12, 0x2c, 0x14, 0xc2, 0x14, 0x74, 0x13, + 0x21, 0x10, 0xa6, 0x0b, 0x76, 0x06, 0x36, 0x02, 0xab, 0xff, 0x43, 0xfe, + 0x70, 0xfe, 0x8f, 0xfe, 0x24, 0x00, 0x73, 0x02, 0xcd, 0x05, 0xb2, 0x0a, + 0xe7, 0x0d, 0xc0, 0x0e, 0x61, 0x0e, 0xe6, 0x0c, 0x84, 0x0c, 0x59, 0x0c, + 0x38, 0x0a, 0xbb, 0x07, 0x3c, 0x05, 0x6e, 0x03, 0x39, 0x03, 0x48, 0x03, + 0xc8, 0x02, 0xb8, 0x03, 0x6c, 0x03, 0x9f, 0x03, 0x15, 0x03, 0x3e, 0x02, + 0xbb, 0x01, 0x21, 0x01, 0x98, 0x00, 0x0d, 0x00, 0xf2, 0xff, 0x6c, 0x01, + 0xd6, 0x02, 0x25, 0x05, 0x7c, 0x07, 0xd0, 0x09, 0x5a, 0x0c, 0x15, 0x0e, + 0xb3, 0x0f, 0x7f, 0x10, 0x60, 0x10, 0x42, 0x0f, 0x72, 0x0d, 0xe2, 0x0a, + 0xb3, 0x08, 0xea, 0x05, 0xef, 0x03, 0x94, 0x01, 0x1e, 0x00, 0x21, 0xff, + 0xc4, 0xfe, 0xd0, 0xfe, 0xbb, 0xfe, 0x47, 0xfe, 0x49, 0xfe, 0xac, 0xfd, + 0x54, 0xfd, 0x08, 0xfc, 0x71, 0xfa, 0x2e, 0xf8, 0xe9, 0xf5, 0x34, 0xf4, + 0xce, 0xf2, 0x79, 0xf1, 0x6a, 0xf0, 0xb0, 0xee, 0x63, 0xec, 0x58, 0xeb, + 0x27, 0xe9, 0x42, 0xe7, 0x9d, 0xe3, 0xdc, 0xde, 0x55, 0xda, 0x51, 0xd7, + 0x89, 0xd7, 0xd8, 0xdc, 0x99, 0xe5, 0x96, 0xf1, 0xbe, 0xfb, 0x22, 0x04, + 0xe5, 0x0a, 0x5b, 0x11, 0x21, 0x18, 0xbc, 0x1b, 0x70, 0x19, 0xe3, 0x11, + 0xfb, 0x06, 0x43, 0xfe, 0x95, 0xf7, 0xb2, 0xf3, 0xc6, 0xef, 0xaf, 0xec, + 0x42, 0xeb, 0x54, 0xec, 0xd0, 0xef, 0x2f, 0xf3, 0xa9, 0xf7, 0x63, 0xfb, + 0xeb, 0xfd, 0xb9, 0xfe, 0x79, 0xfe, 0x20, 0xfe, 0xc0, 0xfe, 0xf2, 0xff, + 0x97, 0x01, 0x65, 0x03, 0x85, 0x06, 0xd2, 0x09, 0x2a, 0x0d, 0xc9, 0x0f, + 0xc2, 0x11, 0x8b, 0x13, 0xbe, 0x14, 0xdd, 0x12, 0xfa, 0x0f, 0xdb, 0x0b, + 0xa2, 0x08, 0x0a, 0x07, 0x4c, 0x05, 0xae, 0x03, 0x3c, 0x02, 0x15, 0x02, + 0xaa, 0x03, 0x8b, 0x05, 0x3f, 0x07, 0x03, 0x08, 0xe4, 0x08, 0x26, 0x09, + 0xce, 0x09, 0x6d, 0x09, 0x36, 0x08, 0x87, 0x07, 0x33, 0x06, 0x9d, 0x05, + 0x4d, 0x04, 0x9e, 0x03, 0xf6, 0x02, 0x9a, 0x03, 0x63, 0x04, 0x1a, 0x05, + 0x2d, 0x05, 0x35, 0x05, 0xc2, 0x04, 0x1b, 0x04, 0x9e, 0x03, 0x0a, 0x03, + 0x42, 0x02, 0xe0, 0x01, 0x74, 0x01, 0x53, 0x01, 0x73, 0x02, 0x48, 0x04, + 0x3c, 0x06, 0x73, 0x08, 0xe5, 0x09, 0x4a, 0x0b, 0x9c, 0x0c, 0x70, 0x0d, + 0xcd, 0x0d, 0x8b, 0x0d, 0x90, 0x0c, 0xf6, 0x0a, 0xba, 0x09, 0xfb, 0x07, + 0x62, 0x06, 0x30, 0x05, 0xf9, 0x03, 0xad, 0x02, 0xb3, 0x01, 0x78, 0x00, + 0x90, 0xff, 0xe0, 0xfe, 0xa4, 0xfe, 0x6a, 0xfd, 0x43, 0xfd, 0x76, 0xfb, + 0x7c, 0xf9, 0x2a, 0xf8, 0xb3, 0xf5, 0xf5, 0xf4, 0x81, 0xf3, 0xb9, 0xf2, + 0x2a, 0xf0, 0x5c, 0xee, 0xf5, 0xec, 0x79, 0xeb, 0xcc, 0xea, 0x4f, 0xe8, + 0x0c, 0xe5, 0x4f, 0xe1, 0x44, 0xdd, 0x23, 0xdb, 0x22, 0xdc, 0x8d, 0xdf, + 0x78, 0xe6, 0x03, 0xee, 0x6a, 0xf4, 0x09, 0xfc, 0xb2, 0x02, 0x07, 0x09, + 0xfe, 0x0e, 0xf9, 0x10, 0x22, 0x10, 0xab, 0x0c, 0x66, 0x07, 0xb5, 0x00, + 0x8c, 0xfb, 0x5b, 0xf7, 0xcf, 0xf4, 0x1d, 0xf4, 0x54, 0xf3, 0xfd, 0xf2, + 0xf4, 0xf3, 0x79, 0xf6, 0xbc, 0xf9, 0xb9, 0xfc, 0x45, 0xfe, 0x39, 0xfe, + 0x90, 0xfd, 0xcc, 0xfd, 0x4b, 0xfe, 0x24, 0xfe, 0xc5, 0xfe, 0x5e, 0xff, + 0x54, 0x01, 0xe0, 0x03, 0xf4, 0x06, 0xdc, 0x09, 0xeb, 0x0c, 0x95, 0x0f, + 0xd2, 0x10, 0x76, 0x11, 0xec, 0x10, 0x23, 0x10, 0x63, 0x0e, 0x8c, 0x0c, + 0x24, 0x0a, 0x35, 0x08, 0x44, 0x07, 0x26, 0x06, 0x01, 0x06, 0xd7, 0x05, + 0x55, 0x06, 0x4f, 0x07, 0x15, 0x08, 0x61, 0x08, 0xbe, 0x08, 0x4c, 0x08, + 0xd4, 0x07, 0xa3, 0x06, 0x29, 0x05, 0x18, 0x04, 0xfb, 0x02, 0x41, 0x02, + 0x3f, 0x01, 0x30, 0x01, 0x35, 0x01, 0x0c, 0x02, 0xdd, 0x02, 0x4c, 0x03, + 0x94, 0x04, 0x3b, 0x05, 0x8d, 0x05, 0x62, 0x05, 0x43, 0x04, 0xf7, 0x03, + 0xb7, 0x03, 0xda, 0x03, 0x77, 0x03, 0xa6, 0x03, 0x34, 0x04, 0xe8, 0x04, + 0x4f, 0x06, 0x3d, 0x07, 0xc7, 0x08, 0x14, 0x0a, 0xf2, 0x0a, 0x35, 0x0b, + 0xf6, 0x0a, 0xae, 0x0a, 0x48, 0x0a, 0x50, 0x09, 0xec, 0x07, 0x55, 0x06, + 0x08, 0x05, 0x30, 0x04, 0xdf, 0x03, 0xfa, 0x02, 0x2e, 0x02, 0x38, 0x01, + 0x29, 0x00, 0xb2, 0xff, 0x10, 0xff, 0x7b, 0xfe, 0x93, 0xfd, 0x55, 0xfc, + 0x24, 0xfb, 0x75, 0xf9, 0x0a, 0xf8, 0x73, 0xf6, 0x08, 0xf5, 0x8b, 0xf3, + 0x93, 0xf1, 0xe1, 0xef, 0x4d, 0xee, 0xc0, 0xed, 0x70, 0xed, 0x02, 0xed, + 0xff, 0xeb, 0x30, 0xeb, 0x2b, 0xea, 0xec, 0xe8, 0x9f, 0xe8, 0x3b, 0xe9, + 0x36, 0xeb, 0x22, 0xee, 0xf1, 0xf0, 0x1e, 0xf4, 0x5b, 0xf7, 0xbb, 0xfa, + 0xae, 0xfd, 0x81, 0xff, 0xa4, 0x00, 0x59, 0x00, 0x86, 0xff, 0x84, 0xfd, + 0xcd, 0xfa, 0xa2, 0xf8, 0x35, 0xf7, 0x7c, 0xf7, 0xdc, 0xf7, 0x6a, 0xf8, + 0xc5, 0xf8, 0xe7, 0xf9, 0x4f, 0xfc, 0xb5, 0xfe, 0xd7, 0x00, 0xd8, 0x01, + 0x93, 0x01, 0x2e, 0x01, 0xac, 0x00, 0x76, 0x00, 0x46, 0x00, 0x31, 0x00, + 0x99, 0x00, 0x11, 0x01, 0xdd, 0x01, 0x0b, 0x03, 0x78, 0x04, 0x4a, 0x06, + 0xce, 0x07, 0xcd, 0x08, 0x1c, 0x09, 0xe6, 0x08, 0x3c, 0x08, 0xd4, 0x07, + 0x98, 0x07, 0x4e, 0x07, 0xad, 0x06, 0xf8, 0x05, 0x89, 0x05, 0xa4, 0x05, + 0xf2, 0x05, 0x3d, 0x06, 0x5d, 0x06, 0x72, 0x06, 0xcf, 0x06, 0xbc, 0x06, + 0x85, 0x06, 0x58, 0x06, 0xfa, 0x05, 0x93, 0x05, 0x0b, 0x05, 0x72, 0x04, + 0x00, 0x04, 0xca, 0x03, 0x92, 0x03, 0xdf, 0x03, 0x81, 0x04, 0xf5, 0x04, + 0x87, 0x05, 0xc8, 0x05, 0x1e, 0x06, 0x92, 0x06, 0xbb, 0x06, 0xa2, 0x06, + 0x51, 0x06, 0x5e, 0x06, 0x5c, 0x06, 0x18, 0x06, 0x23, 0x06, 0x3a, 0x06, + 0xac, 0x06, 0x3e, 0x07, 0x7e, 0x07, 0xd4, 0x07, 0x21, 0x08, 0xb9, 0x08, + 0x09, 0x09, 0xef, 0x08, 0x95, 0x08, 0x1d, 0x08, 0xe5, 0x07, 0x63, 0x07, + 0xc9, 0x06, 0x54, 0x06, 0x12, 0x06, 0x1b, 0x06, 0x09, 0x06, 0xbf, 0x05, + 0x7e, 0x05, 0x67, 0x05, 0x57, 0x05, 0xe3, 0x04, 0x30, 0x04, 0x63, 0x03, + 0xb2, 0x02, 0x07, 0x02, 0x08, 0x01, 0xc7, 0xff, 0x9a, 0xfe, 0x5d, 0xfd, + 0x65, 0xfc, 0x4b, 0xfb, 0x34, 0xfa, 0x50, 0xf9, 0x6a, 0xf8, 0x7c, 0xf7, + 0x74, 0xf6, 0x53, 0xf5, 0x47, 0xf4, 0x1f, 0xf3, 0xca, 0xf1, 0x90, 0xf0, + 0x83, 0xef, 0x07, 0xef, 0xf8, 0xee, 0x34, 0xef, 0xac, 0xef, 0x29, 0xf0, + 0xc6, 0xf0, 0xc1, 0xf0, 0xea, 0xef, 0x96, 0xee, 0x6f, 0xed, 0xcb, 0xec, + 0xac, 0xec, 0x8f, 0xec, 0x41, 0xec, 0x75, 0xec, 0xc1, 0xed, 0xad, 0xef, + 0x69, 0xf1, 0x72, 0xf2, 0x55, 0xf3, 0x9c, 0xf4, 0x06, 0xf6, 0xa3, 0xf6, + 0x80, 0xf6, 0x6f, 0xf6, 0x41, 0xf7, 0xac, 0xf8, 0xb3, 0xf9, 0x3e, 0xfa, + 0x0f, 0xfb, 0xd5, 0xfc, 0x4a, 0xff, 0x59, 0x01, 0xa4, 0x02, 0xb7, 0x03, + 0xd7, 0x04, 0xfa, 0x05, 0x6f, 0x06, 0x5c, 0x06, 0x18, 0x06, 0xb1, 0x05, + 0xad, 0x05, 0xd3, 0x05, 0x06, 0x06, 0x9f, 0x06, 0x6c, 0x07, 0x65, 0x08, + 0x39, 0x09, 0xe6, 0x09, 0x6b, 0x0a, 0xab, 0x0a, 0xce, 0x0a, 0xc3, 0x0a, + 0x76, 0x0a, 0x37, 0x0a, 0x15, 0x0a, 0xe7, 0x09, 0xbf, 0x09, 0xa2, 0x09, + 0xe0, 0x09, 0x73, 0x0a, 0xf5, 0x0a, 0x60, 0x0b, 0x9f, 0x0b, 0x54, 0x0c, + 0x2f, 0x0d, 0xb5, 0x0d, 0xc8, 0x0d, 0x7d, 0x0d, 0x8d, 0x0d, 0xba, 0x0d, + 0xc3, 0x0d, 0x92, 0x0d, 0x41, 0x0d, 0x46, 0x0d, 0x62, 0x0d, 0x7c, 0x0d, + 0x60, 0x0d, 0x2e, 0x0d, 0x38, 0x0d, 0x2d, 0x0d, 0x02, 0x0d, 0xa4, 0x0c, + 0x1c, 0x0c, 0xbc, 0x0b, 0x72, 0x0b, 0x3e, 0x0b, 0xe0, 0x0a, 0x46, 0x0a, + 0xb4, 0x09, 0x19, 0x09, 0xb5, 0x08, 0x37, 0x08, 0x5d, 0x07, 0x7b, 0x06, + 0xb5, 0x05, 0x1e, 0x05, 0x72, 0x04, 0x8f, 0x03, 0x71, 0x02, 0x61, 0x01, + 0x6f, 0x00, 0x40, 0xff, 0xaf, 0xfd, 0x0d, 0xfc, 0x90, 0xfa, 0x3d, 0xf9, + 0xe7, 0xf7, 0x4b, 0xf6, 0xc3, 0xf4, 0x72, 0xf3, 0x56, 0xf2, 0x4d, 0xf1, + 0x16, 0xf0, 0xf2, 0xee, 0xa2, 0xed, 0x79, 0xec, 0x34, 0xeb, 0xa4, 0xe9, + 0x68, 0xe8, 0xa8, 0xe7, 0xc0, 0xe7, 0x24, 0xe8, 0x49, 0xe8, 0x43, 0xe8, + 0x2d, 0xe8, 0x9b, 0xe8, 0xd0, 0xe8, 0x4e, 0xe8, 0x86, 0xe7, 0x22, 0xe7, + 0xce, 0xe7, 0x8f, 0xe8, 0xfc, 0xe8, 0x98, 0xe9, 0x01, 0xeb, 0xbf, 0xed, + 0x0a, 0xf0, 0xe9, 0xf0, 0x52, 0xf1, 0x5f, 0xf2, 0x3f, 0xf4, 0x99, 0xf5, + 0xef, 0xf5, 0x12, 0xf6, 0x59, 0xf7, 0xf5, 0xf9, 0x29, 0xfc, 0x7d, 0xfd, + 0xec, 0xfe, 0x24, 0x01, 0x03, 0x04, 0x69, 0x06, 0xb9, 0x07, 0x6a, 0x08, + 0x4d, 0x09, 0x6f, 0x0a, 0x31, 0x0b, 0x1e, 0x0b, 0xbd, 0x0a, 0xd5, 0x0a, + 0x6d, 0x0b, 0x41, 0x0c, 0xd8, 0x0c, 0x77, 0x0d, 0x66, 0x0e, 0xa0, 0x0f, + 0xef, 0x10, 0xac, 0x11, 0xdd, 0x11, 0xb0, 0x11, 0x63, 0x11, 0x42, 0x11, + 0xba, 0x10, 0xcc, 0x0f, 0xd8, 0x0e, 0x26, 0x0e, 0xff, 0x0d, 0xd5, 0x0d, + 0x78, 0x0d, 0x2a, 0x0d, 0x45, 0x0d, 0xf1, 0x0d, 0x99, 0x0e, 0xbd, 0x0e, + 0x7c, 0x0e, 0x3f, 0x0e, 0x52, 0x0e, 0x1e, 0x0e, 0x5a, 0x0d, 0x4c, 0x0c, + 0x6a, 0x0b, 0x25, 0x0b, 0x05, 0x0b, 0x7f, 0x0a, 0xfb, 0x09, 0xd7, 0x09, + 0x2c, 0x0a, 0x7e, 0x0a, 0x55, 0x0a, 0xd1, 0x09, 0x78, 0x09, 0x6e, 0x09, + 0x28, 0x09, 0x5c, 0x08, 0x71, 0x07, 0xb8, 0x06, 0x61, 0x06, 0x02, 0x06, + 0x42, 0x05, 0x7e, 0x04, 0x0f, 0x04, 0xf4, 0x03, 0xcf, 0x03, 0x43, 0x03, + 0x96, 0x02, 0x0d, 0x02, 0xb6, 0x01, 0x27, 0x01, 0x0c, 0x00, 0xd7, 0xfe, + 0xab, 0xfd, 0xb7, 0xfc, 0xa8, 0xfb, 0x2e, 0xfa, 0xbe, 0xf8, 0x7c, 0xf7, + 0x8e, 0xf6, 0xa9, 0xf5, 0x5f, 0xf4, 0x01, 0xf3, 0xab, 0xf1, 0xc5, 0xf0, + 0xd1, 0xef, 0x8d, 0xee, 0x0f, 0xed, 0xa2, 0xeb, 0x67, 0xea, 0x34, 0xe9, + 0xff, 0xe7, 0x51, 0xe7, 0x76, 0xe7, 0x1d, 0xe8, 0x61, 0xe8, 0x33, 0xe8, + 0x56, 0xe8, 0xb2, 0xe8, 0xe5, 0xe8, 0x5c, 0xe8, 0x87, 0xe7, 0x8d, 0xe7, + 0x8f, 0xe8, 0x49, 0xe9, 0x85, 0xe9, 0x1e, 0xea, 0xe1, 0xeb, 0x7d, 0xee, + 0x8e, 0xf0, 0x6d, 0xf1, 0x0d, 0xf2, 0x90, 0xf3, 0xa7, 0xf5, 0xf1, 0xf6, + 0x5d, 0xf7, 0xee, 0xf7, 0x9f, 0xf9, 0x14, 0xfc, 0x13, 0xfe, 0x62, 0xff, + 0xfd, 0x00, 0x81, 0x03, 0x8c, 0x06, 0xe3, 0x08, 0x17, 0x0a, 0xe9, 0x0a, + 0xf7, 0x0b, 0x29, 0x0d, 0x8a, 0x0d, 0x19, 0x0d, 0xae, 0x0c, 0xdf, 0x0c, + 0xaa, 0x0d, 0x5e, 0x0e, 0xbf, 0x0e, 0x5b, 0x0f, 0x62, 0x10, 0xcd, 0x11, + 0xba, 0x12, 0xd8, 0x12, 0x92, 0x12, 0x38, 0x12, 0x28, 0x12, 0xb3, 0x11, + 0xc5, 0x10, 0xdd, 0x0f, 0x17, 0x0f, 0xd6, 0x0e, 0x9a, 0x0e, 0x3f, 0x0e, + 0xe9, 0x0d, 0xbc, 0x0d, 0xf1, 0x0d, 0x02, 0x0e, 0xe9, 0x0d, 0x92, 0x0d, + 0x0a, 0x0d, 0xce, 0x0c, 0x6a, 0x0c, 0xd7, 0x0b, 0x1c, 0x0b, 0x59, 0x0a, + 0xbf, 0x09, 0x5b, 0x09, 0x23, 0x09, 0xeb, 0x08, 0xb4, 0x08, 0x97, 0x08, + 0x80, 0x08, 0x5d, 0x08, 0x1d, 0x08, 0xb9, 0x07, 0x55, 0x07, 0xe4, 0x06, + 0x5f, 0x06, 0xe6, 0x05, 0x69, 0x05, 0xed, 0x04, 0x79, 0x04, 0x0a, 0x04, + 0xac, 0x03, 0x64, 0x03, 0x01, 0x03, 0x82, 0x02, 0xf6, 0x01, 0x89, 0x01, + 0x34, 0x01, 0xc8, 0x00, 0x36, 0x00, 0x81, 0xff, 0xe4, 0xfe, 0x57, 0xfe, + 0x99, 0xfd, 0xab, 0xfc, 0xb0, 0xfb, 0xd9, 0xfa, 0x07, 0xfa, 0x1f, 0xf9, + 0x01, 0xf8, 0xe1, 0xf6, 0xdf, 0xf5, 0xdd, 0xf4, 0xcf, 0xf3, 0xc2, 0xf2, + 0xb0, 0xf1, 0xa1, 0xf0, 0x9d, 0xef, 0xaf, 0xee, 0xa5, 0xed, 0x7d, 0xec, + 0x24, 0xeb, 0xd3, 0xe9, 0x46, 0xe9, 0x76, 0xe9, 0x16, 0xea, 0x0c, 0xea, + 0xb7, 0xe9, 0x01, 0xea, 0x7d, 0xea, 0xbc, 0xea, 0x04, 0xea, 0xf5, 0xe8, + 0xfb, 0xe8, 0x2b, 0xea, 0x4a, 0xeb, 0x2d, 0xeb, 0x3e, 0xeb, 0xda, 0xec, + 0x97, 0xef, 0xe5, 0xf1, 0x73, 0xf2, 0x6f, 0xf2, 0x95, 0xf3, 0xca, 0xf5, + 0x4c, 0xf7, 0x59, 0xf7, 0xa2, 0xf7, 0x94, 0xf9, 0x97, 0xfc, 0xcb, 0xfe, + 0xc7, 0xff, 0xd1, 0x00, 0x29, 0x03, 0x33, 0x06, 0x55, 0x08, 0x3e, 0x09, + 0xd2, 0x09, 0xe0, 0x0a, 0xf7, 0x0b, 0x7e, 0x0c, 0x5f, 0x0c, 0x08, 0x0c, + 0x14, 0x0c, 0xc4, 0x0c, 0x9c, 0x0d, 0x05, 0x0e, 0x24, 0x0e, 0xac, 0x0e, + 0xd6, 0x0f, 0xef, 0x10, 0x31, 0x11, 0xb4, 0x10, 0x2c, 0x10, 0x1a, 0x10, + 0x15, 0x10, 0x89, 0x0f, 0x85, 0x0e, 0xce, 0x0d, 0xc5, 0x0d, 0xda, 0x0d, + 0x80, 0x0d, 0xdf, 0x0c, 0x81, 0x0c, 0xc0, 0x0c, 0x0a, 0x0d, 0xe2, 0x0c, + 0x7a, 0x0c, 0x1d, 0x0c, 0x04, 0x0c, 0xe3, 0x0b, 0x77, 0x0b, 0xd7, 0x0a, + 0x43, 0x0a, 0xec, 0x09, 0x9a, 0x09, 0x49, 0x09, 0x05, 0x09, 0xea, 0x08, + 0xed, 0x08, 0xe4, 0x08, 0xce, 0x08, 0xa1, 0x08, 0x66, 0x08, 0x1f, 0x08, + 0xcc, 0x07, 0x69, 0x07, 0xf5, 0x06, 0x84, 0x06, 0x0f, 0x06, 0x9a, 0x05, + 0x32, 0x05, 0xd7, 0x04, 0x78, 0x04, 0xf7, 0x03, 0x70, 0x03, 0xf4, 0x02, + 0x87, 0x02, 0x23, 0x02, 0x9f, 0x01, 0x1e, 0x01, 0x94, 0x00, 0x00, 0x00, + 0x4e, 0xff, 0x69, 0xfe, 0x7c, 0xfd, 0x98, 0xfc, 0xbf, 0xfb, 0xc3, 0xfa, + 0x95, 0xf9, 0x80, 0xf8, 0x79, 0xf7, 0x98, 0xf6, 0x9f, 0xf5, 0x79, 0xf4, + 0x65, 0xf3, 0x71, 0xf2, 0x80, 0xf1, 0x75, 0xf0, 0x57, 0xef, 0x36, 0xee, + 0x0e, 0xed, 0xea, 0xeb, 0x9a, 0xea, 0x7e, 0xe9, 0x1c, 0xe9, 0x57, 0xe9, + 0xcf, 0xe9, 0xfb, 0xe9, 0xea, 0xe9, 0x22, 0xea, 0x7c, 0xea, 0x64, 0xea, + 0xb4, 0xe9, 0xfb, 0xe8, 0x1e, 0xe9, 0x0b, 0xea, 0xcd, 0xea, 0xed, 0xea, + 0x75, 0xeb, 0x60, 0xed, 0xec, 0xef, 0xc2, 0xf1, 0x6b, 0xf2, 0xd6, 0xf2, + 0x45, 0xf4, 0x34, 0xf6, 0x42, 0xf7, 0x77, 0xf7, 0x24, 0xf8, 0x3a, 0xfa, + 0xcf, 0xfc, 0x85, 0xfe, 0xad, 0xff, 0x5a, 0x01, 0xdb, 0x03, 0x75, 0x06, + 0x4e, 0x08, 0x78, 0x09, 0x8d, 0x0a, 0xa6, 0x0b, 0x54, 0x0c, 0x6e, 0x0c, + 0x5f, 0x0c, 0x58, 0x0c, 0x6a, 0x0c, 0x9f, 0x0c, 0x16, 0x0d, 0xc5, 0x0d, + 0x8a, 0x0e, 0x3b, 0x0f, 0xef, 0x0f, 0xc0, 0x10, 0x38, 0x11, 0x24, 0x11, + 0x9a, 0x10, 0xfc, 0x0f, 0x9a, 0x0f, 0x27, 0x0f, 0x80, 0x0e, 0xc8, 0x0d, + 0x5c, 0x0d, 0x3a, 0x0d, 0x0a, 0x0d, 0xce, 0x0c, 0xa1, 0x0c, 0x9c, 0x0c, + 0xa0, 0x0c, 0x94, 0x0c, 0x77, 0x0c, 0x3d, 0x0c, 0x09, 0x0c, 0xb1, 0x0b, + 0x33, 0x0b, 0xaa, 0x0a, 0x2c, 0x0a, 0xa6, 0x09, 0x13, 0x09, 0xbd, 0x08, + 0xa5, 0x08, 0xbc, 0x08, 0xc5, 0x08, 0x86, 0x08, 0x50, 0x08, 0x44, 0x08, + 0x3a, 0x08, 0xe9, 0x07, 0x54, 0x07, 0xc9, 0x06, 0x68, 0x06, 0x1e, 0x06, + 0xa9, 0x05, 0x0d, 0x05, 0x97, 0x04, 0x51, 0x04, 0x10, 0x04, 0x94, 0x03, + 0xf0, 0x02, 0x6a, 0x02, 0x15, 0x02, 0xbf, 0x01, 0x41, 0x01, 0xaf, 0x00, + 0x17, 0x00, 0x8b, 0xff, 0xe3, 0xfe, 0x09, 0xfe, 0x24, 0xfd, 0x41, 0xfc, + 0x65, 0xfb, 0x7c, 0xfa, 0x7e, 0xf9, 0x86, 0xf8, 0x84, 0xf7, 0x7e, 0xf6, + 0x86, 0xf5, 0x8e, 0xf4, 0xa2, 0xf3, 0xaa, 0xf2, 0xb4, 0xf1, 0xc9, 0xf0, + 0xfd, 0xef, 0x1c, 0xef, 0x0a, 0xee, 0xd2, 0xec, 0xaf, 0xeb, 0xac, 0xea, + 0xe4, 0xe9, 0xb4, 0xe9, 0xed, 0xe9, 0x71, 0xea, 0xad, 0xea, 0xaa, 0xea, + 0xdd, 0xea, 0x20, 0xeb, 0x1f, 0xeb, 0xa4, 0xea, 0x31, 0xea, 0x98, 0xea, + 0x8b, 0xeb, 0x5a, 0xec, 0x9f, 0xec, 0x31, 0xed, 0x1b, 0xef, 0x7f, 0xf1, + 0x0f, 0xf3, 0x95, 0xf3, 0x2e, 0xf4, 0xe9, 0xf5, 0xf0, 0xf7, 0xef, 0xf8, + 0x32, 0xf9, 0x28, 0xfa, 0x71, 0xfc, 0xec, 0xfe, 0x62, 0x00, 0x43, 0x01, + 0xdc, 0x02, 0x6a, 0x05, 0xd7, 0x07, 0x4c, 0x09, 0x0f, 0x0a, 0xf1, 0x0a, + 0x0e, 0x0c, 0xe6, 0x0c, 0xef, 0x0c, 0x9c, 0x0c, 0x8c, 0x0c, 0xdc, 0x0c, + 0x61, 0x0d, 0xc2, 0x0d, 0x11, 0x0e, 0x9b, 0x0e, 0x51, 0x0f, 0x07, 0x10, + 0x57, 0x10, 0x44, 0x10, 0xfe, 0x0f, 0xa8, 0x0f, 0x58, 0x0f, 0xe6, 0x0e, + 0x35, 0x0e, 0x8c, 0x0d, 0x0d, 0x0d, 0xe4, 0x0c, 0xbc, 0x0c, 0x55, 0x0c, + 0xf3, 0x0b, 0xcc, 0x0b, 0xde, 0x0b, 0xf8, 0x0b, 0xd3, 0x0b, 0x84, 0x0b, + 0x52, 0x0b, 0x3b, 0x0b, 0x0c, 0x0b, 0x7d, 0x0a, 0xc1, 0x09, 0x40, 0x09, + 0xfe, 0x08, 0xd6, 0x08, 0x8b, 0x08, 0x44, 0x08, 0x24, 0x08, 0x32, 0x08, + 0x43, 0x08, 0xff, 0x07, 0xac, 0x07, 0x8b, 0x07, 0x67, 0x07, 0x24, 0x07, + 0xa7, 0x06, 0x21, 0x06, 0xc2, 0x05, 0x7c, 0x05, 0x2b, 0x05, 0xa4, 0x04, + 0x1a, 0x04, 0xab, 0x03, 0x44, 0x03, 0xd3, 0x02, 0x4e, 0x02, 0xd3, 0x01, + 0x7f, 0x01, 0x23, 0x01, 0xb2, 0x00, 0x02, 0x00, 0x57, 0xff, 0xaf, 0xfe, + 0xf6, 0xfd, 0x23, 0xfd, 0x1c, 0xfc, 0x16, 0xfb, 0x25, 0xfa, 0x40, 0xf9, + 0x3b, 0xf8, 0x0f, 0xf7, 0x1a, 0xf6, 0x40, 0xf5, 0x99, 0xf4, 0xda, 0xf3, + 0xc5, 0xf2, 0xd8, 0xf1, 0x10, 0xf1, 0x65, 0xf0, 0x9d, 0xef, 0x44, 0xee, + 0xcf, 0xec, 0x9f, 0xeb, 0x92, 0xea, 0xdc, 0xe9, 0x73, 0xe9, 0xd1, 0xe9, + 0x9a, 0xea, 0x4c, 0xeb, 0xae, 0xeb, 0xae, 0xeb, 0x1d, 0xec, 0x38, 0xec, + 0xb6, 0xeb, 0x33, 0xeb, 0x1e, 0xeb, 0xcd, 0xeb, 0x9d, 0xec, 0xec, 0xec, + 0x7f, 0xed, 0x25, 0xef, 0x98, 0xf1, 0x52, 0xf3, 0x11, 0xf4, 0xe9, 0xf4, + 0x65, 0xf6, 0x51, 0xf8, 0x91, 0xf9, 0xee, 0xf9, 0xd1, 0xfa, 0xb5, 0xfc, + 0xc8, 0xfe, 0x2a, 0x00, 0x38, 0x01, 0xd0, 0x02, 0xf6, 0x04, 0x5f, 0x07, + 0x23, 0x09, 0x4b, 0x0a, 0x6b, 0x0b, 0x5e, 0x0c, 0x2e, 0x0d, 0xbb, 0x0d, + 0xb3, 0x0d, 0x68, 0x0d, 0x41, 0x0d, 0x8e, 0x0d, 0x01, 0x0e, 0x52, 0x0e, + 0x85, 0x0e, 0xb0, 0x0e, 0x33, 0x0f, 0xea, 0x0f, 0x1c, 0x10, 0xb3, 0x0f, + 0x35, 0x0f, 0x09, 0x0f, 0x12, 0x0f, 0xda, 0x0e, 0x07, 0x0e, 0x36, 0x0d, + 0xdb, 0x0c, 0xbd, 0x0c, 0x4b, 0x0c, 0x9d, 0x0b, 0x0d, 0x0b, 0xfc, 0x0a, + 0x86, 0x0b, 0xc4, 0x0b, 0x93, 0x0b, 0x3d, 0x0b, 0x0d, 0x0b, 0x32, 0x0b, + 0x1e, 0x0b, 0x7b, 0x0a, 0x8a, 0x09, 0xdd, 0x08, 0xac, 0x08, 0x8c, 0x08, + 0x4e, 0x08, 0xf6, 0x07, 0xc5, 0x07, 0xfa, 0x07, 0x10, 0x08, 0xde, 0x07, + 0x7e, 0x07, 0x1b, 0x07, 0xfa, 0x06, 0xd6, 0x06, 0x62, 0x06, 0xc9, 0x05, + 0x38, 0x05, 0xc6, 0x04, 0x64, 0x04, 0xdf, 0x03, 0x50, 0x03, 0xc1, 0x02, + 0x54, 0x02, 0x00, 0x02, 0x8f, 0x01, 0x1a, 0x01, 0xad, 0x00, 0x3d, 0x00, + 0xcd, 0xff, 0x25, 0xff, 0x82, 0xfe, 0xd4, 0xfd, 0x0f, 0xfd, 0x45, 0xfc, + 0x5e, 0xfb, 0x5b, 0xfa, 0x5a, 0xf9, 0x4c, 0xf8, 0x5b, 0xf7, 0x3a, 0xf6, + 0x13, 0xf5, 0xfa, 0xf3, 0xf7, 0xf2, 0x49, 0xf2, 0x8c, 0xf1, 0xef, 0xf0, + 0x38, 0xf0, 0x77, 0xef, 0xc9, 0xee, 0xc9, 0xed, 0xd1, 0xec, 0x6e, 0xeb, + 0x4e, 0xea, 0xbc, 0xe9, 0xcb, 0xe9, 0x5f, 0xea, 0xaf, 0xea, 0x01, 0xeb, + 0x69, 0xeb, 0x1a, 0xec, 0xda, 0xec, 0xc2, 0xec, 0x53, 0xec, 0x5b, 0xec, + 0xdf, 0xec, 0xa6, 0xed, 0xcd, 0xed, 0xef, 0xed, 0xe1, 0xee, 0xc3, 0xf0, + 0xd0, 0xf2, 0x18, 0xf4, 0x21, 0xf5, 0xa0, 0xf6, 0x56, 0xf8, 0xd5, 0xf9, + 0xe1, 0xfa, 0x0b, 0xfc, 0xd2, 0xfd, 0xd0, 0xff, 0x49, 0x01, 0x65, 0x02, + 0x8c, 0x03, 0x41, 0x05, 0x11, 0x07, 0xb4, 0x08, 0x18, 0x0a, 0x4c, 0x0b, + 0x5c, 0x0c, 0x0d, 0x0d, 0xab, 0x0d, 0xf7, 0x0d, 0x53, 0x0e, 0xb3, 0x0e, + 0xf3, 0x0e, 0x35, 0x0f, 0x83, 0x0f, 0xdf, 0x0f, 0x28, 0x10, 0x6f, 0x10, + 0x9e, 0x10, 0x98, 0x10, 0x63, 0x10, 0xe9, 0x0f, 0x7f, 0x0f, 0x23, 0x0f, + 0x86, 0x0e, 0x1a, 0x0e, 0xb6, 0x0d, 0xb7, 0x0d, 0x89, 0x0d, 0xf0, 0x0c, + 0x46, 0x0c, 0xa5, 0x0b, 0x73, 0x0b, 0x05, 0x0b, 0x87, 0x0a, 0x2d, 0x0a, + 0x27, 0x0a, 0x3e, 0x0a, 0xfe, 0x09, 0x7d, 0x09, 0xfe, 0x08, 0xc5, 0x08, + 0x3c, 0x08, 0x82, 0x07, 0xe5, 0x06, 0x9e, 0x06, 0x77, 0x06, 0x19, 0x06, + 0x9b, 0x05, 0x5f, 0x05, 0x66, 0x05, 0x5b, 0x05, 0x13, 0x05, 0xc1, 0x04, + 0x73, 0x04, 0x45, 0x04, 0x0b, 0x04, 0xa6, 0x03, 0x73, 0x03, 0x25, 0x03, + 0xba, 0x02, 0x35, 0x02, 0x73, 0x01, 0xc7, 0x00, 0x50, 0x00, 0xdd, 0xff, + 0x74, 0xff, 0x04, 0xff, 0xfc, 0xfe, 0x9f, 0xfe, 0x20, 0xfe, 0x5f, 0xfd, + 0x66, 0xfc, 0x5b, 0xfb, 0x2c, 0xfa, 0xc5, 0xf8, 0x2a, 0xf7, 0xd1, 0xf5, + 0xd0, 0xf4, 0x86, 0xf3, 0x2c, 0xf3, 0x2a, 0xf2, 0x4f, 0xf1, 0x2a, 0xf0, + 0x5c, 0xef, 0xf5, 0xee, 0x3e, 0xee, 0x05, 0xed, 0x10, 0xeb, 0x01, 0xe9, + 0x0d, 0xe7, 0xf0, 0xe5, 0x1a, 0xe4, 0x9f, 0xe2, 0xee, 0xe1, 0x12, 0xe3, + 0x72, 0xe6, 0xbe, 0xea, 0xf6, 0xed, 0xf0, 0xf0, 0xfa, 0xf2, 0x3e, 0xf5, + 0x75, 0xf8, 0xc0, 0xf9, 0xe4, 0xf9, 0x32, 0xf9, 0xfd, 0xf6, 0x4f, 0xf7, + 0x21, 0xf7, 0x91, 0xf8, 0x28, 0xfa, 0x63, 0xfb, 0x5c, 0xfe, 0xd6, 0x00, + 0x56, 0x03, 0xae, 0x05, 0x30, 0x07, 0x5a, 0x08, 0xa6, 0x09, 0x94, 0x09, + 0x2e, 0x09, 0xa4, 0x07, 0x8c, 0x06, 0xc6, 0x05, 0x6a, 0x05, 0xea, 0x05, + 0xf4, 0x06, 0x18, 0x08, 0x92, 0x09, 0x3b, 0x0b, 0x3d, 0x0c, 0x24, 0x0e, + 0xf9, 0x0e, 0x01, 0x10, 0x44, 0x10, 0x44, 0x0f, 0xab, 0x0d, 0xa4, 0x0c, + 0x34, 0x0c, 0x59, 0x0c, 0xa3, 0x0c, 0x4b, 0x0c, 0x74, 0x0c, 0xed, 0x0b, + 0x60, 0x0c, 0x05, 0x0d, 0xbc, 0x0c, 0x58, 0x0d, 0xc8, 0x0c, 0xe9, 0x0b, + 0x13, 0x0b, 0x4e, 0x09, 0xf5, 0x07, 0xe8, 0x06, 0xcd, 0x05, 0x28, 0x05, + 0xcf, 0x03, 0x63, 0x04, 0x16, 0x04, 0x17, 0x04, 0x6c, 0x05, 0x9c, 0x04, + 0x26, 0x05, 0xdf, 0x03, 0x22, 0x03, 0xe9, 0x01, 0x52, 0x01, 0x0e, 0x00, + 0xcd, 0xfe, 0x08, 0xfe, 0xab, 0xfd, 0x26, 0xfe, 0x34, 0xfe, 0xa5, 0xfe, + 0x30, 0xff, 0xc5, 0x00, 0xc1, 0x01, 0xe3, 0x02, 0xf6, 0x02, 0x13, 0x03, + 0x76, 0x03, 0x60, 0x03, 0x6a, 0x03, 0xf0, 0x02, 0x72, 0x02, 0x7f, 0x02, + 0x4b, 0x02, 0x4b, 0x02, 0xab, 0x02, 0xe3, 0x02, 0x7c, 0x03, 0x35, 0x03, + 0xaf, 0x02, 0xc3, 0x01, 0xf0, 0x00, 0x22, 0x00, 0x20, 0xff, 0xfa, 0xfd, + 0x97, 0xfc, 0xc9, 0xfb, 0xbc, 0xfa, 0x90, 0xfa, 0x11, 0xfa, 0x8b, 0xf9, + 0xd8, 0xf8, 0xc9, 0xf7, 0x72, 0xf6, 0x41, 0xf4, 0x6d, 0xf2, 0xbd, 0xf0, + 0x26, 0xef, 0x20, 0xee, 0xe8, 0xeb, 0x92, 0xea, 0x5e, 0xe8, 0x2b, 0xe7, + 0x4e, 0xe6, 0x3e, 0xe5, 0x75, 0xe4, 0xc6, 0xe2, 0xd3, 0xe1, 0x5c, 0xe1, + 0x7c, 0xe3, 0x15, 0xe7, 0x20, 0xee, 0xd5, 0xf3, 0xbe, 0xf9, 0xe9, 0xfc, + 0x7d, 0xff, 0xc1, 0x01, 0x6c, 0x04, 0x57, 0x07, 0xa7, 0x07, 0x23, 0x07, + 0xff, 0x03, 0xc4, 0x00, 0x9f, 0x00, 0x40, 0x01, 0xba, 0x02, 0x96, 0x03, + 0x36, 0x04, 0x84, 0x03, 0x7f, 0x04, 0x75, 0x05, 0x4e, 0x05, 0xaf, 0x06, + 0xe5, 0x04, 0x0e, 0x05, 0x28, 0x02, 0xd9, 0x00, 0x3e, 0x00, 0xa9, 0xff, + 0x04, 0x01, 0x7d, 0x01, 0x5d, 0x02, 0xcf, 0x03, 0x0c, 0x06, 0x07, 0x09, + 0x67, 0x0b, 0x8c, 0x0c, 0x61, 0x0d, 0x95, 0x0d, 0x8e, 0x0e, 0xbe, 0x0f, + 0x92, 0x0f, 0xa0, 0x0e, 0xcf, 0x0c, 0xc0, 0x0b, 0xf6, 0x0b, 0x55, 0x0d, + 0x09, 0x0d, 0x9f, 0x0c, 0x5f, 0x0b, 0xcf, 0x0a, 0x14, 0x0a, 0x86, 0x09, + 0xc2, 0x09, 0x09, 0x09, 0xd3, 0x08, 0xfa, 0x06, 0x3a, 0x05, 0x67, 0x03, + 0x9c, 0x02, 0xc9, 0x03, 0x38, 0x04, 0x56, 0x03, 0x80, 0x02, 0x75, 0x00, + 0xb5, 0x00, 0xd5, 0x00, 0x63, 0x02, 0x5d, 0x02, 0x5e, 0x02, 0xb3, 0x01, + 0x69, 0x01, 0x50, 0x02, 0x4f, 0x03, 0x3e, 0x04, 0x06, 0x05, 0x88, 0x05, + 0x09, 0x06, 0xd1, 0x06, 0xe5, 0x06, 0x4e, 0x07, 0x6c, 0x07, 0x73, 0x07, + 0x80, 0x07, 0x2e, 0x07, 0x22, 0x06, 0x99, 0x05, 0x56, 0x04, 0x4c, 0x03, + 0xc0, 0x02, 0x8e, 0x02, 0xe5, 0x01, 0x06, 0x01, 0x76, 0xff, 0x4a, 0xfe, + 0x8c, 0xfd, 0xab, 0xfd, 0xff, 0xfd, 0x65, 0xfd, 0x97, 0xfc, 0xb6, 0xfa, + 0xeb, 0xf9, 0x86, 0xf9, 0x5e, 0xf8, 0xb0, 0xf7, 0x53, 0xf6, 0x3a, 0xf4, + 0x44, 0xf3, 0x1a, 0xf1, 0xbb, 0xee, 0x3e, 0xee, 0x1e, 0xeb, 0x2d, 0xec, + 0xa4, 0xea, 0x0c, 0xea, 0xfe, 0xeb, 0x44, 0xe9, 0x65, 0xeb, 0x2a, 0xeb, + 0x67, 0xe9, 0xe7, 0xea, 0x7a, 0xe9, 0xb0, 0xe9, 0x8a, 0xe8, 0xf9, 0xe7, + 0x0c, 0xe6, 0x07, 0xe9, 0x32, 0xef, 0x7e, 0xf4, 0xa4, 0xfa, 0xb7, 0xfd, + 0xba, 0xff, 0xf6, 0x05, 0xe2, 0x0a, 0xfa, 0x0d, 0x98, 0x0d, 0x84, 0x0a, + 0x08, 0x08, 0xa6, 0x07, 0x27, 0x07, 0x44, 0x03, 0x2b, 0xff, 0xbb, 0xfb, + 0x0b, 0xfc, 0x8c, 0xff, 0x19, 0x01, 0x04, 0x01, 0x70, 0x01, 0x14, 0x02, + 0x9d, 0x04, 0x6c, 0x06, 0xec, 0x06, 0x21, 0x06, 0xbf, 0x04, 0x41, 0x02, + 0xfa, 0x00, 0x97, 0x00, 0x33, 0x02, 0xf1, 0x03, 0xdd, 0x04, 0x3e, 0x05, + 0xaf, 0x06, 0xa0, 0x09, 0x32, 0x0d, 0x5a, 0x0f, 0x2a, 0x10, 0x79, 0x0f, + 0x7f, 0x10, 0x7d, 0x11, 0x87, 0x10, 0x2b, 0x0e, 0xfd, 0x0a, 0xe1, 0x09, + 0xf8, 0x09, 0x44, 0x0a, 0x4f, 0x09, 0x83, 0x07, 0xa9, 0x06, 0x27, 0x07, + 0x19, 0x07, 0xe0, 0x07, 0xbf, 0x08, 0x9e, 0x08, 0xaf, 0x07, 0x0e, 0x05, + 0xc7, 0x02, 0x50, 0x02, 0x94, 0x02, 0xd2, 0x02, 0xe2, 0x01, 0x9c, 0xff, + 0x43, 0xff, 0xdb, 0xfe, 0x83, 0x00, 0xd6, 0x01, 0x76, 0x03, 0xdb, 0x04, + 0x9b, 0x05, 0x6d, 0x05, 0xdb, 0x05, 0x11, 0x06, 0x99, 0x06, 0x7b, 0x07, + 0xc1, 0x07, 0x58, 0x07, 0xeb, 0x05, 0x35, 0x05, 0xd4, 0x04, 0xd4, 0x05, + 0xd7, 0x07, 0x09, 0x08, 0x19, 0x07, 0xb0, 0x06, 0x9a, 0x05, 0x2f, 0x05, + 0xa5, 0x04, 0x3e, 0x03, 0xb9, 0x01, 0x14, 0x00, 0x5e, 0xfe, 0x66, 0xfc, + 0xf0, 0xfa, 0xf8, 0xf9, 0x04, 0xfa, 0xba, 0xf9, 0x37, 0xf9, 0xdb, 0xf8, + 0x1b, 0xf8, 0x1b, 0xf8, 0x0e, 0xf8, 0x2b, 0xf7, 0x82, 0xf6, 0x79, 0xf5, + 0x33, 0xf4, 0x23, 0xf2, 0x11, 0xf0, 0x5e, 0xee, 0x27, 0xee, 0xd1, 0xed, + 0xa9, 0xed, 0x65, 0xec, 0xe2, 0xeb, 0xa9, 0xec, 0x5d, 0xee, 0x90, 0xef, + 0x08, 0xef, 0xfc, 0xed, 0x85, 0xeb, 0x55, 0xeb, 0x72, 0xe8, 0xe5, 0xe7, + 0xfd, 0xe5, 0xb3, 0xe6, 0x98, 0xe9, 0x39, 0xf0, 0x80, 0xf6, 0x12, 0xfc, + 0x01, 0x02, 0x8f, 0x05, 0xa0, 0x0b, 0xbb, 0x10, 0x34, 0x13, 0xd5, 0x12, + 0x85, 0x0f, 0x27, 0x0b, 0xa1, 0x07, 0x5c, 0x03, 0xff, 0x00, 0xee, 0xfd, + 0x8d, 0xfb, 0xc2, 0xfa, 0x46, 0xfa, 0x7a, 0xfc, 0xf6, 0xfe, 0xb5, 0x01, + 0xd2, 0x03, 0xed, 0x05, 0xed, 0x06, 0xbf, 0x06, 0x5a, 0x06, 0xe2, 0x04, + 0x6c, 0x03, 0xd6, 0x03, 0xf3, 0x02, 0x53, 0x02, 0x04, 0x02, 0x6e, 0x01, + 0xbc, 0x03, 0x32, 0x07, 0xe6, 0x0a, 0xdc, 0x0c, 0x24, 0x0e, 0x56, 0x0f, + 0xfa, 0x10, 0x4f, 0x12, 0x76, 0x13, 0x1f, 0x11, 0x49, 0x0e, 0x2e, 0x0d, + 0xe0, 0x0a, 0xba, 0x09, 0xd4, 0x07, 0x71, 0x04, 0xad, 0x03, 0xfe, 0x03, + 0xdc, 0x04, 0x29, 0x05, 0xc6, 0x05, 0x79, 0x05, 0xc4, 0x06, 0x19, 0x07, + 0x8e, 0x06, 0x53, 0x05, 0x58, 0x04, 0xfb, 0x02, 0x6a, 0x01, 0xa3, 0xff, + 0xc3, 0xfc, 0x43, 0xfc, 0xe2, 0xfc, 0xff, 0xfc, 0xdf, 0xfd, 0x08, 0xff, + 0x63, 0x00, 0x59, 0x03, 0x95, 0x04, 0x2a, 0x06, 0x2b, 0x07, 0x0c, 0x08, + 0xe1, 0x08, 0x4f, 0x08, 0x48, 0x07, 0x3a, 0x06, 0xf1, 0x04, 0x32, 0x04, + 0x4a, 0x04, 0xb7, 0x03, 0xd4, 0x03, 0x61, 0x03, 0xb9, 0x02, 0x3d, 0x03, + 0x89, 0x03, 0xb2, 0x03, 0xd6, 0x02, 0xbc, 0x01, 0x39, 0x00, 0x01, 0xff, + 0xa2, 0xfd, 0x6d, 0xfc, 0x1c, 0xfb, 0x6d, 0xfa, 0x1b, 0xf9, 0x62, 0xf8, + 0x2b, 0xf8, 0xbf, 0xf8, 0x29, 0xf9, 0x40, 0xf9, 0xc1, 0xf8, 0x8c, 0xf8, + 0xa7, 0xf8, 0xd1, 0xf7, 0x9a, 0xf6, 0x62, 0xf4, 0x33, 0xf2, 0xdb, 0xf1, + 0x87, 0xf1, 0x13, 0xf1, 0x66, 0xf0, 0x7c, 0xef, 0x89, 0xef, 0x09, 0xf0, + 0xa9, 0xf1, 0x2c, 0xf2, 0x13, 0xf1, 0x2f, 0xf2, 0x11, 0xf0, 0x66, 0xef, + 0x0b, 0xef, 0xfc, 0xeb, 0xeb, 0xe8, 0xd0, 0xe7, 0xc0, 0xe7, 0xdf, 0xeb, + 0x58, 0xf4, 0x95, 0xf8, 0x14, 0xfc, 0xdd, 0xff, 0x63, 0x05, 0x4c, 0x0d, + 0x5e, 0x15, 0xfe, 0x15, 0x51, 0x14, 0x6b, 0x11, 0x66, 0x0e, 0xd2, 0x0c, + 0x87, 0x09, 0x5d, 0x05, 0x2e, 0x01, 0x9d, 0xfd, 0xa5, 0xfa, 0xf8, 0xf9, + 0x7b, 0xfa, 0x23, 0xfd, 0x72, 0xff, 0xdb, 0x00, 0x5b, 0x02, 0x03, 0x04, + 0x2e, 0x06, 0x0f, 0x07, 0x92, 0x06, 0xa0, 0x05, 0x71, 0x04, 0xe0, 0x02, + 0xf0, 0x01, 0xec, 0x00, 0xd9, 0x00, 0x84, 0x01, 0x0f, 0x02, 0x34, 0x03, + 0xcd, 0x05, 0xb0, 0x08, 0x2b, 0x0b, 0xd5, 0x0c, 0x24, 0x0e, 0xb8, 0x0e, + 0x9a, 0x0f, 0x26, 0x0f, 0x03, 0x0e, 0xe0, 0x0c, 0xb6, 0x0a, 0x96, 0x08, + 0xa9, 0x06, 0xbc, 0x04, 0x42, 0x04, 0x4b, 0x03, 0x49, 0x02, 0x7c, 0x02, + 0xeb, 0x02, 0xfc, 0x03, 0x46, 0x04, 0xf6, 0x03, 0x6d, 0x03, 0x7e, 0x03, + 0x0b, 0x03, 0xfc, 0x01, 0xcc, 0x00, 0xa9, 0xff, 0x44, 0xfe, 0xbf, 0xfd, + 0xed, 0xfc, 0x01, 0xfd, 0x34, 0xfe, 0x3e, 0xff, 0x4c, 0x00, 0x01, 0x01, + 0x10, 0x03, 0x3e, 0x05, 0xfb, 0x05, 0xad, 0x07, 0xcc, 0x07, 0xe5, 0x07, + 0xd9, 0x08, 0xf8, 0x07, 0xa0, 0x06, 0xfd, 0x05, 0xa2, 0x04, 0xb6, 0x04, + 0x0d, 0x03, 0x07, 0x02, 0x87, 0x01, 0x38, 0x00, 0x1f, 0x00, 0x86, 0xff, + 0xc4, 0xfe, 0x9c, 0xfe, 0x3f, 0xfe, 0x57, 0xfd, 0x30, 0xfc, 0x29, 0xfb, + 0x36, 0xfb, 0x77, 0xfb, 0xe0, 0xfa, 0x99, 0xf9, 0x84, 0xf8, 0x9f, 0xf8, + 0x47, 0xf9, 0xef, 0xf9, 0x9f, 0xf9, 0x9b, 0xf8, 0x2d, 0xf8, 0xd8, 0xf6, + 0x49, 0xf6, 0x37, 0xf5, 0x81, 0xf4, 0x6f, 0xf3, 0x41, 0xf2, 0xbd, 0xf0, + 0x41, 0xef, 0x38, 0xef, 0xe6, 0xef, 0x38, 0xf0, 0x63, 0xf0, 0x55, 0xef, + 0xeb, 0xed, 0xe7, 0xed, 0x53, 0xee, 0xaf, 0xeb, 0xef, 0xea, 0x28, 0xe9, + 0x2b, 0xe9, 0xa3, 0xee, 0x1e, 0xf4, 0x2d, 0xf9, 0x6c, 0xfe, 0x85, 0x01, + 0x05, 0x07, 0xe3, 0x0d, 0xb6, 0x14, 0x55, 0x18, 0xfd, 0x17, 0xc8, 0x14, + 0xdd, 0x10, 0xaf, 0x0d, 0x1e, 0x0b, 0x8a, 0x07, 0x64, 0x02, 0x2a, 0xfe, + 0x8e, 0xf8, 0x83, 0xf6, 0xf7, 0xf6, 0x3e, 0xf8, 0x3a, 0xfb, 0x31, 0xfe, + 0x0e, 0xff, 0x7f, 0x01, 0x52, 0x03, 0xd4, 0x04, 0xb8, 0x06, 0xb8, 0x06, + 0x51, 0x06, 0xfc, 0x04, 0xb7, 0x03, 0xc7, 0x02, 0x42, 0x01, 0x93, 0x00, + 0x6c, 0x00, 0x98, 0x01, 0xcc, 0x03, 0xab, 0x05, 0xb2, 0x07, 0x0b, 0x09, + 0xc3, 0x0a, 0xd3, 0x0c, 0x62, 0x0e, 0xcd, 0x0f, 0xe3, 0x0f, 0x2a, 0x0f, + 0x19, 0x0d, 0x5c, 0x0a, 0xc6, 0x08, 0x3d, 0x07, 0xb7, 0x05, 0xa7, 0x04, + 0xe9, 0x02, 0x2d, 0x01, 0xe3, 0xff, 0x65, 0x00, 0x6b, 0x01, 0x15, 0x02, + 0x2b, 0x02, 0xe4, 0x00, 0x4c, 0x00, 0xc7, 0x00, 0x2e, 0x01, 0x8c, 0x00, + 0xe8, 0xff, 0x7a, 0xfe, 0x1b, 0xfd, 0x0e, 0xfd, 0x09, 0xfd, 0xa3, 0xfd, + 0x31, 0xfe, 0xf2, 0xfe, 0x0f, 0x00, 0xa7, 0x01, 0x65, 0x03, 0xe8, 0x04, + 0x20, 0x06, 0xb0, 0x07, 0x81, 0x09, 0x53, 0x0a, 0x88, 0x0a, 0x63, 0x0a, + 0xd3, 0x08, 0x58, 0x08, 0x93, 0x08, 0xfa, 0x06, 0x4d, 0x05, 0xe3, 0x02, + 0xd1, 0xff, 0x52, 0xfe, 0xd2, 0xfd, 0xfb, 0xfc, 0xd7, 0xfb, 0x85, 0xfa, + 0x26, 0xf9, 0xf2, 0xf8, 0x19, 0xf9, 0x52, 0xfa, 0x99, 0xfa, 0x82, 0xfa, + 0xa0, 0xfa, 0x1d, 0xfb, 0x24, 0xfb, 0x78, 0xfb, 0x27, 0xfb, 0x7e, 0xfa, + 0x14, 0xfa, 0xf7, 0xf8, 0x9a, 0xf7, 0x3b, 0xf6, 0x9a, 0xf4, 0x35, 0xf3, + 0x8e, 0xf2, 0xd7, 0xf0, 0x4e, 0xf2, 0x54, 0xf1, 0xf9, 0xf1, 0xb4, 0xf2, + 0x39, 0xf2, 0x3b, 0xf3, 0x5a, 0xf3, 0xd6, 0xf3, 0x35, 0xf3, 0x2d, 0xf2, + 0x36, 0xef, 0xaf, 0xec, 0x47, 0xea, 0xa2, 0xea, 0x65, 0xeb, 0x36, 0xf1, + 0x3e, 0xf5, 0xcf, 0xf7, 0x09, 0xfd, 0xd9, 0x00, 0x05, 0x09, 0xb9, 0x13, + 0x5a, 0x18, 0x75, 0x18, 0xb9, 0x16, 0xa2, 0x14, 0x59, 0x14, 0xa9, 0x12, + 0x28, 0x0e, 0x9a, 0x06, 0x43, 0xff, 0x01, 0xfa, 0xbb, 0xf6, 0x54, 0xf5, + 0xad, 0xf4, 0x02, 0xf5, 0x01, 0xf6, 0x54, 0xf8, 0xe0, 0xfb, 0x94, 0xff, + 0x7d, 0x03, 0x46, 0x06, 0x49, 0x08, 0x64, 0x09, 0xfa, 0x09, 0x26, 0x09, + 0xed, 0x06, 0x55, 0x04, 0x4c, 0x02, 0xfe, 0x00, 0xbe, 0xff, 0x66, 0xff, + 0x55, 0xff, 0xe6, 0xfe, 0x67, 0x00, 0x25, 0x03, 0x75, 0x07, 0xe4, 0x0a, + 0x9e, 0x0d, 0x72, 0x0e, 0x97, 0x0f, 0x99, 0x11, 0xf1, 0x11, 0x53, 0x10, + 0xe9, 0x0d, 0x7d, 0x0b, 0x1a, 0x09, 0xf6, 0x05, 0x14, 0x02, 0x96, 0xfe, + 0x1a, 0xfd, 0x04, 0xfd, 0x3f, 0xfc, 0x16, 0xfc, 0xf1, 0xfb, 0x64, 0xfc, + 0xd2, 0xfd, 0xbc, 0xfe, 0x8e, 0x00, 0xb2, 0x01, 0xb0, 0x01, 0x50, 0x00, + 0xd5, 0xfe, 0x81, 0xfe, 0x7c, 0xfe, 0xd2, 0xff, 0xaf, 0xfe, 0xd1, 0xfc, + 0x40, 0xfd, 0x4c, 0xfe, 0x34, 0x01, 0x23, 0x04, 0x73, 0x06, 0x1e, 0x08, + 0x8b, 0x09, 0xdb, 0x0b, 0x73, 0x0d, 0xc1, 0x0e, 0xf1, 0x0e, 0xd8, 0x0d, + 0x37, 0x0b, 0x99, 0x08, 0xdb, 0x05, 0x11, 0x02, 0x3b, 0xff, 0x39, 0xfc, + 0x1d, 0xf9, 0x29, 0xf7, 0x0e, 0xf6, 0x48, 0xf4, 0x29, 0xf5, 0x53, 0xf6, + 0xbc, 0xf7, 0x33, 0xfa, 0x3e, 0xfb, 0x9f, 0xfc, 0x37, 0xfe, 0x89, 0xff, + 0xf1, 0x00, 0x6c, 0x01, 0xca, 0x00, 0xed, 0xff, 0x92, 0xfe, 0xd0, 0xfc, + 0xfe, 0xfa, 0xf2, 0xf8, 0x5e, 0xf6, 0xf8, 0xf4, 0x5b, 0xf4, 0x90, 0xf4, + 0x58, 0xf4, 0xa5, 0xf3, 0x6c, 0xf5, 0x56, 0xf6, 0x27, 0xf7, 0x39, 0xf8, + 0x25, 0xf6, 0x50, 0xf6, 0x33, 0xf6, 0x02, 0xf5, 0x02, 0xf3, 0x72, 0xef, + 0xef, 0xec, 0x35, 0xe8, 0x0b, 0xe9, 0xb6, 0xea, 0x93, 0xec, 0x82, 0xf1, + 0x4f, 0xf5, 0x25, 0xf9, 0x80, 0x00, 0x11, 0x09, 0x31, 0x0f, 0x8c, 0x15, + 0x57, 0x18, 0x3b, 0x18, 0xa2, 0x18, 0xc3, 0x17, 0xf1, 0x14, 0x03, 0x11, + 0x74, 0x0b, 0xc9, 0x04, 0xd5, 0xfe, 0xab, 0xf9, 0x58, 0xf6, 0xc8, 0xf4, + 0xd7, 0xf3, 0x8a, 0xf4, 0x65, 0xf5, 0xc9, 0xf6, 0x11, 0xfa, 0x9c, 0xfd, + 0xa2, 0x00, 0x15, 0x04, 0x52, 0x05, 0x6f, 0x05, 0x4d, 0x05, 0x71, 0x04, + 0xd1, 0x03, 0x99, 0x02, 0x71, 0x00, 0x54, 0xfe, 0xf0, 0xfc, 0xaa, 0xfc, + 0xe9, 0xfc, 0x10, 0xfe, 0xe1, 0xff, 0xd3, 0x02, 0x25, 0x07, 0xdf, 0x09, + 0x39, 0x0c, 0x2b, 0x0f, 0xaf, 0x10, 0x33, 0x13, 0xe6, 0x13, 0x5e, 0x12, + 0x9c, 0x0f, 0x9d, 0x0c, 0x82, 0x09, 0x62, 0x06, 0x5b, 0x03, 0x7e, 0x00, + 0x27, 0xfd, 0x12, 0xfa, 0x2d, 0xf8, 0x76, 0xf7, 0x52, 0xf9, 0x0a, 0xfb, + 0x74, 0xfb, 0x90, 0xfa, 0xc1, 0xfb, 0x0f, 0xfe, 0xec, 0xff, 0xf4, 0x00, + 0xcf, 0x00, 0x06, 0x00, 0xf3, 0x00, 0xf7, 0x00, 0x3e, 0x00, 0xc1, 0x00, + 0x3c, 0x01, 0xa3, 0x02, 0xa9, 0x03, 0x33, 0x04, 0x00, 0x06, 0x5f, 0x08, + 0xa5, 0x0a, 0x59, 0x0c, 0x39, 0x0d, 0x07, 0x0d, 0xbe, 0x0d, 0x53, 0x0d, + 0x46, 0x0b, 0x77, 0x09, 0xd0, 0x06, 0xb6, 0x03, 0x54, 0x01, 0x6f, 0xfe, + 0x7e, 0xfa, 0x7b, 0xf8, 0x2b, 0xf7, 0x72, 0xf6, 0xa8, 0xf6, 0x03, 0xf7, + 0x90, 0xf7, 0xee, 0xf8, 0x8d, 0xfa, 0x88, 0xfc, 0xdc, 0xfe, 0x65, 0x01, + 0x6c, 0x02, 0x92, 0x02, 0xa2, 0x02, 0xd4, 0x02, 0xb7, 0x02, 0xa8, 0x02, + 0x8a, 0x00, 0x81, 0xfe, 0x4d, 0xfc, 0x55, 0xf9, 0xe1, 0xf8, 0x10, 0xf8, + 0xfa, 0xf6, 0x01, 0xf7, 0x18, 0xf5, 0x62, 0xf4, 0x9c, 0xf4, 0x00, 0xf5, + 0x83, 0xf5, 0x35, 0xf4, 0xfd, 0xf3, 0x08, 0xf3, 0x74, 0xf2, 0x61, 0xf1, + 0xf9, 0xee, 0xf4, 0xec, 0x23, 0xeb, 0x73, 0xeb, 0xbd, 0xec, 0x22, 0xf0, + 0x48, 0xf2, 0x54, 0xf6, 0xb6, 0xf9, 0x69, 0xff, 0xce, 0x06, 0x63, 0x0c, + 0x65, 0x11, 0xf6, 0x14, 0x5d, 0x17, 0x6a, 0x17, 0x20, 0x17, 0x5f, 0x15, + 0x5c, 0x12, 0x77, 0x0f, 0x74, 0x0a, 0x90, 0x03, 0x87, 0xfd, 0x1e, 0xf9, + 0x45, 0xf7, 0x15, 0xf5, 0x87, 0xf3, 0x78, 0xf1, 0x28, 0xf0, 0x72, 0xf2, + 0xdd, 0xf5, 0x37, 0xf8, 0x10, 0xfb, 0x6e, 0xfc, 0x49, 0xfe, 0x4c, 0x00, + 0xec, 0x01, 0xaa, 0x02, 0xcf, 0x02, 0xf3, 0x01, 0xd8, 0x00, 0xd3, 0xff, + 0x29, 0xff, 0x12, 0xff, 0x3a, 0xff, 0x9a, 0xff, 0x8d, 0x00, 0x2b, 0x02, + 0xaa, 0x04, 0xc8, 0x06, 0xfb, 0x09, 0xdb, 0x0c, 0x21, 0x0f, 0x13, 0x11, + 0x5b, 0x11, 0x8a, 0x11, 0x86, 0x11, 0x63, 0x10, 0x19, 0x0e, 0x25, 0x0b, + 0x8e, 0x07, 0xd7, 0x03, 0x3d, 0x00, 0x26, 0xfd, 0x88, 0xfa, 0xc0, 0xf8, + 0xdd, 0xf6, 0x26, 0xf5, 0x2c, 0xf5, 0xc5, 0xf5, 0x99, 0xf7, 0xf1, 0xf9, + 0xb9, 0xfb, 0x2f, 0xfd, 0x4d, 0xfe, 0xf3, 0xff, 0xf7, 0x02, 0x35, 0x05, + 0x1e, 0x06, 0x5f, 0x06, 0x06, 0x05, 0xe9, 0x04, 0x13, 0x07, 0x32, 0x08, + 0x50, 0x08, 0x1a, 0x08, 0xd0, 0x06, 0x29, 0x07, 0x76, 0x08, 0xb5, 0x09, + 0xd2, 0x09, 0x62, 0x09, 0x4d, 0x08, 0x68, 0x07, 0x2c, 0x06, 0xbb, 0x04, + 0x19, 0x04, 0x81, 0x02, 0x58, 0x00, 0x4c, 0xfd, 0xec, 0xfa, 0x0c, 0xfa, + 0x2c, 0xf9, 0x14, 0xf9, 0x58, 0xf9, 0x92, 0xf8, 0xc9, 0xf8, 0x83, 0xfa, + 0x74, 0xfc, 0x48, 0xfe, 0xdc, 0xff, 0x57, 0x01, 0xc3, 0x02, 0x50, 0x04, + 0x58, 0x05, 0x0a, 0x05, 0x02, 0x04, 0x7a, 0x03, 0x25, 0x03, 0x91, 0x00, + 0xc9, 0xfe, 0x53, 0xfc, 0x9e, 0xf8, 0xf1, 0xf7, 0xb4, 0xf6, 0xac, 0xf3, + 0xf9, 0xf2, 0xea, 0xf1, 0xaf, 0xef, 0xe7, 0xef, 0x57, 0xf0, 0x08, 0xef, + 0x6e, 0xef, 0xb2, 0xee, 0x36, 0xed, 0xac, 0xee, 0x29, 0xee, 0x7b, 0xed, + 0xf2, 0xec, 0x30, 0xee, 0x17, 0xf2, 0x7f, 0xf7, 0x16, 0xfb, 0x04, 0xfe, + 0x9d, 0x00, 0xae, 0x05, 0x0b, 0x0d, 0x03, 0x13, 0xed, 0x15, 0xb7, 0x16, + 0x2f, 0x16, 0xd3, 0x14, 0x83, 0x14, 0x83, 0x13, 0xf5, 0x0f, 0xeb, 0x0a, + 0x38, 0x04, 0xfc, 0xfc, 0x40, 0xf9, 0x7e, 0xf6, 0x8b, 0xf3, 0x9c, 0xf0, + 0x3e, 0xee, 0xcf, 0xec, 0xf8, 0xed, 0xb9, 0xf0, 0x21, 0xf3, 0x20, 0xf6, + 0xd7, 0xf8, 0xb2, 0xfb, 0x25, 0xff, 0xb5, 0x01, 0xe0, 0x02, 0x2b, 0x03, + 0xa6, 0x03, 0x4a, 0x05, 0x86, 0x05, 0x40, 0x04, 0xa0, 0x01, 0x05, 0xff, + 0xc8, 0xff, 0x07, 0x02, 0x50, 0x03, 0x7f, 0x03, 0xfe, 0x03, 0x93, 0x05, + 0x99, 0x08, 0x22, 0x0c, 0xe1, 0x0e, 0xa2, 0x10, 0xac, 0x11, 0x90, 0x11, + 0x3e, 0x10, 0xa5, 0x0e, 0xf3, 0x0d, 0x0f, 0x0c, 0x2c, 0x08, 0xb2, 0x03, + 0xe6, 0xfe, 0xef, 0xfa, 0xab, 0xf8, 0x93, 0xf6, 0x71, 0xf4, 0x87, 0xf3, + 0xd7, 0xf2, 0x98, 0xf2, 0xdd, 0xf4, 0xea, 0xf7, 0x70, 0xfb, 0xce, 0xfe, + 0xc3, 0x00, 0xa2, 0x03, 0x69, 0x06, 0xcc, 0x09, 0xc7, 0x0b, 0xf1, 0x0b, + 0x4f, 0x0c, 0x34, 0x0c, 0xfe, 0x0b, 0x07, 0x0b, 0xcf, 0x09, 0x1b, 0x08, + 0xbe, 0x07, 0x98, 0x06, 0xfe, 0x04, 0x6d, 0x04, 0xca, 0x03, 0x28, 0x04, + 0x90, 0x04, 0xcc, 0x03, 0xec, 0x02, 0xf5, 0x02, 0x0b, 0x03, 0xc7, 0x02, + 0x6e, 0x02, 0xe3, 0x00, 0xaa, 0xff, 0x59, 0xff, 0x3a, 0xfe, 0x60, 0xfd, + 0xe2, 0xfc, 0x57, 0xfc, 0x20, 0xfc, 0xf0, 0xfb, 0x4a, 0xfc, 0x1e, 0xfd, + 0x62, 0xfe, 0xab, 0xff, 0x35, 0x00, 0x3b, 0x00, 0x0a, 0x01, 0xcb, 0x01, + 0x41, 0x02, 0xf6, 0x01, 0x94, 0x00, 0xe4, 0xfe, 0x89, 0xfd, 0xdf, 0xfb, + 0x7d, 0xfa, 0x7a, 0xf8, 0xd9, 0xf5, 0xc5, 0xf3, 0xcf, 0xf1, 0x99, 0xf0, + 0x9d, 0xef, 0x0e, 0xef, 0x2b, 0xef, 0x0a, 0xee, 0xe7, 0xed, 0xdc, 0xec, + 0xcf, 0xec, 0x86, 0xee, 0xea, 0xee, 0x65, 0xef, 0xa6, 0xef, 0x71, 0xf2, + 0x55, 0xf6, 0xeb, 0xf9, 0xf9, 0xfd, 0x88, 0x00, 0x9b, 0x03, 0xcc, 0x09, + 0x29, 0x0e, 0xca, 0x10, 0x12, 0x12, 0xd1, 0x12, 0x1f, 0x13, 0xf5, 0x12, + 0xf1, 0x11, 0x9f, 0x0d, 0x64, 0x09, 0xf5, 0x05, 0xc1, 0x01, 0x93, 0xfd, + 0x5a, 0xf9, 0xb7, 0xf4, 0xb3, 0xf1, 0xb8, 0xf0, 0x9e, 0xf0, 0x91, 0xf0, + 0x6d, 0xf0, 0x50, 0xf1, 0xd3, 0xf3, 0x80, 0xf8, 0xce, 0xfb, 0x15, 0xfe, + 0x27, 0xff, 0x53, 0x00, 0xd7, 0x02, 0x69, 0x05, 0xf7, 0x05, 0x8e, 0x05, + 0x7f, 0x04, 0x06, 0x03, 0x8a, 0x02, 0x60, 0x02, 0x8b, 0x02, 0x33, 0x03, + 0x4e, 0x03, 0x9b, 0x03, 0x7d, 0x04, 0x8d, 0x06, 0x54, 0x09, 0x43, 0x0c, + 0xfc, 0x0d, 0x64, 0x0e, 0xd6, 0x0e, 0x45, 0x0f, 0x29, 0x10, 0x98, 0x0f, + 0x0a, 0x0e, 0xcc, 0x0a, 0x31, 0x07, 0x62, 0x04, 0x18, 0x01, 0x73, 0xfe, + 0x9b, 0xfb, 0x0c, 0xf8, 0xf5, 0xf6, 0x6c, 0xf6, 0x9b, 0xf5, 0x81, 0xf6, + 0x84, 0xf7, 0xbe, 0xf9, 0xa9, 0xfc, 0x18, 0xff, 0x7b, 0x00, 0xeb, 0x02, + 0x1b, 0x06, 0xd8, 0x07, 0x33, 0x09, 0x98, 0x09, 0x85, 0x09, 0x87, 0x09, + 0xaa, 0x09, 0x52, 0x08, 0x6a, 0x07, 0x1d, 0x07, 0xce, 0x05, 0x23, 0x05, + 0x06, 0x05, 0x30, 0x04, 0x62, 0x04, 0x4b, 0x05, 0x6a, 0x04, 0x75, 0x04, + 0xf6, 0x04, 0x1c, 0x04, 0x17, 0x04, 0x12, 0x04, 0x7f, 0x02, 0x9d, 0x01, + 0x0c, 0x01, 0x3e, 0xff, 0x1b, 0xfe, 0xec, 0xfc, 0xf6, 0xfb, 0xa3, 0xfb, + 0x6d, 0xfb, 0x86, 0xfb, 0xaf, 0xfb, 0x30, 0xfc, 0x86, 0xfd, 0xcc, 0xfe, + 0x31, 0x00, 0x5e, 0x01, 0x7b, 0x01, 0x53, 0x01, 0x89, 0x02, 0x05, 0x02, + 0x85, 0x00, 0x03, 0xff, 0xd3, 0xfc, 0x20, 0xfb, 0x34, 0xfa, 0x21, 0xf7, + 0xaa, 0xf4, 0xa0, 0xf1, 0x11, 0xf1, 0x2e, 0xf1, 0xd9, 0xef, 0x5e, 0xef, + 0x2f, 0xed, 0xb2, 0xec, 0x90, 0xee, 0xef, 0xef, 0x32, 0xf0, 0x71, 0xef, + 0xbe, 0xed, 0xf4, 0xed, 0x57, 0xf1, 0xc0, 0xf4, 0xec, 0xf7, 0xd5, 0xfa, + 0x82, 0xfb, 0x15, 0xfe, 0xe2, 0x03, 0x43, 0x09, 0x9c, 0x0d, 0x72, 0x10, + 0xce, 0x10, 0x21, 0x11, 0x1f, 0x12, 0xf0, 0x11, 0xc1, 0x10, 0xf2, 0x0e, + 0x20, 0x0b, 0xfd, 0x04, 0xef, 0xff, 0xb8, 0xfc, 0xe6, 0xf9, 0x08, 0xf7, + 0x0a, 0xf3, 0x3f, 0xef, 0x8a, 0xee, 0x3a, 0xf0, 0xf6, 0xf0, 0xc1, 0xf1, + 0x90, 0xf3, 0x84, 0xf6, 0x67, 0xfa, 0x06, 0xfe, 0x2e, 0xff, 0x21, 0x00, + 0x4c, 0x02, 0x37, 0x05, 0xbd, 0x06, 0x17, 0x06, 0x7b, 0x04, 0x01, 0x03, + 0x24, 0x03, 0xeb, 0x03, 0x6f, 0x03, 0x2a, 0x03, 0x21, 0x03, 0x5b, 0x03, + 0x0a, 0x04, 0x17, 0x06, 0xf1, 0x08, 0x0f, 0x0c, 0x83, 0x0d, 0x47, 0x0d, + 0x8a, 0x0d, 0x64, 0x0f, 0x4e, 0x11, 0xcb, 0x11, 0x12, 0x0f, 0x4d, 0x0b, + 0xd3, 0x08, 0x14, 0x07, 0x51, 0x05, 0x3e, 0x02, 0xb6, 0xfd, 0x4b, 0xfa, + 0x83, 0xf8, 0x8f, 0xf7, 0xfb, 0xf6, 0x6c, 0xf6, 0x58, 0xf6, 0xae, 0xf7, + 0x85, 0xf9, 0x16, 0xfb, 0x73, 0xfd, 0x0e, 0x00, 0xab, 0x02, 0xc4, 0x04, + 0x0e, 0x06, 0xb6, 0x07, 0xe2, 0x08, 0x8b, 0x09, 0x34, 0x0a, 0x97, 0x09, + 0x02, 0x09, 0x8f, 0x08, 0xbe, 0x07, 0xa3, 0x06, 0x59, 0x05, 0xf9, 0x04, + 0xaa, 0x04, 0x14, 0x04, 0x58, 0x03, 0x6d, 0x02, 0x59, 0x02, 0x98, 0x02, + 0x9a, 0x02, 0x6f, 0x02, 0xb9, 0x01, 0x0a, 0x01, 0x18, 0x01, 0xa9, 0x00, + 0x02, 0x00, 0x90, 0xff, 0xd7, 0xfe, 0x29, 0xfe, 0x54, 0xfe, 0x9b, 0xfe, + 0x3a, 0xfe, 0xa9, 0xfe, 0x69, 0xff, 0xe7, 0xff, 0xac, 0x00, 0x56, 0x01, + 0xb0, 0x01, 0x72, 0x01, 0xf4, 0x00, 0xd5, 0xff, 0xfe, 0xfe, 0xf6, 0xfd, + 0x6a, 0xfc, 0x26, 0xfa, 0x75, 0xf7, 0xe7, 0xf5, 0xab, 0xf4, 0xb6, 0xf2, + 0x7a, 0xf1, 0x15, 0xf0, 0x52, 0xef, 0xb4, 0xee, 0xf4, 0xee, 0x97, 0xee, + 0x49, 0xee, 0xa4, 0xef, 0xb5, 0xef, 0x5c, 0xf0, 0xe2, 0xf1, 0xd8, 0xf1, + 0x33, 0xf2, 0x18, 0xf3, 0x5f, 0xf5, 0x7e, 0xf9, 0xf4, 0xfd, 0xe1, 0xff, + 0x6c, 0x00, 0xfa, 0x02, 0x3c, 0x07, 0xf9, 0x0d, 0xce, 0x11, 0x0f, 0x11, + 0xb8, 0x0f, 0xc5, 0x0f, 0x12, 0x10, 0xdc, 0x10, 0x33, 0x0f, 0xc2, 0x09, + 0x5e, 0x05, 0x15, 0x01, 0xd7, 0xfc, 0x09, 0xf9, 0x84, 0xf6, 0xcc, 0xf3, + 0xe5, 0xf0, 0x86, 0xee, 0xd5, 0xec, 0xf6, 0xed, 0xb3, 0xf0, 0xa3, 0xf3, + 0xb2, 0xf4, 0x46, 0xf6, 0x2b, 0xf9, 0x38, 0xfd, 0x4d, 0x01, 0xef, 0x02, + 0xfc, 0x03, 0x0e, 0x05, 0xc6, 0x06, 0xbb, 0x07, 0x83, 0x07, 0x24, 0x06, + 0x9c, 0x05, 0x56, 0x06, 0x16, 0x06, 0x6d, 0x05, 0x22, 0x05, 0xdd, 0x05, + 0x90, 0x07, 0x13, 0x09, 0xef, 0x09, 0x37, 0x0b, 0x82, 0x0c, 0xfe, 0x0d, + 0x68, 0x0f, 0xfc, 0x0f, 0x8d, 0x0f, 0x61, 0x0e, 0xea, 0x0c, 0x82, 0x0b, + 0x97, 0x09, 0xd3, 0x06, 0x6b, 0x03, 0x00, 0x00, 0x82, 0xfd, 0x82, 0xfb, + 0x1c, 0xf9, 0x30, 0xf7, 0x8f, 0xf6, 0x13, 0xf6, 0x8a, 0xf6, 0xd9, 0xf7, + 0xbb, 0xf8, 0xbe, 0xfa, 0xb1, 0xfd, 0xcc, 0xff, 0x14, 0x02, 0x69, 0x04, + 0x0a, 0x06, 0x2e, 0x08, 0x06, 0x0a, 0x99, 0x0a, 0xbd, 0x0a, 0x8d, 0x0a, + 0x42, 0x0a, 0x85, 0x09, 0x40, 0x08, 0xc3, 0x06, 0x97, 0x05, 0xaf, 0x04, + 0x25, 0x03, 0xd7, 0x01, 0x7e, 0x00, 0x01, 0x00, 0xb2, 0x00, 0x96, 0x00, + 0x26, 0x00, 0xad, 0xff, 0xbb, 0xff, 0xce, 0x00, 0xb4, 0x01, 0xbc, 0x01, + 0x95, 0x01, 0x49, 0x01, 0x59, 0x01, 0x9c, 0x01, 0xbf, 0x01, 0x97, 0x01, + 0x83, 0x01, 0x5c, 0x01, 0x9a, 0x00, 0x92, 0x00, 0x80, 0x00, 0x5f, 0x00, + 0xe8, 0xff, 0xe4, 0xfe, 0x0c, 0xfe, 0x1b, 0xfd, 0xcf, 0xfb, 0x2d, 0xfb, + 0x94, 0xf9, 0x73, 0xf8, 0x06, 0xf7, 0x07, 0xf5, 0x4c, 0xf3, 0xaa, 0xf2, + 0x59, 0xf1, 0xe1, 0xf0, 0x3a, 0xf0, 0xea, 0xee, 0x53, 0xee, 0xe9, 0xee, + 0x33, 0xef, 0xe1, 0xef, 0x47, 0xf0, 0x15, 0xf0, 0xc3, 0xf0, 0x7c, 0xf1, + 0xb3, 0xf3, 0x76, 0xf6, 0x6d, 0xf8, 0x4f, 0xfb, 0x27, 0xfe, 0x5f, 0x00, + 0xf0, 0x04, 0xa8, 0x08, 0x9e, 0x0c, 0xf1, 0x0e, 0xb1, 0x0f, 0xcd, 0x10, + 0x59, 0x11, 0x43, 0x12, 0xad, 0x11, 0x5a, 0x0e, 0xf8, 0x0a, 0x50, 0x07, + 0xf4, 0x03, 0xb5, 0x00, 0x73, 0xfc, 0x2f, 0xf8, 0x59, 0xf4, 0x35, 0xf2, + 0xc7, 0xf0, 0xb2, 0xef, 0x1e, 0xef, 0x15, 0xef, 0x0e, 0xf1, 0x8d, 0xf3, + 0x88, 0xf5, 0x74, 0xf8, 0x69, 0xfa, 0xf1, 0xfc, 0xd0, 0x00, 0xc4, 0x02, + 0xfc, 0x03, 0x3d, 0x05, 0x18, 0x06, 0x7f, 0x06, 0x28, 0x07, 0x77, 0x07, + 0x9c, 0x06, 0x65, 0x06, 0xfa, 0x06, 0x0a, 0x07, 0x23, 0x07, 0x64, 0x07, + 0xc1, 0x08, 0x3c, 0x0a, 0x78, 0x0b, 0x18, 0x0c, 0xa1, 0x0c, 0xae, 0x0d, + 0x09, 0x0f, 0x4d, 0x0f, 0x48, 0x0e, 0x7d, 0x0d, 0x63, 0x0c, 0xb2, 0x0a, + 0xb4, 0x08, 0x61, 0x06, 0x99, 0x03, 0xf1, 0x00, 0x42, 0xfe, 0x16, 0xfc, + 0x18, 0xfa, 0x51, 0xf8, 0x00, 0xf7, 0x4d, 0xf6, 0xa3, 0xf6, 0x3c, 0xf7, + 0x1e, 0xf8, 0xb7, 0xf9, 0x5b, 0xfb, 0x65, 0xfd, 0xef, 0xff, 0xcf, 0x01, + 0xe2, 0x03, 0xd1, 0x05, 0x03, 0x07, 0xf8, 0x07, 0xad, 0x08, 0x00, 0x09, + 0xac, 0x08, 0x35, 0x08, 0x35, 0x07, 0xf4, 0x05, 0x14, 0x05, 0xf5, 0x03, + 0xd1, 0x02, 0xa9, 0x01, 0x7d, 0x00, 0xdc, 0xff, 0x7c, 0xff, 0x71, 0xff, + 0x8e, 0xff, 0x96, 0xff, 0xf3, 0xff, 0x1d, 0x00, 0x16, 0x00, 0xc7, 0x00, + 0x85, 0x01, 0x3e, 0x02, 0x84, 0x02, 0x88, 0x01, 0x73, 0x01, 0x2b, 0x02, + 0xac, 0x02, 0xa5, 0x02, 0x24, 0x02, 0x6c, 0x01, 0x5c, 0x01, 0x65, 0x01, + 0x4a, 0x01, 0xd4, 0x00, 0x3d, 0x00, 0x70, 0xff, 0x51, 0xfe, 0xdc, 0xfc, + 0xb3, 0xfb, 0x40, 0xfb, 0xa0, 0xf9, 0xc3, 0xf7, 0xf8, 0xf5, 0xf7, 0xf3, + 0xd3, 0xf3, 0x62, 0xf3, 0x04, 0xf2, 0x74, 0xf1, 0x43, 0xf0, 0x07, 0xf0, + 0xde, 0xf0, 0x24, 0xf1, 0x22, 0xf1, 0x79, 0xf1, 0x6d, 0xf2, 0xd4, 0xf2, + 0x90, 0xf4, 0xf0, 0xf5, 0x12, 0xf6, 0x56, 0xf8, 0x9e, 0xfa, 0x08, 0xfc, + 0xb2, 0xfe, 0x42, 0x01, 0x33, 0x03, 0x80, 0x06, 0x18, 0x09, 0x20, 0x0a, + 0x27, 0x0c, 0x95, 0x0e, 0x10, 0x0f, 0x34, 0x0f, 0xba, 0x0e, 0x24, 0x0c, + 0x29, 0x0b, 0xe2, 0x09, 0xad, 0x06, 0x7c, 0x03, 0x46, 0xff, 0xf2, 0xfb, + 0xc0, 0xf9, 0x55, 0xf7, 0x33, 0xf4, 0x5e, 0xf2, 0x04, 0xf2, 0x8b, 0xf1, + 0x6b, 0xf1, 0xf5, 0xf1, 0x27, 0xf3, 0x1f, 0xf6, 0x61, 0xf9, 0xb4, 0xfa, + 0x2a, 0xfb, 0xec, 0xfe, 0x55, 0x02, 0xa1, 0x04, 0x05, 0x05, 0x63, 0x05, + 0x4a, 0x06, 0x3c, 0x08, 0xd5, 0x08, 0x72, 0x07, 0x83, 0x06, 0x79, 0x06, + 0x4d, 0x07, 0xe0, 0x06, 0x6c, 0x06, 0x43, 0x06, 0xe6, 0x06, 0xf9, 0x07, + 0x48, 0x08, 0x77, 0x08, 0x96, 0x09, 0xc6, 0x0a, 0xe1, 0x0b, 0xfb, 0x0b, + 0x24, 0x0b, 0x65, 0x0a, 0xcc, 0x0a, 0x74, 0x0a, 0x03, 0x09, 0x73, 0x06, + 0xe6, 0x03, 0x1f, 0x02, 0xf7, 0x00, 0x17, 0xff, 0x95, 0xfc, 0x63, 0xfa, + 0x90, 0xf9, 0x2c, 0xf9, 0x48, 0xf8, 0xb6, 0xf7, 0x12, 0xf8, 0x5f, 0xf9, + 0x99, 0xfa, 0x8f, 0xfb, 0x60, 0xfc, 0xa0, 0xfd, 0x74, 0xff, 0x75, 0x01, + 0x90, 0x02, 0x85, 0x02, 0x1f, 0x03, 0xb5, 0x03, 0xee, 0x03, 0x9a, 0x04, + 0xe7, 0x03, 0x89, 0x02, 0x77, 0x02, 0x4c, 0x02, 0xcd, 0x01, 0x7f, 0x01, + 0x5d, 0x01, 0xf1, 0x00, 0x44, 0x01, 0x92, 0x01, 0x92, 0x01, 0x7e, 0x02, + 0x58, 0x03, 0x0d, 0x04, 0x68, 0x04, 0x90, 0x04, 0xe9, 0x04, 0x9c, 0x05, + 0x24, 0x06, 0x1f, 0x06, 0x5a, 0x05, 0x90, 0x04, 0x25, 0x04, 0xec, 0x03, + 0x2b, 0x03, 0xd8, 0x01, 0x94, 0x00, 0x6b, 0xff, 0x81, 0xfe, 0x78, 0xfd, + 0x2e, 0xfc, 0x67, 0xfb, 0xa1, 0xfa, 0x33, 0xf9, 0x83, 0xf8, 0xb4, 0xf7, + 0xef, 0xf6, 0x01, 0xf7, 0xf8, 0xf5, 0xf6, 0xf4, 0xc7, 0xf4, 0x26, 0xf4, + 0xea, 0xf3, 0x1a, 0xf3, 0x4f, 0xf2, 0xf6, 0xf1, 0x6b, 0xf2, 0x0c, 0xf3, + 0x03, 0xf3, 0xd5, 0xf2, 0xe3, 0xf3, 0xd9, 0xf5, 0xbf, 0xf7, 0x01, 0xfa, + 0xce, 0xfb, 0x42, 0xfd, 0x70, 0xff, 0xc5, 0x02, 0xe7, 0x04, 0xb4, 0x06, + 0xe8, 0x08, 0x18, 0x09, 0x55, 0x09, 0x0d, 0x0a, 0xca, 0x09, 0x19, 0x0a, + 0x67, 0x09, 0x54, 0x07, 0xbf, 0x04, 0x20, 0x03, 0xbc, 0x02, 0x65, 0x02, + 0xee, 0x00, 0x07, 0xff, 0xa8, 0xfd, 0x7b, 0xfd, 0x05, 0xfe, 0x4e, 0xfe, + 0x48, 0xfe, 0xfc, 0xfd, 0x16, 0xfe, 0xf0, 0xfd, 0xf2, 0xfd, 0xce, 0xfd, + 0xad, 0xfd, 0xb3, 0xfd, 0xe4, 0xfc, 0x8c, 0xfb, 0x96, 0xfa, 0xb2, 0xf9, + 0x72, 0xf9, 0xcf, 0xf9, 0x5d, 0xf9, 0xf5, 0xf8, 0x70, 0xf9, 0x26, 0xfa, + 0xa0, 0xfb, 0xd9, 0xfd, 0xb1, 0xff, 0xb1, 0x01, 0x44, 0x04, 0xb3, 0x06, + 0xa2, 0x08, 0x15, 0x0b, 0x6e, 0x0d, 0x4d, 0x0f, 0x7f, 0x10, 0xe1, 0x10, + 0xc7, 0x10, 0x99, 0x10, 0x37, 0x10, 0x2a, 0x0f, 0x83, 0x0d, 0x90, 0x0b, + 0x3b, 0x09, 0xe0, 0x06, 0x2f, 0x05, 0xc5, 0x03, 0xe8, 0x01, 0xed, 0xff, + 0x9c, 0xfe, 0xe8, 0xfd, 0xa8, 0xfd, 0x6e, 0xfd, 0x0c, 0xfd, 0x1b, 0xfd, + 0x6e, 0xfd, 0x90, 0xfd, 0xa2, 0xfd, 0x12, 0xfe, 0x43, 0xfe, 0xe3, 0xfd, + 0xab, 0xfd, 0x41, 0xfd, 0xcd, 0xfc, 0xb0, 0xfc, 0x35, 0xfc, 0x83, 0xfb, + 0x34, 0xfb, 0x57, 0xfb, 0x57, 0xfb, 0x9d, 0xfb, 0x15, 0xfc, 0xe0, 0xfc, + 0x02, 0xfe, 0xe8, 0xfe, 0x38, 0x00, 0xa0, 0x01, 0x0c, 0x03, 0x81, 0x04, + 0xb4, 0x05, 0xdc, 0x06, 0xff, 0x07, 0xd2, 0x08, 0x3a, 0x09, 0x4b, 0x09, + 0x6a, 0x09, 0x2c, 0x09, 0xad, 0x08, 0x0c, 0x08, 0x46, 0x07, 0xf5, 0x05, + 0x7c, 0x04, 0x4a, 0x03, 0xa8, 0x01, 0x2e, 0x00, 0x39, 0xff, 0xe8, 0xfc, + 0xfd, 0xfa, 0xf1, 0xf9, 0xe4, 0xf7, 0xc3, 0xf6, 0x4f, 0xf5, 0xef, 0xf2, + 0xf2, 0xf1, 0xce, 0xf0, 0x3e, 0xef, 0xfc, 0xed, 0xc0, 0xeb, 0xc5, 0xea, + 0xbf, 0xe9, 0x3a, 0xe9, 0xbc, 0xe9, 0x1d, 0xea, 0x40, 0xeb, 0x5e, 0xec, + 0xfb, 0xed, 0x41, 0xf1, 0x5e, 0xf5, 0xb6, 0xf8, 0xa4, 0xfc, 0xd8, 0x00, + 0xff, 0x04, 0x82, 0x08, 0xcd, 0x0b, 0xd4, 0x0e, 0x26, 0x12, 0x58, 0x14, + 0xb7, 0x14, 0x2e, 0x14, 0x95, 0x13, 0xf3, 0x12, 0xa7, 0x11, 0x1f, 0x0f, + 0x88, 0x0c, 0xca, 0x0a, 0x3a, 0x08, 0xe6, 0x04, 0xd4, 0x01, 0x57, 0x00, + 0xac, 0xff, 0x79, 0xff, 0x1d, 0xfe, 0x8a, 0xfb, 0xa6, 0xfa, 0x17, 0xfb, + 0xaf, 0xfb, 0xb6, 0xfb, 0x37, 0xfb, 0x09, 0xfa, 0xc3, 0xf8, 0xbb, 0xf7, + 0x04, 0xf7, 0xd7, 0xf6, 0x29, 0xf6, 0xf8, 0xf4, 0xe1, 0xf2, 0x8e, 0xf1, + 0x03, 0xf2, 0x2e, 0xf3, 0x5a, 0xf4, 0x7e, 0xf5, 0x7b, 0xf6, 0xf5, 0xf7, + 0x30, 0xfb, 0x54, 0xff, 0x63, 0x03, 0x3f, 0x07, 0x4b, 0x0a, 0x15, 0x0d, + 0x8d, 0x10, 0xe2, 0x13, 0x8b, 0x16, 0x3a, 0x18, 0x94, 0x18, 0xb1, 0x18, + 0xf7, 0x17, 0x58, 0x16, 0xa8, 0x14, 0xc7, 0x12, 0x54, 0x10, 0x4e, 0x0d, + 0xae, 0x09, 0x0e, 0x06, 0xb0, 0x03, 0xcd, 0x01, 0x90, 0xff, 0x75, 0xfd, + 0x7a, 0xfb, 0x9f, 0xfa, 0x31, 0xfa, 0x99, 0xf9, 0x98, 0xf9, 0x20, 0xfa, + 0x78, 0xfa, 0xaa, 0xfa, 0xaa, 0xfa, 0x54, 0xfa, 0xd4, 0xfa, 0xee, 0xfb, + 0x27, 0xfc, 0x22, 0xfb, 0x3e, 0xfa, 0x43, 0xfa, 0x97, 0xfa, 0xd5, 0xfa, + 0xc7, 0xfa, 0xb5, 0xfa, 0x03, 0xfb, 0x98, 0xfb, 0x1f, 0xfc, 0x3e, 0xfd, + 0x05, 0xff, 0xc5, 0x00, 0x02, 0x02, 0xc7, 0x02, 0xe8, 0x03, 0xea, 0x05, + 0x0d, 0x08, 0x2a, 0x09, 0xd2, 0x09, 0x31, 0x0a, 0x10, 0x0a, 0x60, 0x0a, + 0x8a, 0x0a, 0x50, 0x0a, 0xbc, 0x09, 0x1e, 0x08, 0x49, 0x06, 0xac, 0x04, + 0x3e, 0x03, 0x9d, 0x01, 0xe8, 0xff, 0x98, 0xfd, 0x4b, 0xfb, 0x4e, 0xf9, + 0x9c, 0xf7, 0xe6, 0xf5, 0x61, 0xf4, 0x52, 0xf2, 0x1c, 0xf0, 0xf0, 0xee, + 0xa6, 0xed, 0x2a, 0xec, 0x2d, 0xea, 0x8a, 0xe8, 0xee, 0xe6, 0x63, 0xe6, + 0x99, 0xe6, 0x1e, 0xe7, 0xe8, 0xe7, 0x9e, 0xe8, 0x9b, 0xea, 0x88, 0xed, + 0x99, 0xf1, 0x09, 0xf6, 0x1b, 0xfa, 0x66, 0xfe, 0x36, 0x03, 0xd4, 0x06, + 0xc3, 0x0a, 0xd6, 0x0f, 0xb8, 0x13, 0x4d, 0x16, 0x9e, 0x16, 0x0e, 0x16, + 0xc4, 0x16, 0x55, 0x17, 0x2d, 0x16, 0xd3, 0x13, 0xb9, 0x10, 0x42, 0x0d, + 0x05, 0x0b, 0xb9, 0x08, 0x1d, 0x06, 0x35, 0x04, 0x40, 0x02, 0xe3, 0xff, + 0x0f, 0xfe, 0x20, 0xfd, 0xfe, 0xfc, 0x0f, 0xfd, 0x61, 0xfc, 0x40, 0xfb, + 0x50, 0xfa, 0xf4, 0xf9, 0xe1, 0xf9, 0x50, 0xf9, 0x55, 0xf8, 0x5a, 0xf6, + 0xfb, 0xf4, 0x15, 0xf4, 0x6b, 0xf3, 0xf1, 0xf2, 0x20, 0xf2, 0x96, 0xf1, + 0xdd, 0xf1, 0x22, 0xf3, 0xe3, 0xf4, 0x90, 0xf7, 0x7a, 0xf9, 0xa5, 0xfb, + 0x20, 0xff, 0x41, 0x03, 0xf9, 0x06, 0x19, 0x0b, 0x79, 0x0e, 0x07, 0x11, + 0x38, 0x13, 0xfc, 0x14, 0x30, 0x17, 0xe7, 0x18, 0x33, 0x19, 0x60, 0x17, + 0xed, 0x14, 0x69, 0x13, 0x31, 0x12, 0x3e, 0x10, 0x73, 0x0d, 0xbd, 0x09, + 0x31, 0x06, 0xcf, 0x03, 0xbd, 0x01, 0xfa, 0xff, 0x7a, 0xfe, 0xb9, 0xfc, + 0x58, 0xfb, 0x7c, 0xfa, 0x82, 0xfa, 0x86, 0xfa, 0x7f, 0xfa, 0xde, 0xfa, + 0xf8, 0xfa, 0x55, 0xfb, 0x6f, 0xfb, 0x29, 0xfb, 0x18, 0xfb, 0x65, 0xfb, + 0x76, 0xfb, 0xe5, 0xfa, 0x99, 0xfa, 0x19, 0xfa, 0x84, 0xf9, 0x9a, 0xf9, + 0xdb, 0xf9, 0x87, 0xfa, 0x17, 0xfb, 0x59, 0xfb, 0x34, 0xfc, 0xd0, 0xfc, + 0x69, 0xfe, 0xeb, 0x00, 0x9f, 0x02, 0xe7, 0x03, 0x4a, 0x05, 0x14, 0x06, + 0xd3, 0x07, 0xd3, 0x09, 0xa1, 0x0a, 0x2f, 0x0b, 0x79, 0x0b, 0x2f, 0x0b, + 0x93, 0x0a, 0xe0, 0x09, 0xd1, 0x08, 0x1c, 0x08, 0xe7, 0x06, 0x53, 0x04, + 0x81, 0x01, 0x46, 0xff, 0x80, 0xfd, 0x33, 0xfc, 0x43, 0xfa, 0xd1, 0xf7, + 0x3d, 0xf5, 0x2e, 0xf3, 0x04, 0xf1, 0xdd, 0xef, 0x5b, 0xef, 0xdf, 0xed, + 0xfb, 0xeb, 0xb8, 0xe9, 0x0f, 0xe8, 0x57, 0xe7, 0x71, 0xe7, 0x97, 0xe8, + 0x26, 0xe9, 0xbc, 0xe8, 0x3f, 0xe9, 0xff, 0xea, 0xfb, 0xed, 0x51, 0xf3, + 0x87, 0xf7, 0x84, 0xf9, 0xd5, 0xfc, 0x2c, 0x01, 0xb2, 0x05, 0x78, 0x0a, + 0x8c, 0x0e, 0xfa, 0x10, 0x4d, 0x13, 0xbd, 0x14, 0x04, 0x15, 0xba, 0x15, + 0x21, 0x16, 0xa7, 0x15, 0xc2, 0x13, 0xd7, 0x10, 0x67, 0x0e, 0x55, 0x0c, + 0x3b, 0x0a, 0x38, 0x08, 0xd3, 0x05, 0x7b, 0x03, 0x8b, 0x01, 0xf6, 0xff, + 0xd3, 0xfe, 0xf4, 0xfd, 0x4c, 0xfd, 0x90, 0xfc, 0x34, 0xfc, 0x48, 0xfb, + 0xf7, 0xf9, 0x63, 0xf9, 0x64, 0xf9, 0xcd, 0xf8, 0x91, 0xf7, 0xf6, 0xf5, + 0xdf, 0xf4, 0xb1, 0xf4, 0x0b, 0xf4, 0x49, 0xf3, 0x46, 0xf3, 0x03, 0xf4, + 0xde, 0xf4, 0x67, 0xf5, 0x98, 0xf6, 0x07, 0xf9, 0x4f, 0xfc, 0x56, 0xff, + 0x06, 0x02, 0x8c, 0x04, 0xab, 0x07, 0x4f, 0x0b, 0xb3, 0x0e, 0x82, 0x11, + 0x13, 0x13, 0x2f, 0x14, 0x7c, 0x15, 0x38, 0x16, 0x3f, 0x16, 0x77, 0x15, + 0xd0, 0x13, 0x29, 0x12, 0x8b, 0x10, 0xd5, 0x0d, 0xde, 0x0a, 0x63, 0x08, + 0x6f, 0x06, 0x8f, 0x04, 0xa1, 0x01, 0x26, 0xff, 0xbf, 0xfd, 0x27, 0xfd, + 0x61, 0xfc, 0x56, 0xfb, 0xc2, 0xfa, 0x73, 0xfa, 0xfa, 0xfa, 0x39, 0xfb, + 0xcd, 0xfa, 0x22, 0xfb, 0x96, 0xfb, 0x5f, 0xfb, 0x77, 0xfb, 0x29, 0xfb, + 0xbe, 0xfa, 0xf3, 0xfa, 0x9f, 0xfa, 0x1a, 0xfa, 0xe5, 0xf9, 0xab, 0xf9, + 0xe2, 0xf9, 0x67, 0xfa, 0x5c, 0xfa, 0xdc, 0xfa, 0x1a, 0xfc, 0x57, 0xfd, + 0xc6, 0xfe, 0x11, 0x00, 0x37, 0x01, 0x05, 0x03, 0x1e, 0x05, 0xe0, 0x06, + 0x45, 0x08, 0x10, 0x09, 0x0b, 0x0a, 0xff, 0x0a, 0x59, 0x0b, 0xaf, 0x0b, + 0x54, 0x0b, 0x51, 0x0a, 0x13, 0x09, 0x48, 0x07, 0x86, 0x05, 0xbe, 0x03, + 0x00, 0x02, 0x27, 0x00, 0x1b, 0xfd, 0xca, 0xf9, 0xf2, 0xf7, 0x8c, 0xf6, + 0x61, 0xf4, 0xf8, 0xf2, 0x70, 0xf0, 0x80, 0xed, 0xe4, 0xec, 0xb2, 0xeb, + 0x8a, 0xea, 0xc4, 0xe9, 0xfb, 0xe7, 0xd5, 0xe6, 0x6f, 0xe7, 0xad, 0xe8, + 0xd8, 0xe9, 0x8c, 0xeb, 0x7d, 0xec, 0x7c, 0xee, 0x51, 0xf2, 0xaf, 0xf5, + 0x3d, 0xfa, 0x37, 0xfe, 0x0d, 0x01, 0xcc, 0x04, 0x90, 0x08, 0xdc, 0x0b, + 0x40, 0x0f, 0x29, 0x12, 0x60, 0x13, 0xdb, 0x13, 0xb9, 0x13, 0x9f, 0x13, + 0x64, 0x13, 0x79, 0x12, 0xe4, 0x10, 0x94, 0x0e, 0xc1, 0x0b, 0xab, 0x09, + 0x2b, 0x08, 0x85, 0x06, 0x11, 0x05, 0x12, 0x03, 0x21, 0x01, 0x5c, 0x00, + 0xca, 0xff, 0xaf, 0xfe, 0xcf, 0xfd, 0x85, 0xfd, 0x60, 0xfd, 0xdd, 0xfc, + 0xb6, 0xfb, 0x23, 0xfa, 0x25, 0xf9, 0xef, 0xf8, 0xb9, 0xf8, 0xeb, 0xf7, + 0x0e, 0xf6, 0x7c, 0xf4, 0xd6, 0xf3, 0x06, 0xf4, 0xe6, 0xf4, 0x86, 0xf5, + 0xea, 0xf5, 0xfc, 0xf6, 0x23, 0xf8, 0xb1, 0xf9, 0x8d, 0xfc, 0x9b, 0x00, + 0x53, 0x04, 0x87, 0x06, 0xf1, 0x07, 0xf4, 0x09, 0x86, 0x0d, 0x4d, 0x11, + 0x7e, 0x13, 0x28, 0x14, 0xd2, 0x13, 0x70, 0x13, 0x84, 0x13, 0x36, 0x13, + 0x96, 0x12, 0x2b, 0x11, 0xb3, 0x0e, 0xb0, 0x0b, 0xe6, 0x08, 0xec, 0x06, + 0x92, 0x05, 0x23, 0x04, 0x26, 0x02, 0xb6, 0xff, 0xa8, 0xfd, 0xad, 0xfc, + 0x81, 0xfc, 0xc3, 0xfc, 0x8a, 0xfc, 0xe9, 0xfb, 0x66, 0xfb, 0x7d, 0xfb, + 0x98, 0xfb, 0xa4, 0xfb, 0x44, 0xfc, 0x73, 0xfc, 0xd5, 0xfb, 0x2a, 0xfb, + 0x7d, 0xfa, 0x10, 0xfa, 0x6f, 0xfa, 0x6d, 0xfa, 0xe9, 0xf9, 0x78, 0xf9, + 0x0a, 0xf9, 0x67, 0xf9, 0x2e, 0xfa, 0xe5, 0xfa, 0x12, 0xfc, 0x4e, 0xfd, + 0x7d, 0xfe, 0xd7, 0xff, 0x58, 0x01, 0xf4, 0x02, 0x36, 0x05, 0x6c, 0x07, + 0x1e, 0x08, 0xd5, 0x08, 0x2e, 0x0a, 0xd2, 0x0a, 0x13, 0x0b, 0x43, 0x0b, + 0x9d, 0x0a, 0x8c, 0x09, 0x5a, 0x08, 0x5d, 0x06, 0x32, 0x04, 0xdf, 0x02, + 0xf8, 0x00, 0x9e, 0xfe, 0x23, 0xfc, 0x7f, 0xf9, 0x4f, 0xf7, 0x37, 0xf5, + 0xce, 0xf3, 0xf4, 0xf1, 0x08, 0xf0, 0x6d, 0xee, 0x72, 0xec, 0x42, 0xeb, + 0xf1, 0xe9, 0xb4, 0xe8, 0xd8, 0xe8, 0xc6, 0xe8, 0x32, 0xe9, 0x61, 0xe9, + 0xda, 0xe9, 0x40, 0xec, 0xfb, 0xee, 0x86, 0xf1, 0xdd, 0xf4, 0x24, 0xf8, + 0x13, 0xfb, 0x74, 0xfe, 0x46, 0x02, 0x33, 0x06, 0x1b, 0x0a, 0xd9, 0x0c, + 0x3c, 0x0e, 0xc2, 0x0f, 0x70, 0x11, 0xb2, 0x12, 0x19, 0x13, 0x5c, 0x12, + 0x35, 0x11, 0x15, 0x10, 0x9f, 0x0e, 0x0b, 0x0d, 0x4f, 0x0b, 0xa5, 0x09, + 0x2c, 0x08, 0x3c, 0x06, 0x43, 0x04, 0x28, 0x03, 0x87, 0x02, 0xdb, 0x01, + 0xd8, 0x00, 0x34, 0xff, 0x20, 0xfe, 0x31, 0xfe, 0x53, 0xfe, 0x97, 0xfd, + 0xf4, 0xfb, 0x89, 0xfa, 0xc3, 0xf9, 0x6f, 0xf9, 0xd2, 0xf8, 0x1f, 0xf8, + 0xd5, 0xf6, 0xd4, 0xf5, 0x1d, 0xf5, 0x25, 0xf5, 0x66, 0xf6, 0xf2, 0xf6, + 0x87, 0xf7, 0x0a, 0xf8, 0x26, 0xf9, 0xad, 0xfb, 0xaa, 0xfe, 0x5a, 0x01, + 0x75, 0x03, 0x69, 0x05, 0xd2, 0x07, 0x68, 0x0a, 0xe2, 0x0c, 0x27, 0x0f, + 0xae, 0x10, 0x55, 0x11, 0x8f, 0x11, 0x94, 0x11, 0x97, 0x11, 0x78, 0x11, + 0x79, 0x10, 0x7d, 0x0e, 0x78, 0x0c, 0xf1, 0x0a, 0x19, 0x09, 0x43, 0x07, + 0x71, 0x05, 0x80, 0x03, 0xdf, 0x01, 0x76, 0x00, 0x2f, 0xff, 0x17, 0xfe, + 0xa3, 0xfd, 0x22, 0xfd, 0x6d, 0xfc, 0x56, 0xfc, 0x54, 0xfc, 0x66, 0xfc, + 0xdb, 0xfb, 0x64, 0xfb, 0xd0, 0xfb, 0xfe, 0xfb, 0xa1, 0xfb, 0x02, 0xfb, + 0x24, 0xfa, 0xf0, 0xf9, 0x1b, 0xfa, 0x0f, 0xfa, 0x8c, 0xf9, 0x22, 0xf9, + 0x5f, 0xf9, 0xb3, 0xf9, 0x2a, 0xfa, 0x0c, 0xfb, 0x47, 0xfc, 0x58, 0xfd, + 0x97, 0xfe, 0xe1, 0xff, 0x47, 0x01, 0x55, 0x03, 0x52, 0x05, 0x92, 0x06, + 0x72, 0x07, 0x80, 0x08, 0x8c, 0x09, 0x5a, 0x0a, 0xdd, 0x0a, 0x5f, 0x0a, + 0x5b, 0x09, 0x21, 0x08, 0x5d, 0x07, 0x4b, 0x06, 0x19, 0x04, 0x1f, 0x02, + 0xff, 0xff, 0xbf, 0xfd, 0xd6, 0xfb, 0x4f, 0xf9, 0x5f, 0xf7, 0xd5, 0xf5, + 0xae, 0xf3, 0x77, 0xf1, 0x9b, 0xef, 0x3a, 0xee, 0x6c, 0xed, 0xf1, 0xeb, + 0x33, 0xea, 0xe6, 0xe8, 0x03, 0xe9, 0x9b, 0xe9, 0x89, 0xea, 0x9a, 0xeb, + 0x9d, 0xeb, 0x00, 0xed, 0xef, 0xef, 0x88, 0xf3, 0x68, 0xf7, 0xda, 0xf9, + 0xc8, 0xfb, 0x2b, 0xff, 0x33, 0x03, 0xe3, 0x06, 0xbb, 0x0a, 0xc6, 0x0c, + 0x67, 0x0d, 0xce, 0x0e, 0x02, 0x10, 0x84, 0x11, 0x64, 0x12, 0xa0, 0x11, + 0xd8, 0x0f, 0x0e, 0x0e, 0x01, 0x0d, 0xaf, 0x0c, 0xdc, 0x0b, 0xbe, 0x09, + 0x27, 0x07, 0x29, 0x05, 0x47, 0x04, 0x40, 0x04, 0x8f, 0x03, 0xdd, 0x01, + 0xa8, 0x00, 0x88, 0xff, 0xcc, 0xfe, 0xb5, 0xfe, 0xa4, 0xfe, 0x3b, 0xfe, + 0x93, 0xfc, 0xaa, 0xfa, 0xcd, 0xf9, 0xf5, 0xf9, 0xcf, 0xf9, 0x06, 0xf9, + 0x6a, 0xf7, 0x80, 0xf6, 0x74, 0xf6, 0x86, 0xf6, 0xff, 0xf6, 0xb4, 0xf7, + 0x44, 0xf8, 0x98, 0xf9, 0xce, 0xfa, 0xd2, 0xfb, 0x5b, 0xfe, 0xfc, 0x00, + 0x45, 0x03, 0x94, 0x05, 0x32, 0x07, 0x1d, 0x09, 0x9d, 0x0b, 0x42, 0x0d, + 0x72, 0x0e, 0x66, 0x0f, 0x23, 0x10, 0x81, 0x10, 0x0b, 0x10, 0x03, 0x0f, + 0x1b, 0x0e, 0x7a, 0x0d, 0x55, 0x0c, 0xc9, 0x0a, 0x9b, 0x08, 0x96, 0x06, + 0x18, 0x05, 0xb7, 0x03, 0x79, 0x02, 0x35, 0x01, 0xe1, 0xff, 0xb7, 0xfe, + 0xad, 0xfd, 0xf5, 0xfc, 0x0d, 0xfd, 0x27, 0xfd, 0xb2, 0xfc, 0xf9, 0xfb, + 0x76, 0xfb, 0x98, 0xfb, 0x0a, 0xfc, 0xf8, 0xfb, 0x3b, 0xfb, 0xd0, 0xfa, + 0xbc, 0xfa, 0x56, 0xfa, 0x1e, 0xfa, 0x01, 0xfa, 0xe7, 0xf9, 0xbe, 0xf9, + 0xba, 0xf9, 0x05, 0xfa, 0x95, 0xfa, 0x5a, 0xfb, 0x28, 0xfc, 0x23, 0xfd, + 0x5a, 0xfe, 0x02, 0x00, 0xc9, 0x01, 0xf1, 0x02, 0x27, 0x04, 0xc6, 0x05, + 0x72, 0x07, 0xeb, 0x08, 0xe7, 0x09, 0x0c, 0x0a, 0x06, 0x0a, 0x15, 0x0a, + 0xc5, 0x09, 0x39, 0x09, 0xc8, 0x07, 0x3b, 0x06, 0x0c, 0x04, 0xfe, 0x01, + 0x7e, 0x00, 0x51, 0xfe, 0x15, 0xfc, 0xb9, 0xf9, 0x08, 0xf7, 0x22, 0xf5, + 0x95, 0xf3, 0xc3, 0xf1, 0x14, 0xf0, 0x5f, 0xee, 0x8a, 0xec, 0x42, 0xeb, + 0x93, 0xea, 0xd0, 0xe9, 0x08, 0xea, 0x63, 0xea, 0xb9, 0xea, 0x8d, 0xeb, + 0xca, 0xec, 0x0d, 0xef, 0xe6, 0xf1, 0x88, 0xf4, 0x42, 0xf7, 0x35, 0xfa, + 0x1d, 0xfd, 0x79, 0x00, 0x9e, 0x03, 0x6d, 0x06, 0x3c, 0x09, 0xb6, 0x0b, + 0x19, 0x0d, 0x32, 0x0e, 0xdc, 0x0e, 0x26, 0x0f, 0xf6, 0x0f, 0x19, 0x10, + 0x76, 0x0f, 0x9e, 0x0d, 0x79, 0x0b, 0xd3, 0x0a, 0xdb, 0x0a, 0xf5, 0x09, + 0x15, 0x08, 0x29, 0x06, 0xd2, 0x04, 0x22, 0x04, 0xdc, 0x03, 0x01, 0x03, + 0x17, 0x02, 0xf7, 0x00, 0x07, 0x00, 0x56, 0xff, 0x52, 0xfe, 0xca, 0xfd, + 0x57, 0xfd, 0x4b, 0xfc, 0xe8, 0xfa, 0xa3, 0xf9, 0x0a, 0xf9, 0xcc, 0xf8, + 0x3d, 0xf8, 0x37, 0xf7, 0xe6, 0xf6, 0x44, 0xf7, 0x92, 0xf7, 0x15, 0xf8, + 0x7c, 0xf8, 0xc0, 0xf9, 0x9e, 0xfb, 0x29, 0xfd, 0xd5, 0xfe, 0xb7, 0x00, + 0xbc, 0x02, 0x0b, 0x05, 0xe4, 0x06, 0x9b, 0x08, 0xde, 0x0a, 0x9d, 0x0c, + 0x41, 0x0d, 0xfa, 0x0d, 0x91, 0x0e, 0xf3, 0x0e, 0x52, 0x0f, 0xd5, 0x0e, + 0xa8, 0x0d, 0x9d, 0x0c, 0x31, 0x0b, 0xed, 0x09, 0x1d, 0x09, 0x90, 0x07, + 0xcd, 0x05, 0xfb, 0x03, 0x52, 0x02, 0x7f, 0x01, 0xa5, 0x00, 0xad, 0xff, + 0xd3, 0xfe, 0xd2, 0xfd, 0x56, 0xfd, 0xed, 0xfc, 0x9d, 0xfc, 0xb1, 0xfc, + 0x90, 0xfc, 0x18, 0xfc, 0x97, 0xfb, 0x29, 0xfb, 0x22, 0xfb, 0x57, 0xfb, + 0xf2, 0xfa, 0x4f, 0xfa, 0xc3, 0xf9, 0x6b, 0xf9, 0x89, 0xf9, 0xc4, 0xf9, + 0xd5, 0xf9, 0xe1, 0xf9, 0x07, 0xfa, 0xc5, 0xfa, 0xfe, 0xfb, 0x0d, 0xfd, + 0x2b, 0xfe, 0xc7, 0xff, 0x11, 0x01, 0x6c, 0x02, 0x2d, 0x04, 0xd9, 0x05, + 0x5a, 0x07, 0x7b, 0x08, 0x28, 0x09, 0xd0, 0x09, 0x4e, 0x0a, 0x5b, 0x0a, + 0xf7, 0x09, 0x17, 0x09, 0xc5, 0x07, 0x34, 0x06, 0x71, 0x04, 0xb1, 0x02, + 0x09, 0x01, 0x7a, 0xfe, 0xcd, 0xfb, 0xab, 0xf9, 0xd9, 0xf7, 0x9e, 0xf5, + 0xe4, 0xf3, 0xae, 0xf1, 0xce, 0xef, 0x56, 0xee, 0xa6, 0xec, 0x5f, 0xeb, + 0x17, 0xeb, 0xe5, 0xea, 0x3a, 0xea, 0x54, 0xea, 0x7e, 0xeb, 0xc3, 0xec, + 0x51, 0xee, 0x4e, 0xf0, 0x6e, 0xf2, 0x28, 0xf5, 0xf2, 0xf7, 0xe4, 0xfa, + 0xf3, 0xfd, 0xa8, 0x00, 0x18, 0x03, 0x40, 0x06, 0x6c, 0x08, 0x41, 0x0a, + 0xdc, 0x0b, 0xc4, 0x0c, 0x58, 0x0d, 0xdb, 0x0d, 0xf9, 0x0d, 0xd2, 0x0d, + 0x76, 0x0d, 0x49, 0x0c, 0x00, 0x0b, 0x27, 0x0a, 0x9d, 0x09, 0x42, 0x09, + 0x21, 0x08, 0x87, 0x06, 0x93, 0x05, 0x1a, 0x05, 0xc4, 0x04, 0x58, 0x04, + 0x46, 0x03, 0x73, 0x02, 0xda, 0x01, 0xf2, 0x00, 0x08, 0x00, 0x5d, 0xff, + 0x80, 0xfe, 0x61, 0xfd, 0x1a, 0xfc, 0xe6, 0xfa, 0x10, 0xfa, 0x2f, 0xf9, + 0x1d, 0xf8, 0x94, 0xf7, 0x64, 0xf7, 0x4b, 0xf7, 0x78, 0xf7, 0x81, 0xf7, + 0xfd, 0xf7, 0x7f, 0xf9, 0x36, 0xfb, 0xd3, 0xfc, 0x40, 0xfe, 0xc7, 0xff, + 0x1c, 0x02, 0x51, 0x04, 0x44, 0x06, 0x6a, 0x08, 0x1e, 0x0a, 0x69, 0x0b, + 0x7a, 0x0c, 0x33, 0x0d, 0x0e, 0x0e, 0xbb, 0x0e, 0xb9, 0x0e, 0x06, 0x0e, + 0xad, 0x0c, 0xc1, 0x0b, 0x52, 0x0b, 0x4e, 0x0a, 0xd1, 0x08, 0xc6, 0x06, + 0x1b, 0x05, 0x2d, 0x04, 0x1d, 0x03, 0x0c, 0x02, 0xd2, 0x00, 0xe4, 0xff, + 0x44, 0xff, 0x93, 0xfe, 0x16, 0xfe, 0x04, 0xfe, 0xfe, 0xfd, 0x8a, 0xfd, + 0xe3, 0xfc, 0x8d, 0xfc, 0xab, 0xfc, 0x9a, 0xfc, 0xf2, 0xfb, 0x40, 0xfb, + 0xd6, 0xfa, 0x84, 0xfa, 0x15, 0xfa, 0xa0, 0xf9, 0x50, 0xf9, 0x2d, 0xf9, + 0x17, 0xf9, 0x0c, 0xf9, 0x8a, 0xf9, 0x51, 0xfa, 0x28, 0xfb, 0x07, 0xfc, + 0x1c, 0xfd, 0x91, 0xfe, 0x2c, 0x00, 0xc2, 0x01, 0x26, 0x03, 0xad, 0x04, + 0x14, 0x06, 0x4b, 0x07, 0x7b, 0x08, 0x1f, 0x09, 0x48, 0x09, 0x30, 0x09, + 0xe8, 0x08, 0x69, 0x08, 0x66, 0x07, 0xca, 0x05, 0x4d, 0x04, 0xa6, 0x02, + 0xba, 0x00, 0x9d, 0xfe, 0x6c, 0xfc, 0x57, 0xfa, 0x4f, 0xf8, 0x65, 0xf6, + 0x5b, 0xf4, 0x1f, 0xf2, 0x93, 0xf0, 0x2c, 0xef, 0xd6, 0xed, 0x98, 0xec, + 0x91, 0xeb, 0xff, 0xea, 0x65, 0xeb, 0x27, 0xec, 0x83, 0xec, 0x8b, 0xed, + 0xec, 0xee, 0xff, 0xf0, 0xa7, 0xf3, 0xfa, 0xf5, 0x89, 0xf8, 0x2c, 0xfb, + 0xb5, 0xfd, 0x88, 0x00, 0x2c, 0x03, 0x5e, 0x05, 0x60, 0x07, 0x0b, 0x09, + 0x03, 0x0a, 0x12, 0x0b, 0xc9, 0x0b, 0x1c, 0x0c, 0x55, 0x0c, 0xec, 0x0b, + 0x17, 0x0b, 0xcd, 0x0a, 0x62, 0x0a, 0x9f, 0x09, 0x22, 0x09, 0x4a, 0x08, + 0x91, 0x07, 0x1d, 0x07, 0xa5, 0x06, 0x4b, 0x06, 0xfa, 0x05, 0x46, 0x05, + 0xac, 0x04, 0x38, 0x04, 0xa3, 0x03, 0x25, 0x03, 0x56, 0x02, 0x2f, 0x01, + 0x4c, 0x00, 0x22, 0xff, 0xdf, 0xfd, 0xd9, 0xfc, 0xd4, 0xfb, 0xbc, 0xfa, + 0x97, 0xf9, 0x93, 0xf8, 0xfb, 0xf7, 0xd5, 0xf7, 0xd8, 0xf7, 0x15, 0xf8, + 0x71, 0xf8, 0x07, 0xf9, 0x52, 0xfa, 0xf4, 0xfb, 0x5e, 0xfd, 0xfc, 0xfe, + 0xe7, 0x00, 0xe3, 0x02, 0xc5, 0x04, 0x70, 0x06, 0xf4, 0x07, 0x5c, 0x09, + 0xbe, 0x0a, 0xe3, 0x0b, 0x5e, 0x0c, 0x5f, 0x0c, 0x2e, 0x0c, 0x17, 0x0c, + 0xe7, 0x0b, 0x2c, 0x0b, 0x11, 0x0a, 0xd4, 0x08, 0xb3, 0x07, 0xa7, 0x06, + 0x92, 0x05, 0x93, 0x04, 0xb1, 0x03, 0xdb, 0x02, 0xb7, 0x01, 0xf4, 0x00, + 0xb3, 0x00, 0x7d, 0x00, 0x24, 0x00, 0xa3, 0xff, 0x2f, 0xff, 0xf3, 0xfe, + 0xc5, 0xfe, 0x5a, 0xfe, 0xd4, 0xfd, 0x49, 0xfd, 0xdf, 0xfc, 0x35, 0xfc, + 0x52, 0xfb, 0x8c, 0xfa, 0xfe, 0xf9, 0x94, 0xf9, 0x31, 0xf9, 0xce, 0xf8, + 0xa5, 0xf8, 0xbf, 0xf8, 0xe5, 0xf8, 0x5e, 0xf9, 0x59, 0xfa, 0x87, 0xfb, + 0xaf, 0xfc, 0xc5, 0xfd, 0xf3, 0xfe, 0x79, 0x00, 0x2a, 0x02, 0xdf, 0x03, + 0x2a, 0x05, 0x14, 0x06, 0xdf, 0x06, 0x68, 0x07, 0xc9, 0x07, 0x1e, 0x08, + 0xf4, 0x07, 0x2d, 0x07, 0xe3, 0x05, 0x84, 0x04, 0x5f, 0x03, 0x11, 0x02, + 0x5b, 0x00, 0x74, 0xfe, 0x62, 0xfc, 0x2f, 0xfa, 0xc4, 0xf8, 0x5a, 0xf7, + 0x73, 0xf5, 0xf3, 0xf3, 0x3f, 0xf2, 0x92, 0xf0, 0x6e, 0xef, 0xa7, 0xee, + 0x0c, 0xee, 0xdf, 0xed, 0x9a, 0xed, 0x81, 0xed, 0x25, 0xee, 0x1e, 0xef, + 0xaf, 0xf0, 0x9b, 0xf2, 0x42, 0xf4, 0x0e, 0xf6, 0x47, 0xf8, 0xa5, 0xfa, + 0x42, 0xfd, 0xfe, 0xff, 0x01, 0x02, 0xcb, 0x03, 0xba, 0x05, 0x28, 0x07, + 0xa5, 0x08, 0xdf, 0x09, 0x94, 0x0a, 0xcf, 0x0a, 0x82, 0x0a, 0x46, 0x0a, + 0x5e, 0x0a, 0x7e, 0x0a, 0xf4, 0x09, 0xf3, 0x08, 0xfb, 0x07, 0x65, 0x07, + 0x3a, 0x07, 0x4c, 0x07, 0xfd, 0x06, 0x2a, 0x06, 0x0d, 0x05, 0xc8, 0x04, + 0x22, 0x05, 0xe8, 0x04, 0x6c, 0x04, 0x9c, 0x03, 0xd8, 0x02, 0x2b, 0x02, + 0x51, 0x01, 0x6b, 0x00, 0xbf, 0xff, 0xe5, 0xfe, 0xb4, 0xfd, 0x63, 0xfc, + 0x0d, 0xfb, 0x55, 0xfa, 0x45, 0xfa, 0xc8, 0xf9, 0x38, 0xf9, 0xe4, 0xf8, + 0x13, 0xf9, 0xce, 0xf9, 0x9d, 0xfa, 0x9d, 0xfb, 0xe8, 0xfc, 0x55, 0xfe, + 0xec, 0xff, 0x91, 0x01, 0x00, 0x03, 0xa6, 0x04, 0x69, 0x06, 0xf4, 0x07, + 0x4d, 0x09, 0x0b, 0x0a, 0x7b, 0x0a, 0x04, 0x0b, 0x55, 0x0b, 0x4f, 0x0b, + 0x24, 0x0b, 0x72, 0x0a, 0x8c, 0x09, 0x9f, 0x08, 0x9a, 0x07, 0xb9, 0x06, + 0xdc, 0x05, 0xf3, 0x04, 0xfe, 0x03, 0xd5, 0x02, 0xf9, 0x01, 0x95, 0x01, + 0x2d, 0x01, 0xe1, 0x00, 0x7f, 0x00, 0xd4, 0xff, 0x6a, 0xff, 0x63, 0xff, + 0x2d, 0xff, 0xf4, 0xfe, 0x7e, 0xfe, 0xb8, 0xfd, 0x24, 0xfd, 0x8f, 0xfc, + 0xde, 0xfb, 0x72, 0xfb, 0xc6, 0xfa, 0xd6, 0xf9, 0x35, 0xf9, 0xd8, 0xf8, + 0xc2, 0xf8, 0xcc, 0xf8, 0xec, 0xf8, 0x31, 0xf9, 0xae, 0xf9, 0x95, 0xfa, + 0xa7, 0xfb, 0x00, 0xfd, 0x64, 0xfe, 0xa5, 0xff, 0x08, 0x01, 0x74, 0x02, + 0xec, 0x03, 0x2b, 0x05, 0x0f, 0x06, 0xb7, 0x06, 0xe4, 0x06, 0xdf, 0x06, + 0xdd, 0x06, 0x21, 0x06, 0x25, 0x05, 0x28, 0x04, 0xa9, 0x02, 0x36, 0x01, + 0x83, 0xff, 0xb6, 0xfd, 0x24, 0xfc, 0x85, 0xfa, 0xf8, 0xf8, 0x29, 0xf7, + 0x55, 0xf5, 0xe2, 0xf3, 0xb6, 0xf2, 0x7f, 0xf1, 0x8a, 0xf0, 0xa6, 0xef, + 0x15, 0xef, 0xfb, 0xee, 0xfc, 0xee, 0x9a, 0xef, 0x7e, 0xf0, 0x2d, 0xf1, + 0x89, 0xf2, 0x2c, 0xf4, 0xcd, 0xf5, 0xd1, 0xf7, 0xf0, 0xf9, 0xe8, 0xfb, + 0x02, 0xfe, 0xd8, 0xff, 0x80, 0x01, 0x7d, 0x03, 0x16, 0x05, 0x5c, 0x06, + 0x54, 0x07, 0x88, 0x07, 0xdb, 0x07, 0xb1, 0x08, 0x19, 0x09, 0x11, 0x09, + 0x92, 0x08, 0xcc, 0x07, 0x9e, 0x07, 0xeb, 0x07, 0xde, 0x07, 0xa7, 0x07, + 0xfe, 0x06, 0x69, 0x06, 0x7d, 0x06, 0xb0, 0x06, 0xb7, 0x06, 0x72, 0x06, + 0xc4, 0x05, 0x5e, 0x05, 0x43, 0x05, 0xd1, 0x04, 0x1c, 0x04, 0x58, 0x03, + 0x80, 0x02, 0x94, 0x01, 0x74, 0x00, 0x44, 0xff, 0x84, 0xfe, 0xb6, 0xfd, + 0x72, 0xfc, 0x49, 0xfb, 0xae, 0xfa, 0x81, 0xfa, 0x60, 0xfa, 0x25, 0xfa, + 0xfd, 0xf9, 0x52, 0xfa, 0x49, 0xfb, 0x6a, 0xfc, 0x84, 0xfd, 0x66, 0xfe, + 0x9a, 0xff, 0x26, 0x01, 0x96, 0x02, 0xe3, 0x03, 0x41, 0x05, 0x8d, 0x06, + 0x79, 0x07, 0x20, 0x08, 0x8c, 0x08, 0x2f, 0x09, 0xc8, 0x09, 0xbf, 0x09, + 0x40, 0x09, 0xbd, 0x08, 0x66, 0x08, 0x0e, 0x08, 0x6b, 0x07, 0x98, 0x06, + 0xe7, 0x05, 0x37, 0x05, 0x60, 0x04, 0xb4, 0x03, 0x2c, 0x03, 0xdf, 0x02, + 0x5c, 0x02, 0x9c, 0x01, 0x10, 0x01, 0x9e, 0x00, 0x66, 0x00, 0x1f, 0x00, + 0x76, 0xff, 0xbe, 0xfe, 0x1e, 0xfe, 0x80, 0xfd, 0x09, 0xfd, 0x63, 0xfc, + 0xa2, 0xfb, 0xdc, 0xfa, 0x11, 0xfa, 0x94, 0xf9, 0x65, 0xf9, 0x2c, 0xf9, + 0xd6, 0xf8, 0xc4, 0xf8, 0x0c, 0xf9, 0x93, 0xf9, 0x54, 0xfa, 0x26, 0xfb, + 0x1e, 0xfc, 0x38, 0xfd, 0x52, 0xfe, 0x95, 0xff, 0xee, 0x00, 0x42, 0x02, + 0x5e, 0x03, 0x2a, 0x04, 0xd5, 0x04, 0x62, 0x05, 0xd5, 0x05, 0xd1, 0x05, + 0x57, 0x05, 0xa4, 0x04, 0xe4, 0x03, 0xe6, 0x02, 0xdf, 0x01, 0x35, 0x00, + 0xa2, 0xfe, 0xa0, 0xfd, 0x09, 0xfc, 0x51, 0xfa, 0xe3, 0xf8, 0x5f, 0xf7, + 0x2c, 0xf6, 0x26, 0xf5, 0x58, 0xf3, 0x3c, 0xf2, 0xaf, 0xf1, 0xc9, 0xf0, + 0x83, 0xf0, 0x81, 0xf0, 0x6b, 0xf0, 0x20, 0xf1, 0xc4, 0xf1, 0x7a, 0xf2, + 0xb8, 0xf3, 0x89, 0xf5, 0x65, 0xf7, 0x09, 0xf9, 0xcd, 0xfa, 0x6f, 0xfc, + 0x4c, 0xfe, 0x6a, 0x00, 0x42, 0x02, 0xa6, 0x03, 0xe3, 0x04, 0xce, 0x05, + 0x54, 0x06, 0xf9, 0x06, 0xa9, 0x07, 0x11, 0x08, 0x16, 0x08, 0x83, 0x07, + 0x2e, 0x07, 0x30, 0x07, 0x36, 0x07, 0x3e, 0x07, 0x0b, 0x07, 0x92, 0x06, + 0x85, 0x06, 0x90, 0x06, 0x81, 0x06, 0xa1, 0x06, 0xba, 0x06, 0xb0, 0x06, + 0x77, 0x06, 0xea, 0x05, 0x72, 0x05, 0x6a, 0x05, 0x22, 0x05, 0x60, 0x04, + 0x26, 0x03, 0x11, 0x02, 0x49, 0x01, 0x55, 0x00, 0x39, 0xff, 0x4a, 0xfe, + 0x9b, 0xfd, 0xaa, 0xfc, 0xa3, 0xfb, 0xf4, 0xfa, 0x85, 0xfa, 0xec, 0xfa, + 0x8c, 0xfb, 0xa5, 0xfb, 0xbc, 0xfb, 0x1f, 0xfc, 0x36, 0xfd, 0xc3, 0xfe, + 0x1b, 0x00, 0x47, 0x01, 0x44, 0x02, 0x1e, 0x03, 0x3d, 0x04, 0x61, 0x05, + 0x47, 0x06, 0x37, 0x07, 0xe1, 0x07, 0xf6, 0x07, 0xc2, 0x07, 0x8d, 0x07, + 0xac, 0x07, 0xf7, 0x07, 0xac, 0x07, 0xeb, 0x06, 0x27, 0x06, 0x75, 0x05, + 0x08, 0x05, 0xdb, 0x04, 0x88, 0x04, 0x07, 0x04, 0x70, 0x03, 0xea, 0x02, + 0x60, 0x02, 0xff, 0x01, 0xf9, 0x01, 0xd1, 0x01, 0x47, 0x01, 0x92, 0x00, + 0xdb, 0xff, 0x1d, 0xff, 0xbe, 0xfe, 0x43, 0xfe, 0x8e, 0xfd, 0x8d, 0xfc, + 0xa2, 0xfb, 0xc6, 0xfa, 0x2d, 0xfa, 0x9d, 0xf9, 0x43, 0xf9, 0x38, 0xf9, + 0x0a, 0xf9, 0xdd, 0xf8, 0xfe, 0xf8, 0x7e, 0xf9, 0x64, 0xfa, 0x9e, 0xfb, + 0x98, 0xfc, 0x82, 0xfd, 0x80, 0xfe, 0x9b, 0xff, 0xe2, 0x00, 0x31, 0x02, + 0x63, 0x03, 0xf2, 0x03, 0x35, 0x04, 0x3e, 0x04, 0x53, 0x04, 0x6d, 0x04, + 0x4c, 0x04, 0xa9, 0x03, 0x6e, 0x02, 0x12, 0x01, 0x2a, 0x00, 0x54, 0xff, + 0x43, 0xfe, 0xf8, 0xfc, 0x30, 0xfb, 0xe8, 0xf9, 0xcc, 0xf8, 0xaf, 0xf7, + 0x6f, 0xf6, 0x5e, 0xf5, 0x0c, 0xf4, 0xf5, 0xf2, 0x77, 0xf2, 0x0c, 0xf2, + 0xcf, 0xf1, 0xda, 0xf1, 0x08, 0xf2, 0x5f, 0xf2, 0xf2, 0xf2, 0x39, 0xf4, + 0xe0, 0xf5, 0x38, 0xf7, 0x9f, 0xf8, 0x1a, 0xfa, 0xcd, 0xfb, 0xcd, 0xfd, + 0xd3, 0xff, 0x4e, 0x01, 0x77, 0x02, 0x99, 0x03, 0x7f, 0x04, 0x89, 0x05, + 0xaf, 0x06, 0xd8, 0x06, 0x88, 0x06, 0x64, 0x06, 0x74, 0x06, 0xda, 0x06, + 0xae, 0x06, 0x08, 0x06, 0x8b, 0x05, 0x4f, 0x05, 0x7d, 0x05, 0xc7, 0x05, + 0xc8, 0x05, 0x90, 0x05, 0x8b, 0x05, 0xa9, 0x05, 0xed, 0x05, 0x2b, 0x06, + 0x3f, 0x06, 0x6b, 0x06, 0x26, 0x06, 0x83, 0x05, 0xcd, 0x04, 0x68, 0x04, + 0x4a, 0x04, 0xde, 0x03, 0x73, 0x02, 0x03, 0x01, 0xeb, 0xff, 0x64, 0xff, + 0xde, 0xfe, 0xba, 0xfd, 0xaf, 0xfc, 0x48, 0xfc, 0x5f, 0xfc, 0x1f, 0xfc, + 0x79, 0xfb, 0xa4, 0xfb, 0x9a, 0xfc, 0xe8, 0xfd, 0xe0, 0xfe, 0xfd, 0xfe, + 0x6b, 0xff, 0xb3, 0x00, 0x67, 0x02, 0xdf, 0x03, 0xa4, 0x04, 0x3c, 0x05, + 0xcb, 0x05, 0x30, 0x06, 0xa9, 0x06, 0x1d, 0x07, 0xa2, 0x07, 0xc7, 0x07, + 0x29, 0x07, 0x54, 0x06, 0xac, 0x05, 0x9b, 0x05, 0xc8, 0x05, 0x80, 0x05, + 0xb0, 0x04, 0xa8, 0x03, 0x2e, 0x03, 0xf2, 0x02, 0xfd, 0x02, 0xfd, 0x02, + 0xb1, 0x02, 0x2e, 0x02, 0xa0, 0x01, 0x28, 0x01, 0xf4, 0x00, 0x04, 0x01, + 0xcd, 0x00, 0x09, 0x00, 0xff, 0xfe, 0xf3, 0xfd, 0x62, 0xfd, 0xff, 0xfc, + 0x6f, 0xfc, 0xa3, 0xfb, 0xac, 0xfa, 0xf0, 0xf9, 0x8a, 0xf9, 0x65, 0xf9, + 0x6f, 0xf9, 0x9b, 0xf9, 0x06, 0xfa, 0x5f, 0xfa, 0xd8, 0xfa, 0xb3, 0xfb, + 0xc7, 0xfc, 0x12, 0xfe, 0x54, 0xff, 0x54, 0x00, 0x34, 0x01, 0xec, 0x01, + 0xbf, 0x02, 0x74, 0x03, 0x0a, 0x04, 0x47, 0x04, 0xf4, 0x03, 0x7a, 0x03, + 0x18, 0x03, 0x77, 0x02, 0xb2, 0x01, 0xa7, 0x00, 0x86, 0xff, 0x71, 0xfe, + 0x36, 0xfd, 0xec, 0xfb, 0x9c, 0xfa, 0x72, 0xf9, 0x74, 0xf8, 0x5a, 0xf7, + 0xde, 0xf5, 0x8d, 0xf4, 0xb6, 0xf3, 0x0b, 0xf3, 0xa8, 0xf2, 0x75, 0xf2, + 0x3f, 0xf2, 0xe9, 0xf1, 0x3c, 0xf2, 0x34, 0xf3, 0x89, 0xf4, 0xf9, 0xf5, + 0xff, 0xf6, 0xfb, 0xf7, 0x5d, 0xf9, 0x92, 0xfb, 0xb1, 0xfd, 0x44, 0xff, + 0x58, 0x00, 0x7c, 0x01, 0xb9, 0x02, 0xee, 0x03, 0xf1, 0x04, 0x85, 0x05, + 0xc2, 0x05, 0xe8, 0x05, 0xd8, 0x05, 0xc4, 0x05, 0xd2, 0x05, 0xe1, 0x05, + 0xa8, 0x05, 0x47, 0x05, 0x0d, 0x05, 0x16, 0x05, 0x58, 0x05, 0xa0, 0x05, + 0xb6, 0x05, 0xae, 0x05, 0xee, 0x05, 0x3e, 0x06, 0x9b, 0x06, 0xe2, 0x06, + 0xc9, 0x06, 0xb2, 0x06, 0x74, 0x06, 0x1d, 0x06, 0xce, 0x05, 0x2c, 0x05, + 0x4d, 0x04, 0x7c, 0x03, 0x66, 0x02, 0x5d, 0x01, 0x7d, 0x00, 0x8e, 0xff, + 0xaf, 0xfe, 0xbc, 0xfd, 0xf7, 0xfc, 0x74, 0xfc, 0x64, 0xfc, 0x71, 0xfc, + 0x43, 0xfc, 0x83, 0xfc, 0x39, 0xfd, 0x06, 0xfe, 0xc4, 0xfe, 0x9f, 0xff, + 0x9a, 0x00, 0x76, 0x01, 0x85, 0x02, 0x97, 0x03, 0x6f, 0x04, 0x06, 0x05, + 0x7b, 0x05, 0xeb, 0x05, 0x46, 0x06, 0x6a, 0x06, 0x5d, 0x06, 0x19, 0x06, + 0xe2, 0x05, 0x9b, 0x05, 0x05, 0x05, 0xaf, 0x04, 0x4f, 0x04, 0x20, 0x04, + 0xc3, 0x03, 0x42, 0x03, 0x01, 0x03, 0xd8, 0x02, 0xeb, 0x02, 0xc0, 0x02, + 0x81, 0x02, 0x73, 0x02, 0x3b, 0x02, 0xde, 0x01, 0x78, 0x01, 0x24, 0x01, + 0xca, 0x00, 0x39, 0x00, 0x74, 0xff, 0x7c, 0xfe, 0x9a, 0xfd, 0x31, 0xfd, + 0xa2, 0xfc, 0xbf, 0xfb, 0x04, 0xfb, 0x6c, 0xfa, 0x36, 0xfa, 0x0a, 0xfa, + 0x3a, 0xfa, 0x79, 0xfa, 0xb5, 0xfa, 0x38, 0xfb, 0xd9, 0xfb, 0xc2, 0xfc, + 0xe8, 0xfd, 0xdd, 0xfe, 0xa0, 0xff, 0x6e, 0x00, 0x4b, 0x01, 0x13, 0x02, + 0xaf, 0x02, 0xf5, 0x02, 0x0c, 0x03, 0xff, 0x02, 0xb6, 0x02, 0x61, 0x02, + 0xcc, 0x01, 0xf8, 0x00, 0x25, 0x00, 0x36, 0xff, 0x41, 0xfe, 0x0b, 0xfd, + 0x10, 0xfc, 0x45, 0xfb, 0x14, 0xfa, 0xca, 0xf8, 0x87, 0xf7, 0x54, 0xf6, + 0x7c, 0xf5, 0xd3, 0xf4, 0xcd, 0xf3, 0xe8, 0xf2, 0x8e, 0xf2, 0x74, 0xf2, + 0xa0, 0xf2, 0x11, 0xf3, 0x6a, 0xf3, 0x33, 0xf4, 0x26, 0xf5, 0xa2, 0xf6, + 0x51, 0xf8, 0x96, 0xf9, 0x64, 0xfb, 0xf3, 0xfc, 0x47, 0xfe, 0xfc, 0xff, + 0x99, 0x01, 0xdc, 0x02, 0xd5, 0x03, 0x7b, 0x04, 0xf5, 0x04, 0x80, 0x05, + 0xc7, 0x05, 0xc7, 0x05, 0xca, 0x05, 0xa3, 0x05, 0x4e, 0x05, 0x0d, 0x05, + 0xda, 0x04, 0xd7, 0x04, 0xef, 0x04, 0xe9, 0x04, 0xe9, 0x04, 0x0a, 0x05, + 0x68, 0x05, 0xc2, 0x05, 0xfb, 0x05, 0x5a, 0x06, 0x95, 0x06, 0xbe, 0x06, + 0xae, 0x06, 0x92, 0x06, 0x51, 0x06, 0x04, 0x06, 0x7f, 0x05, 0xbf, 0x04, + 0xce, 0x03, 0xc5, 0x02, 0xe0, 0x01, 0xd8, 0x00, 0xc7, 0xff, 0xf9, 0xfe, + 0xfe, 0xfd, 0x23, 0xfd, 0xb3, 0xfc, 0x6f, 0xfc, 0x50, 0xfc, 0x6e, 0xfc, + 0x7a, 0xfc, 0x0c, 0xfd, 0xe7, 0xfd, 0xb2, 0xfe, 0xa3, 0xff, 0x79, 0x00, + 0x62, 0x01, 0x7c, 0x02, 0xa0, 0x03, 0x53, 0x04, 0xf8, 0x04, 0x6f, 0x05, + 0xf3, 0x05, 0x59, 0x06, 0x38, 0x06, 0x24, 0x06, 0x1b, 0x06, 0xc2, 0x05, + 0x5f, 0x05, 0xdf, 0x04, 0x6d, 0x04, 0x2d, 0x04, 0xd8, 0x03, 0x71, 0x03, + 0x21, 0x03, 0xf0, 0x02, 0x06, 0x03, 0xde, 0x02, 0xb3, 0x02, 0xb3, 0x02, + 0xb0, 0x02, 0x83, 0x02, 0x60, 0x02, 0x08, 0x02, 0xa2, 0x01, 0x42, 0x01, + 0x91, 0x00, 0xe4, 0xff, 0x0f, 0xff, 0x18, 0xfe, 0x50, 0xfd, 0x85, 0xfc, + 0x80, 0xfb, 0xcb, 0xfa, 0x34, 0xfa, 0xb9, 0xf9, 0x93, 0xf9, 0x71, 0xf9, + 0xa3, 0xf9, 0x1c, 0xfa, 0xc5, 0xfa, 0x7d, 0xfb, 0x50, 0xfc, 0x78, 0xfd, + 0x8d, 0xfe, 0x8d, 0xff, 0x85, 0x00, 0x60, 0x01, 0x26, 0x02, 0xbd, 0x02, + 0x1f, 0x03, 0x39, 0x03, 0x18, 0x03, 0xc3, 0x02, 0x4e, 0x02, 0xc2, 0x01, + 0x30, 0x01, 0x44, 0x00, 0x2f, 0xff, 0x43, 0xfe, 0x60, 0xfd, 0x8d, 0xfc, + 0xbe, 0xfb, 0xcf, 0xfa, 0xb1, 0xf9, 0x7e, 0xf8, 0x8f, 0xf7, 0xb8, 0xf6, + 0x1b, 0xf6, 0x76, 0xf5, 0x76, 0xf4, 0x3a, 0xf3, 0x17, 0xf3, 0x85, 0xf3, + 0x08, 0xf4, 0xf7, 0xf3, 0xd6, 0xf3, 0x9f, 0xf4, 0xb0, 0xf5, 0x2d, 0xf7, + 0x8f, 0xf8, 0x91, 0xf9, 0xef, 0xfa, 0x8b, 0xfc, 0xdb, 0xfd, 0x56, 0xff, + 0x7b, 0x00, 0xb6, 0x01, 0x15, 0x03, 0xcd, 0x03, 0xff, 0x03, 0x5e, 0x04, + 0xa8, 0x04, 0x2d, 0x05, 0x99, 0x05, 0x72, 0x05, 0x13, 0x05, 0xce, 0x04, + 0xc2, 0x04, 0xf0, 0x04, 0x16, 0x05, 0x4a, 0x05, 0x4f, 0x05, 0x2f, 0x05, + 0x40, 0x05, 0x8a, 0x05, 0xd7, 0x05, 0x1f, 0x06, 0x83, 0x06, 0x86, 0x06, + 0x23, 0x06, 0xc4, 0x05, 0x79, 0x05, 0x71, 0x05, 0x23, 0x05, 0x59, 0x04, + 0xff, 0x02, 0x20, 0x02, 0x7a, 0x01, 0xa5, 0x00, 0xcf, 0xff, 0x00, 0xff, + 0x5b, 0xfe, 0xa5, 0xfd, 0x28, 0xfd, 0xd1, 0xfc, 0xcf, 0xfc, 0x42, 0xfd, + 0xbc, 0xfd, 0x1d, 0xfe, 0x7a, 0xfe, 0x15, 0xff, 0x23, 0x00, 0x3e, 0x01, + 0x39, 0x02, 0xfa, 0x02, 0xaa, 0x03, 0x3f, 0x04, 0xbc, 0x04, 0x1e, 0x05, + 0x97, 0x05, 0xe1, 0x05, 0xdc, 0x05, 0x7f, 0x05, 0xfd, 0x04, 0xb1, 0x04, + 0x93, 0x04, 0x62, 0x04, 0xf7, 0x03, 0x81, 0x03, 0x0f, 0x03, 0xce, 0x02, + 0xb0, 0x02, 0xa9, 0x02, 0xb0, 0x02, 0xaa, 0x02, 0x7f, 0x02, 0x4a, 0x02, + 0x4a, 0x02, 0x3d, 0x02, 0x11, 0x02, 0xc6, 0x01, 0x49, 0x01, 0xc6, 0x00, + 0x2f, 0x00, 0x72, 0xff, 0xa9, 0xfe, 0xd6, 0xfd, 0x18, 0xfd, 0x62, 0xfc, + 0x9b, 0xfb, 0xbd, 0xfa, 0x35, 0xfa, 0xfc, 0xf9, 0xf5, 0xf9, 0xf7, 0xf9, + 0x0b, 0xfa, 0x5b, 0xfa, 0xf5, 0xfa, 0xc2, 0xfb, 0xb0, 0xfc, 0x96, 0xfd, + 0x92, 0xfe, 0x90, 0xff, 0x73, 0x00, 0x50, 0x01, 0x0c, 0x02, 0x7a, 0x02, + 0xe9, 0x02, 0x16, 0x03, 0x19, 0x03, 0xdf, 0x02, 0x54, 0x02, 0xd4, 0x01, + 0x36, 0x01, 0x73, 0x00, 0x95, 0xff, 0x9a, 0xfe, 0xb9, 0xfd, 0xc2, 0xfc, + 0xbb, 0xfb, 0xae, 0xfa, 0xc1, 0xf9, 0x10, 0xf9, 0x12, 0xf8, 0x2c, 0xf7, + 0x2e, 0xf6, 0x48, 0xf5, 0xdd, 0xf4, 0xa2, 0xf4, 0x6f, 0xf4, 0x30, 0xf4, + 0x0f, 0xf4, 0x42, 0xf4, 0xca, 0xf4, 0x96, 0xf5, 0x91, 0xf6, 0x64, 0xf7, + 0x4b, 0xf8, 0x5e, 0xf9, 0x91, 0xfa, 0xb7, 0xfb, 0x0e, 0xfd, 0x88, 0xfe, + 0x85, 0xff, 0x36, 0x00, 0xcc, 0x00, 0x8e, 0x01, 0x96, 0x02, 0x4b, 0x03, + 0x80, 0x03, 0x8a, 0x03, 0x86, 0x03, 0xd2, 0x03, 0x31, 0x04, 0x65, 0x04, + 0x6d, 0x04, 0x8b, 0x04, 0xb2, 0x04, 0xca, 0x04, 0x07, 0x05, 0x60, 0x05, + 0x95, 0x05, 0xf0, 0x05, 0x39, 0x06, 0x2f, 0x06, 0x1e, 0x06, 0x38, 0x06, + 0x55, 0x06, 0x39, 0x06, 0xc9, 0x05, 0x36, 0x05, 0xb5, 0x04, 0x23, 0x04, + 0x92, 0x03, 0xc7, 0x02, 0xf4, 0x01, 0x35, 0x01, 0x7d, 0x00, 0xeb, 0xff, + 0x38, 0xff, 0xb4, 0xfe, 0x62, 0xfe, 0x49, 0xfe, 0x4c, 0xfe, 0x44, 0xfe, + 0x4a, 0xfe, 0xb5, 0xfe, 0x64, 0xff, 0x0a, 0x00, 0x67, 0x00, 0xf5, 0x00, + 0xc1, 0x01, 0x84, 0x02, 0x2a, 0x03, 0xa6, 0x03, 0x0e, 0x04, 0x88, 0x04, + 0xe0, 0x04, 0x20, 0x05, 0x1a, 0x05, 0x05, 0x05, 0xec, 0x04, 0xd2, 0x04, + 0x88, 0x04, 0x2e, 0x04, 0xd9, 0x03, 0x7e, 0x03, 0x2e, 0x03, 0xd8, 0x02, + 0x9a, 0x02, 0x5d, 0x02, 0x1d, 0x02, 0xdd, 0x01, 0xb2, 0x01, 0x96, 0x01, + 0x6e, 0x01, 0x35, 0x01, 0xf4, 0x00, 0x97, 0x00, 0x69, 0x00, 0x21, 0x00, + 0xa5, 0xff, 0x07, 0xff, 0x53, 0xfe, 0xda, 0xfd, 0x77, 0xfd, 0xee, 0xfc, + 0x47, 0xfc, 0x9c, 0xfb, 0x30, 0xfb, 0xff, 0xfa, 0xf1, 0xfa, 0xf3, 0xfa, + 0x05, 0xfb, 0x33, 0xfb, 0x8d, 0xfb, 0x21, 0xfc, 0xe3, 0xfc, 0xa6, 0xfd, + 0x7a, 0xfe, 0x4e, 0xff, 0x1a, 0x00, 0xda, 0x00, 0x8a, 0x01, 0x10, 0x02, + 0x8b, 0x02, 0xec, 0x02, 0x16, 0x03, 0x1b, 0x03, 0xb3, 0x02, 0x29, 0x02, + 0xcd, 0x01, 0x42, 0x01, 0xc1, 0x00, 0xe9, 0xff, 0xc2, 0xfe, 0xbb, 0xfd, + 0x23, 0xfd, 0x73, 0xfc, 0xa8, 0xfb, 0xa6, 0xfa, 0x6e, 0xf9, 0xa2, 0xf8, + 0xea, 0xf7, 0x47, 0xf7, 0xc0, 0xf6, 0x3d, 0xf6, 0xb2, 0xf5, 0x25, 0xf5, + 0xf1, 0xf4, 0x29, 0xf5, 0xc5, 0xf5, 0x2a, 0xf6, 0x67, 0xf6, 0xfb, 0xf6, + 0xb1, 0xf7, 0xb7, 0xf8, 0x3b, 0xfa, 0x4b, 0xfb, 0x18, 0xfc, 0xea, 0xfc, + 0xdb, 0xfd, 0x26, 0xff, 0x44, 0x00, 0xce, 0x00, 0xfd, 0x00, 0x96, 0x01, + 0x4c, 0x02, 0xca, 0x02, 0xad, 0x02, 0x82, 0x02, 0xc9, 0x02, 0x18, 0x03, + 0x52, 0x03, 0x3f, 0x03, 0x47, 0x03, 0x84, 0x03, 0xa0, 0x03, 0x02, 0x04, + 0x6b, 0x04, 0xdc, 0x04, 0x33, 0x05, 0x52, 0x05, 0x6b, 0x05, 0x9f, 0x05, + 0xf7, 0x05, 0x58, 0x06, 0x47, 0x06, 0xe0, 0x05, 0x4f, 0x05, 0xef, 0x04, + 0xb1, 0x04, 0x43, 0x04, 0xbf, 0x03, 0xdb, 0x02, 0xf0, 0x01, 0x4c, 0x01, + 0xc6, 0x00, 0x72, 0x00, 0x05, 0x00, 0xa6, 0xff, 0x65, 0xff, 0x41, 0xff, + 0x64, 0xff, 0xa0, 0xff, 0x1d, 0x00, 0xa4, 0x00, 0x26, 0x01, 0xa6, 0x01, + 0x39, 0x02, 0xf4, 0x02, 0xb5, 0x03, 0x42, 0x04, 0xb8, 0x04, 0x09, 0x05, + 0x43, 0x05, 0x66, 0x05, 0x75, 0x05, 0x6e, 0x05, 0x1d, 0x05, 0xc4, 0x04, + 0x74, 0x04, 0xe7, 0x03, 0x90, 0x03, 0x28, 0x03, 0x85, 0x02, 0x2b, 0x02, + 0xe5, 0x01, 0x95, 0x01, 0x65, 0x01, 0x26, 0x01, 0xe9, 0x00, 0xfb, 0x00, + 0x07, 0x01, 0x00, 0x01, 0xe9, 0x00, 0xbd, 0x00, 0x94, 0x00, 0x59, 0x00, + 0x3a, 0x00, 0xdf, 0xff, 0x5a, 0xff, 0xd7, 0xfe, 0x40, 0xfe, 0xaf, 0xfd, + 0x1c, 0xfd, 0x94, 0xfc, 0x1b, 0xfc, 0xb1, 0xfb, 0x61, 0xfb, 0x18, 0xfb, + 0x18, 0xfb, 0x56, 0xfb, 0xb1, 0xfb, 0x1c, 0xfc, 0x9e, 0xfc, 0x45, 0xfd, + 0x13, 0xfe, 0xd8, 0xfe, 0x94, 0xff, 0x67, 0x00, 0x10, 0x01, 0x8e, 0x01, + 0xf4, 0x01, 0x24, 0x02, 0x48, 0x02, 0x48, 0x02, 0x01, 0x02, 0x98, 0x01, + 0x02, 0x01, 0x6b, 0x00, 0xc7, 0xff, 0x11, 0xff, 0x6f, 0xfe, 0x93, 0xfd, + 0xa6, 0xfc, 0x08, 0xfc, 0x4f, 0xfb, 0xb0, 0xfa, 0xff, 0xf9, 0x7e, 0xf9, + 0xef, 0xf8, 0x45, 0xf8, 0xcd, 0xf7, 0xa0, 0xf7, 0x54, 0xf7, 0x1d, 0xf7, + 0xd2, 0xf6, 0xda, 0xf6, 0x1e, 0xf7, 0x73, 0xf7, 0xca, 0xf7, 0x38, 0xf8, + 0xe6, 0xf8, 0x81, 0xf9, 0x8d, 0xfa, 0x62, 0xfb, 0x38, 0xfc, 0x25, 0xfd, + 0x02, 0xfe, 0xad, 0xfe, 0x7a, 0xff, 0x3e, 0x00, 0xe5, 0x00, 0x69, 0x01, + 0xb4, 0x01, 0xfc, 0x01, 0x47, 0x02, 0x7d, 0x02, 0xae, 0x02, 0xcb, 0x02, + 0x1d, 0x03, 0x2c, 0x03, 0x01, 0x03, 0x40, 0x03, 0x8a, 0x03, 0xdf, 0x03, + 0x34, 0x04, 0x4c, 0x04, 0x5a, 0x04, 0x7f, 0x04, 0xc4, 0x04, 0x06, 0x05, + 0x2a, 0x05, 0x1a, 0x05, 0xe5, 0x04, 0x98, 0x04, 0x52, 0x04, 0x1d, 0x04, + 0xc4, 0x03, 0x56, 0x03, 0xfe, 0x02, 0x5c, 0x02, 0xc1, 0x01, 0x5c, 0x01, + 0xf5, 0x00, 0xbd, 0x00, 0x88, 0x00, 0x57, 0x00, 0x1e, 0x00, 0x20, 0x00, + 0x51, 0x00, 0x89, 0x00, 0xdb, 0x00, 0x3d, 0x01, 0xb3, 0x01, 0x42, 0x02, + 0xa2, 0x02, 0xf8, 0x02, 0x6a, 0x03, 0xee, 0x03, 0x6f, 0x04, 0xb9, 0x04, + 0xd6, 0x04, 0xc7, 0x04, 0xce, 0x04, 0xdf, 0x04, 0xbc, 0x04, 0xad, 0x04, + 0x7a, 0x04, 0x20, 0x04, 0xb1, 0x03, 0x5c, 0x03, 0x40, 0x03, 0x12, 0x03, + 0xd0, 0x02, 0xa7, 0x02, 0x4f, 0x02, 0x0f, 0x02, 0xfd, 0x01, 0xd6, 0x01, + 0x9d, 0x01, 0x63, 0x01, 0x19, 0x01, 0xb7, 0x00, 0x3a, 0x00, 0xd2, 0xff, + 0x7c, 0xff, 0x0b, 0xff, 0x84, 0xfe, 0xb8, 0xfd, 0x46, 0xfd, 0xfb, 0xfc, + 0x97, 0xfc, 0x49, 0xfc, 0xf0, 0xfb, 0xd2, 0xfb, 0xd3, 0xfb, 0xf4, 0xfb, + 0x2b, 0xfc, 0x6f, 0xfc, 0xcc, 0xfc, 0x49, 0xfd, 0xd2, 0xfd, 0x3f, 0xfe, + 0xbb, 0xfe, 0x4d, 0xff, 0xe8, 0xff, 0x56, 0x00, 0xa5, 0x00, 0xfa, 0x00, + 0x2a, 0x01, 0x48, 0x01, 0x5c, 0x01, 0x4e, 0x01, 0x29, 0x01, 0x03, 0x01, + 0xcc, 0x00, 0x88, 0x00, 0x3c, 0x00, 0xc8, 0xff, 0x7f, 0xff, 0x25, 0xff, + 0x9f, 0xfe, 0x1b, 0xfe, 0xa0, 0xfd, 0x08, 0xfd, 0x92, 0xfc, 0xee, 0xfb, + 0x36, 0xfb, 0xbc, 0xfa, 0x24, 0xfa, 0x7d, 0xf9, 0xd9, 0xf8, 0x5c, 0xf8, + 0xf3, 0xf7, 0x91, 0xf7, 0x4c, 0xf7, 0x0a, 0xf7, 0x22, 0xf7, 0x60, 0xf7, + 0x7f, 0xf7, 0xda, 0xf7, 0x4c, 0xf8, 0xf3, 0xf8, 0x88, 0xf9, 0x8d, 0xfa, + 0x56, 0xfb, 0xfd, 0xfb, 0xa7, 0xfc, 0x06, 0xfd, 0x38, 0xfe, 0x32, 0xff, + 0x8a, 0xff, 0xf5, 0xff, 0x52, 0x00, 0xbd, 0x00, 0x23, 0x01, 0xb7, 0x01, + 0xfc, 0x01, 0x2d, 0x02, 0x73, 0x02, 0x96, 0x02, 0xe2, 0x02, 0x2b, 0x03, + 0x84, 0x03, 0xd3, 0x03, 0x0d, 0x04, 0x1f, 0x04, 0x53, 0x04, 0x5c, 0x04, + 0x88, 0x04, 0xc1, 0x04, 0x9e, 0x04, 0x78, 0x04, 0x55, 0x04, 0x28, 0x04, + 0xc8, 0x03, 0x63, 0x03, 0x39, 0x03, 0xf0, 0x02, 0x6d, 0x02, 0xc8, 0x01, + 0x64, 0x01, 0x40, 0x01, 0x17, 0x01, 0xcf, 0x00, 0x78, 0x00, 0x5c, 0x00, + 0x68, 0x00, 0x53, 0x00, 0x7a, 0x00, 0xae, 0x00, 0xe5, 0x00, 0x4d, 0x01, + 0x85, 0x01, 0xb6, 0x01, 0x1e, 0x02, 0x7b, 0x02, 0xeb, 0x02, 0x45, 0x03, + 0x84, 0x03, 0xa9, 0x03, 0xc4, 0x03, 0xd8, 0x03, 0xe0, 0x03, 0xe4, 0x03, + 0xe5, 0x03, 0xc1, 0x03, 0x50, 0x03, 0x0f, 0x03, 0xef, 0x02, 0xd9, 0x02, + 0xaa, 0x02, 0x6d, 0x02, 0x27, 0x02, 0xfe, 0x01, 0xd6, 0x01, 0xa6, 0x01, + 0x93, 0x01, 0x7f, 0x01, 0x51, 0x01, 0xea, 0x00, 0x80, 0x00, 0x37, 0x00, + 0x03, 0x00, 0xbc, 0xff, 0x4b, 0xff, 0xcc, 0xfe, 0x4f, 0xfe, 0xd8, 0xfd, + 0x9e, 0xfd, 0x82, 0xfd, 0x6a, 0xfd, 0x3f, 0xfd, 0x07, 0xfd, 0x09, 0xfd, + 0x2d, 0xfd, 0x89, 0xfd, 0xec, 0xfd, 0x43, 0xfe, 0x7f, 0xfe, 0xc2, 0xfe, + 0x14, 0xff, 0x8b, 0xff, 0x12, 0x00, 0x60, 0x00, 0x83, 0x00, 0x99, 0x00, + 0xde, 0x00, 0x20, 0x01, 0x33, 0x01, 0x24, 0x01, 0x16, 0x01, 0x35, 0x01, + 0x26, 0x01, 0xf4, 0x00, 0xbc, 0x00, 0x8a, 0x00, 0x78, 0x00, 0x34, 0x00, + 0xef, 0xff, 0xca, 0xff, 0x93, 0xff, 0xe9, 0xfe, 0x6f, 0xfe, 0x42, 0xfe, + 0xe5, 0xfd, 0x86, 0xfd, 0xd0, 0xfc, 0x1e, 0xfc, 0x7f, 0xfb, 0x30, 0xfb, + 0xcb, 0xfa, 0x26, 0xfa, 0xbd, 0xf9, 0x59, 0xf9, 0xed, 0xf8, 0xee, 0xf8, + 0xbc, 0xf8, 0x8b, 0xf8, 0x8d, 0xf8, 0x70, 0xf8, 0x94, 0xf8, 0xc8, 0xf8, + 0x0c, 0xf9, 0x3f, 0xf9, 0x67, 0xf9, 0x97, 0xf9, 0x29, 0xfa, 0xe5, 0xfa, + 0x61, 0xfb, 0xbb, 0xfb, 0x17, 0xfc, 0xa1, 0xfc, 0x7f, 0xfd, 0x17, 0xfe, + 0x58, 0xfe, 0xc8, 0xfe, 0x7c, 0xff, 0xf2, 0xff, 0xf5, 0xff, 0x59, 0x00, + 0xe7, 0x00, 0x4e, 0x01, 0x7e, 0x01, 0x90, 0x01, 0xb6, 0x01, 0x05, 0x02, + 0x9d, 0x02, 0xbc, 0x02, 0xbf, 0x02, 0xbf, 0x02, 0xe4, 0x02, 0x16, 0x03, + 0x31, 0x03, 0x3d, 0x03, 0x22, 0x03, 0x0c, 0x03, 0xf4, 0x02, 0xe9, 0x02, + 0xe0, 0x02, 0xae, 0x02, 0x7c, 0x02, 0x53, 0x02, 0x45, 0x02, 0x1f, 0x02, + 0x09, 0x02, 0xef, 0x01, 0xde, 0x01, 0xe8, 0x01, 0xe2, 0x01, 0xd6, 0x01, + 0xd1, 0x01, 0xef, 0x01, 0xfd, 0x01, 0xe5, 0x01, 0xfd, 0x01, 0x1c, 0x02, + 0x0b, 0x02, 0x0d, 0x02, 0xf3, 0x01, 0xf7, 0x01, 0x39, 0x02, 0x40, 0x02, + 0x39, 0x02, 0x59, 0x02, 0x7a, 0x02, 0x9d, 0x02, 0xcb, 0x02, 0x12, 0x03, + 0x3d, 0x03, 0x5e, 0x03, 0x62, 0x03, 0x72, 0x03, 0x81, 0x03, 0x8a, 0x03, + 0x70, 0x03, 0x37, 0x03, 0x1b, 0x03, 0xc1, 0x02, 0x71, 0x02, 0x17, 0x02, + 0xd2, 0x01, 0x80, 0x01, 0x29, 0x01, 0xe9, 0x00, 0x83, 0x00, 0x37, 0x00, + 0xf9, 0xff, 0xe2, 0xff, 0xe2, 0xff, 0xbf, 0xff, 0x8a, 0xff, 0x5b, 0xff, + 0x3f, 0xff, 0x51, 0xff, 0x4c, 0xff, 0x3a, 0xff, 0x3f, 0xff, 0x29, 0xff, + 0x1d, 0xff, 0x14, 0xff, 0x0e, 0xff, 0x3a, 0xff, 0x65, 0xff, 0x70, 0xff, + 0x86, 0xff, 0x9f, 0xff, 0xb4, 0xff, 0xd9, 0xff, 0x2d, 0x00, 0x6b, 0x00, + 0xa6, 0x00, 0xb0, 0x00, 0xb0, 0x00, 0xc4, 0x00, 0xe1, 0x00, 0x0d, 0x01, + 0x03, 0x01, 0xeb, 0x00, 0xb3, 0x00, 0x83, 0x00, 0x51, 0x00, 0x3e, 0x00, + 0x09, 0x00, 0xc0, 0xff, 0x82, 0xff, 0x39, 0xff, 0xcf, 0xfe, 0x85, 0xfe, + 0x4a, 0xfe, 0x08, 0xfe, 0xd3, 0xfd, 0x5e, 0xfd, 0x24, 0xfd, 0xf1, 0xfc, + 0xba, 0xfc, 0x95, 0xfc, 0x68, 0xfc, 0x07, 0xfc, 0xaf, 0xfb, 0x85, 0xfb, + 0x79, 0xfb, 0x50, 0xfb, 0x1c, 0xfb, 0xe7, 0xfa, 0xc9, 0xfa, 0xeb, 0xfa, + 0x03, 0xfb, 0x15, 0xfb, 0x00, 0xfb, 0x5e, 0xfb, 0x5d, 0xfb, 0xa6, 0xfb, + 0xf8, 0xfb, 0xeb, 0xfb, 0x10, 0xfc, 0x42, 0xfc, 0x71, 0xfc, 0xb5, 0xfc, + 0xa5, 0xfc, 0x93, 0xfc, 0x92, 0xfc, 0xd3, 0xfc, 0x48, 0xfd, 0xfb, 0xfc, + 0x37, 0xfd, 0x43, 0xfd, 0xb9, 0xfd, 0x13, 0xfe, 0x4b, 0xfe, 0xda, 0xfe, + 0x6b, 0xff, 0xc3, 0xff, 0xf4, 0xff, 0x3c, 0x00, 0x9b, 0x00, 0xe6, 0x00, + 0xfe, 0x00, 0xf0, 0x00, 0xd3, 0x00, 0xe5, 0x00, 0xa3, 0x00, 0x80, 0x00, + 0x90, 0x00, 0x9e, 0x00, 0x90, 0x00, 0x5e, 0x00, 0x75, 0x00, 0x7a, 0x00, + 0x74, 0x00, 0x62, 0x00, 0x40, 0x00, 0x38, 0x00, 0x23, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xfa, 0xff, + 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xf8, 0xff, 0xf7, 0xff, 0xf7, 0xff, + 0xf8, 0xff, 0xf8, 0xff, 0xf8, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, + 0xfa, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xf9, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfc, 0xff, + 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, + 0xfa, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, + 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfd, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, + 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0xfb, 0xff, + 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfb, 0xff, + 0xfb, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; +uint32_t left_channel_bin_len = 47666; \ No newline at end of file diff --git a/examples/galactic_unicorn/balls.cpp b/examples/galactic_unicorn/balls.cpp new file mode 100644 index 00000000..00d6b3d3 --- /dev/null +++ b/examples/galactic_unicorn/balls.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// extra row of pixels for sourcing flames and averaging +float heat[53][13] = {0.0f}; + +int main() { + + stdio_init_all(); + + galactic_unicorn.init(); + + while(true) { + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + graphics.set_pen(0, 0, 0); + graphics.clear(); + + + for(int y = 0; y < 12; y++) { + for(int x = 0; x < 53; x++) { + if(heat[x][y] > 0.5f) { + graphics.set_pen(255, 255, 180); + graphics.pixel(Point(x, y)); + }else if(heat[x][y] > 0.4f) { + graphics.set_pen(220, 160, 0); + graphics.pixel(Point(x, y)); + }else if(heat[x][y] > 0.3f) { + graphics.set_pen(180, 50, 0); + graphics.pixel(Point(x, y)); + }else if(heat[x][y] > 0.2f) { + graphics.set_pen(40, 40, 40); + graphics.pixel(Point(x, y)); + } + + // update this pixel by averaging the below pixels + if(x == 0) { + heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x + 1][y + 1]) / 4.0f; + } else if(x == 52) { + heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1]) / 4.0f; + } else { + heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1] + heat[x + 1][y + 1]) / 5.0f; + } + + heat[x][y] -= 0.01f; + heat[x][y] = heat[x][y] < 0.0f ? 0.0f: heat[x][y]; + } + } + + galactic_unicorn.update(graphics); + + // clear the bottom row and then add a new fire seed to it + for(int x = 0; x < 53; x++) { + heat[x][11] = 0.0f; + } + + // add a new random heat source + for(int c = 0; c < 5; c++) { + int px = (rand() % 51) + 1; + heat[px][11] = 1.0f; + heat[px + 1][11] = 1.0f; + heat[px - 1][11] = 1.0f; + heat[px][12] = 1.0f; + heat[px + 1][12] = 1.0f; + heat[px - 1][12] = 1.0f; + } + + sleep_ms(50); + } + + return 0; +} diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index 517c2d68..29ca709d 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -114,6 +114,9 @@ gpio_set_function(28, GPIO_FUNC_SIO); float brightness = 0.5f; float curve = 4.0f; + int x = 10; + int y = 5; + while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { hue_offset += 0.05; @@ -143,6 +146,27 @@ gpio_set_function(28, GPIO_FUNC_SIO); if(curve < 0.5) curve = 0.5; } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + x -= 1; + sleep_ms(250); + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + x += 1; + sleep_ms(250); + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) { + y -= 1; + sleep_ms(250); + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_D)) { + y += 1; + sleep_ms(250); + } + +/* for(int y = 0; y < 11; y++) { for(int x = 0; x < 53; x++) { float fx = x / 53.0f; @@ -150,27 +174,18 @@ gpio_set_function(28, GPIO_FUNC_SIO); float twopi = M_PI * 2; float hue = fy + (sin(fx * twopi / curve)); float fade = 1.0f; - /* if(hue < 0.0f) { - fade += (hue * 10.0f); - if(fade < 0.0f) fade = 0.0f; - } - if(hue > 1.0f) { - fade -= ((hue - 1.0f) * 10.0f); - if(fade < 0.0f) fade = 0.0f; - }*/ hue += hue_offset; while(hue < 0.0f) {hue += 1.0f;} while(hue > 1.0f) {hue -= 1.0f;} hue = 1.0f - hue; -/* - uint8_t r = 0, g = 0, b = 0; - from_hsv(hue, 1.0f, brightness * fade, r, g, b);*/ ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade}; ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f); } - } + }*/ + + galactic_unicorn.set_pixel(x, y, 255, 255, 255); /*i++; graphics.set_pen(0, 0, 0); diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp index 7bf5d2f4..ca2a79b7 100644 --- a/examples/galactic_unicorn/demo2.cpp +++ b/examples/galactic_unicorn/demo2.cpp @@ -37,9 +37,9 @@ void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { p.x += (53 / 2) - (w / 2); p.y += (11 / 2); graphics.text(t, Point(p.x, p.y), -1, s, a); - graphics.text(t, Point(p.x + 1, p.y), -1, s, a); - graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); - graphics.text(t, Point(p.x, p.y + 1), -1, s, a); + //graphics.text(t, Point(p.x + 1, p.y), -1, s, a); + //graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); + //graphics.text(t, Point(p.x, p.y + 1), -1, s, a); } struct star_t { @@ -73,6 +73,8 @@ void step_star(star_t &s) { int main() { + stdio_init_all(); + uint8_t hue_map[53][3]; for(int i = 0; i < 53; i++) { from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); @@ -103,18 +105,17 @@ gpio_set_function(28, GPIO_FUNC_SIO); bool x_pressed = false; bool y_pressed = false; */ - graphics.set_font("sans"); +graphics.set_font("bitmap8"); uint i = 0; - int v = 255; float hue_offset = 0.0f; - float brightness = 0.5f; - float curve = 4.0f; while(true) { + i++; + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { hue_offset += 0.05; if(hue_offset > 1.0f) hue_offset = 1.0f; @@ -125,69 +126,37 @@ gpio_set_function(28, GPIO_FUNC_SIO); } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { - brightness += 0.05; - if(brightness > 1.0f) brightness = 1.0f; + galactic_unicorn.adjust_brightness(+0.01); } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { - brightness -= 0.05; - if(brightness < 0.0f) brightness = 0.0f; + galactic_unicorn.adjust_brightness(-0.01); } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { - curve += 0.5; - if(curve > 100.0f) curve = 100.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { - curve -= 0.5; - if(curve < 0.5) curve = 0.5; - } -i++; - - graphics.set_pen(0, 0, 0); - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} - graphics.clear(); - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} - - - for(int i = 0; i < 100; i++) { - star_t &star = stars[i]; - step_star(star); - - uint b = star.brightness(); - graphics.set_pen(b, b, b); - //graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2))); - } - -graphics.set_pen(255, 255, 255); - float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f); +/* + graphics.set_pen(255, 255, 255); + float s = 0.65f;//0.65f + (sin(i / 25.0f) * 0.15f); float a = 1.0f;// (sin(i / 25.0f) * 100.0f); - float x = (sin(i / 25.0f) * 40.0f) * s; - float y = (cos(i / 15.0f) * 10.0f) * s; - text("Galactic", Point(x, y), s, a); - - uint16_t *p = (uint16_t *)graphics.frame_buffer; - for(size_t i = 0; i < 53 * 11; i++) { - int x = i % 53; - int y = i / 53; - uint r = ((*p & 0b1111100000000000) >> 11) << 3; - uint g = ((*p & 0b0000011111100000) >> 5) << 2; - uint b = ((*p & 0b0000000000011111) >> 0) << 3; - p++; + float x = (sin(i / 74.0f) * 80.0f) * s; + float y = (cos(i / 43.0f) * 6.0f) * s; + text("Chester smells!", Point(x, y - 3), s, a); +*/ - if(r > 200 && g > 200 && b > 200) { - r = hue_map[x][0]; - g = hue_map[x][1]; - b = hue_map[x][2]; + for(int x = 0; x < 53; x++) { + for(int y = 0; y < 11; y++) { + int v = ((sin((x + y) / 3.0f + i / 15.0f) + 1.5f) / 2.5f) * 255.0f; + + graphics.set_pen(v, v, v); + graphics.pixel(Point(x, y)); } - - galactic_unicorn.set_pixel(x, y, r, g, b); } + + galactic_unicorn.update(graphics); + - - sleep_ms(10); + printf("%d\n", galactic_unicorn.light()); + sleep_ms(20); } diff --git a/examples/galactic_unicorn/eighties_super_computer.cpp b/examples/galactic_unicorn/eighties_super_computer.cpp new file mode 100644 index 00000000..377ede56 --- /dev/null +++ b/examples/galactic_unicorn/eighties_super_computer.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +float lifetime[53][11]; +float age[53][11]; + +int main() { + + stdio_init_all(); + + for(int y = 0; y < 11; y++) { + for(int x = 0; x < 53; x++) { + lifetime[x][y] = 1.0f + ((rand() % 10) / 100.0f); + age[x][y] = ((rand() % 100) / 100.0f) * lifetime[x][y]; + } + } + + galactic_unicorn.init(); + + while(true) { + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + graphics.set_pen(0, 0, 0); + graphics.clear(); + + + for(int y = 0; y < 11; y++) { + for(int x = 0; x < 53; x++) { + if(age[x][y] < lifetime[x][y] * 0.3f) { + graphics.set_pen(230, 150, 0); + graphics.pixel(Point(x, y)); + }else if(age[x][y] < lifetime[x][y] * 0.5f) { + float decay = (lifetime[x][y] * 0.5f - age[x][y]) * 5.0f; + graphics.set_pen(decay * 230, decay * 150, 0); + graphics.pixel(Point(x, y)); + } + + if(age[x][y] >= lifetime[x][y]) { + age[x][y] = 0.0f; + lifetime[x][y] = 1.0f + ((rand() % 10) / 100.0f); + } + + age[x][y] += 0.01f; + } + } + + galactic_unicorn.update(graphics); + + sleep_ms(10); + } + + return 0; +} diff --git a/examples/galactic_unicorn/feature_test.cpp b/examples/galactic_unicorn/feature_test.cpp new file mode 100644 index 00000000..fda7cab6 --- /dev/null +++ b/examples/galactic_unicorn/feature_test.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// left_channel_bin and right_channel_bin are in audio_samples.cpp +extern uint8_t left_channel_bin[]; +extern uint32_t left_channel_bin_len; +extern uint8_t right_channel_bin[]; +extern uint32_t right_channel_bin_len; + +void gradient(uint8_t r, uint8_t g, uint8_t b) { + for(int y = 0; y < 12; y++) { + for(int x = 0; x < 53; x++) { + graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); + graphics.pixel(Point(x, y)); + } + } +} + +typedef void (*shader_func_t)(int ms, int x, int y); + +void grid(int ms, int x, int y) { + int v = (x + y + (ms / 1000)) % 2 == 0 ? 255 : 0; + graphics.set_pen(v, v, v); + graphics.pixel(Point(x, y)); +} + +void shader_fill(int ms, shader_func_t f) { + for(int y = 0; y < 12; y++) { + for(int x = 0; x < 53; x++) { + f(ms, x, y); + } + } +} + +void outline_text(std::string text) { + uint ms = to_ms_since_boot(get_absolute_time()); + + graphics.set_font("bitmap8"); + uint8_t v = (sin(ms / 100.0f) + 1.0f) * 127.0f; + uint w = graphics.measure_text(text, 1); + + int x = 53 / 2 - w / 2 + 1, y = 2; + + graphics.set_pen(0, 0, 0); + graphics.text(text, Point(x - 1, y - 1), -1, 1); + graphics.text(text, Point(x , y - 1), -1, 1); + graphics.text(text, Point(x + 1, y - 1), -1, 1); + graphics.text(text, Point(x - 1, y ), -1, 1); + graphics.text(text, Point(x + 1, y ), -1, 1); + graphics.text(text, Point(x - 1, y + 1), -1, 1); + graphics.text(text, Point(x , y + 1), -1, 1); + graphics.text(text, Point(x + 1, y + 1), -1, 1); + + graphics.set_pen(v, v, v); + graphics.text(text, Point(x, y), -1, 1); +} + +int main() { + stdio_init_all(); + + galactic_unicorn.init(); + + // galactic_unicorn.play_sample(left_channel_bin, left_channel_bin_len); + + while(true) { + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + uint ms = to_ms_since_boot(get_absolute_time()); + + uint8_t test = (ms / 5000) % 4; + + graphics.set_pen(0, 0, 0); + graphics.clear(); + + switch(test) { + case 0: { + printf("grid pattern"); + shader_fill(ms, grid); + }break; + + case 1: { + printf("green gradient"); + gradient(0, 255, 0); + }break; + + case 2: { + printf("blue gradient"); + gradient(0, 0, 255); + }break; + + case 3: { + printf("white gradient"); + gradient(255, 255, 255); + }break; + } + + printf("%d\n", galactic_unicorn.light()); + + std::string text = ""; + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_A)) { + text = "Button A"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_B)) { + text = "Button B"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_C)) { + text = "Button C"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_D)) { + text = "Button D"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_VOLUME_UP)) { + text = "Louder!"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_VOLUME_DOWN)) { + text = "quieter"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_BRIGHTNESS_UP)) { + text = "Brighter!"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_BRIGHTNESS_DOWN)) { + text = "Darker"; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_SLEEP)) { + text = "Zzz... zzz..."; + } + + outline_text(text); + + graphics.set_pen(255, 255, 255); + graphics.clear(); + + galactic_unicorn.update(graphics); + + sleep_ms(50); + } + + return 0; +} diff --git a/examples/galactic_unicorn/fire_effect.cpp b/examples/galactic_unicorn/fire_effect.cpp new file mode 100644 index 00000000..d335807b --- /dev/null +++ b/examples/galactic_unicorn/fire_effect.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// extra row of pixels for sourcing flames and averaging +float heat[53][15] = {0.0f}; + +int main() { + + stdio_init_all(); + + galactic_unicorn.init(); + + while(true) { + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + graphics.set_pen(0, 0, 0); + graphics.clear(); + + + for(int y = 0; y < 14; y++) { + for(int x = 0; x < 53; x++) { + if(heat[x][y] > 0.5f) { + graphics.set_pen(255, 255, 180); + graphics.pixel(Point(x, y)); + }else if(heat[x][y] > 0.4f) { + graphics.set_pen(220, 160, 0); + graphics.pixel(Point(x, y)); + }else if(heat[x][y] > 0.3f) { + graphics.set_pen(180, 50, 0); + graphics.pixel(Point(x, y)); + }else if(heat[x][y] > 0.2f) { + graphics.set_pen(40, 40, 40); + graphics.pixel(Point(x, y)); + } + + // update this pixel by averaging the below pixels + if(x == 0) { + heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x + 1][y + 1]) / 4.0f; + } else if(x == 52) { + heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1]) / 4.0f; + } else { + heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1] + heat[x + 1][y + 1]) / 5.0f; + } + + heat[x][y] -= 0.01f; + heat[x][y] = heat[x][y] < 0.0f ? 0.0f: heat[x][y]; + } + } + + galactic_unicorn.update(graphics); + + // clear the bottom row and then add a new fire seed to it + for(int x = 0; x < 53; x++) { + heat[x][14] = 0.0f; + } + + // add a new random heat source + for(int c = 0; c < 5; c++) { + int px = (rand() % 51) + 1; + heat[px][13] = 1.0f; + heat[px + 1][13] = 1.0f; + heat[px - 1][13] = 1.0f; + heat[px][14] = 1.0f; + heat[px + 1][14] = 1.0f; + heat[px - 1][14] = 1.0f; + } + + sleep_ms(50); + } + + return 0; +} diff --git a/examples/galactic_unicorn/lava_lamp.cpp b/examples/galactic_unicorn/lava_lamp.cpp new file mode 100644 index 00000000..caa539bb --- /dev/null +++ b/examples/galactic_unicorn/lava_lamp.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +struct blob_t { + float x, y; + float r; + float dx, dy; +}; + +constexpr int blob_count = 20; + +int main() { + + stdio_init_all(); + + galactic_unicorn.init(); + + // randomise blob start positions, directions, and size + std::array blobs; + for(auto &blob : blobs) { + blob.x = rand() % 11; + blob.y = rand() % 53; + blob.r = ((rand() % 40) / 10.0f) + 5.0f; + blob.dx = ((rand() % 2) / 10.0f) - 0.05f; + blob.dy = ((rand() % 3) / 10.0f) - 0.1f; + } + + float hue = 0.0f; + + while(true) { + // allow user to adjust brightness + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + uint start_ms = to_ms_since_boot(get_absolute_time()); + + // calculate the influence of each blob on the liquid based + // on their distance to each pixel. this causes blobs to + // "merge" into each other when we use fixed thresholds to + // determine which colour to draw with + float liquid[11][53] = {0.0f}; + for(auto &blob : blobs) { + float r_sq = blob.r * blob.r; + for(int y = 0; y < 53; y++) { + for(int x = 0; x < 11; x++) { + float d_sq = (x - blob.x) * (x - blob.x) + (y - blob.y) * (y - blob.y); + if(d_sq <= r_sq) { + // add this blobs influence to this pixel + liquid[x][y] += 1.0f - (d_sq / r_sq); + } + } + } + } + + // update the blob positions + for(auto &blob : blobs) { + blob.x += blob.dx; + blob.y += blob.dy; + + // if we hit the edge then bounce! + if(blob.x < 0.0f || blob.x >= 11.0f) { + blob.dx *= -1.0f; + } + if(blob.y < 0.0f || blob.y >= 53.0f) { + blob.dy *= -1.0f; + } + } + + // rotate the hue + hue += 0.001f; + + // calculate dark, medium, and bright shades for rendering the + // lava + uint8_t dark_r, dark_g, dark_b; + from_hsv(hue, 1.0f, 0.3f, dark_r, dark_g, dark_b); + uint8_t mid_r, mid_g, mid_b; + from_hsv(hue, 1.0f, 0.6f, mid_r, mid_g, mid_b); + uint8_t bright_r, bright_g, bright_b; + from_hsv(hue, 1.0f, 1.0f, bright_r, bright_g, bright_b); + + // clear the canvas + graphics.set_pen(0, 0, 0); + graphics.clear(); + + // render the lava + for(int y = 0; y < 53; y++) { + for(int x = 0; x < 11; x++) { + float v = liquid[x][y]; + + // select a colour for this pixel based on how much + // "blobfluence" there is at this position in the liquid + if(v >= 1.5f) { + graphics.set_pen(bright_r, bright_g, bright_b); + graphics.pixel(Point(y, x)); + }else if(v >= 1.25f) { + graphics.set_pen(mid_r, mid_g, mid_b); + graphics.pixel(Point(y, x)); + }else if(v >= 1.0f) { + graphics.set_pen(dark_r, dark_g, dark_b); + graphics.pixel(Point(y, x)); + } + } + } + + uint end_ms = to_ms_since_boot(get_absolute_time()); + + printf("rendering took %dms\n", end_ms - start_ms); + + galactic_unicorn.update(graphics); + } + + return 0; +} diff --git a/examples/galactic_unicorn/nostalgia_prompt.cpp b/examples/galactic_unicorn/nostalgia_prompt.cpp new file mode 100644 index 00000000..845be4ac --- /dev/null +++ b/examples/galactic_unicorn/nostalgia_prompt.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +std::array c64 = { + "", + " OOOOO OOOOOO OO OOOO OO OO XXXXXXX", + " OO OO OO OOOO OO OO OO OO XXXXXXX", + " OO OO OO OO OO OO OO OO OO XXXXXXX", + " OOOOO OOOO OOOOOO OO OO OOOO XXXXXXX", + " OOOO OO OO OO OO OO OO XXXXXXX", + " OO OO OO OO OO OO OO OO OO XXXXXXX", + " OO OO OOOOOO OO OO OOOO OO OO XXXXXXX", + " XXXXXXX" +}; + +std::array spectrum = { + "", + " O OOOO OOOO OOOOO O O O O XXXXXXXX", + " O O O O O O O O O O O X XXXXXX", + " O O O O O O O X XXXXXX", + " O O O OOOOOO O O X XXXXXX", + " O O O O O O O X XXXXXX", + " OOOOOO OOOO O O OOOOO X XXXXXX", + " X X", + " XXXXXXXX" +}; + +std::array bbc_micro = { + "", + " OOOOO OO OOOO OOO OOOO O ", + " O O O O O O O O O O ", + " O O O O O O O O ", + " OOOOO O O OOOO O O O ", + " O O OOOOOO O O O O ", + " O O O O O O O O O O ", + " OOOOO O O OOOO OOO OOOO O ", + " XXXXXXX" +}; + + +constexpr uint PROMPT_C64 = 0; +constexpr uint PROMPT_SPECTRUM = 1; +constexpr uint PROMPT_BBC_MICRO = 2; +uint prompt = 0; + +int main() { + + stdio_init_all(); + + galactic_unicorn.init(); + + while(true) { + uint time_ms = to_ms_since_boot(get_absolute_time()); + + prompt = (time_ms / 3000) % 3; + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + std::array image = c64; + if(prompt == PROMPT_C64) { + image = c64; + }else if(prompt == PROMPT_SPECTRUM) { + image = spectrum; + }else if(prompt == PROMPT_BBC_MICRO) { + image = bbc_micro; + } + + if(prompt == PROMPT_C64) { + graphics.set_pen(20, 20, 120); + }else if(prompt == PROMPT_SPECTRUM){ + graphics.set_pen(180, 150, 150); + }else if(prompt == PROMPT_BBC_MICRO){ + graphics.set_pen(0, 0, 0); + } + + graphics.clear(); + + if(prompt == PROMPT_C64) { + graphics.set_pen(230, 210, 250); + }else if(prompt == PROMPT_SPECTRUM){ + graphics.set_pen(0, 0, 0); + }else if(prompt == PROMPT_BBC_MICRO){ + graphics.set_pen(255, 255, 255); + } + + for(size_t y = 0; y < image.size(); y++) { + for(size_t x = 0; x < image[y].length(); x++) { + // draw the prompt text + if(image[y][x] == 'O') { + graphics.pixel(Point(x, y + 1)); + } + + // draw the caret blinking + if(image[y][x] == 'X' && (time_ms / 300) % 2) { + graphics.pixel(Point(x, y + 1)); + } + } + } + + galactic_unicorn.update(graphics); + + sleep_ms(10); + } + + return 0; +} diff --git a/examples/galactic_unicorn/scroll_text.cpp b/examples/galactic_unicorn/scroll_text.cpp new file mode 100644 index 00000000..9e24b4ce --- /dev/null +++ b/examples/galactic_unicorn/scroll_text.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +std::string message = "Pirate. Monkey. Robot. Ninja."; + +int main() { + + stdio_init_all(); + + galactic_unicorn.init(); + + float scroll = -53.0f; + + while(true) { + //uint time_ms = to_ms_since_boot(get_absolute_time()); + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + int width = graphics.measure_text(message, 1); + scroll += 0.25f; + + if(scroll > width) { + scroll = -53.0f; + } + + graphics.set_pen(0, 0, 0); + graphics.clear(); + + ok_color::HSL hsl{scroll / 100.0f, 1.0f, 0.5f}; + ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); + graphics.set_pen(rgb.r * 255, rgb.g * 255, rgb.b * 255); + graphics.text(message, Point(0 - scroll, 5), -1, 0.55); + /*graphics.text(message, Point(0 - scroll + 1, 5), -1, 0.5); + graphics.text(message, Point(0 - scroll, 5 + 1), -1, 0.5); + graphics.text(message, Point(0 - scroll + 1, 5 + 1), -1, 0.5);*/ +/* + for(int x = 0; x < 53; x++) { + for(int y = 0; y < 2; y++) { + float b = sin((x - y * 3 + int(scroll) + 100) / 3.0f); + graphics.set_pen(180 * b, 150 * b, 0); + graphics.pixel(Point(52 - x, y)); + graphics.pixel(Point(52 - x, y + 9)); + } + }*/ + + galactic_unicorn.update(graphics); + + sleep_ms(10); + } + + return 0; +} diff --git a/libraries/galactic_unicorn/CMakeLists.txt b/libraries/galactic_unicorn/CMakeLists.txt index 1322707e..db39dd3e 100644 --- a/libraries/galactic_unicorn/CMakeLists.txt +++ b/libraries/galactic_unicorn/CMakeLists.txt @@ -1,12 +1 @@ -add_library(galactic_unicorn INTERFACE) - -pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) - -target_sources(galactic_unicorn INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp -) - -target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) - -# Pull in pico libraries that we need -target_link_libraries(galactic_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) +include(galactic_unicorn.cmake) \ No newline at end of file diff --git a/libraries/galactic_unicorn/README.md b/libraries/galactic_unicorn/README.md index c568977e..bd41b3df 100644 --- a/libraries/galactic_unicorn/README.md +++ b/libraries/galactic_unicorn/README.md @@ -17,6 +17,7 @@ We've included helper functions to handle every aspect of drawing to the display - [init](#init) - [set_pixel](#set_pixel) - [is_pressed](#is_pressed) +- [Examples](#examples) ## Example Program @@ -98,4 +99,16 @@ The button vaule should be a `uint8_t` denoting a pin, and constants `A`, `B`, ` ```c++ bool is_a_button_pressed = pico_unicorn.is_pressed(PicoUnicorn::A) -``` \ No newline at end of file +``` + +# Examples + +## Game of Life + +## Retro Super-computer + +Random LEDs blink on and off mimicing the look of a movie super computer doing it's work in the eighties. + +## Nostalgia Terminal + +A collection of copies of classic terminal styles including C64, MS-DOS, Spectrum, and more. \ No newline at end of file diff --git a/libraries/galactic_unicorn/audio_i2s.pio b/libraries/galactic_unicorn/audio_i2s.pio new file mode 100644 index 00000000..1c306f4f --- /dev/null +++ b/libraries/galactic_unicorn/audio_i2s.pio @@ -0,0 +1,63 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +; Transmit a mono or stereo I2S audio stream as stereo +; This is 16 bits per sample; can be altered by modifying the "set" params, +; or made programmable by replacing "set x" with "mov x, y" and using Y as a config register. +; +; Autopull must be enabled, with threshold set to 32. +; Since I2S is MSB-first, shift direction should be to left. +; Hence the format of the FIFO word is: +; +; | 31 : 16 | 15 : 0 | +; | sample ws=0 | sample ws=1 | +; +; Data is output at 1 bit per clock. Use clock divider to adjust frequency. +; Fractional divider will probably be needed to get correct bit clock period, +; but for common syslck freqs this should still give a constant word select period. +; +; One output pin is used for the data output. +; Two side-set pins are used. Bit 0 is clock, bit 1 is word select. + +; Send 16 bit words to the PIO for mono, 32 bit words for stereo + +.program audio_i2s +.side_set 2 + + ; /--- LRCLK + ; |/-- BCLK +bitloop1: ; || + out pins, 1 side 0b10 + jmp x-- bitloop1 side 0b11 + out pins, 1 side 0b00 + set x, 14 side 0b01 + +bitloop0: + out pins, 1 side 0b00 + jmp x-- bitloop0 side 0b01 + out pins, 1 side 0b10 +public entry_point: + set x, 14 side 0b11 + +% c-sdk { + +static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base) { + pio_sm_config sm_config = audio_i2s_program_get_default_config(offset); + + sm_config_set_out_pins(&sm_config, data_pin, 1); + sm_config_set_sideset_pins(&sm_config, clock_pin_base); + sm_config_set_out_shift(&sm_config, false, true, 32); + + pio_sm_init(pio, sm, offset, &sm_config); + + uint pin_mask = (1u << data_pin) | (3u << clock_pin_base); + pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask); + pio_sm_set_pins(pio, sm, 0); // clear pins + + pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point)); +} + +%} \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.cmake b/libraries/galactic_unicorn/galactic_unicorn.cmake index fd2a3c5c..c99a3473 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cmake +++ b/libraries/galactic_unicorn/galactic_unicorn.cmake @@ -1,12 +1,14 @@ -add_library(pico_unicorn INTERFACE) +add_library(galactic_unicorn INTERFACE) -pico_generate_pio_header(pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.pio) +pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) +pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pio) -target_sources(pico_unicorn INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.cpp + +target_sources(galactic_unicorn INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp ) -target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) +target_link_libraries(galactic_unicorn INTERFACE pico_stdlib pico_graphics hardware_adc hardware_pio hardware_dma) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index c1b32c38..9c98aa5f 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -2,88 +2,47 @@ #include "hardware/dma.h" #include "hardware/irq.h" +#include "hardware/adc.h" +#include "hardware/clocks.h" + #include "galactic_unicorn.pio.h" +#include "audio_i2s.pio.h" + #include "galactic_unicorn.hpp" // pixel data is stored as a stream of bits delivered in the // order the PIO needs to manage the shift registers, row // selects, delays, and latching/blanking // -// the data consists of 11 rows each of which has 14 frames of -// bcd timing data +// the pins used are: // -// bits are output in order: +// - 13: column clock (sideset) +// - 14: column data (out base) +// - 15: column latch +// - 16: column blank +// - 17: row select bit 0 +// - 18: row select bit 1 +// - 19: row select bit 2 +// - 20: row select bit 3 // -// ROW_CLEAR, ROW_DATA1, ROW_DATA0, LED_BLANK, LED_LATCH, LED_CLOCK, LED_DATA0, LED_DATA1 +// the framebuffer data is structured like this: // -// the data is structured like this: -// -// loop through the eleven rows of the display... -// -// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) -// 00000000 00000000 00000000 // dummy bytes to align to dwords -// -// within this row we loop through the 14 bcd frames for this row... -// -// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high -// 162: 10011000 // LATCH pixel data -// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) -// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) -// 166: 10010000 // turn BLANK back on -// 167: 00000000 // dummy byte to ensure dword aligned +// for each row: +// for each bcd frame: +// 0: 00110110 // row pixel count (minus one) +// 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data +// 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align +// 56: xxxxrrrr // row select bits +// 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) // // .. and back to the start -/* -enum pin { - LED_DATA = 8, - LED_CLOCK = 9, - LED_LATCH = 10, - LED_BLANK = 11, - ROW_0 = 22, - ROW_1 = 21, - ROW_2 = 20, - ROW_3 = 19, - ROW_4 = 18, - ROW_5 = 17, - ROW_6 = 16, - A = 12, - B = 13, - X = 14, - Y = 15, -};*/ - -enum pin { - LED_DATA1 = 12, - LED_DATA0 = 13, - LED_CLOCK = 14, - LED_LATCH = 15, - LED_BLANK = 16, - - ROW_DATA0 = 17, - ROW_DATA1 = 18, - ROW_CLEAR = 19, - ROW_CLOCK = 20, - - SWITCH_A = 0, - SWITCH_B = 1, - SWITCH_C = 3, - SWITCH_D = 6, - SWITCH_E = 2, - SWITCH_VOLUME_UP = 21, - SWITCH_VOLUME_DOWN = 26, - SWITCH_BRIGHTNESS_UP = 7, - SWITCH_BRIGHTNESS_DOWN = 8 -}; - - - constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t ROW_BYTES = 4; -constexpr uint32_t ROW_FRAME_BYTES = 168; -constexpr uint32_t BCD_FRAMES = 15; // includes fet discharge frame -constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES + ROW_COUNT * ROW_FRAME_BYTES * BCD_FRAMES); +constexpr uint32_t BCD_FRAME_COUNT = 14; +constexpr uint32_t BCD_FRAME_BYTES = 60; +constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; +constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); // must be aligned for 32bit dma transfer alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0}; @@ -93,38 +52,7 @@ static uint16_t g_gamma_lut[256] = {0}; static uint16_t b_gamma_lut[256] = {0}; static uint32_t dma_channel; - -static inline void unicorn_jetpack_program_init(PIO pio, uint sm, uint offset) { - pio_gpio_init(pio, pin::LED_DATA1); - pio_gpio_init(pio, pin::LED_DATA0); - pio_gpio_init(pio, pin::LED_CLOCK); - pio_gpio_init(pio, pin::LED_LATCH); - pio_gpio_init(pio, pin::LED_BLANK); - - pio_gpio_init(pio, pin::ROW_DATA0); - pio_gpio_init(pio, pin::ROW_DATA1); - pio_gpio_init(pio, pin::ROW_CLEAR); - pio_gpio_init(pio, pin::ROW_CLOCK); - - pio_sm_set_consecutive_pindirs(pio, sm, pin::LED_DATA1, 5, true); - pio_sm_set_consecutive_pindirs(pio, sm, pin::ROW_DATA0, 4, true); - - pio_sm_config c = galactic_unicorn_program_get_default_config(offset); - - // osr shifts right, autopull on, autopull threshold 8 - sm_config_set_out_shift(&c, true, false, 32); - - // configure out, set, and sideset pins - sm_config_set_out_pins(&c, pin::LED_DATA1, 8); - sm_config_set_sideset_pins(&c, pin::ROW_CLOCK); - - // join fifos as only tx needed (gives 8 deep fifo instead of 4) - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - - pio_sm_init(pio, sm, offset, &c); - pio_sm_set_enabled(pio, sm, true); - ///pio_sm_set_clkdiv(pio, sm, 4.0f); -} +static uint32_t audio_dma_channel; namespace pimoroni { @@ -154,118 +82,124 @@ namespace pimoroni { pio_sm_restart(bitstream_pio, bitstream_sm); } + uint16_t GalacticUnicorn::light() { + adc_select_input(2); + return adc_read(); + } + void GalacticUnicorn::init() { // todo: shouldn't need to do this if things were cleaned up properly but without // this any attempt to run a micropython script twice will fail static bool already_init = false; - // setup pins - gpio_init(pin::LED_DATA0); gpio_set_dir(pin::LED_DATA0, GPIO_OUT); - gpio_init(pin::LED_DATA1); gpio_set_dir(pin::LED_DATA1, GPIO_OUT); - gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT); - gpio_init(pin::LED_LATCH); gpio_set_dir(pin::LED_LATCH, GPIO_OUT); - gpio_init(pin::LED_BLANK); gpio_set_dir(pin::LED_BLANK, GPIO_OUT); - - gpio_init(pin::ROW_DATA0); gpio_set_dir(pin::ROW_DATA0, GPIO_OUT); - gpio_init(pin::ROW_DATA1); gpio_set_dir(pin::ROW_DATA1, GPIO_OUT); - gpio_init(pin::ROW_CLEAR); gpio_set_dir(pin::ROW_CLEAR, GPIO_OUT); - gpio_init(pin::ROW_CLOCK); gpio_set_dir(pin::ROW_CLOCK, GPIO_OUT); - // create 14-bit gamma luts for(uint16_t v = 0; v < 256; v++) { // gamma correct the provided 0-255 brightness value onto a // 0-65535 range for the pwm counter - float r_gamma = 2.8f; - r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * 16383.0f + 0.5f); - - float g_gamma = 2.8f; - g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * 16383.0f + 0.5f); - - float b_gamma = 2.8f; - b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * 16383.0f + 0.5f); + float r_gamma = 1.8f; + r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float g_gamma = 2.0f; + g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float b_gamma = 1.8f; + b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); } + + // for each row: + // for each bcd frame: + // 0: 00110110 // row pixel count (minus one) + // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data + // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align + // 56: xxxxrrrr // row select bits + // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) + // + // .. and back to the start -// the data is structured like this: -// -// loop through the eleven rows of the display... -// -// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) -// 00000000 00000000 00000000 // dummy bytes to align to dwords -// -// within this row we loop through the 14 bcd frames for this row... -// -// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high -// 162: 10011000 // LATCH pixel data -// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) -// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) -// 166: 10010000 // turn BLANK back on -// 167: 00000000 // dummy byte to ensure dword aligned -// -// .. and back to the start // initialise the bcd timing values and row selects in the bitstream for(uint8_t row = 0; row < HEIGHT; row++) { - uint16_t row_offset = row * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); + for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { + // find the offset of this row and frame in the bitstream + uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; - // setup row select on rows 0 and 8 - uint8_t row_select = row == 0 ? 0b10111000 : (row == 8 ? 0b11011000 : 0b10011000); - bitstream[row_offset + 0] = row_select; - - for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { - uint16_t frame_offset = row_offset + ROW_BYTES + (ROW_FRAME_BYTES * frame); - - bitstream[frame_offset + 162] = 0b10011000; // LATCH pixel data - bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs + p[ 0] = WIDTH - 1; // row pixel count + p[56] = row; // row select // set the number of bcd ticks for this frame - uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 1 : 1 << frame; - bitstream[frame_offset + 164] = (bcd_ticks & 0xff); - bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8; - - bitstream[frame_offset + 166] = 0b10010000; // BLANK high again to disable outputs - - // setup empty pixels with BLANK high and a clock pulse - for(uint8_t col = 0; col < 162; col += 2) { - bitstream[frame_offset + col + 0] = 0b10010000; - bitstream[frame_offset + col + 1] = 0b10010100; - } - -/* - uint16_t row_select_offset = offset + 164; - uint16_t bcd_offset = offset + 165; - - // the last bcd frame is used to allow the fets to discharge to avoid ghosting - if(frame == BCD_FRAMES - 1) { - uint16_t bcd_ticks = 65535; - bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; - bitstream[bcd_offset] = (bcd_ticks & 0xff); - }else{ - uint8_t row_select = row == 0 ? 0b01000000 : (row == 8 ? 0b00100000 : 0b00000000); - bitstream[row_select_offset] = row_select; - - uint16_t bcd_ticks = 1 << frame; - bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; - bitstream[bcd_offset] = (bcd_ticks & 0xff); - }*/ + uint32_t bcd_ticks = (1 << frame); + p[57] = (bcd_ticks & 0xff) >> 0; + p[58] = (bcd_ticks & 0xff00) >> 8; + p[59] = (bcd_ticks & 0xff0000) >> 16; } -/* - for(size_t i = 0; i < sizeof(bitstream); i++) { - bitstream[i] = 0b11100000; - }*/ } + // setup light sensor adc + adc_init(); + adc_gpio_init(LIGHT_SENSOR); + + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + + gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); + gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); + gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); + + sleep_ms(100); + + // configure full output current in register 2 + + uint16_t reg1 = 0b1111111111001110; + + // clock the register value to the first 9 driver chips + for(int j = 0; j < 9; j++) { + for(int i = 0; i < 16; i++) { + if(reg1 & (1U << (15 - i))) { + gpio_put(COLUMN_DATA, true); + }else{ + gpio_put(COLUMN_DATA, false); + } + sleep_us(10); + gpio_put(COLUMN_CLOCK, true); + sleep_us(10); + gpio_put(COLUMN_CLOCK, false); + } + } + + // clock the last chip and latch the value + for(int i = 0; i < 16; i++) { + if(reg1 & (1U << (15 - i))) { + gpio_put(COLUMN_DATA, true); + }else{ + gpio_put(COLUMN_DATA, false); + } + + sleep_us(10); + gpio_put(COLUMN_CLOCK, true); + sleep_us(10); + gpio_put(COLUMN_CLOCK, false); + + if(i == 4) { + gpio_put(COLUMN_LATCH, true); + } + } + gpio_put(COLUMN_LATCH, false); + + + gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); + // setup button inputs - gpio_set_function(pin::SWITCH_A, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_A, GPIO_IN); gpio_pull_up(pin::SWITCH_A); - gpio_set_function(pin::SWITCH_B, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_B, GPIO_IN); gpio_pull_up(pin::SWITCH_B); - gpio_set_function(pin::SWITCH_C, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_C, GPIO_IN); gpio_pull_up(pin::SWITCH_C); - gpio_set_function(pin::SWITCH_D, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_D, GPIO_IN); gpio_pull_up(pin::SWITCH_D); - gpio_set_function(pin::SWITCH_E, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_E, GPIO_IN); gpio_pull_up(pin::SWITCH_E); + gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); + gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); + gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); + gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); - gpio_set_function(pin::SWITCH_BRIGHTNESS_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_UP); - gpio_set_function(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_DOWN); + gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); - gpio_set_function(pin::SWITCH_VOLUME_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_UP); - gpio_set_function(pin::SWITCH_VOLUME_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_DOWN); + gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); + gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); + + gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); + gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); if(already_init) { // stop and release the dma channel @@ -288,9 +222,38 @@ namespace pimoroni { // setup the pio bitstream_pio = pio0; - bitstream_sm = pio_claim_unused_sm(pio0, true); - sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); - unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset); + bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); + bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); + + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + pio_gpio_init(bitstream_pio, COLUMN_BLANK); + + pio_gpio_init(bitstream_pio, ROW_BIT_0); + pio_gpio_init(bitstream_pio, ROW_BIT_1); + pio_gpio_init(bitstream_pio, ROW_BIT_2); + pio_gpio_init(bitstream_pio, ROW_BIT_3); + + // set all led driving pins as outputs + pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); + + pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); + + // osr shifts right, autopull on, autopull threshold 8 + sm_config_set_out_shift(&c, true, true, 32); + + // configure out, set, and sideset pins + sm_config_set_out_pins(&c, ROW_BIT_0, 4); + sm_config_set_set_pins(&c, COLUMN_DATA, 3); + sm_config_set_sideset_pins(&c, COLUMN_CLOCK); + + // join fifos as only tx needed (gives 8 deep fifo instead of 4) + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); + pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); + // setup dma transfer for pixel data to the pio dma_channel = dma_claim_unused_channel(true); @@ -308,6 +271,52 @@ namespace pimoroni { dma_channel_set_read_addr(dma_channel, bitstream, true); already_init = true; + + + // setup audio pio program + /* + audio_pio = pio0; + audio_sm = pio_claim_unused_sm(audio_pio, true); + audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); + audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); + //pio_sm_set_enabled(audio_pio, audio_sm, true); + + uint32_t system_clock_frequency = clock_get_hz(clk_sys); + uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow + pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); + + + + audio_dma_channel = dma_claim_unused_channel(true); + dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); + channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_32); + channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian + channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); + dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); + dma_channel_set_irq0_enabled(audio_dma_channel, true); + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ + //irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); + //irq_set_enabled(DMA_IRQ_0, true); + +/* dma_channel_set_trans_count(audio_dma_channel, BITSTREAM_LENGTH / 4, false); + dma_channel_set_read_addr(audio_dma_channel, bitstream, true);*/ + //pio_sm_config audio_i2s_config = audio_i2s_program_get_default_config(audio_sm_offset); + + // osr shifts right, autopull on, autopull threshold 8 + //sm_config_set_out_shift(&audio_i2s_config, true, true, 32); + + // // configure out, set, and sideset pins + // sm_config_set_out_pins(&audio_i2s_config, ROW_BIT_0, 4); + // sm_config_set_set_pins(&audio_i2s_config, COLUMN_DATA, 3); + // sm_config_set_sideset_pins(&audio_i2s_config, COLUMN_CLOCK); + + // // join fifos as only tx needed (gives 8 deep fifo instead of 4) + // sm_config_set_fifo_join(&audio_i2s_config, PIO_FIFO_JOIN_TX); + + + //pio_sm_init(audio_pio, audio_sm, audio_sm_offset, &audio_i2s_config); + //pio_sm_set_enabled(audio_pio, audio_sm, true); + } void GalacticUnicorn::clear() { @@ -318,65 +327,44 @@ namespace pimoroni { } } - void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { - + void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { + dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 4); + } + void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; // make those coordinates sane x = (WIDTH - 1) - x; y = (HEIGHT - 1) - y; - // determine offset in the buffer for this row - uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); + uint16_t gamma_r = r_gamma_lut[r]; + uint16_t gamma_g = g_gamma_lut[g]; + uint16_t gamma_b = b_gamma_lut[b]; - uint16_t bits[3] = {r_gamma_lut[b], g_gamma_lut[g], b_gamma_lut[r]}; - //uint16_t gr = r_gamma_lut[r]; - //uint16_t gg = g_gamma_lut[g]; - //uint16_t gb = b_gamma_lut[b]; + // for each row: + // for each bcd frame: + // 0: 00110110 // row pixel count (minus one) + // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data + // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align + // 56: xxxxrrrr // row select bits + // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) + // + // .. and back to the start // set the appropriate bits in the separate bcd frames - for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { - uint16_t frame_offset = (ROW_FRAME_BYTES * frame) + 4; - uint16_t offset = row_offset + frame_offset;// + byte_offset; + for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { + uint8_t *p = &bitstream[y * ROW_BYTES + (BCD_FRAME_BYTES * frame) + 1 + x]; -// loop through the eleven rows of the display... -// -// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) -// 00000000 00000000 00000000 // dummy bytes to align to dwords -// -// within this row we loop through the 14 bcd frames for this row... -// -// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high -// 162: 10011000 // LATCH pixel data -// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) -// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) -// 166: 10010000 // turn BLANK back on -// 167: 00000000 // dummy byte to ensure dword aligned -// -// .. and back to the start + uint8_t red_bit = gamma_r & 0b1; + uint8_t green_bit = gamma_g & 0b1; + uint8_t blue_bit = gamma_b & 0b1; - // work out the byte offset of this pixel - /*if(bit_offset >= 160) { - bit_offset -= 160; - }*/ + *p = (blue_bit << 2) | (green_bit << 1) | (red_bit << 0); - for(int bit = 0; bit < 3; bit++) { - int16_t bit_offset = x * 6 + 4 + (bit * 2); - - - uint8_t bit_position = bit_offset >= 160 ? 1 : 0; - uint8_t mask = 0b1 << bit_position; - uint8_t value = (bits[bit] & 0b1) << bit_position; - - bitstream[offset + (bit_offset % 160) + 0] &= ~mask; - bitstream[offset + (bit_offset % 160) + 0] |= value; - bitstream[offset + (bit_offset % 160) + 1] &= ~mask; - bitstream[offset + (bit_offset % 160) + 1] |= value; - - //bit_offset += 2; - bits[bit] >>= 1; - } + gamma_r >>= 1; + gamma_g >>= 1; + gamma_b >>= 1; } } @@ -384,6 +372,55 @@ namespace pimoroni { set_pixel(x, y, v, v, v); } + void GalacticUnicorn::set_brightness(float value) { + value = value < 0.0f ? 0.0f : value; + value = value > 1.0f ? 1.0f : value; + this->brightness = floor(value * 255.0f); + } + + float GalacticUnicorn::get_brightness() { + return this->brightness / 255.0f; + } + + void GalacticUnicorn::adjust_brightness(float delta) { + this->set_brightness(this->get_brightness() + delta); + } + + void GalacticUnicorn::set_volume(float value) { + value = value < 0.0f ? 0.0f : value; + value = value > 1.0f ? 1.0f : value; + this->volume = floor(value * 255.0f); + } + + float GalacticUnicorn::get_volume() { + return this->volume / 255.0f; + } + + void GalacticUnicorn::adjust_volume(float delta) { + this->set_volume(this->get_volume() + delta); + } + + + void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { + uint16_t *p = (uint16_t *)graphics.frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint16_t col = __builtin_bswap16(*p); + uint8_t r = ((col & 0b1111100000000000) >> 11) << 3; + uint8_t g = ((col & 0b0000011111100000) >> 5) << 2; + uint8_t b = ((col & 0b0000000000011111) >> 0) << 3; + p++; + + r = (r * this->brightness) >> 8; + g = (g * this->brightness) >> 8; + b = (b * this->brightness) >> 8; + + set_pixel(x, y, b, g, r); + } + } + bool GalacticUnicorn::is_pressed(uint8_t button) { return !gpio_get(button); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 768977f9..3714c843 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -1,6 +1,7 @@ #pragma once #include "hardware/pio.h" +#include "pico_graphics.hpp" namespace pimoroni { @@ -8,30 +9,81 @@ namespace pimoroni { public: static const int WIDTH = 53; static const int HEIGHT = 11; - static const uint8_t SWITCH_A = 0; - static const uint8_t SWITCH_B = 1; - static const uint8_t SWITCH_C = 3; - static const uint8_t SWITCH_D = 6; - static const uint8_t SWITCH_E = 2; - static const uint8_t SWITCH_VOLUME_UP = 21; - static const uint8_t SWITCH_VOLUME_DOWN = 26; - static const uint8_t SWITCH_BRIGHTNESS_UP = 7; - static const uint8_t SWITCH_BRIGHTNESS_DOWN = 8; + + // pin assignments + static const uint8_t COLUMN_CLOCK = 13; + static const uint8_t COLUMN_DATA = 14; + static const uint8_t COLUMN_LATCH = 15; + static const uint8_t COLUMN_BLANK = 16; + + static const uint8_t ROW_BIT_0 = 17; + static const uint8_t ROW_BIT_1 = 18; + static const uint8_t ROW_BIT_2 = 19; + static const uint8_t ROW_BIT_3 = 20; + + static const uint8_t LIGHT_SENSOR = 28; + + static const uint8_t MUTE = 22; + + static const uint8_t I2S_DATA = 9; + static const uint8_t I2S_BCLK = 10; + static const uint8_t I2S_LRCLK = 11; + + static const uint8_t I2C_SDA = 4; + static const uint8_t I2C_SCL = 5; + + static const uint8_t SWITCH_A = 0; + static const uint8_t SWITCH_B = 1; + static const uint8_t SWITCH_C = 3; + static const uint8_t SWITCH_D = 6; + + static const uint8_t SWITCH_SLEEP = 27; + + static const uint8_t SWITCH_VOLUME_UP = 7; + static const uint8_t SWITCH_VOLUME_DOWN = 8; + static const uint8_t SWITCH_BRIGHTNESS_UP = 21; + static const uint8_t SWITCH_BRIGHTNESS_DOWN = 26; private: PIO bitstream_pio = pio0; uint bitstream_sm = 0; - uint sm_offset = 0; + uint bitstream_sm_offset = 0; + + PIO audio_pio = pio0; + uint audio_sm = 0; + uint audio_sm_offset = 0; + + uint8_t brightness = 255; + uint8_t volume = 127; + public: ~GalacticUnicorn(); void init(); + static inline void pio_program_init(PIO pio, uint sm, uint offset); void clear(); + + void update(PicoGraphics_PenRGB565 &graphics); + + void set_brightness(float value); + float get_brightness(); + void adjust_brightness(float delta); + + void set_volume(float value); + float get_volume(); + void adjust_volume(float delta); + + void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b); void set_pixel(int x, int y, uint8_t v); + uint16_t light(); + bool is_pressed(uint8_t button); + + void play_sample(uint8_t *data, uint32_t length); + }; } \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.pio b/libraries/galactic_unicorn/galactic_unicorn.pio index a843cc58..d919f401 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.pio +++ b/libraries/galactic_unicorn/galactic_unicorn.pio @@ -2,65 +2,79 @@ .side_set 1 opt ; out pins: -; 0: data1 (base) -; 1: data0 -; 2: clock -; 3: latch -; 4: blank -; 5: row1 -; 6: row2 -; 7: row_clear +; +; - 3: row select bit 0 +; - 4: row select bit 1 +; - 5: row select bit 2 +; - 6: row select bit 3 +; set pins: +; +; - 0: column data (base) +; - 1: column latch +; - 2: column blank + +; sideset pin: +; +; - 0: column clock + +; for each row: +; for each bcd frame: +; 0: 00110110 // row pixel count (minus one) +; 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data +; 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align +; 56: xxxxrrrr // row select bits +; 57 - 59: tttttttt, tttttttt, tttttttt, // bcd tick count (0-65536) +; +; .. and back to the start -; sideset pin: row_clock .wrap_target - -; set row select pins - pull - out pins, 8 side 0 [4] - nop side 1 [4] ; pulse row select clock - out null, 24 ; discard dummy data - -; loop for bcd frames - set x, 14 -bcd_frame: - -; clock out 53 pixels worth of data - two pixels at a time, so 27 (actually 26.5) bits of data - set y, 26 ; 26 because `jmp` test is pre decrement - +; loop over row pixels + out y, 8 ; get row pixel count (minus 1 because test is pre decrement) pixels: - - pull ifempty - out pins, 8 [1] ; two red bits.. - out pins, 8 [1] ; ..with clock pulse - - pull ifempty - out pins, 8 [1] ; two green bits.. - out pins, 8 [1] ; ..with green pulse - - pull ifempty - out pins, 8 [1] ; two blue bits.. - out pins, 8 [1] ; ..with blue pulse - - jmp y-- pixels - out pins, 8 ; LATCH pixel data - out pins, 8 ; turn off BLANK signal + ; red bit + out x, 1 side 0 [1] ; pull in blue bit from OSR into register x, clear clock + set pins, 0b100 ; clear data bit, blank high + jmp !x endb ; if bit was zero jump + set pins, 0b101 ; set data bit, blank high + endb: + nop side 1 [2] ; clock in bit - pull + ; green bit + out x, 1 side 0 [1] ; pull in green bit from OSR into register X, clear clock + set pins, 0b100 ; clear data bit, blank high + jmp !x endg ; if bit was zero jump + set pins, 0b101 ; set data bit, blank high + endg: + nop side 1 [2] ; clock in bit -; pull bcd tick count into x register - out y, 16 + ; blue bit + out x, 1 side 0 [1] ; pull in red bit from OSR into register X, clear clock + set pins, 0b100 ; clear data bit, blank high + jmp !x endr ; if bit was zero jump + set pins, 0b101 ; set data bit, blank high + endr: + out null, 5 side 1 [2] ; clock in bit -bcd_count: - jmp y-- bcd_count ; loop until bcd delay complete + ;out null, 5 side 0 ; discard the five dummy bits for this pixel -; disable led output (blank) and clear latch pin - out pins, 8 ; turn off BLANK signal and clear row output - out null, 8 ; discard dummy data + jmp y-- pixels - jmp x-- bcd_frame ; loop to next bcd frame + out null, 16 ; discard dummy bytes + + out pins, 8 ; output row select + + set pins, 0b110 [5] ; latch high, blank high + set pins, 0b000 ; blank low (enable output) + +; loop over bcd delay period + out y, 24 ; get bcd delay counter value +bcd_delay: + jmp y-- bcd_delay + + set pins 0b100 ; blank high (disable output) .wrap \ No newline at end of file diff --git a/libraries/pico_graphics/pico_graphics.cpp b/libraries/pico_graphics/pico_graphics.cpp index 2c4b3bbf..3e481f6d 100644 --- a/libraries/pico_graphics/pico_graphics.cpp +++ b/libraries/pico_graphics/pico_graphics.cpp @@ -276,8 +276,6 @@ namespace pimoroni { void PicoGraphics::line(Point p1, Point p2) { // fast horizontal line if(p1.y == p2.y) { - p1 = p1.clamp(clip); - p2 = p2.clamp(clip); int32_t start = std::min(p1.x, p2.x); int32_t end = std::max(p1.x, p2.x); pixel_span(Point(start, p1.y), end - start); @@ -286,13 +284,11 @@ namespace pimoroni { // fast vertical line if(p1.x == p2.x) { - p1 = p1.clamp(clip); - p2 = p2.clamp(clip); int32_t start = std::min(p1.y, p2.y); int32_t length = std::max(p1.y, p2.y) - start; Point dest(p1.x, start); while(length--) { - set_pixel(dest); + pixel(dest); dest.y++; } return; @@ -314,7 +310,7 @@ namespace pimoroni { int32_t y = p1.y << 16; while(s--) { Point p(x, y >> 16); - if(clip.contains(p)) set_pixel(p); + pixel(p); y += sy; x += sx; } @@ -327,7 +323,7 @@ namespace pimoroni { int32_t x = p1.x << 16; while(s--) { Point p(x >> 16, y); - if(clip.contains(p)) set_pixel(p); + pixel(p); y += sy; x += sx; } From a4861504700558d30ec13efcfbd4bf59f46051e6 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 04:42:17 +0100 Subject: [PATCH 05/42] Playing basic audio samples now works, added rainbow example for photoshoot --- examples/galactic_unicorn/CMakeLists.txt | 10 +- examples/galactic_unicorn/feature_test.cpp | 23 +++-- examples/galactic_unicorn/fire_effect.cpp | 97 +++++++++++++------ .../{demo2.cpp => rainbow.cpp} | 51 ++++++++-- .../galactic_unicorn/galactic_unicorn.cpp | 43 +++----- 5 files changed, 142 insertions(+), 82 deletions(-) rename examples/galactic_unicorn/{demo2.cpp => rainbow.cpp} (73%) diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index 86b25380..7b145552 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -13,16 +13,16 @@ pico_add_extra_outputs(galactic_unicorn_demo) add_executable( - galactic_unicorn_demo2 - demo2.cpp + rainbow + rainbow.cpp ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(galactic_unicorn_demo2 1) +target_link_libraries(rainbow pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(rainbow 1) # create map/bin/hex file etc. -pico_add_extra_outputs(galactic_unicorn_demo2) +pico_add_extra_outputs(rainbow) diff --git a/examples/galactic_unicorn/feature_test.cpp b/examples/galactic_unicorn/feature_test.cpp index fda7cab6..b3ac4074 100644 --- a/examples/galactic_unicorn/feature_test.cpp +++ b/examples/galactic_unicorn/feature_test.cpp @@ -71,19 +71,20 @@ int main() { galactic_unicorn.init(); - // galactic_unicorn.play_sample(left_channel_bin, left_channel_bin_len); + + galactic_unicorn.set_brightness(0.5f); while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { - galactic_unicorn.adjust_brightness(+0.01); + galactic_unicorn.adjust_brightness(+0.01f); } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { - galactic_unicorn.adjust_brightness(-0.01); + galactic_unicorn.adjust_brightness(-0.01f); } uint ms = to_ms_since_boot(get_absolute_time()); - uint8_t test = (ms / 5000) % 4; + uint8_t test = (ms / 1000) % 4; graphics.set_pen(0, 0, 0); graphics.clear(); @@ -113,6 +114,17 @@ int main() { printf("%d\n", galactic_unicorn.light()); std::string text = ""; + static bool was_a_pressed = false; + + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_A)) { + if(!was_a_pressed) { + galactic_unicorn.play_sample(left_channel_bin, left_channel_bin_len); + } + was_a_pressed = true; + }else{ + was_a_pressed = false; + } + if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_A)) { text = "Button A"; } @@ -143,9 +155,6 @@ int main() { outline_text(text); - graphics.set_pen(255, 255, 255); - graphics.clear(); - galactic_unicorn.update(graphics); sleep_ms(50); diff --git a/examples/galactic_unicorn/fire_effect.cpp b/examples/galactic_unicorn/fire_effect.cpp index d335807b..b69a8fdc 100644 --- a/examples/galactic_unicorn/fire_effect.cpp +++ b/examples/galactic_unicorn/fire_effect.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "pico/stdlib.h" #include "libraries/pico_graphics/pico_graphics.hpp" @@ -13,7 +14,19 @@ PicoGraphics_PenRGB565 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // extra row of pixels for sourcing flames and averaging -float heat[53][15] = {0.0f}; +int width = 53; +int height = 15; + +// a buffer that's at least big enough to store 55 x 15 values (to allow for both orientations) +float heat[1000] = {0.0f}; + +void set(int x, int y, float v) { + heat[x + y * width] = v; +} + +float get(int x, int y) { + return heat[x + y * width]; +} int main() { @@ -21,6 +34,8 @@ int main() { galactic_unicorn.init(); + bool landscape = true; + while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { galactic_unicorn.adjust_brightness(+0.01); @@ -29,59 +44,77 @@ int main() { galactic_unicorn.adjust_brightness(-0.01); } - graphics.set_pen(0, 0, 0); - graphics.clear(); - + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + landscape = true; + width = 53; + height = 15; + memset(heat, 0, sizeof(heat)); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + landscape = false; + width = 11; + height = 55; + memset(heat, 0, sizeof(heat)); + } - for(int y = 0; y < 14; y++) { - for(int x = 0; x < 53; x++) { - if(heat[x][y] > 0.5f) { + for(int y = 0; y < height; y++) { + for(int x = 0; x < width; x++) { + float value = get(x, y); + + graphics.set_pen(0, 0, 0); + if(value > 0.5f) { graphics.set_pen(255, 255, 180); - graphics.pixel(Point(x, y)); - }else if(heat[x][y] > 0.4f) { + }else if(value > 0.4f) { graphics.set_pen(220, 160, 0); - graphics.pixel(Point(x, y)); - }else if(heat[x][y] > 0.3f) { + }else if(value > 0.3f) { graphics.set_pen(180, 50, 0); - graphics.pixel(Point(x, y)); - }else if(heat[x][y] > 0.2f) { + }else if(value > 0.2f) { graphics.set_pen(40, 40, 40); - graphics.pixel(Point(x, y)); } + + if(landscape) { + graphics.pixel(Point(x, y)); + }else{ + graphics.pixel(Point(y, x)); + } + // update this pixel by averaging the below pixels + float average = 0.0f; if(x == 0) { - heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x + 1][y + 1]) / 4.0f; + average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x + 1, y + 1)) / 4.0f; } else if(x == 52) { - heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1]) / 4.0f; + average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1)) / 4.0f; } else { - heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1] + heat[x + 1][y + 1]) / 5.0f; - } + average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0f; + } - heat[x][y] -= 0.01f; - heat[x][y] = heat[x][y] < 0.0f ? 0.0f: heat[x][y]; + average -= landscape ? 0.01f : 0.004f; + average = average < 0.0f ? 0.0f: average; + set(x, y, average); } } galactic_unicorn.update(graphics); // clear the bottom row and then add a new fire seed to it - for(int x = 0; x < 53; x++) { - heat[x][14] = 0.0f; + for(int x = 0; x < width; x++) { + set(x, height - 1, 0.0f); } // add a new random heat source - for(int c = 0; c < 5; c++) { - int px = (rand() % 51) + 1; - heat[px][13] = 1.0f; - heat[px + 1][13] = 1.0f; - heat[px - 1][13] = 1.0f; - heat[px][14] = 1.0f; - heat[px + 1][14] = 1.0f; - heat[px - 1][14] = 1.0f; + int source_count = landscape ? 5 : 1; + for(int c = 0; c < source_count; c++) { + int px = (rand() % (width - 4)) + 2; + set(px , height - 2, 1.0f); + set(px + 1, height - 2, 1.0f); + set(px - 1, height - 2, 1.0f); + set(px , height - 1, 1.0f); + set(px + 1, height - 1, 1.0f); + set(px - 1, height - 1, 1.0f); } - - sleep_ms(50); + + sleep_ms(20); } return 0; diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/rainbow.cpp similarity index 73% rename from examples/galactic_unicorn/demo2.cpp rename to examples/galactic_unicorn/rainbow.cpp index ca2a79b7..804584bd 100644 --- a/examples/galactic_unicorn/demo2.cpp +++ b/examples/galactic_unicorn/rainbow.cpp @@ -109,19 +109,28 @@ graphics.set_font("bitmap8"); - uint i = 0; + float i = 0; float hue_offset = 0.0f; + bool animate = true; + + float stripe_width = 3.0f; + float speed = 1.0f; + float curve = 0.0f; + while(true) { - i++; + + if(animate) { + i += speed; + } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { - hue_offset += 0.05; + curve += 0.05; if(hue_offset > 1.0f) hue_offset = 1.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { - hue_offset -= 0.05; + curve -= 0.05; if(hue_offset < 0.0f) hue_offset = 0.0f; } @@ -132,8 +141,31 @@ graphics.set_font("bitmap8"); galactic_unicorn.adjust_brightness(-0.01); } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_SLEEP)) { + animate = false; + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + speed += 0.05f; + speed = speed >= 10.0f ? 10.0f : speed; + animate = true; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + speed -= 0.05f; + speed = speed <= 0.0f ? 0.0f : speed; + animate = true; + } + + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) { + stripe_width += 0.05f; + stripe_width = stripe_width >= 10.0f ? 10.0f : stripe_width; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_D)) { + stripe_width -= 0.05f; + stripe_width = stripe_width <= 1.0f ? 1.0f : stripe_width; + } - /* graphics.set_pen(255, 255, 255); float s = 0.65f;//0.65f + (sin(i / 25.0f) * 0.15f); @@ -145,9 +177,14 @@ graphics.set_font("bitmap8"); for(int x = 0; x < 53; x++) { for(int y = 0; y < 11; y++) { - int v = ((sin((x + y) / 3.0f + i / 15.0f) + 1.5f) / 2.5f) * 255.0f; + int v = ((sin((x + y) / stripe_width + (sin((y * 3.1415927f * 2.0f) / 11.0f) * curve) + i / 15.0f) + 1.5f) / 2.5f) * 255.0f; - graphics.set_pen(v, v, v); + + uint8_t r = (hue_map[x][0] * v) / 256; + uint8_t g = (hue_map[x][1] * v) / 256; + uint8_t b = (hue_map[x][2] * v) / 256; + + graphics.set_pen(r, g, b); graphics.pixel(Point(x, y)); } } diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 9c98aa5f..ba0a456d 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -39,7 +39,7 @@ // .. and back to the start constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t BCD_FRAME_COUNT = 14; +constexpr uint32_t BCD_FRAME_COUNT = 12; constexpr uint32_t BCD_FRAME_BYTES = 60; constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); @@ -274,48 +274,29 @@ namespace pimoroni { // setup audio pio program - /* audio_pio = pio0; audio_sm = pio_claim_unused_sm(audio_pio, true); audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); - audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); - //pio_sm_set_enabled(audio_pio, audio_sm, true); + pio_gpio_init(audio_pio, I2S_DATA); + pio_gpio_init(audio_pio, I2S_BCLK); + pio_gpio_init(audio_pio, I2S_LRCLK); + + audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); uint32_t system_clock_frequency = clock_get_hz(clk_sys); uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - + pio_sm_set_enabled(audio_pio, audio_sm, true); audio_dma_channel = dma_claim_unused_channel(true); dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); - channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_32); - channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian + channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); + //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); - dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ - //irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); - //irq_set_enabled(DMA_IRQ_0, true); - -/* dma_channel_set_trans_count(audio_dma_channel, BITSTREAM_LENGTH / 4, false); - dma_channel_set_read_addr(audio_dma_channel, bitstream, true);*/ - //pio_sm_config audio_i2s_config = audio_i2s_program_get_default_config(audio_sm_offset); - - // osr shifts right, autopull on, autopull threshold 8 - //sm_config_set_out_shift(&audio_i2s_config, true, true, 32); - - // // configure out, set, and sideset pins - // sm_config_set_out_pins(&audio_i2s_config, ROW_BIT_0, 4); - // sm_config_set_set_pins(&audio_i2s_config, COLUMN_DATA, 3); - // sm_config_set_sideset_pins(&audio_i2s_config, COLUMN_CLOCK); - - // // join fifos as only tx needed (gives 8 deep fifo instead of 4) - // sm_config_set_fifo_join(&audio_i2s_config, PIO_FIFO_JOIN_TX); - - - //pio_sm_init(audio_pio, audio_sm, audio_sm_offset, &audio_i2s_config); - //pio_sm_set_enabled(audio_pio, audio_sm, true); + //dma_channel_set_irq0_enabled(audio_dma_channel, true); + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true); } @@ -328,7 +309,7 @@ namespace pimoroni { } void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { - dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 4); + dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); } void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { From c91c5d6bf497940a944316b603ebae303494ee9b Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 05:05:23 +0100 Subject: [PATCH 06/42] Update to use new RGB888 pen type --- examples/galactic_unicorn/balls.cpp | 2 +- examples/galactic_unicorn/demo.cpp | 2 +- examples/galactic_unicorn/eighties_super_computer.cpp | 2 +- examples/galactic_unicorn/feature_test.cpp | 2 +- examples/galactic_unicorn/fire_effect.cpp | 2 +- examples/galactic_unicorn/lava_lamp.cpp | 2 +- examples/galactic_unicorn/nostalgia_prompt.cpp | 2 +- examples/galactic_unicorn/rainbow.cpp | 2 +- examples/galactic_unicorn/scroll_text.cpp | 2 +- libraries/galactic_unicorn/galactic_unicorn.cpp | 8 ++++---- libraries/galactic_unicorn/galactic_unicorn.hpp | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/galactic_unicorn/balls.cpp b/examples/galactic_unicorn/balls.cpp index 00d6b3d3..2012d4fe 100644 --- a/examples/galactic_unicorn/balls.cpp +++ b/examples/galactic_unicorn/balls.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // extra row of pixels for sourcing flames and averaging diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index 29ca709d..f65b15e5 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel diff --git a/examples/galactic_unicorn/eighties_super_computer.cpp b/examples/galactic_unicorn/eighties_super_computer.cpp index 377ede56..fd6271ae 100644 --- a/examples/galactic_unicorn/eighties_super_computer.cpp +++ b/examples/galactic_unicorn/eighties_super_computer.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; float lifetime[53][11]; diff --git a/examples/galactic_unicorn/feature_test.cpp b/examples/galactic_unicorn/feature_test.cpp index b3ac4074..66361158 100644 --- a/examples/galactic_unicorn/feature_test.cpp +++ b/examples/galactic_unicorn/feature_test.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // left_channel_bin and right_channel_bin are in audio_samples.cpp diff --git a/examples/galactic_unicorn/fire_effect.cpp b/examples/galactic_unicorn/fire_effect.cpp index b69a8fdc..e70fc218 100644 --- a/examples/galactic_unicorn/fire_effect.cpp +++ b/examples/galactic_unicorn/fire_effect.cpp @@ -10,7 +10,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // extra row of pixels for sourcing flames and averaging diff --git a/examples/galactic_unicorn/lava_lamp.cpp b/examples/galactic_unicorn/lava_lamp.cpp index caa539bb..0b5819c1 100644 --- a/examples/galactic_unicorn/lava_lamp.cpp +++ b/examples/galactic_unicorn/lava_lamp.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel diff --git a/examples/galactic_unicorn/nostalgia_prompt.cpp b/examples/galactic_unicorn/nostalgia_prompt.cpp index 845be4ac..e36e85e1 100644 --- a/examples/galactic_unicorn/nostalgia_prompt.cpp +++ b/examples/galactic_unicorn/nostalgia_prompt.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; std::array c64 = { diff --git a/examples/galactic_unicorn/rainbow.cpp b/examples/galactic_unicorn/rainbow.cpp index 804584bd..52cc4e59 100644 --- a/examples/galactic_unicorn/rainbow.cpp +++ b/examples/galactic_unicorn/rainbow.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel diff --git a/examples/galactic_unicorn/scroll_text.cpp b/examples/galactic_unicorn/scroll_text.cpp index 9e24b4ce..d90e6f77 100644 --- a/examples/galactic_unicorn/scroll_text.cpp +++ b/examples/galactic_unicorn/scroll_text.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; std::string message = "Pirate. Monkey. Robot. Ninja."; diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index ba0a456d..9dda38b1 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -382,16 +382,16 @@ namespace pimoroni { } - void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { + void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t j = 0; j < 53 * 11; j++) { int x = j % 53; int y = j / 53; uint16_t col = __builtin_bswap16(*p); - uint8_t r = ((col & 0b1111100000000000) >> 11) << 3; - uint8_t g = ((col & 0b0000011111100000) >> 5) << 2; - uint8_t b = ((col & 0b0000000000011111) >> 0) << 3; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; p++; r = (r * this->brightness) >> 8; diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 3714c843..d4499cb0 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -64,7 +64,7 @@ namespace pimoroni { void clear(); - void update(PicoGraphics_PenRGB565 &graphics); + void update(PicoGraphics_PenRGB888 &graphics); void set_brightness(float value); float get_brightness(); From a322c400f09aa350e05cd0565f9d7b08f7bf3fc6 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 05:31:33 +0100 Subject: [PATCH 07/42] Added support for new RGB888 pen type --- examples/galactic_unicorn/feature_test.cpp | 5 +-- .../galactic_unicorn/galactic_unicorn.cpp | 34 +++++++++++++++---- .../galactic_unicorn/galactic_unicorn.hpp | 5 +-- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/examples/galactic_unicorn/feature_test.cpp b/examples/galactic_unicorn/feature_test.cpp index 66361158..c2016afb 100644 --- a/examples/galactic_unicorn/feature_test.cpp +++ b/examples/galactic_unicorn/feature_test.cpp @@ -21,7 +21,8 @@ extern uint32_t right_channel_bin_len; void gradient(uint8_t r, uint8_t g, uint8_t b) { for(int y = 0; y < 12; y++) { for(int x = 0; x < 53; x++) { - graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); +// graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); + graphics.set_pen(x, x, x); graphics.pixel(Point(x, y)); } } @@ -72,7 +73,7 @@ int main() { galactic_unicorn.init(); - galactic_unicorn.set_brightness(0.5f); + //galactic_unicorn.set_brightness(0.5f); while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 9dda38b1..0f2718f5 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -39,7 +39,7 @@ // .. and back to the start constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t BCD_FRAME_COUNT = 12; +constexpr uint32_t BCD_FRAME_COUNT = 14; constexpr uint32_t BCD_FRAME_BYTES = 60; constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); @@ -98,7 +98,7 @@ namespace pimoroni { // 0-65535 range for the pwm counter float r_gamma = 1.8f; r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float g_gamma = 2.0f; + float g_gamma = 1.8f; g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); float b_gamma = 1.8f; b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); @@ -356,7 +356,7 @@ namespace pimoroni { void GalacticUnicorn::set_brightness(float value) { value = value < 0.0f ? 0.0f : value; value = value > 1.0f ? 1.0f : value; - this->brightness = floor(value * 255.0f); + this->brightness = floor(value * 256.0f); } float GalacticUnicorn::get_brightness() { @@ -382,16 +382,16 @@ namespace pimoroni { } - void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { + void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t j = 0; j < 53 * 11; j++) { int x = j % 53; int y = j / 53; uint16_t col = __builtin_bswap16(*p); - uint8_t r = (col & 0xff0000) >> 16; - uint8_t g = (col & 0x00ff00) >> 8; - uint8_t b = (col & 0x0000ff) >> 0; + uint8_t r = (col & 0b1111100000000000) >> 8; + uint8_t g = (col & 0b0000011111100000) >> 3; + uint8_t b = (col & 0b0000000000011111) << 3; p++; r = (r * this->brightness) >> 8; @@ -402,6 +402,26 @@ namespace pimoroni { } } + void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { + uint32_t *p = (uint32_t *)graphics.frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + p++; + + r = (r * this->brightness) >> 8; + g = (g * this->brightness) >> 8; + b = (b * this->brightness) >> 8; + + set_pixel(x, y, b, g, r); + } + } + bool GalacticUnicorn::is_pressed(uint8_t button) { return !gpio_get(button); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index d4499cb0..340e767f 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -53,8 +53,8 @@ namespace pimoroni { uint audio_sm = 0; uint audio_sm_offset = 0; - uint8_t brightness = 255; - uint8_t volume = 127; + uint16_t brightness = 256; + uint16_t volume = 127; public: ~GalacticUnicorn(); @@ -64,6 +64,7 @@ namespace pimoroni { void clear(); + void update(PicoGraphics_PenRGB565 &graphics); void update(PicoGraphics_PenRGB888 &graphics); void set_brightness(float value); From 241be438b886f80edf584db2c91e98efff05b2c0 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 06:07:30 +0100 Subject: [PATCH 08/42] Fixed a couple of small bugs in fire demo --- examples/galactic_unicorn/fire_effect.cpp | 28 ++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/galactic_unicorn/fire_effect.cpp b/examples/galactic_unicorn/fire_effect.cpp index e70fc218..b5ee4bfd 100644 --- a/examples/galactic_unicorn/fire_effect.cpp +++ b/examples/galactic_unicorn/fire_effect.cpp @@ -25,6 +25,12 @@ void set(int x, int y, float v) { } float get(int x, int y) { + /*if(x < 0 || x >= width || y < 0 || y >= height) { + return 0.0f; + }*/ + x = x < 0 ? 0 : x; + x = x >= width ? width - 1 : x; + return heat[x + y * width]; } @@ -33,6 +39,7 @@ int main() { stdio_init_all(); galactic_unicorn.init(); + galactic_unicorn.set_brightness(0.5); bool landscape = true; @@ -67,9 +74,9 @@ int main() { }else if(value > 0.4f) { graphics.set_pen(220, 160, 0); }else if(value > 0.3f) { - graphics.set_pen(180, 50, 0); - }else if(value > 0.2f) { - graphics.set_pen(40, 40, 40); + graphics.set_pen(180, 30, 0); + }else if(value > 0.22f) { + graphics.set_pen(20, 20, 20); } if(landscape) { @@ -80,17 +87,12 @@ int main() { // update this pixel by averaging the below pixels - float average = 0.0f; - if(x == 0) { - average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x + 1, y + 1)) / 4.0f; - } else if(x == 52) { - average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1)) / 4.0f; - } else { - average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0f; - } + float average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0f; - average -= landscape ? 0.01f : 0.004f; - average = average < 0.0f ? 0.0f: average; + // damping factor to ensure flame tapers out towards the top of the displays + average *= landscape ? 0.95f : 0.99f; + + // update the heat map with our newly averaged value set(x, y, average); } } From 09846ab2214439b041cb74d53efc89d5a82a0c50 Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 29 Jun 2022 08:54:30 +0100 Subject: [PATCH 09/42] Galactic Unicorn: Initial C++ experimentaion. --- examples/galactic_unicorn/CMakeLists.txt | 117 +--- examples/galactic_unicorn/demo.cpp | 87 +-- libraries/galactic_unicorn/CMakeLists.txt | 13 +- libraries/galactic_unicorn/README.md | 15 +- .../galactic_unicorn/galactic_unicorn.cmake | 14 +- .../galactic_unicorn/galactic_unicorn.cpp | 551 +++++++++--------- .../galactic_unicorn/galactic_unicorn.hpp | 73 +-- .../galactic_unicorn/galactic_unicorn.pio | 110 ++-- 8 files changed, 361 insertions(+), 619 deletions(-) diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index 7b145552..c5d9167b 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -4,122 +4,7 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(galactic_unicorn_demo 1) +target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo) - - - -add_executable( - rainbow - rainbow.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(rainbow pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(rainbow 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(rainbow) - - - -add_executable( - nostalgia_prompt - nostalgia_prompt.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(nostalgia_prompt pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(nostalgia_prompt 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(nostalgia_prompt) - - - -add_executable( - eighties_super_computer - eighties_super_computer.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(eighties_super_computer pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(eighties_super_computer 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(eighties_super_computer) - - - - -add_executable( - fire_effect - fire_effect.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(fire_effect pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(fire_effect 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(fire_effect) - - - - -add_executable( - scroll_text - scroll_text.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(scroll_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(scroll_text 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(scroll_text) - - -add_executable( - balls - balls.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(balls pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(balls 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(balls) - - - -add_executable( - lava_lamp - lava_lamp.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(lava_lamp pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(lava_lamp 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(lava_lamp) - - - -add_executable( - feature_test - feature_test.cpp - audio_samples.cpp -) - -# Pull in pico libraries that we need -target_link_libraries(feature_test pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(feature_test 1) - -# create map/bin/hex file etc. -pico_add_extra_outputs(feature_test) \ No newline at end of file diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index f65b15e5..c491e490 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -5,11 +5,10 @@ #include "libraries/pico_graphics/pico_graphics.hpp" #include "galactic_unicorn.hpp" -#include "okcolor.hpp" using namespace pimoroni; -PicoGraphics_PenRGB888 graphics(53, 11, nullptr); +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel @@ -107,86 +106,10 @@ gpio_set_function(28, GPIO_FUNC_SIO); - //uint i = 0; - //int v = 255; - - float hue_offset = 0.0f; - float brightness = 0.5f; - float curve = 4.0f; - - int x = 10; - int y = 5; - + uint i = 0; + int v = 255; while(true) { - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { - hue_offset += 0.05; - if(hue_offset > 1.0f) hue_offset = 1.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { - hue_offset -= 0.05; - if(hue_offset < 0.0f) hue_offset = 0.0f; - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { - brightness += 0.05; - if(brightness > 1.0f) brightness = 1.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { - brightness -= 0.05; - if(brightness < 0.0f) brightness = 0.0f; - } - - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { - curve += 0.5; - if(curve > 100.0f) curve = 100.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { - curve -= 0.5; - if(curve < 0.5) curve = 0.5; - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { - x -= 1; - sleep_ms(250); - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { - x += 1; - sleep_ms(250); - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) { - y -= 1; - sleep_ms(250); - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_D)) { - y += 1; - sleep_ms(250); - } - -/* - for(int y = 0; y < 11; y++) { - for(int x = 0; x < 53; x++) { - float fx = x / 53.0f; - float fy = (y / 11.0f) - 0.5f; - float twopi = M_PI * 2; - float hue = fy + (sin(fx * twopi / curve)); - float fade = 1.0f; - - hue += hue_offset; - while(hue < 0.0f) {hue += 1.0f;} - while(hue > 1.0f) {hue -= 1.0f;} - hue = 1.0f - hue; - ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade}; - ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); - galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f); - } - }*/ - - galactic_unicorn.set_pixel(x, y, 255, 255, 255); - /*i++; + i++; graphics.set_pen(0, 0, 0); if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} @@ -228,7 +151,7 @@ graphics.set_pen(255, 255, 255); } galactic_unicorn.set_pixel(x, y, r, g, b); } -*/ + sleep_ms(10); } diff --git a/libraries/galactic_unicorn/CMakeLists.txt b/libraries/galactic_unicorn/CMakeLists.txt index db39dd3e..1322707e 100644 --- a/libraries/galactic_unicorn/CMakeLists.txt +++ b/libraries/galactic_unicorn/CMakeLists.txt @@ -1 +1,12 @@ -include(galactic_unicorn.cmake) \ No newline at end of file +add_library(galactic_unicorn INTERFACE) + +pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) + +target_sources(galactic_unicorn INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp +) + +target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(galactic_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) diff --git a/libraries/galactic_unicorn/README.md b/libraries/galactic_unicorn/README.md index bd41b3df..c568977e 100644 --- a/libraries/galactic_unicorn/README.md +++ b/libraries/galactic_unicorn/README.md @@ -17,7 +17,6 @@ We've included helper functions to handle every aspect of drawing to the display - [init](#init) - [set_pixel](#set_pixel) - [is_pressed](#is_pressed) -- [Examples](#examples) ## Example Program @@ -99,16 +98,4 @@ The button vaule should be a `uint8_t` denoting a pin, and constants `A`, `B`, ` ```c++ bool is_a_button_pressed = pico_unicorn.is_pressed(PicoUnicorn::A) -``` - -# Examples - -## Game of Life - -## Retro Super-computer - -Random LEDs blink on and off mimicing the look of a movie super computer doing it's work in the eighties. - -## Nostalgia Terminal - -A collection of copies of classic terminal styles including C64, MS-DOS, Spectrum, and more. \ No newline at end of file +``` \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.cmake b/libraries/galactic_unicorn/galactic_unicorn.cmake index c99a3473..fd2a3c5c 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cmake +++ b/libraries/galactic_unicorn/galactic_unicorn.cmake @@ -1,14 +1,12 @@ -add_library(galactic_unicorn INTERFACE) +add_library(pico_unicorn INTERFACE) -pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) -pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pio) +pico_generate_pio_header(pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.pio) - -target_sources(galactic_unicorn INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp +target_sources(pico_unicorn INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.cpp ) -target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn INTERFACE pico_stdlib pico_graphics hardware_adc hardware_pio hardware_dma) +target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 0f2718f5..37b6ef7a 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -2,47 +2,88 @@ #include "hardware/dma.h" #include "hardware/irq.h" -#include "hardware/adc.h" -#include "hardware/clocks.h" - #include "galactic_unicorn.pio.h" -#include "audio_i2s.pio.h" - #include "galactic_unicorn.hpp" // pixel data is stored as a stream of bits delivered in the // order the PIO needs to manage the shift registers, row // selects, delays, and latching/blanking // -// the pins used are: +// the data consists of 11 rows each of which has 14 frames of +// bcd timing data // -// - 13: column clock (sideset) -// - 14: column data (out base) -// - 15: column latch -// - 16: column blank -// - 17: row select bit 0 -// - 18: row select bit 1 -// - 19: row select bit 2 -// - 20: row select bit 3 +// bits are output in order: // -// the framebuffer data is structured like this: +// ROW_CLEAR, ROW_DATA1, ROW_DATA0, LED_BLANK, LED_LATCH, LED_CLOCK, LED_DATA0, LED_DATA1 // -// for each row: -// for each bcd frame: -// 0: 00110110 // row pixel count (minus one) -// 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data -// 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align -// 56: xxxxrrrr // row select bits -// 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) +// the data is structured like this: +// +// loop through the eleven rows of the display... +// +// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) +// 00000000 00000000 00000000 // dummy bytes to align to dwords +// +// within this row we loop through the 14 bcd frames for this row... +// +// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high +// 162: 10011000 // LATCH pixel data +// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) +// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) +// 166: 10010000 // turn BLANK back on +// 167: 00000000 // dummy byte to ensure dword aligned // // .. and back to the start +/* +enum pin { + LED_DATA = 8, + LED_CLOCK = 9, + LED_LATCH = 10, + LED_BLANK = 11, + ROW_0 = 22, + ROW_1 = 21, + ROW_2 = 20, + ROW_3 = 19, + ROW_4 = 18, + ROW_5 = 17, + ROW_6 = 16, + A = 12, + B = 13, + X = 14, + Y = 15, +};*/ + +enum pin { + LED_DATA1 = 12, + LED_DATA0 = 13, + LED_CLOCK = 14, + LED_LATCH = 15, + LED_BLANK = 16, + + ROW_DATA0 = 17, + ROW_DATA1 = 18, + ROW_CLEAR = 19, + ROW_CLOCK = 20, + + SWITCH_A = 0, + SWITCH_B = 1, + SWITCH_C = 3, + SWITCH_D = 6, + SWITCH_E = 2, + SWITCH_VOLUME_UP = 21, + SWITCH_VOLUME_DOWN = 26, + SWITCH_BRIGHTNESS_UP = 7, + SWITCH_BRIGHTNESS_DOWN = 8 +}; + + + constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t BCD_FRAME_COUNT = 14; -constexpr uint32_t BCD_FRAME_BYTES = 60; -constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; -constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); +constexpr uint32_t ROW_BYTES = 4; +constexpr uint32_t ROW_FRAME_BYTES = 168; +constexpr uint32_t BCD_FRAMES = 15; // includes fet discharge frame +constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES + ROW_COUNT * ROW_FRAME_BYTES * BCD_FRAMES); // must be aligned for 32bit dma transfer alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0}; @@ -52,7 +93,38 @@ static uint16_t g_gamma_lut[256] = {0}; static uint16_t b_gamma_lut[256] = {0}; static uint32_t dma_channel; -static uint32_t audio_dma_channel; + +static inline void unicorn_jetpack_program_init(PIO pio, uint sm, uint offset) { + pio_gpio_init(pio, pin::LED_DATA1); + pio_gpio_init(pio, pin::LED_DATA0); + pio_gpio_init(pio, pin::LED_CLOCK); + pio_gpio_init(pio, pin::LED_LATCH); + pio_gpio_init(pio, pin::LED_BLANK); + + pio_gpio_init(pio, pin::ROW_DATA0); + pio_gpio_init(pio, pin::ROW_DATA1); + pio_gpio_init(pio, pin::ROW_CLEAR); + pio_gpio_init(pio, pin::ROW_CLOCK); + + pio_sm_set_consecutive_pindirs(pio, sm, pin::LED_DATA1, 5, true); + pio_sm_set_consecutive_pindirs(pio, sm, pin::ROW_DATA0, 4, true); + + pio_sm_config c = galactic_unicorn_program_get_default_config(offset); + + // osr shifts right, autopull on, autopull threshold 8 + sm_config_set_out_shift(&c, true, false, 32); + + // configure out, set, and sideset pins + sm_config_set_out_pins(&c, pin::LED_DATA1, 8); + sm_config_set_sideset_pins(&c, pin::ROW_CLOCK); + + // join fifos as only tx needed (gives 8 deep fifo instead of 4) + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); + ///pio_sm_set_clkdiv(pio, sm, 4.0f); +} namespace pimoroni { @@ -82,124 +154,118 @@ namespace pimoroni { pio_sm_restart(bitstream_pio, bitstream_sm); } - uint16_t GalacticUnicorn::light() { - adc_select_input(2); - return adc_read(); - } - void GalacticUnicorn::init() { // todo: shouldn't need to do this if things were cleaned up properly but without // this any attempt to run a micropython script twice will fail static bool already_init = false; + // setup pins + gpio_init(pin::LED_DATA0); gpio_set_dir(pin::LED_DATA0, GPIO_OUT); + gpio_init(pin::LED_DATA1); gpio_set_dir(pin::LED_DATA1, GPIO_OUT); + gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT); + gpio_init(pin::LED_LATCH); gpio_set_dir(pin::LED_LATCH, GPIO_OUT); + gpio_init(pin::LED_BLANK); gpio_set_dir(pin::LED_BLANK, GPIO_OUT); + + gpio_init(pin::ROW_DATA0); gpio_set_dir(pin::ROW_DATA0, GPIO_OUT); + gpio_init(pin::ROW_DATA1); gpio_set_dir(pin::ROW_DATA1, GPIO_OUT); + gpio_init(pin::ROW_CLEAR); gpio_set_dir(pin::ROW_CLEAR, GPIO_OUT); + gpio_init(pin::ROW_CLOCK); gpio_set_dir(pin::ROW_CLOCK, GPIO_OUT); + // create 14-bit gamma luts for(uint16_t v = 0; v < 256; v++) { // gamma correct the provided 0-255 brightness value onto a // 0-65535 range for the pwm counter - float r_gamma = 1.8f; - r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float g_gamma = 1.8f; - g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float b_gamma = 1.8f; - b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - } - - // for each row: - // for each bcd frame: - // 0: 00110110 // row pixel count (minus one) - // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data - // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align - // 56: xxxxrrrr // row select bits - // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) - // - // .. and back to the start + float r_gamma = 2.8f; + r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * 16383.0f + 0.5f); + float g_gamma = 2.8f; + g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * 16383.0f + 0.5f); + + float b_gamma = 2.8f; + b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * 16383.0f + 0.5f); + } + +// the data is structured like this: +// +// loop through the eleven rows of the display... +// +// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) +// 00000000 00000000 00000000 // dummy bytes to align to dwords +// +// within this row we loop through the 14 bcd frames for this row... +// +// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high +// 162: 10011000 // LATCH pixel data +// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) +// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) +// 166: 10010000 // turn BLANK back on +// 167: 00000000 // dummy byte to ensure dword aligned +// +// .. and back to the start // initialise the bcd timing values and row selects in the bitstream for(uint8_t row = 0; row < HEIGHT; row++) { - for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { - // find the offset of this row and frame in the bitstream - uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; + uint16_t row_offset = row * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); - p[ 0] = WIDTH - 1; // row pixel count - p[56] = row; // row select + // setup row select on rows 0 and 8 + uint8_t row_select = row == 0 ? 0b10111000 : (row == 8 ? 0b11011000 : 0b10011000); + bitstream[row_offset + 0] = row_select; + + for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { + uint16_t frame_offset = row_offset + ROW_BYTES + (ROW_FRAME_BYTES * frame); + + bitstream[frame_offset + 162] = 0b10011000; // LATCH pixel data + bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs // set the number of bcd ticks for this frame - uint32_t bcd_ticks = (1 << frame); - p[57] = (bcd_ticks & 0xff) >> 0; - p[58] = (bcd_ticks & 0xff00) >> 8; - p[59] = (bcd_ticks & 0xff0000) >> 16; - } - } + uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 65535 : 1 << frame; + bitstream[frame_offset + 164] = (bcd_ticks & 0xff); + bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8; - // setup light sensor adc - adc_init(); - adc_gpio_init(LIGHT_SENSOR); + bitstream[frame_offset + 166] = 0b10010000; // BLANK high again to disable outputs - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); - - gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); - gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); - gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); - - sleep_ms(100); - - // configure full output current in register 2 - - uint16_t reg1 = 0b1111111111001110; - - // clock the register value to the first 9 driver chips - for(int j = 0; j < 9; j++) { - for(int i = 0; i < 16; i++) { - if(reg1 & (1U << (15 - i))) { - gpio_put(COLUMN_DATA, true); - }else{ - gpio_put(COLUMN_DATA, false); + // setup empty pixels with BLANK high and a clock pulse + for(uint8_t col = 0; col < 162; col += 2) { + bitstream[frame_offset + col + 0] = 0b10010000; + bitstream[frame_offset + col + 1] = 0b10010100; } - sleep_us(10); - gpio_put(COLUMN_CLOCK, true); - sleep_us(10); - gpio_put(COLUMN_CLOCK, false); + +/* + uint16_t row_select_offset = offset + 164; + uint16_t bcd_offset = offset + 165; + + // the last bcd frame is used to allow the fets to discharge to avoid ghosting + if(frame == BCD_FRAMES - 1) { + uint16_t bcd_ticks = 65535; + bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; + bitstream[bcd_offset] = (bcd_ticks & 0xff); + }else{ + uint8_t row_select = row == 0 ? 0b01000000 : (row == 8 ? 0b00100000 : 0b00000000); + bitstream[row_select_offset] = row_select; + + uint16_t bcd_ticks = 1 << frame; + bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; + bitstream[bcd_offset] = (bcd_ticks & 0xff); + }*/ } +/* + for(size_t i = 0; i < sizeof(bitstream); i++) { + bitstream[i] = 0b11100000; + }*/ } - // clock the last chip and latch the value - for(int i = 0; i < 16; i++) { - if(reg1 & (1U << (15 - i))) { - gpio_put(COLUMN_DATA, true); - }else{ - gpio_put(COLUMN_DATA, false); - } - - sleep_us(10); - gpio_put(COLUMN_CLOCK, true); - sleep_us(10); - gpio_put(COLUMN_CLOCK, false); - - if(i == 4) { - gpio_put(COLUMN_LATCH, true); - } - } - gpio_put(COLUMN_LATCH, false); - - - gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); - // setup button inputs - gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); - gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); - gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); - gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); + gpio_set_function(pin::SWITCH_A, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_A, GPIO_IN); gpio_pull_up(pin::SWITCH_A); + gpio_set_function(pin::SWITCH_B, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_B, GPIO_IN); gpio_pull_up(pin::SWITCH_B); + gpio_set_function(pin::SWITCH_C, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_C, GPIO_IN); gpio_pull_up(pin::SWITCH_C); + gpio_set_function(pin::SWITCH_D, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_D, GPIO_IN); gpio_pull_up(pin::SWITCH_D); + gpio_set_function(pin::SWITCH_E, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_E, GPIO_IN); gpio_pull_up(pin::SWITCH_E); - gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); + gpio_set_function(pin::SWITCH_BRIGHTNESS_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_UP); + gpio_set_function(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_DOWN); - gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); - gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); - - gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); - gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); + gpio_set_function(pin::SWITCH_VOLUME_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_UP); + gpio_set_function(pin::SWITCH_VOLUME_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_DOWN); if(already_init) { // stop and release the dma channel @@ -222,38 +288,9 @@ namespace pimoroni { // setup the pio bitstream_pio = pio0; - bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); - bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); - - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); - pio_gpio_init(bitstream_pio, COLUMN_BLANK); - - pio_gpio_init(bitstream_pio, ROW_BIT_0); - pio_gpio_init(bitstream_pio, ROW_BIT_1); - pio_gpio_init(bitstream_pio, ROW_BIT_2); - pio_gpio_init(bitstream_pio, ROW_BIT_3); - - // set all led driving pins as outputs - pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); - - pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); - - // osr shifts right, autopull on, autopull threshold 8 - sm_config_set_out_shift(&c, true, true, 32); - - // configure out, set, and sideset pins - sm_config_set_out_pins(&c, ROW_BIT_0, 4); - sm_config_set_set_pins(&c, COLUMN_DATA, 3); - sm_config_set_sideset_pins(&c, COLUMN_CLOCK); - - // join fifos as only tx needed (gives 8 deep fifo instead of 4) - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - - pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); - pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); - + bitstream_sm = pio_claim_unused_sm(pio0, true); + sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); + unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset); // setup dma transfer for pixel data to the pio dma_channel = dma_claim_unused_channel(true); @@ -271,33 +308,6 @@ namespace pimoroni { dma_channel_set_read_addr(dma_channel, bitstream, true); already_init = true; - - - // setup audio pio program - audio_pio = pio0; - audio_sm = pio_claim_unused_sm(audio_pio, true); - audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); - - pio_gpio_init(audio_pio, I2S_DATA); - pio_gpio_init(audio_pio, I2S_BCLK); - pio_gpio_init(audio_pio, I2S_LRCLK); - - audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); - uint32_t system_clock_frequency = clock_get_hz(clk_sys); - uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow - pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - pio_sm_set_enabled(audio_pio, audio_sm, true); - - - audio_dma_channel = dma_claim_unused_channel(true); - dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); - channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); - //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian - channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); - dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); - //dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true); - } void GalacticUnicorn::clear() { @@ -308,44 +318,108 @@ namespace pimoroni { } } - void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { - dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); - } - void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { + + if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; // make those coordinates sane x = (WIDTH - 1) - x; y = (HEIGHT - 1) - y; - uint16_t gamma_r = r_gamma_lut[r]; - uint16_t gamma_g = g_gamma_lut[g]; - uint16_t gamma_b = b_gamma_lut[b]; + // determine offset in the buffer for this row + uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); - // for each row: - // for each bcd frame: - // 0: 00110110 // row pixel count (minus one) - // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data - // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align - // 56: xxxxrrrr // row select bits - // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) - // - // .. and back to the start + uint16_t bits[3] = {r_gamma_lut[r], g_gamma_lut[g], b_gamma_lut[b]}; + //uint16_t gr = r_gamma_lut[r]; + //uint16_t gg = g_gamma_lut[g]; + //uint16_t gb = b_gamma_lut[b]; // set the appropriate bits in the separate bcd frames - for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { - uint8_t *p = &bitstream[y * ROW_BYTES + (BCD_FRAME_BYTES * frame) + 1 + x]; + for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { + uint16_t frame_offset = (ROW_FRAME_BYTES * frame) + 4; + uint16_t offset = row_offset + frame_offset;// + byte_offset; - uint8_t red_bit = gamma_r & 0b1; - uint8_t green_bit = gamma_g & 0b1; - uint8_t blue_bit = gamma_b & 0b1; +// loop through the eleven rows of the display... +// +// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) +// 00000000 00000000 00000000 // dummy bytes to align to dwords +// +// within this row we loop through the 14 bcd frames for this row... +// +// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high +// 162: 10011000 // LATCH pixel data +// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) +// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) +// 166: 10010000 // turn BLANK back on +// 167: 00000000 // dummy byte to ensure dword aligned +// +// .. and back to the start - *p = (blue_bit << 2) | (green_bit << 1) | (red_bit << 0); + // work out the byte offset of this pixel + /*if(bit_offset >= 160) { + bit_offset -= 160; + }*/ - gamma_r >>= 1; - gamma_g >>= 1; - gamma_b >>= 1; + for(int bit = 0; bit < 3; bit++) { + int16_t bit_offset = x * 6 + 4 + (bit * 2); + + + uint8_t bit_position = bit_offset >= 160 ? 1 : 0; + uint8_t mask = 0b1 << bit_position; + uint8_t value = (bits[bit] & 0b1) << bit_position; + + bitstream[offset + (bit_offset % 160) + 0] &= ~mask; + bitstream[offset + (bit_offset % 160) + 0] |= value; + bitstream[offset + (bit_offset % 160) + 1] &= ~mask; + bitstream[offset + (bit_offset % 160) + 1] |= value; + + //bit_offset += 2; + bits[bit] >>= 1; + } + /* // setup pixel data and matching mask + uint8_t bit_position = x >= 26 ? 1 : 0; + uint8_t mask = 0b1 << bit_position; + uint8_t red = (gr & 0b1) << bit_position; + uint8_t green = (gg & 0b1) << bit_position; + uint8_t blue = (gb & 0b1) << bit_position; + + // clear existing data and set new data + bitstream[offset + 0] &= ~mask; + bitstream[offset + 0] |= red; + bitstream[offset + 1] &= ~mask; + bitstream[offset + 1] |= red; + bitstream[offset + 2] &= ~mask; + bitstream[offset + 2] |= green; + bitstream[offset + 3] &= ~mask; + bitstream[offset + 3] |= green; + bitstream[offset + 4] &= ~mask; + bitstream[offset + 4] |= blue; + bitstream[offset + 5] &= ~mask; + bitstream[offset + 5] |= blue;*/ +/* + + uint8_t mask = 0b11; + uint8_t red = ((gr & 0b1) << 1) | (gr & 0b1) ; + uint8_t green = ((gg & 0b1) << 1) | (gg & 0b1) ; + uint8_t blue = ((gb & 0b1) << 1) | (gb & 0b1) ; + + bitstream[offset + 0] &= ~mask; + bitstream[offset + 0] |= red; + bitstream[offset + 1] &= ~mask; + bitstream[offset + 1] |= red; + bitstream[offset + 2] &= ~mask; + bitstream[offset + 2] |= green; + bitstream[offset + 3] &= ~mask; + bitstream[offset + 3] |= green; + bitstream[offset + 4] &= ~mask; + bitstream[offset + 4] |= blue; + bitstream[offset + 5] &= ~mask; + bitstream[offset + 5] |= blue; +*/ + /* gr >>= 1; + gg >>= 1; + gb >>= 1;*/ } } @@ -353,75 +427,6 @@ namespace pimoroni { set_pixel(x, y, v, v, v); } - void GalacticUnicorn::set_brightness(float value) { - value = value < 0.0f ? 0.0f : value; - value = value > 1.0f ? 1.0f : value; - this->brightness = floor(value * 256.0f); - } - - float GalacticUnicorn::get_brightness() { - return this->brightness / 255.0f; - } - - void GalacticUnicorn::adjust_brightness(float delta) { - this->set_brightness(this->get_brightness() + delta); - } - - void GalacticUnicorn::set_volume(float value) { - value = value < 0.0f ? 0.0f : value; - value = value > 1.0f ? 1.0f : value; - this->volume = floor(value * 255.0f); - } - - float GalacticUnicorn::get_volume() { - return this->volume / 255.0f; - } - - void GalacticUnicorn::adjust_volume(float delta) { - this->set_volume(this->get_volume() + delta); - } - - - void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { - uint16_t *p = (uint16_t *)graphics.frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; - - uint16_t col = __builtin_bswap16(*p); - uint8_t r = (col & 0b1111100000000000) >> 8; - uint8_t g = (col & 0b0000011111100000) >> 3; - uint8_t b = (col & 0b0000000000011111) << 3; - p++; - - r = (r * this->brightness) >> 8; - g = (g * this->brightness) >> 8; - b = (b * this->brightness) >> 8; - - set_pixel(x, y, b, g, r); - } - } - - void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { - uint32_t *p = (uint32_t *)graphics.frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; - - uint32_t col = *p; - uint8_t r = (col & 0xff0000) >> 16; - uint8_t g = (col & 0x00ff00) >> 8; - uint8_t b = (col & 0x0000ff) >> 0; - p++; - - r = (r * this->brightness) >> 8; - g = (g * this->brightness) >> 8; - b = (b * this->brightness) >> 8; - - set_pixel(x, y, b, g, r); - } - } - bool GalacticUnicorn::is_pressed(uint8_t button) { return !gpio_get(button); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 340e767f..768977f9 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -1,7 +1,6 @@ #pragma once #include "hardware/pio.h" -#include "pico_graphics.hpp" namespace pimoroni { @@ -9,82 +8,30 @@ namespace pimoroni { public: static const int WIDTH = 53; static const int HEIGHT = 11; - - // pin assignments - static const uint8_t COLUMN_CLOCK = 13; - static const uint8_t COLUMN_DATA = 14; - static const uint8_t COLUMN_LATCH = 15; - static const uint8_t COLUMN_BLANK = 16; - - static const uint8_t ROW_BIT_0 = 17; - static const uint8_t ROW_BIT_1 = 18; - static const uint8_t ROW_BIT_2 = 19; - static const uint8_t ROW_BIT_3 = 20; - - static const uint8_t LIGHT_SENSOR = 28; - - static const uint8_t MUTE = 22; - - static const uint8_t I2S_DATA = 9; - static const uint8_t I2S_BCLK = 10; - static const uint8_t I2S_LRCLK = 11; - - static const uint8_t I2C_SDA = 4; - static const uint8_t I2C_SCL = 5; - - static const uint8_t SWITCH_A = 0; - static const uint8_t SWITCH_B = 1; - static const uint8_t SWITCH_C = 3; - static const uint8_t SWITCH_D = 6; - - static const uint8_t SWITCH_SLEEP = 27; - - static const uint8_t SWITCH_VOLUME_UP = 7; - static const uint8_t SWITCH_VOLUME_DOWN = 8; - static const uint8_t SWITCH_BRIGHTNESS_UP = 21; - static const uint8_t SWITCH_BRIGHTNESS_DOWN = 26; + static const uint8_t SWITCH_A = 0; + static const uint8_t SWITCH_B = 1; + static const uint8_t SWITCH_C = 3; + static const uint8_t SWITCH_D = 6; + static const uint8_t SWITCH_E = 2; + static const uint8_t SWITCH_VOLUME_UP = 21; + static const uint8_t SWITCH_VOLUME_DOWN = 26; + static const uint8_t SWITCH_BRIGHTNESS_UP = 7; + static const uint8_t SWITCH_BRIGHTNESS_DOWN = 8; private: PIO bitstream_pio = pio0; uint bitstream_sm = 0; - uint bitstream_sm_offset = 0; - - PIO audio_pio = pio0; - uint audio_sm = 0; - uint audio_sm_offset = 0; - - uint16_t brightness = 256; - uint16_t volume = 127; - + uint sm_offset = 0; public: ~GalacticUnicorn(); void init(); - static inline void pio_program_init(PIO pio, uint sm, uint offset); void clear(); - - void update(PicoGraphics_PenRGB565 &graphics); - void update(PicoGraphics_PenRGB888 &graphics); - - void set_brightness(float value); - float get_brightness(); - void adjust_brightness(float delta); - - void set_volume(float value); - float get_volume(); - void adjust_volume(float delta); - - void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b); void set_pixel(int x, int y, uint8_t v); - uint16_t light(); - bool is_pressed(uint8_t button); - - void play_sample(uint8_t *data, uint32_t length); - }; } \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.pio b/libraries/galactic_unicorn/galactic_unicorn.pio index d919f401..a843cc58 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.pio +++ b/libraries/galactic_unicorn/galactic_unicorn.pio @@ -2,79 +2,65 @@ .side_set 1 opt ; out pins: -; -; - 3: row select bit 0 -; - 4: row select bit 1 -; - 5: row select bit 2 -; - 6: row select bit 3 +; 0: data1 (base) +; 1: data0 +; 2: clock +; 3: latch +; 4: blank +; 5: row1 +; 6: row2 +; 7: row_clear -; set pins: -; -; - 0: column data (base) -; - 1: column latch -; - 2: column blank - -; sideset pin: -; -; - 0: column clock - -; for each row: -; for each bcd frame: -; 0: 00110110 // row pixel count (minus one) -; 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data -; 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align -; 56: xxxxrrrr // row select bits -; 57 - 59: tttttttt, tttttttt, tttttttt, // bcd tick count (0-65536) -; -; .. and back to the start +; sideset pin: row_clock .wrap_target -; loop over row pixels - out y, 8 ; get row pixel count (minus 1 because test is pre decrement) + +; set row select pins + pull + out pins, 8 side 0 [4] + nop side 1 [4] ; pulse row select clock + out null, 24 ; discard dummy data + +; loop for bcd frames + set x, 14 +bcd_frame: + +; clock out 53 pixels worth of data - two pixels at a time, so 27 (actually 26.5) bits of data + set y, 26 ; 26 because `jmp` test is pre decrement + pixels: + + pull ifempty + out pins, 8 [1] ; two red bits.. + out pins, 8 [1] ; ..with clock pulse + + pull ifempty + out pins, 8 [1] ; two green bits.. + out pins, 8 [1] ; ..with green pulse + + pull ifempty + out pins, 8 [1] ; two blue bits.. + out pins, 8 [1] ; ..with blue pulse + + jmp y-- pixels - ; red bit - out x, 1 side 0 [1] ; pull in blue bit from OSR into register x, clear clock - set pins, 0b100 ; clear data bit, blank high - jmp !x endb ; if bit was zero jump - set pins, 0b101 ; set data bit, blank high - endb: - nop side 1 [2] ; clock in bit + out pins, 8 ; LATCH pixel data + out pins, 8 ; turn off BLANK signal - ; green bit - out x, 1 side 0 [1] ; pull in green bit from OSR into register X, clear clock - set pins, 0b100 ; clear data bit, blank high - jmp !x endg ; if bit was zero jump - set pins, 0b101 ; set data bit, blank high - endg: - nop side 1 [2] ; clock in bit + pull - ; blue bit - out x, 1 side 0 [1] ; pull in red bit from OSR into register X, clear clock - set pins, 0b100 ; clear data bit, blank high - jmp !x endr ; if bit was zero jump - set pins, 0b101 ; set data bit, blank high - endr: - out null, 5 side 1 [2] ; clock in bit +; pull bcd tick count into x register + out y, 16 - ;out null, 5 side 0 ; discard the five dummy bits for this pixel +bcd_count: + jmp y-- bcd_count ; loop until bcd delay complete - jmp y-- pixels +; disable led output (blank) and clear latch pin + out pins, 8 ; turn off BLANK signal and clear row output + out null, 8 ; discard dummy data - out null, 16 ; discard dummy bytes - - out pins, 8 ; output row select - - set pins, 0b110 [5] ; latch high, blank high - set pins, 0b000 ; blank low (enable output) - -; loop over bcd delay period - out y, 24 ; get bcd delay counter value -bcd_delay: - jmp y-- bcd_delay - - set pins 0b100 ; blank high (disable output) + jmp x-- bcd_frame ; loop to next bcd frame .wrap \ No newline at end of file From a3d37072841ad5d7cdd4afda05449c24543246c7 Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 29 Jun 2022 21:45:25 +0100 Subject: [PATCH 10/42] more stuff --- examples/galactic_unicorn/CMakeLists.txt | 13 ++ examples/galactic_unicorn/demo.cpp | 70 ++++++- examples/galactic_unicorn/demo2.cpp | 178 ++++++++++++++++++ .../galactic_unicorn/galactic_unicorn.cpp | 4 +- 4 files changed, 259 insertions(+), 6 deletions(-) create mode 100644 examples/galactic_unicorn/demo2.cpp diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index c5d9167b..60165650 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -8,3 +8,16 @@ target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dm # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo) + + + +add_executable( + galactic_unicorn_demo2 + demo2.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) + +# create map/bin/hex file etc. +pico_add_extra_outputs(galactic_unicorn_demo2) diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index c491e490..517c2d68 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -5,6 +5,7 @@ #include "libraries/pico_graphics/pico_graphics.hpp" #include "galactic_unicorn.hpp" +#include "okcolor.hpp" using namespace pimoroni; @@ -106,10 +107,71 @@ gpio_set_function(28, GPIO_FUNC_SIO); - uint i = 0; - int v = 255; + //uint i = 0; + //int v = 255; + + float hue_offset = 0.0f; + float brightness = 0.5f; + float curve = 4.0f; + while(true) { - i++; + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { + hue_offset += 0.05; + if(hue_offset > 1.0f) hue_offset = 1.0f; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { + hue_offset -= 0.05; + if(hue_offset < 0.0f) hue_offset = 0.0f; + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + brightness += 0.05; + if(brightness > 1.0f) brightness = 1.0f; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + brightness -= 0.05; + if(brightness < 0.0f) brightness = 0.0f; + } + + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + curve += 0.5; + if(curve > 100.0f) curve = 100.0f; + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + curve -= 0.5; + if(curve < 0.5) curve = 0.5; + } + + for(int y = 0; y < 11; y++) { + for(int x = 0; x < 53; x++) { + float fx = x / 53.0f; + float fy = (y / 11.0f) - 0.5f; + float twopi = M_PI * 2; + float hue = fy + (sin(fx * twopi / curve)); + float fade = 1.0f; + /* if(hue < 0.0f) { + fade += (hue * 10.0f); + if(fade < 0.0f) fade = 0.0f; + } + if(hue > 1.0f) { + fade -= ((hue - 1.0f) * 10.0f); + if(fade < 0.0f) fade = 0.0f; + }*/ + + hue += hue_offset; + while(hue < 0.0f) {hue += 1.0f;} + while(hue > 1.0f) {hue -= 1.0f;} + hue = 1.0f - hue; +/* + uint8_t r = 0, g = 0, b = 0; + from_hsv(hue, 1.0f, brightness * fade, r, g, b);*/ + ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade}; + ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); + galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f); + } + } + /*i++; graphics.set_pen(0, 0, 0); if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} @@ -151,7 +213,7 @@ graphics.set_pen(255, 255, 255); } galactic_unicorn.set_pixel(x, y, r, g, b); } - +*/ sleep_ms(10); } diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp new file mode 100644 index 00000000..ce06cec1 --- /dev/null +++ b/examples/galactic_unicorn/demo2.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { + int w = graphics.measure_text(t, s); + p.x += (53 / 2) - (w / 2); + p.y += (11 / 2); + graphics.text(t, Point(p.x, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); + graphics.text(t, Point(p.x, p.y + 1), -1, s, a); +} + +struct star_t { + float dx, dy, x, y, a; + + uint8_t brightness() { + int b = a / 5; + return b > 15 ? 15 : b; + } +}; + +void init_star(star_t &s) { + s.x = ((rand() % 100) / 5.0f) - 10.0f; + s.y = ((rand() % 100) / 10.0f) - 5.0f; + + s.dx = s.x / 10.0f; + s.dy = s.y / 10.0f; + s.a = 0; +} + +void step_star(star_t &s) { + s.x += s.dx; + s.y += s.dy; + s.a++; + + if(s.a > 100) { + init_star(s); + } +} + +void number(int n, int x, int y) { + switch(n) { + case 6: { + graphics.rectangle(Rect(x, y, 6, 2)); + graphics.rectangle(Rect(x, y + 4, 6, 2)); + graphics.rectangle(Rect(x, y + 9, 6, 2)); + graphics.rectangle(Rect(x, y, 2, 11)); + graphics.rectangle(Rect(x + 4, y + 4, 2, 5)); + }break; + + case 9: { + graphics.rectangle(Rect(x, y, 6, 2)); + graphics.rectangle(Rect(x, y + 4, 6, 2)); + graphics.rectangle(Rect(x, y + 9, 6, 2)); + graphics.rectangle(Rect(x + 4, y, 2, 11)); + graphics.rectangle(Rect(x, y, 2, 5)); + }break; + + case 4: { + graphics.rectangle(Rect(x, y + 4, 6, 2)); + graphics.rectangle(Rect(x + 4, y, 2, 11)); + graphics.rectangle(Rect(x, y, 2, 5)); + }break; + + case 0: { + graphics.rectangle(Rect(x, y, 6, 2)); + graphics.rectangle(Rect(x + 4, y, 2, 11)); + graphics.rectangle(Rect(x, y, 2, 11)); + graphics.rectangle(Rect(x, y + 9, 6, 2)); + }break; + } +} + +int main() { + + galactic_unicorn.init(); + + // graphics.set_font("sans"); + + + while(true) { + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + } + + graphics.set_pen(0, 0, 0); + graphics.clear(); + graphics.set_pen(200, 200, 0); + number(6, 23, 0); + number(9, 31, 0); + number(4, 39, 0); + number(0, 47, 0); + + graphics.set_pen(200, 0, 0); + graphics.circle(Point(8, 5), 6); + + graphics.set_pen(255, 255, 255); + std::vector triangle = {Point(5, 2), Point(10, 5), Point(5, 7)}; + graphics.polygon(triangle); + + + graphics.set_pen(255, 0, 0); + graphics.rectangle(Rect(0, 0, 10, 11)); + graphics.set_pen(0, 255, 0); + graphics.rectangle(Rect(10, 0, 10, 11)); + graphics.set_pen(0, 0, 255); + graphics.rectangle(Rect(20, 0, 10, 11)); + + uint16_t *p = (uint16_t *)graphics.frame_buffer; + for(size_t i = 0; i < 53 * 11; i++) { + int x = i % 53; + int y = i / 53; + /* uint r = ((*p & 0b0111110000000000) >> 10) << 3; + uint g = ((*p & 0b0000001111100000) >> 5) << 3; + uint b = ((*p & 0b0000000000011111) >> 0) << 3;*/ + p++; + +/* if(r > 200 && g > 200 && b > 200) { + r = hue_map[x][0]; + g = hue_map[x][1]; + b = hue_map[x][2]; + }*/ + galactic_unicorn.set_pixel(x, y, 0, 0, 255); + } + + + sleep_ms(10); + } + + + + printf("done\n"); + + return 0; +} diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 37b6ef7a..ace3b5bd 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -218,7 +218,7 @@ namespace pimoroni { bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs // set the number of bcd ticks for this frame - uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 65535 : 1 << frame; + uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 1 : 1 << frame; bitstream[frame_offset + 164] = (bcd_ticks & 0xff); bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8; @@ -330,7 +330,7 @@ namespace pimoroni { // determine offset in the buffer for this row uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); - uint16_t bits[3] = {r_gamma_lut[r], g_gamma_lut[g], b_gamma_lut[b]}; + uint16_t bits[3] = {r_gamma_lut[b], g_gamma_lut[g], b_gamma_lut[r]}; //uint16_t gr = r_gamma_lut[r]; //uint16_t gg = g_gamma_lut[g]; //uint16_t gb = b_gamma_lut[b]; From 5fdd08438fc320dbb6618f77afd5ef003cb52b3c Mon Sep 17 00:00:00 2001 From: jon Date: Thu, 30 Jun 2022 14:17:41 +0100 Subject: [PATCH 11/42] stuff --- examples/galactic_unicorn/demo2.cpp | 132 ++++++++++-------- .../galactic_unicorn/galactic_unicorn.cpp | 43 ------ 2 files changed, 76 insertions(+), 99 deletions(-) diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp index ce06cec1..7bf5d2f4 100644 --- a/examples/galactic_unicorn/demo2.cpp +++ b/examples/galactic_unicorn/demo2.cpp @@ -70,100 +70,120 @@ void step_star(star_t &s) { } } -void number(int n, int x, int y) { - switch(n) { - case 6: { - graphics.rectangle(Rect(x, y, 6, 2)); - graphics.rectangle(Rect(x, y + 4, 6, 2)); - graphics.rectangle(Rect(x, y + 9, 6, 2)); - graphics.rectangle(Rect(x, y, 2, 11)); - graphics.rectangle(Rect(x + 4, y + 4, 2, 5)); - }break; - - case 9: { - graphics.rectangle(Rect(x, y, 6, 2)); - graphics.rectangle(Rect(x, y + 4, 6, 2)); - graphics.rectangle(Rect(x, y + 9, 6, 2)); - graphics.rectangle(Rect(x + 4, y, 2, 11)); - graphics.rectangle(Rect(x, y, 2, 5)); - }break; - - case 4: { - graphics.rectangle(Rect(x, y + 4, 6, 2)); - graphics.rectangle(Rect(x + 4, y, 2, 11)); - graphics.rectangle(Rect(x, y, 2, 5)); - }break; - - case 0: { - graphics.rectangle(Rect(x, y, 6, 2)); - graphics.rectangle(Rect(x + 4, y, 2, 11)); - graphics.rectangle(Rect(x, y, 2, 11)); - graphics.rectangle(Rect(x, y + 9, 6, 2)); - }break; - } -} int main() { + uint8_t hue_map[53][3]; + for(int i = 0; i < 53; i++) { + from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); + } + + star_t stars[100]; + for(int i = 0; i < 100; i++) { + init_star(stars[i]); + stars[i].a = i; + } + +gpio_set_function(28, GPIO_FUNC_SIO); + gpio_set_dir(28, GPIO_OUT); + + for(int i = 0; i < 10; i++) { + gpio_put(28, !gpio_get(28)); + sleep_ms(100); + } + sleep_ms(1000); + + gpio_put(28,true); + galactic_unicorn.init(); - // graphics.set_font("sans"); +/* + bool a_pressed = false; + bool b_pressed = false; + bool x_pressed = false; + bool y_pressed = false; +*/ + graphics.set_font("sans"); + + uint i = 0; + int v = 255; + + float hue_offset = 0.0f; + float brightness = 0.5f; + float curve = 4.0f; + while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { + hue_offset += 0.05; + if(hue_offset > 1.0f) hue_offset = 1.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { + hue_offset -= 0.05; + if(hue_offset < 0.0f) hue_offset = 0.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + brightness += 0.05; + if(brightness > 1.0f) brightness = 1.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + brightness -= 0.05; + if(brightness < 0.0f) brightness = 0.0f; } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + curve += 0.5; + if(curve > 100.0f) curve = 100.0f; } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + curve -= 0.5; + if(curve < 0.5) curve = 0.5; } +i++; graphics.set_pen(0, 0, 0); + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} graphics.clear(); - graphics.set_pen(200, 200, 0); - number(6, 23, 0); - number(9, 31, 0); - number(4, 39, 0); - number(0, 47, 0); - graphics.set_pen(200, 0, 0); - graphics.circle(Point(8, 5), 6); - - graphics.set_pen(255, 255, 255); - std::vector triangle = {Point(5, 2), Point(10, 5), Point(5, 7)}; - graphics.polygon(triangle); + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} - graphics.set_pen(255, 0, 0); - graphics.rectangle(Rect(0, 0, 10, 11)); - graphics.set_pen(0, 255, 0); - graphics.rectangle(Rect(10, 0, 10, 11)); - graphics.set_pen(0, 0, 255); - graphics.rectangle(Rect(20, 0, 10, 11)); + for(int i = 0; i < 100; i++) { + star_t &star = stars[i]; + step_star(star); + uint b = star.brightness(); + graphics.set_pen(b, b, b); + //graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2))); + } + +graphics.set_pen(255, 255, 255); + float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f); + float a = 1.0f;// (sin(i / 25.0f) * 100.0f); + float x = (sin(i / 25.0f) * 40.0f) * s; + float y = (cos(i / 15.0f) * 10.0f) * s; + text("Galactic", Point(x, y), s, a); + uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t i = 0; i < 53 * 11; i++) { int x = i % 53; int y = i / 53; - /* uint r = ((*p & 0b0111110000000000) >> 10) << 3; - uint g = ((*p & 0b0000001111100000) >> 5) << 3; - uint b = ((*p & 0b0000000000011111) >> 0) << 3;*/ + uint r = ((*p & 0b1111100000000000) >> 11) << 3; + uint g = ((*p & 0b0000011111100000) >> 5) << 2; + uint b = ((*p & 0b0000000000011111) >> 0) << 3; p++; -/* if(r > 200 && g > 200 && b > 200) { + if(r > 200 && g > 200 && b > 200) { r = hue_map[x][0]; g = hue_map[x][1]; b = hue_map[x][2]; - }*/ - galactic_unicorn.set_pixel(x, y, 0, 0, 255); + } + + galactic_unicorn.set_pixel(x, y, r, g, b); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index ace3b5bd..c1b32c38 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -377,49 +377,6 @@ namespace pimoroni { //bit_offset += 2; bits[bit] >>= 1; } - /* // setup pixel data and matching mask - uint8_t bit_position = x >= 26 ? 1 : 0; - uint8_t mask = 0b1 << bit_position; - uint8_t red = (gr & 0b1) << bit_position; - uint8_t green = (gg & 0b1) << bit_position; - uint8_t blue = (gb & 0b1) << bit_position; - - // clear existing data and set new data - bitstream[offset + 0] &= ~mask; - bitstream[offset + 0] |= red; - bitstream[offset + 1] &= ~mask; - bitstream[offset + 1] |= red; - bitstream[offset + 2] &= ~mask; - bitstream[offset + 2] |= green; - bitstream[offset + 3] &= ~mask; - bitstream[offset + 3] |= green; - bitstream[offset + 4] &= ~mask; - bitstream[offset + 4] |= blue; - bitstream[offset + 5] &= ~mask; - bitstream[offset + 5] |= blue;*/ -/* - - uint8_t mask = 0b11; - uint8_t red = ((gr & 0b1) << 1) | (gr & 0b1) ; - uint8_t green = ((gg & 0b1) << 1) | (gg & 0b1) ; - uint8_t blue = ((gb & 0b1) << 1) | (gb & 0b1) ; - - bitstream[offset + 0] &= ~mask; - bitstream[offset + 0] |= red; - bitstream[offset + 1] &= ~mask; - bitstream[offset + 1] |= red; - bitstream[offset + 2] &= ~mask; - bitstream[offset + 2] |= green; - bitstream[offset + 3] &= ~mask; - bitstream[offset + 3] |= green; - bitstream[offset + 4] &= ~mask; - bitstream[offset + 4] |= blue; - bitstream[offset + 5] &= ~mask; - bitstream[offset + 5] |= blue; -*/ - /* gr >>= 1; - gg >>= 1; - gb >>= 1;*/ } } From eaaed2e862f4a1915856c3e114e06492eae80fcf Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 25 Jul 2022 11:24:00 +0100 Subject: [PATCH 12/42] Galactic Unicorn: Examples + features. --- examples/galactic_unicorn/CMakeLists.txt | 106 +++- examples/galactic_unicorn/demo.cpp | 39 +- examples/galactic_unicorn/demo2.cpp | 87 +-- libraries/galactic_unicorn/CMakeLists.txt | 13 +- libraries/galactic_unicorn/README.md | 15 +- .../galactic_unicorn/galactic_unicorn.cmake | 14 +- .../galactic_unicorn/galactic_unicorn.cpp | 511 ++++++++++-------- .../galactic_unicorn/galactic_unicorn.hpp | 72 ++- .../galactic_unicorn/galactic_unicorn.pio | 110 ++-- 9 files changed, 580 insertions(+), 387 deletions(-) diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index 60165650..86b25380 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -4,7 +4,8 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) +target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(galactic_unicorn_demo 1) # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo) @@ -17,7 +18,108 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn) +target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(galactic_unicorn_demo2 1) # create map/bin/hex file etc. pico_add_extra_outputs(galactic_unicorn_demo2) + + + +add_executable( + nostalgia_prompt + nostalgia_prompt.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(nostalgia_prompt pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(nostalgia_prompt 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(nostalgia_prompt) + + + +add_executable( + eighties_super_computer + eighties_super_computer.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(eighties_super_computer pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(eighties_super_computer 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(eighties_super_computer) + + + + +add_executable( + fire_effect + fire_effect.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(fire_effect pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(fire_effect 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(fire_effect) + + + + +add_executable( + scroll_text + scroll_text.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(scroll_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(scroll_text 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(scroll_text) + + +add_executable( + balls + balls.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(balls pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(balls 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(balls) + + + +add_executable( + lava_lamp + lava_lamp.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(lava_lamp pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(lava_lamp 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(lava_lamp) + + + +add_executable( + feature_test + feature_test.cpp + audio_samples.cpp +) + +# Pull in pico libraries that we need +target_link_libraries(feature_test pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(feature_test 1) + +# create map/bin/hex file etc. +pico_add_extra_outputs(feature_test) \ No newline at end of file diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index 517c2d68..29ca709d 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -114,6 +114,9 @@ gpio_set_function(28, GPIO_FUNC_SIO); float brightness = 0.5f; float curve = 4.0f; + int x = 10; + int y = 5; + while(true) { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { hue_offset += 0.05; @@ -143,6 +146,27 @@ gpio_set_function(28, GPIO_FUNC_SIO); if(curve < 0.5) curve = 0.5; } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { + x -= 1; + sleep_ms(250); + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { + x += 1; + sleep_ms(250); + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) { + y -= 1; + sleep_ms(250); + } + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_D)) { + y += 1; + sleep_ms(250); + } + +/* for(int y = 0; y < 11; y++) { for(int x = 0; x < 53; x++) { float fx = x / 53.0f; @@ -150,27 +174,18 @@ gpio_set_function(28, GPIO_FUNC_SIO); float twopi = M_PI * 2; float hue = fy + (sin(fx * twopi / curve)); float fade = 1.0f; - /* if(hue < 0.0f) { - fade += (hue * 10.0f); - if(fade < 0.0f) fade = 0.0f; - } - if(hue > 1.0f) { - fade -= ((hue - 1.0f) * 10.0f); - if(fade < 0.0f) fade = 0.0f; - }*/ hue += hue_offset; while(hue < 0.0f) {hue += 1.0f;} while(hue > 1.0f) {hue -= 1.0f;} hue = 1.0f - hue; -/* - uint8_t r = 0, g = 0, b = 0; - from_hsv(hue, 1.0f, brightness * fade, r, g, b);*/ ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade}; ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f); } - } + }*/ + + galactic_unicorn.set_pixel(x, y, 255, 255, 255); /*i++; graphics.set_pen(0, 0, 0); diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp index 7bf5d2f4..ca2a79b7 100644 --- a/examples/galactic_unicorn/demo2.cpp +++ b/examples/galactic_unicorn/demo2.cpp @@ -37,9 +37,9 @@ void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { p.x += (53 / 2) - (w / 2); p.y += (11 / 2); graphics.text(t, Point(p.x, p.y), -1, s, a); - graphics.text(t, Point(p.x + 1, p.y), -1, s, a); - graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); - graphics.text(t, Point(p.x, p.y + 1), -1, s, a); + //graphics.text(t, Point(p.x + 1, p.y), -1, s, a); + //graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); + //graphics.text(t, Point(p.x, p.y + 1), -1, s, a); } struct star_t { @@ -73,6 +73,8 @@ void step_star(star_t &s) { int main() { + stdio_init_all(); + uint8_t hue_map[53][3]; for(int i = 0; i < 53; i++) { from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); @@ -103,18 +105,17 @@ gpio_set_function(28, GPIO_FUNC_SIO); bool x_pressed = false; bool y_pressed = false; */ - graphics.set_font("sans"); +graphics.set_font("bitmap8"); uint i = 0; - int v = 255; float hue_offset = 0.0f; - float brightness = 0.5f; - float curve = 4.0f; while(true) { + i++; + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { hue_offset += 0.05; if(hue_offset > 1.0f) hue_offset = 1.0f; @@ -125,69 +126,37 @@ gpio_set_function(28, GPIO_FUNC_SIO); } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { - brightness += 0.05; - if(brightness > 1.0f) brightness = 1.0f; + galactic_unicorn.adjust_brightness(+0.01); } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { - brightness -= 0.05; - if(brightness < 0.0f) brightness = 0.0f; + galactic_unicorn.adjust_brightness(-0.01); } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { - curve += 0.5; - if(curve > 100.0f) curve = 100.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { - curve -= 0.5; - if(curve < 0.5) curve = 0.5; - } -i++; - - graphics.set_pen(0, 0, 0); - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} - graphics.clear(); - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} - - - for(int i = 0; i < 100; i++) { - star_t &star = stars[i]; - step_star(star); - - uint b = star.brightness(); - graphics.set_pen(b, b, b); - //graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2))); - } - -graphics.set_pen(255, 255, 255); - float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f); +/* + graphics.set_pen(255, 255, 255); + float s = 0.65f;//0.65f + (sin(i / 25.0f) * 0.15f); float a = 1.0f;// (sin(i / 25.0f) * 100.0f); - float x = (sin(i / 25.0f) * 40.0f) * s; - float y = (cos(i / 15.0f) * 10.0f) * s; - text("Galactic", Point(x, y), s, a); - - uint16_t *p = (uint16_t *)graphics.frame_buffer; - for(size_t i = 0; i < 53 * 11; i++) { - int x = i % 53; - int y = i / 53; - uint r = ((*p & 0b1111100000000000) >> 11) << 3; - uint g = ((*p & 0b0000011111100000) >> 5) << 2; - uint b = ((*p & 0b0000000000011111) >> 0) << 3; - p++; + float x = (sin(i / 74.0f) * 80.0f) * s; + float y = (cos(i / 43.0f) * 6.0f) * s; + text("Chester smells!", Point(x, y - 3), s, a); +*/ - if(r > 200 && g > 200 && b > 200) { - r = hue_map[x][0]; - g = hue_map[x][1]; - b = hue_map[x][2]; + for(int x = 0; x < 53; x++) { + for(int y = 0; y < 11; y++) { + int v = ((sin((x + y) / 3.0f + i / 15.0f) + 1.5f) / 2.5f) * 255.0f; + + graphics.set_pen(v, v, v); + graphics.pixel(Point(x, y)); } - - galactic_unicorn.set_pixel(x, y, r, g, b); } + + galactic_unicorn.update(graphics); + - - sleep_ms(10); + printf("%d\n", galactic_unicorn.light()); + sleep_ms(20); } diff --git a/libraries/galactic_unicorn/CMakeLists.txt b/libraries/galactic_unicorn/CMakeLists.txt index 1322707e..db39dd3e 100644 --- a/libraries/galactic_unicorn/CMakeLists.txt +++ b/libraries/galactic_unicorn/CMakeLists.txt @@ -1,12 +1 @@ -add_library(galactic_unicorn INTERFACE) - -pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) - -target_sources(galactic_unicorn INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp -) - -target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) - -# Pull in pico libraries that we need -target_link_libraries(galactic_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) +include(galactic_unicorn.cmake) \ No newline at end of file diff --git a/libraries/galactic_unicorn/README.md b/libraries/galactic_unicorn/README.md index c568977e..bd41b3df 100644 --- a/libraries/galactic_unicorn/README.md +++ b/libraries/galactic_unicorn/README.md @@ -17,6 +17,7 @@ We've included helper functions to handle every aspect of drawing to the display - [init](#init) - [set_pixel](#set_pixel) - [is_pressed](#is_pressed) +- [Examples](#examples) ## Example Program @@ -98,4 +99,16 @@ The button vaule should be a `uint8_t` denoting a pin, and constants `A`, `B`, ` ```c++ bool is_a_button_pressed = pico_unicorn.is_pressed(PicoUnicorn::A) -``` \ No newline at end of file +``` + +# Examples + +## Game of Life + +## Retro Super-computer + +Random LEDs blink on and off mimicing the look of a movie super computer doing it's work in the eighties. + +## Nostalgia Terminal + +A collection of copies of classic terminal styles including C64, MS-DOS, Spectrum, and more. \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.cmake b/libraries/galactic_unicorn/galactic_unicorn.cmake index fd2a3c5c..c99a3473 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cmake +++ b/libraries/galactic_unicorn/galactic_unicorn.cmake @@ -1,12 +1,14 @@ -add_library(pico_unicorn INTERFACE) +add_library(galactic_unicorn INTERFACE) -pico_generate_pio_header(pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.pio) +pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio) +pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pio) -target_sources(pico_unicorn INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.cpp + +target_sources(galactic_unicorn INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp ) -target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) +target_link_libraries(galactic_unicorn INTERFACE pico_stdlib pico_graphics hardware_adc hardware_pio hardware_dma) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index c1b32c38..9c98aa5f 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -2,88 +2,47 @@ #include "hardware/dma.h" #include "hardware/irq.h" +#include "hardware/adc.h" +#include "hardware/clocks.h" + #include "galactic_unicorn.pio.h" +#include "audio_i2s.pio.h" + #include "galactic_unicorn.hpp" // pixel data is stored as a stream of bits delivered in the // order the PIO needs to manage the shift registers, row // selects, delays, and latching/blanking // -// the data consists of 11 rows each of which has 14 frames of -// bcd timing data +// the pins used are: // -// bits are output in order: +// - 13: column clock (sideset) +// - 14: column data (out base) +// - 15: column latch +// - 16: column blank +// - 17: row select bit 0 +// - 18: row select bit 1 +// - 19: row select bit 2 +// - 20: row select bit 3 // -// ROW_CLEAR, ROW_DATA1, ROW_DATA0, LED_BLANK, LED_LATCH, LED_CLOCK, LED_DATA0, LED_DATA1 +// the framebuffer data is structured like this: // -// the data is structured like this: -// -// loop through the eleven rows of the display... -// -// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) -// 00000000 00000000 00000000 // dummy bytes to align to dwords -// -// within this row we loop through the 14 bcd frames for this row... -// -// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high -// 162: 10011000 // LATCH pixel data -// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) -// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) -// 166: 10010000 // turn BLANK back on -// 167: 00000000 // dummy byte to ensure dword aligned +// for each row: +// for each bcd frame: +// 0: 00110110 // row pixel count (minus one) +// 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data +// 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align +// 56: xxxxrrrr // row select bits +// 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) // // .. and back to the start -/* -enum pin { - LED_DATA = 8, - LED_CLOCK = 9, - LED_LATCH = 10, - LED_BLANK = 11, - ROW_0 = 22, - ROW_1 = 21, - ROW_2 = 20, - ROW_3 = 19, - ROW_4 = 18, - ROW_5 = 17, - ROW_6 = 16, - A = 12, - B = 13, - X = 14, - Y = 15, -};*/ - -enum pin { - LED_DATA1 = 12, - LED_DATA0 = 13, - LED_CLOCK = 14, - LED_LATCH = 15, - LED_BLANK = 16, - - ROW_DATA0 = 17, - ROW_DATA1 = 18, - ROW_CLEAR = 19, - ROW_CLOCK = 20, - - SWITCH_A = 0, - SWITCH_B = 1, - SWITCH_C = 3, - SWITCH_D = 6, - SWITCH_E = 2, - SWITCH_VOLUME_UP = 21, - SWITCH_VOLUME_DOWN = 26, - SWITCH_BRIGHTNESS_UP = 7, - SWITCH_BRIGHTNESS_DOWN = 8 -}; - - - constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t ROW_BYTES = 4; -constexpr uint32_t ROW_FRAME_BYTES = 168; -constexpr uint32_t BCD_FRAMES = 15; // includes fet discharge frame -constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES + ROW_COUNT * ROW_FRAME_BYTES * BCD_FRAMES); +constexpr uint32_t BCD_FRAME_COUNT = 14; +constexpr uint32_t BCD_FRAME_BYTES = 60; +constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; +constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); // must be aligned for 32bit dma transfer alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0}; @@ -93,38 +52,7 @@ static uint16_t g_gamma_lut[256] = {0}; static uint16_t b_gamma_lut[256] = {0}; static uint32_t dma_channel; - -static inline void unicorn_jetpack_program_init(PIO pio, uint sm, uint offset) { - pio_gpio_init(pio, pin::LED_DATA1); - pio_gpio_init(pio, pin::LED_DATA0); - pio_gpio_init(pio, pin::LED_CLOCK); - pio_gpio_init(pio, pin::LED_LATCH); - pio_gpio_init(pio, pin::LED_BLANK); - - pio_gpio_init(pio, pin::ROW_DATA0); - pio_gpio_init(pio, pin::ROW_DATA1); - pio_gpio_init(pio, pin::ROW_CLEAR); - pio_gpio_init(pio, pin::ROW_CLOCK); - - pio_sm_set_consecutive_pindirs(pio, sm, pin::LED_DATA1, 5, true); - pio_sm_set_consecutive_pindirs(pio, sm, pin::ROW_DATA0, 4, true); - - pio_sm_config c = galactic_unicorn_program_get_default_config(offset); - - // osr shifts right, autopull on, autopull threshold 8 - sm_config_set_out_shift(&c, true, false, 32); - - // configure out, set, and sideset pins - sm_config_set_out_pins(&c, pin::LED_DATA1, 8); - sm_config_set_sideset_pins(&c, pin::ROW_CLOCK); - - // join fifos as only tx needed (gives 8 deep fifo instead of 4) - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - - pio_sm_init(pio, sm, offset, &c); - pio_sm_set_enabled(pio, sm, true); - ///pio_sm_set_clkdiv(pio, sm, 4.0f); -} +static uint32_t audio_dma_channel; namespace pimoroni { @@ -154,118 +82,124 @@ namespace pimoroni { pio_sm_restart(bitstream_pio, bitstream_sm); } + uint16_t GalacticUnicorn::light() { + adc_select_input(2); + return adc_read(); + } + void GalacticUnicorn::init() { // todo: shouldn't need to do this if things were cleaned up properly but without // this any attempt to run a micropython script twice will fail static bool already_init = false; - // setup pins - gpio_init(pin::LED_DATA0); gpio_set_dir(pin::LED_DATA0, GPIO_OUT); - gpio_init(pin::LED_DATA1); gpio_set_dir(pin::LED_DATA1, GPIO_OUT); - gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT); - gpio_init(pin::LED_LATCH); gpio_set_dir(pin::LED_LATCH, GPIO_OUT); - gpio_init(pin::LED_BLANK); gpio_set_dir(pin::LED_BLANK, GPIO_OUT); - - gpio_init(pin::ROW_DATA0); gpio_set_dir(pin::ROW_DATA0, GPIO_OUT); - gpio_init(pin::ROW_DATA1); gpio_set_dir(pin::ROW_DATA1, GPIO_OUT); - gpio_init(pin::ROW_CLEAR); gpio_set_dir(pin::ROW_CLEAR, GPIO_OUT); - gpio_init(pin::ROW_CLOCK); gpio_set_dir(pin::ROW_CLOCK, GPIO_OUT); - // create 14-bit gamma luts for(uint16_t v = 0; v < 256; v++) { // gamma correct the provided 0-255 brightness value onto a // 0-65535 range for the pwm counter - float r_gamma = 2.8f; - r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * 16383.0f + 0.5f); - - float g_gamma = 2.8f; - g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * 16383.0f + 0.5f); - - float b_gamma = 2.8f; - b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * 16383.0f + 0.5f); + float r_gamma = 1.8f; + r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float g_gamma = 2.0f; + g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float b_gamma = 1.8f; + b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); } + + // for each row: + // for each bcd frame: + // 0: 00110110 // row pixel count (minus one) + // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data + // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align + // 56: xxxxrrrr // row select bits + // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) + // + // .. and back to the start -// the data is structured like this: -// -// loop through the eleven rows of the display... -// -// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) -// 00000000 00000000 00000000 // dummy bytes to align to dwords -// -// within this row we loop through the 14 bcd frames for this row... -// -// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high -// 162: 10011000 // LATCH pixel data -// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) -// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) -// 166: 10010000 // turn BLANK back on -// 167: 00000000 // dummy byte to ensure dword aligned -// -// .. and back to the start // initialise the bcd timing values and row selects in the bitstream for(uint8_t row = 0; row < HEIGHT; row++) { - uint16_t row_offset = row * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); + for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { + // find the offset of this row and frame in the bitstream + uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; - // setup row select on rows 0 and 8 - uint8_t row_select = row == 0 ? 0b10111000 : (row == 8 ? 0b11011000 : 0b10011000); - bitstream[row_offset + 0] = row_select; - - for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { - uint16_t frame_offset = row_offset + ROW_BYTES + (ROW_FRAME_BYTES * frame); - - bitstream[frame_offset + 162] = 0b10011000; // LATCH pixel data - bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs + p[ 0] = WIDTH - 1; // row pixel count + p[56] = row; // row select // set the number of bcd ticks for this frame - uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 1 : 1 << frame; - bitstream[frame_offset + 164] = (bcd_ticks & 0xff); - bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8; - - bitstream[frame_offset + 166] = 0b10010000; // BLANK high again to disable outputs - - // setup empty pixels with BLANK high and a clock pulse - for(uint8_t col = 0; col < 162; col += 2) { - bitstream[frame_offset + col + 0] = 0b10010000; - bitstream[frame_offset + col + 1] = 0b10010100; - } - -/* - uint16_t row_select_offset = offset + 164; - uint16_t bcd_offset = offset + 165; - - // the last bcd frame is used to allow the fets to discharge to avoid ghosting - if(frame == BCD_FRAMES - 1) { - uint16_t bcd_ticks = 65535; - bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; - bitstream[bcd_offset] = (bcd_ticks & 0xff); - }else{ - uint8_t row_select = row == 0 ? 0b01000000 : (row == 8 ? 0b00100000 : 0b00000000); - bitstream[row_select_offset] = row_select; - - uint16_t bcd_ticks = 1 << frame; - bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8; - bitstream[bcd_offset] = (bcd_ticks & 0xff); - }*/ + uint32_t bcd_ticks = (1 << frame); + p[57] = (bcd_ticks & 0xff) >> 0; + p[58] = (bcd_ticks & 0xff00) >> 8; + p[59] = (bcd_ticks & 0xff0000) >> 16; } -/* - for(size_t i = 0; i < sizeof(bitstream); i++) { - bitstream[i] = 0b11100000; - }*/ } + // setup light sensor adc + adc_init(); + adc_gpio_init(LIGHT_SENSOR); + + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + + gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); + gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); + gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); + + sleep_ms(100); + + // configure full output current in register 2 + + uint16_t reg1 = 0b1111111111001110; + + // clock the register value to the first 9 driver chips + for(int j = 0; j < 9; j++) { + for(int i = 0; i < 16; i++) { + if(reg1 & (1U << (15 - i))) { + gpio_put(COLUMN_DATA, true); + }else{ + gpio_put(COLUMN_DATA, false); + } + sleep_us(10); + gpio_put(COLUMN_CLOCK, true); + sleep_us(10); + gpio_put(COLUMN_CLOCK, false); + } + } + + // clock the last chip and latch the value + for(int i = 0; i < 16; i++) { + if(reg1 & (1U << (15 - i))) { + gpio_put(COLUMN_DATA, true); + }else{ + gpio_put(COLUMN_DATA, false); + } + + sleep_us(10); + gpio_put(COLUMN_CLOCK, true); + sleep_us(10); + gpio_put(COLUMN_CLOCK, false); + + if(i == 4) { + gpio_put(COLUMN_LATCH, true); + } + } + gpio_put(COLUMN_LATCH, false); + + + gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); + // setup button inputs - gpio_set_function(pin::SWITCH_A, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_A, GPIO_IN); gpio_pull_up(pin::SWITCH_A); - gpio_set_function(pin::SWITCH_B, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_B, GPIO_IN); gpio_pull_up(pin::SWITCH_B); - gpio_set_function(pin::SWITCH_C, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_C, GPIO_IN); gpio_pull_up(pin::SWITCH_C); - gpio_set_function(pin::SWITCH_D, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_D, GPIO_IN); gpio_pull_up(pin::SWITCH_D); - gpio_set_function(pin::SWITCH_E, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_E, GPIO_IN); gpio_pull_up(pin::SWITCH_E); + gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); + gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); + gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); + gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); - gpio_set_function(pin::SWITCH_BRIGHTNESS_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_UP); - gpio_set_function(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_DOWN); + gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); - gpio_set_function(pin::SWITCH_VOLUME_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_UP); - gpio_set_function(pin::SWITCH_VOLUME_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_DOWN); + gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); + gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); + + gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); + gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); if(already_init) { // stop and release the dma channel @@ -288,9 +222,38 @@ namespace pimoroni { // setup the pio bitstream_pio = pio0; - bitstream_sm = pio_claim_unused_sm(pio0, true); - sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); - unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset); + bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); + bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); + + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + pio_gpio_init(bitstream_pio, COLUMN_BLANK); + + pio_gpio_init(bitstream_pio, ROW_BIT_0); + pio_gpio_init(bitstream_pio, ROW_BIT_1); + pio_gpio_init(bitstream_pio, ROW_BIT_2); + pio_gpio_init(bitstream_pio, ROW_BIT_3); + + // set all led driving pins as outputs + pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); + + pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); + + // osr shifts right, autopull on, autopull threshold 8 + sm_config_set_out_shift(&c, true, true, 32); + + // configure out, set, and sideset pins + sm_config_set_out_pins(&c, ROW_BIT_0, 4); + sm_config_set_set_pins(&c, COLUMN_DATA, 3); + sm_config_set_sideset_pins(&c, COLUMN_CLOCK); + + // join fifos as only tx needed (gives 8 deep fifo instead of 4) + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); + pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); + // setup dma transfer for pixel data to the pio dma_channel = dma_claim_unused_channel(true); @@ -308,6 +271,52 @@ namespace pimoroni { dma_channel_set_read_addr(dma_channel, bitstream, true); already_init = true; + + + // setup audio pio program + /* + audio_pio = pio0; + audio_sm = pio_claim_unused_sm(audio_pio, true); + audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); + audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); + //pio_sm_set_enabled(audio_pio, audio_sm, true); + + uint32_t system_clock_frequency = clock_get_hz(clk_sys); + uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow + pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); + + + + audio_dma_channel = dma_claim_unused_channel(true); + dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); + channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_32); + channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian + channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); + dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); + dma_channel_set_irq0_enabled(audio_dma_channel, true); + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ + //irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); + //irq_set_enabled(DMA_IRQ_0, true); + +/* dma_channel_set_trans_count(audio_dma_channel, BITSTREAM_LENGTH / 4, false); + dma_channel_set_read_addr(audio_dma_channel, bitstream, true);*/ + //pio_sm_config audio_i2s_config = audio_i2s_program_get_default_config(audio_sm_offset); + + // osr shifts right, autopull on, autopull threshold 8 + //sm_config_set_out_shift(&audio_i2s_config, true, true, 32); + + // // configure out, set, and sideset pins + // sm_config_set_out_pins(&audio_i2s_config, ROW_BIT_0, 4); + // sm_config_set_set_pins(&audio_i2s_config, COLUMN_DATA, 3); + // sm_config_set_sideset_pins(&audio_i2s_config, COLUMN_CLOCK); + + // // join fifos as only tx needed (gives 8 deep fifo instead of 4) + // sm_config_set_fifo_join(&audio_i2s_config, PIO_FIFO_JOIN_TX); + + + //pio_sm_init(audio_pio, audio_sm, audio_sm_offset, &audio_i2s_config); + //pio_sm_set_enabled(audio_pio, audio_sm, true); + } void GalacticUnicorn::clear() { @@ -318,65 +327,44 @@ namespace pimoroni { } } - void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { - + void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { + dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 4); + } + void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; // make those coordinates sane x = (WIDTH - 1) - x; y = (HEIGHT - 1) - y; - // determine offset in the buffer for this row - uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES); + uint16_t gamma_r = r_gamma_lut[r]; + uint16_t gamma_g = g_gamma_lut[g]; + uint16_t gamma_b = b_gamma_lut[b]; - uint16_t bits[3] = {r_gamma_lut[b], g_gamma_lut[g], b_gamma_lut[r]}; - //uint16_t gr = r_gamma_lut[r]; - //uint16_t gg = g_gamma_lut[g]; - //uint16_t gb = b_gamma_lut[b]; + // for each row: + // for each bcd frame: + // 0: 00110110 // row pixel count (minus one) + // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data + // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align + // 56: xxxxrrrr // row select bits + // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) + // + // .. and back to the start // set the appropriate bits in the separate bcd frames - for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) { - uint16_t frame_offset = (ROW_FRAME_BYTES * frame) + 4; - uint16_t offset = row_offset + frame_offset;// + byte_offset; + for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { + uint8_t *p = &bitstream[y * ROW_BYTES + (BCD_FRAME_BYTES * frame) + 1 + x]; -// loop through the eleven rows of the display... -// -// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock) -// 00000000 00000000 00000000 // dummy bytes to align to dwords -// -// within this row we loop through the 14 bcd frames for this row... -// -// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high -// 162: 10011000 // LATCH pixel data -// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords) -// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536) -// 166: 10010000 // turn BLANK back on -// 167: 00000000 // dummy byte to ensure dword aligned -// -// .. and back to the start + uint8_t red_bit = gamma_r & 0b1; + uint8_t green_bit = gamma_g & 0b1; + uint8_t blue_bit = gamma_b & 0b1; - // work out the byte offset of this pixel - /*if(bit_offset >= 160) { - bit_offset -= 160; - }*/ + *p = (blue_bit << 2) | (green_bit << 1) | (red_bit << 0); - for(int bit = 0; bit < 3; bit++) { - int16_t bit_offset = x * 6 + 4 + (bit * 2); - - - uint8_t bit_position = bit_offset >= 160 ? 1 : 0; - uint8_t mask = 0b1 << bit_position; - uint8_t value = (bits[bit] & 0b1) << bit_position; - - bitstream[offset + (bit_offset % 160) + 0] &= ~mask; - bitstream[offset + (bit_offset % 160) + 0] |= value; - bitstream[offset + (bit_offset % 160) + 1] &= ~mask; - bitstream[offset + (bit_offset % 160) + 1] |= value; - - //bit_offset += 2; - bits[bit] >>= 1; - } + gamma_r >>= 1; + gamma_g >>= 1; + gamma_b >>= 1; } } @@ -384,6 +372,55 @@ namespace pimoroni { set_pixel(x, y, v, v, v); } + void GalacticUnicorn::set_brightness(float value) { + value = value < 0.0f ? 0.0f : value; + value = value > 1.0f ? 1.0f : value; + this->brightness = floor(value * 255.0f); + } + + float GalacticUnicorn::get_brightness() { + return this->brightness / 255.0f; + } + + void GalacticUnicorn::adjust_brightness(float delta) { + this->set_brightness(this->get_brightness() + delta); + } + + void GalacticUnicorn::set_volume(float value) { + value = value < 0.0f ? 0.0f : value; + value = value > 1.0f ? 1.0f : value; + this->volume = floor(value * 255.0f); + } + + float GalacticUnicorn::get_volume() { + return this->volume / 255.0f; + } + + void GalacticUnicorn::adjust_volume(float delta) { + this->set_volume(this->get_volume() + delta); + } + + + void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { + uint16_t *p = (uint16_t *)graphics.frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint16_t col = __builtin_bswap16(*p); + uint8_t r = ((col & 0b1111100000000000) >> 11) << 3; + uint8_t g = ((col & 0b0000011111100000) >> 5) << 2; + uint8_t b = ((col & 0b0000000000011111) >> 0) << 3; + p++; + + r = (r * this->brightness) >> 8; + g = (g * this->brightness) >> 8; + b = (b * this->brightness) >> 8; + + set_pixel(x, y, b, g, r); + } + } + bool GalacticUnicorn::is_pressed(uint8_t button) { return !gpio_get(button); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 768977f9..3714c843 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -1,6 +1,7 @@ #pragma once #include "hardware/pio.h" +#include "pico_graphics.hpp" namespace pimoroni { @@ -8,30 +9,81 @@ namespace pimoroni { public: static const int WIDTH = 53; static const int HEIGHT = 11; - static const uint8_t SWITCH_A = 0; - static const uint8_t SWITCH_B = 1; - static const uint8_t SWITCH_C = 3; - static const uint8_t SWITCH_D = 6; - static const uint8_t SWITCH_E = 2; - static const uint8_t SWITCH_VOLUME_UP = 21; - static const uint8_t SWITCH_VOLUME_DOWN = 26; - static const uint8_t SWITCH_BRIGHTNESS_UP = 7; - static const uint8_t SWITCH_BRIGHTNESS_DOWN = 8; + + // pin assignments + static const uint8_t COLUMN_CLOCK = 13; + static const uint8_t COLUMN_DATA = 14; + static const uint8_t COLUMN_LATCH = 15; + static const uint8_t COLUMN_BLANK = 16; + + static const uint8_t ROW_BIT_0 = 17; + static const uint8_t ROW_BIT_1 = 18; + static const uint8_t ROW_BIT_2 = 19; + static const uint8_t ROW_BIT_3 = 20; + + static const uint8_t LIGHT_SENSOR = 28; + + static const uint8_t MUTE = 22; + + static const uint8_t I2S_DATA = 9; + static const uint8_t I2S_BCLK = 10; + static const uint8_t I2S_LRCLK = 11; + + static const uint8_t I2C_SDA = 4; + static const uint8_t I2C_SCL = 5; + + static const uint8_t SWITCH_A = 0; + static const uint8_t SWITCH_B = 1; + static const uint8_t SWITCH_C = 3; + static const uint8_t SWITCH_D = 6; + + static const uint8_t SWITCH_SLEEP = 27; + + static const uint8_t SWITCH_VOLUME_UP = 7; + static const uint8_t SWITCH_VOLUME_DOWN = 8; + static const uint8_t SWITCH_BRIGHTNESS_UP = 21; + static const uint8_t SWITCH_BRIGHTNESS_DOWN = 26; private: PIO bitstream_pio = pio0; uint bitstream_sm = 0; - uint sm_offset = 0; + uint bitstream_sm_offset = 0; + + PIO audio_pio = pio0; + uint audio_sm = 0; + uint audio_sm_offset = 0; + + uint8_t brightness = 255; + uint8_t volume = 127; + public: ~GalacticUnicorn(); void init(); + static inline void pio_program_init(PIO pio, uint sm, uint offset); void clear(); + + void update(PicoGraphics_PenRGB565 &graphics); + + void set_brightness(float value); + float get_brightness(); + void adjust_brightness(float delta); + + void set_volume(float value); + float get_volume(); + void adjust_volume(float delta); + + void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b); void set_pixel(int x, int y, uint8_t v); + uint16_t light(); + bool is_pressed(uint8_t button); + + void play_sample(uint8_t *data, uint32_t length); + }; } \ No newline at end of file diff --git a/libraries/galactic_unicorn/galactic_unicorn.pio b/libraries/galactic_unicorn/galactic_unicorn.pio index a843cc58..d919f401 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.pio +++ b/libraries/galactic_unicorn/galactic_unicorn.pio @@ -2,65 +2,79 @@ .side_set 1 opt ; out pins: -; 0: data1 (base) -; 1: data0 -; 2: clock -; 3: latch -; 4: blank -; 5: row1 -; 6: row2 -; 7: row_clear +; +; - 3: row select bit 0 +; - 4: row select bit 1 +; - 5: row select bit 2 +; - 6: row select bit 3 +; set pins: +; +; - 0: column data (base) +; - 1: column latch +; - 2: column blank + +; sideset pin: +; +; - 0: column clock + +; for each row: +; for each bcd frame: +; 0: 00110110 // row pixel count (minus one) +; 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data +; 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align +; 56: xxxxrrrr // row select bits +; 57 - 59: tttttttt, tttttttt, tttttttt, // bcd tick count (0-65536) +; +; .. and back to the start -; sideset pin: row_clock .wrap_target - -; set row select pins - pull - out pins, 8 side 0 [4] - nop side 1 [4] ; pulse row select clock - out null, 24 ; discard dummy data - -; loop for bcd frames - set x, 14 -bcd_frame: - -; clock out 53 pixels worth of data - two pixels at a time, so 27 (actually 26.5) bits of data - set y, 26 ; 26 because `jmp` test is pre decrement - +; loop over row pixels + out y, 8 ; get row pixel count (minus 1 because test is pre decrement) pixels: - - pull ifempty - out pins, 8 [1] ; two red bits.. - out pins, 8 [1] ; ..with clock pulse - - pull ifempty - out pins, 8 [1] ; two green bits.. - out pins, 8 [1] ; ..with green pulse - - pull ifempty - out pins, 8 [1] ; two blue bits.. - out pins, 8 [1] ; ..with blue pulse - - jmp y-- pixels - out pins, 8 ; LATCH pixel data - out pins, 8 ; turn off BLANK signal + ; red bit + out x, 1 side 0 [1] ; pull in blue bit from OSR into register x, clear clock + set pins, 0b100 ; clear data bit, blank high + jmp !x endb ; if bit was zero jump + set pins, 0b101 ; set data bit, blank high + endb: + nop side 1 [2] ; clock in bit - pull + ; green bit + out x, 1 side 0 [1] ; pull in green bit from OSR into register X, clear clock + set pins, 0b100 ; clear data bit, blank high + jmp !x endg ; if bit was zero jump + set pins, 0b101 ; set data bit, blank high + endg: + nop side 1 [2] ; clock in bit -; pull bcd tick count into x register - out y, 16 + ; blue bit + out x, 1 side 0 [1] ; pull in red bit from OSR into register X, clear clock + set pins, 0b100 ; clear data bit, blank high + jmp !x endr ; if bit was zero jump + set pins, 0b101 ; set data bit, blank high + endr: + out null, 5 side 1 [2] ; clock in bit -bcd_count: - jmp y-- bcd_count ; loop until bcd delay complete + ;out null, 5 side 0 ; discard the five dummy bits for this pixel -; disable led output (blank) and clear latch pin - out pins, 8 ; turn off BLANK signal and clear row output - out null, 8 ; discard dummy data + jmp y-- pixels - jmp x-- bcd_frame ; loop to next bcd frame + out null, 16 ; discard dummy bytes + + out pins, 8 ; output row select + + set pins, 0b110 [5] ; latch high, blank high + set pins, 0b000 ; blank low (enable output) + +; loop over bcd delay period + out y, 24 ; get bcd delay counter value +bcd_delay: + jmp y-- bcd_delay + + set pins 0b100 ; blank high (disable output) .wrap \ No newline at end of file From f2c3d15b8ebd65dcf895d853b04df7df58fa9bd2 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 04:42:17 +0100 Subject: [PATCH 13/42] Galactic Unicorn: Playing basic audio samples now works, added rainbow example for photoshoot --- examples/galactic_unicorn/CMakeLists.txt | 10 +- examples/galactic_unicorn/demo2.cpp | 167 ------------------ .../galactic_unicorn/galactic_unicorn.cpp | 43 ++--- 3 files changed, 17 insertions(+), 203 deletions(-) delete mode 100644 examples/galactic_unicorn/demo2.cpp diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index 86b25380..7b145552 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -13,16 +13,16 @@ pico_add_extra_outputs(galactic_unicorn_demo) add_executable( - galactic_unicorn_demo2 - demo2.cpp + rainbow + rainbow.cpp ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(galactic_unicorn_demo2 1) +target_link_libraries(rainbow pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(rainbow 1) # create map/bin/hex file etc. -pico_add_extra_outputs(galactic_unicorn_demo2) +pico_add_extra_outputs(rainbow) diff --git a/examples/galactic_unicorn/demo2.cpp b/examples/galactic_unicorn/demo2.cpp deleted file mode 100644 index ca2a79b7..00000000 --- a/examples/galactic_unicorn/demo2.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include "pico/stdlib.h" - -#include "libraries/pico_graphics/pico_graphics.hpp" -#include "galactic_unicorn.hpp" -#include "okcolor.hpp" - -using namespace pimoroni; - -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); -GalacticUnicorn galactic_unicorn; - -// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel -// Outputs are rgb in the range 0-255 for each channel -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } -} - -void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { - int w = graphics.measure_text(t, s); - p.x += (53 / 2) - (w / 2); - p.y += (11 / 2); - graphics.text(t, Point(p.x, p.y), -1, s, a); - //graphics.text(t, Point(p.x + 1, p.y), -1, s, a); - //graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); - //graphics.text(t, Point(p.x, p.y + 1), -1, s, a); -} - -struct star_t { - float dx, dy, x, y, a; - - uint8_t brightness() { - int b = a / 5; - return b > 15 ? 15 : b; - } -}; - -void init_star(star_t &s) { - s.x = ((rand() % 100) / 5.0f) - 10.0f; - s.y = ((rand() % 100) / 10.0f) - 5.0f; - - s.dx = s.x / 10.0f; - s.dy = s.y / 10.0f; - s.a = 0; -} - -void step_star(star_t &s) { - s.x += s.dx; - s.y += s.dy; - s.a++; - - if(s.a > 100) { - init_star(s); - } -} - - -int main() { - - stdio_init_all(); - - uint8_t hue_map[53][3]; - for(int i = 0; i < 53; i++) { - from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); - } - - star_t stars[100]; - for(int i = 0; i < 100; i++) { - init_star(stars[i]); - stars[i].a = i; - } - -gpio_set_function(28, GPIO_FUNC_SIO); - gpio_set_dir(28, GPIO_OUT); - - for(int i = 0; i < 10; i++) { - gpio_put(28, !gpio_get(28)); - sleep_ms(100); - } - sleep_ms(1000); - - gpio_put(28,true); - - galactic_unicorn.init(); - -/* - bool a_pressed = false; - bool b_pressed = false; - bool x_pressed = false; - bool y_pressed = false; -*/ -graphics.set_font("bitmap8"); - - - - uint i = 0; - - float hue_offset = 0.0f; - - while(true) { - i++; - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { - hue_offset += 0.05; - if(hue_offset > 1.0f) hue_offset = 1.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { - hue_offset -= 0.05; - if(hue_offset < 0.0f) hue_offset = 0.0f; - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { - galactic_unicorn.adjust_brightness(+0.01); - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { - galactic_unicorn.adjust_brightness(-0.01); - } - - - -/* - graphics.set_pen(255, 255, 255); - float s = 0.65f;//0.65f + (sin(i / 25.0f) * 0.15f); - float a = 1.0f;// (sin(i / 25.0f) * 100.0f); - float x = (sin(i / 74.0f) * 80.0f) * s; - float y = (cos(i / 43.0f) * 6.0f) * s; - text("Chester smells!", Point(x, y - 3), s, a); -*/ - - for(int x = 0; x < 53; x++) { - for(int y = 0; y < 11; y++) { - int v = ((sin((x + y) / 3.0f + i / 15.0f) + 1.5f) / 2.5f) * 255.0f; - - graphics.set_pen(v, v, v); - graphics.pixel(Point(x, y)); - } - } - - galactic_unicorn.update(graphics); - - - printf("%d\n", galactic_unicorn.light()); - sleep_ms(20); - } - - - - printf("done\n"); - - return 0; -} diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 9c98aa5f..ba0a456d 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -39,7 +39,7 @@ // .. and back to the start constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t BCD_FRAME_COUNT = 14; +constexpr uint32_t BCD_FRAME_COUNT = 12; constexpr uint32_t BCD_FRAME_BYTES = 60; constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); @@ -274,48 +274,29 @@ namespace pimoroni { // setup audio pio program - /* audio_pio = pio0; audio_sm = pio_claim_unused_sm(audio_pio, true); audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); - audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); - //pio_sm_set_enabled(audio_pio, audio_sm, true); + pio_gpio_init(audio_pio, I2S_DATA); + pio_gpio_init(audio_pio, I2S_BCLK); + pio_gpio_init(audio_pio, I2S_LRCLK); + + audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); uint32_t system_clock_frequency = clock_get_hz(clk_sys); uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - + pio_sm_set_enabled(audio_pio, audio_sm, true); audio_dma_channel = dma_claim_unused_channel(true); dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); - channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_32); - channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian + channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); + //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); - dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ - //irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); - //irq_set_enabled(DMA_IRQ_0, true); - -/* dma_channel_set_trans_count(audio_dma_channel, BITSTREAM_LENGTH / 4, false); - dma_channel_set_read_addr(audio_dma_channel, bitstream, true);*/ - //pio_sm_config audio_i2s_config = audio_i2s_program_get_default_config(audio_sm_offset); - - // osr shifts right, autopull on, autopull threshold 8 - //sm_config_set_out_shift(&audio_i2s_config, true, true, 32); - - // // configure out, set, and sideset pins - // sm_config_set_out_pins(&audio_i2s_config, ROW_BIT_0, 4); - // sm_config_set_set_pins(&audio_i2s_config, COLUMN_DATA, 3); - // sm_config_set_sideset_pins(&audio_i2s_config, COLUMN_CLOCK); - - // // join fifos as only tx needed (gives 8 deep fifo instead of 4) - // sm_config_set_fifo_join(&audio_i2s_config, PIO_FIFO_JOIN_TX); - - - //pio_sm_init(audio_pio, audio_sm, audio_sm_offset, &audio_i2s_config); - //pio_sm_set_enabled(audio_pio, audio_sm, true); + //dma_channel_set_irq0_enabled(audio_dma_channel, true); + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true); } @@ -328,7 +309,7 @@ namespace pimoroni { } void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { - dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 4); + dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); } void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { From 678be33b538f485b389efd1a1eedd96d3a28e9d9 Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 05:05:23 +0100 Subject: [PATCH 14/42] Update to use new RGB888 pen type --- examples/galactic_unicorn/demo.cpp | 2 +- libraries/galactic_unicorn/galactic_unicorn.cpp | 8 ++++---- libraries/galactic_unicorn/galactic_unicorn.hpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index 29ca709d..f65b15e5 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -9,7 +9,7 @@ using namespace pimoroni; -PicoGraphics_PenRGB565 graphics(53, 11, nullptr); +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); GalacticUnicorn galactic_unicorn; // HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index ba0a456d..9dda38b1 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -382,16 +382,16 @@ namespace pimoroni { } - void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { + void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t j = 0; j < 53 * 11; j++) { int x = j % 53; int y = j / 53; uint16_t col = __builtin_bswap16(*p); - uint8_t r = ((col & 0b1111100000000000) >> 11) << 3; - uint8_t g = ((col & 0b0000011111100000) >> 5) << 2; - uint8_t b = ((col & 0b0000000000011111) >> 0) << 3; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; p++; r = (r * this->brightness) >> 8; diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 3714c843..d4499cb0 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -64,7 +64,7 @@ namespace pimoroni { void clear(); - void update(PicoGraphics_PenRGB565 &graphics); + void update(PicoGraphics_PenRGB888 &graphics); void set_brightness(float value); float get_brightness(); From 5ea389c12a618dff0e30fffa212d2cc349f3fdcd Mon Sep 17 00:00:00 2001 From: jon Date: Tue, 26 Jul 2022 05:31:33 +0100 Subject: [PATCH 15/42] Added support for new RGB888 pen type --- .../galactic_unicorn/galactic_unicorn.cpp | 34 +++++++++++++++---- .../galactic_unicorn/galactic_unicorn.hpp | 5 +-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 9dda38b1..0f2718f5 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -39,7 +39,7 @@ // .. and back to the start constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t BCD_FRAME_COUNT = 12; +constexpr uint32_t BCD_FRAME_COUNT = 14; constexpr uint32_t BCD_FRAME_BYTES = 60; constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); @@ -98,7 +98,7 @@ namespace pimoroni { // 0-65535 range for the pwm counter float r_gamma = 1.8f; r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float g_gamma = 2.0f; + float g_gamma = 1.8f; g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); float b_gamma = 1.8f; b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); @@ -356,7 +356,7 @@ namespace pimoroni { void GalacticUnicorn::set_brightness(float value) { value = value < 0.0f ? 0.0f : value; value = value > 1.0f ? 1.0f : value; - this->brightness = floor(value * 255.0f); + this->brightness = floor(value * 256.0f); } float GalacticUnicorn::get_brightness() { @@ -382,16 +382,16 @@ namespace pimoroni { } - void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { + void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t j = 0; j < 53 * 11; j++) { int x = j % 53; int y = j / 53; uint16_t col = __builtin_bswap16(*p); - uint8_t r = (col & 0xff0000) >> 16; - uint8_t g = (col & 0x00ff00) >> 8; - uint8_t b = (col & 0x0000ff) >> 0; + uint8_t r = (col & 0b1111100000000000) >> 8; + uint8_t g = (col & 0b0000011111100000) >> 3; + uint8_t b = (col & 0b0000000000011111) << 3; p++; r = (r * this->brightness) >> 8; @@ -402,6 +402,26 @@ namespace pimoroni { } } + void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { + uint32_t *p = (uint32_t *)graphics.frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + p++; + + r = (r * this->brightness) >> 8; + g = (g * this->brightness) >> 8; + b = (b * this->brightness) >> 8; + + set_pixel(x, y, b, g, r); + } + } + bool GalacticUnicorn::is_pressed(uint8_t button) { return !gpio_get(button); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index d4499cb0..340e767f 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -53,8 +53,8 @@ namespace pimoroni { uint audio_sm = 0; uint audio_sm_offset = 0; - uint8_t brightness = 255; - uint8_t volume = 127; + uint16_t brightness = 256; + uint16_t volume = 127; public: ~GalacticUnicorn(); @@ -64,6 +64,7 @@ namespace pimoroni { void clear(); + void update(PicoGraphics_PenRGB565 &graphics); void update(PicoGraphics_PenRGB888 &graphics); void set_brightness(float value); From a25699c73de2ebeabe4226f66ddf14786c1d247f Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 26 Jul 2022 20:52:37 +0100 Subject: [PATCH 16/42] Initial setup og GU Micropython --- .../galactic_unicorn/galactic_unicorn.cpp | 29 ++-- .../galactic_unicorn/galactic_unicorn.hpp | 14 ++ .../galactic_unicorn/galactic_unicorn.c | 66 ++++++++ .../galactic_unicorn/galactic_unicorn.cpp | 141 ++++++++++++++++++ .../galactic_unicorn/galactic_unicorn.h | 30 ++++ .../galactic_unicorn/micropython.cmake | 22 +++ micropython/modules/micropython-common.cmake | 2 + micropython/modules/micropython-picow.cmake | 1 + 8 files changed, 291 insertions(+), 14 deletions(-) create mode 100644 micropython/modules/galactic_unicorn/galactic_unicorn.c create mode 100644 micropython/modules/galactic_unicorn/galactic_unicorn.cpp create mode 100644 micropython/modules/galactic_unicorn/galactic_unicorn.h create mode 100644 micropython/modules/galactic_unicorn/micropython.cmake diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 0f2718f5..4b205d73 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -38,15 +38,6 @@ // // .. and back to the start -constexpr uint32_t ROW_COUNT = 11; -constexpr uint32_t BCD_FRAME_COUNT = 14; -constexpr uint32_t BCD_FRAME_BYTES = 60; -constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; -constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); - -// must be aligned for 32bit dma transfer -alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0}; - static uint16_t r_gamma_lut[256] = {0}; static uint16_t g_gamma_lut[256] = {0}; static uint16_t b_gamma_lut[256] = {0}; @@ -56,16 +47,24 @@ static uint32_t audio_dma_channel; namespace pimoroni { + GalacticUnicorn* GalacticUnicorn::unicorn = nullptr; + // once the dma transfer of the scanline is complete we move to the // next scanline (or quit if we're finished) - void __isr dma_complete() { - if (dma_hw->ints0 & (1u << dma_channel)) { - dma_hw->ints0 = (1u << dma_channel); // clear irq flag - dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); - dma_channel_set_read_addr(dma_channel, bitstream, true); + void __isr GalacticUnicorn::dma_complete() { + if(dma_channel_get_irq0_status(dma_channel) && unicorn != nullptr) { + unicorn->next_dma_sequence(); } } + void GalacticUnicorn::next_dma_sequence() { + // Clear any interrupt request caused by our channel + dma_channel_acknowledge_irq0(dma_channel); + + dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); + dma_channel_set_read_addr(dma_channel, bitstream, true); + } + GalacticUnicorn::~GalacticUnicorn() { // stop and release the dma channel irq_set_enabled(DMA_IRQ_0, false); @@ -267,6 +266,8 @@ namespace pimoroni { irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); irq_set_enabled(DMA_IRQ_0, true); + unicorn = this; + dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); dma_channel_set_read_addr(dma_channel, bitstream, true); diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 340e767f..b9d8e2f6 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -44,6 +44,13 @@ namespace pimoroni { static const uint8_t SWITCH_BRIGHTNESS_UP = 21; static const uint8_t SWITCH_BRIGHTNESS_DOWN = 26; + private: + static const uint32_t ROW_COUNT = 11; + static const uint32_t BCD_FRAME_COUNT = 14; + static const uint32_t BCD_FRAME_BYTES = 60; + static const uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; + static const uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); + private: PIO bitstream_pio = pio0; uint bitstream_sm = 0; @@ -56,6 +63,11 @@ namespace pimoroni { uint16_t brightness = 256; uint16_t volume = 127; + // must be aligned for 32bit dma transfer + alignas(4) uint8_t bitstream[BITSTREAM_LENGTH] = {0}; + static GalacticUnicorn* unicorn; + static void dma_complete(); + public: ~GalacticUnicorn(); @@ -85,6 +97,8 @@ namespace pimoroni { void play_sample(uint8_t *data, uint32_t length); + private: + void next_dma_sequence(); }; } \ No newline at end of file diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c new file mode 100644 index 00000000..9028a19e --- /dev/null +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -0,0 +1,66 @@ +#include "galactic_unicorn.h" + + +/***** Methods *****/ +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn___del___obj, GalacticUnicorn___del__); +/*MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear); +MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_update_obj, 1, GalacticUnicorn_update); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_set_brightness_obj, GalacticUnicorn_set_brightness); +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_brightness_obj, GalacticUnicorn_get_brightness); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_brightness_obj, GalacticUnicorn_adjust_brightness); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_set_volume_obj, GalacticUnicorn_set_volume); +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_volume_obj, GalacticUnicorn_get_volume); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adjust_volume); +MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_set_pixel_obj, 1, GalacticUnicorn_set_pixel); +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); +MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_play_sample_obj, 1, GalacticUnicorn_play_sample);*/ + +/***** Binding of Methods *****/ +STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&GalacticUnicorn___del___obj) }, + /*{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&GalacticUnicorn_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&GalacticUnicorn_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_brightness), MP_ROM_PTR(&GalacticUnicorn_set_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_brightness), MP_ROM_PTR(&GalacticUnicorn_get_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_adjust_brightness), MP_ROM_PTR(&GalacticUnicorn_adjust_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_volume), MP_ROM_PTR(&GalacticUnicorn_set_volume_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_volume), MP_ROM_PTR(&GalacticUnicorn_get_volume_obj) }, + { MP_ROM_QSTR(MP_QSTR_adjust_volume), MP_ROM_PTR(&GalacticUnicorn_adjust_volume_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&GalacticUnicorn_set_pixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) },*/ + + { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, + { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, +}; + +STATIC MP_DEFINE_CONST_DICT(GalacticUnicorn_locals_dict, GalacticUnicorn_locals_dict_table); + +/***** Class Definition *****/ +const mp_obj_type_t GalacticUnicorn_type = { + { &mp_type_type }, + .name = MP_QSTR_GalacticUnicorn, + .print = GalacticUnicorn_print, + .make_new = GalacticUnicorn_make_new, + .locals_dict = (mp_obj_dict_t*)&GalacticUnicorn_locals_dict, +}; + +/***** Globals Table *****/ +STATIC const mp_map_elem_t galactic_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_galactic) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GalacticUnicorn), (mp_obj_t)&GalacticUnicorn_type }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_galactic_globals, galactic_globals_table); + +/***** Module Definition *****/ +const mp_obj_module_t galactic_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_galactic_globals, +}; +#if MICROPY_VERSION <= 70144 +MP_REGISTER_MODULE(MP_QSTR_galactic, galactic_user_cmodule, MODULE_GALACTIC_ENABLED); +#else +MP_REGISTER_MODULE(MP_QSTR_galactic, galactic_user_cmodule); +#endif diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp new file mode 100644 index 00000000..0cc0f6d3 --- /dev/null +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -0,0 +1,141 @@ +#include "libraries/galactic_unicorn/galactic_unicorn.hpp" +#include "micropython/modules/util.hpp" +#include +#include + + +using namespace pimoroni; + +extern "C" { +#include "galactic_unicorn.h" +#include "py/builtin.h" + + +/********** GalacticUnicorn **********/ + +/***** Variables Struct *****/ +typedef struct _GalacticUnicorn_obj_t { + mp_obj_base_t base; + GalacticUnicorn* galactic; +} _GalacticUnicorn_obj_t; + + +/***** Print *****/ +void GalacticUnicorn_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; //Unused input parameter + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + mp_print_str(print, "GalacticUnicorn()"); +} + + +/***** Constructor *****/ +mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + _GalacticUnicorn_obj_t *self = nullptr; + + enum { ARG_pio, ARG_sm, ARG_pins, ARG_common_pin, ARG_direction, ARG_counts_per_rev, ARG_count_microsteps, ARG_freq_divider }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pio, MP_ARG_INT }, + { MP_QSTR_sm, MP_ARG_INT } + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int pio_int = args[ARG_pio].u_int; + if(pio_int < 0 || pio_int > (int)NUM_PIOS) { + mp_raise_ValueError("pio out of range. Expected 0 to 1"); + } + //PIO pio = pio_int == 0 ? pio0 : pio1; + + int sm = args[ARG_sm].u_int; + if(sm < 0 || sm > (int)NUM_PIO_STATE_MACHINES) { + mp_raise_ValueError("sm out of range. Expected 0 to 3"); + } + + + GalacticUnicorn *galactic = m_new_class(GalacticUnicorn); + galactic->init(); + //if(!galactic->init()) { + //m_del_class(GalacticUnicorn, galactic); + //mp_raise_msg(&mp_type_RuntimeError, "unable to allocate the hardware resources needed to initialise this GalacticUnicorn. Try running `import gc` followed by `gc.collect()` before creating it"); + //} + + self = m_new_obj_with_finaliser(_GalacticUnicorn_obj_t); + self->base.type = &GalacticUnicorn_type; + self->galactic = galactic; + + return MP_OBJ_FROM_PTR(self); +} + + +/***** Destructor ******/ +mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + m_del_class(GalacticUnicorn, self->galactic); + return mp_const_none; +} + + +/***** Methods *****/ +extern mp_obj_t GalacticUnicorn_clear(mp_obj_t self_in) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + //self->galactic->clear(); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_set_brightness(mp_obj_t self_in, mp_obj_t value) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_get_brightness(mp_obj_t self_in) { +//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_adjust_brightness(mp_obj_t self_in, mp_obj_t delta) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_set_volume(mp_obj_t self_in, mp_obj_t value) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_get_volume(mp_obj_t self_in) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_adjust_volume(mp_obj_t self_in, mp_obj_t delta) { +//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in) { +//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button) { +//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_const_none; +} +} diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h new file mode 100644 index 00000000..009c02dc --- /dev/null +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -0,0 +1,30 @@ +// Include MicroPython API. +#include "py/runtime.h" + +/***** Extern of Class Definition *****/ +extern const mp_obj_type_t GalacticUnicorn_type; + +/***** Extern of Class Methods *****/ +extern void GalacticUnicorn_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +extern mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); +extern mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in); +extern mp_obj_t GalacticUnicorn_clear(mp_obj_t self_in); + +extern mp_obj_t GalacticUnicorn_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +//extern mp_obj_t GalacticUnicorn_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + +extern mp_obj_t GalacticUnicorn_set_brightness(mp_obj_t self_in, mp_obj_t value); +extern mp_obj_t GalacticUnicorn_get_brightness(mp_obj_t self_in); +extern mp_obj_t GalacticUnicorn_adjust_brightness(mp_obj_t self_in, mp_obj_t delta); + +extern mp_obj_t GalacticUnicorn_set_volume(mp_obj_t self_in, mp_obj_t value); +extern mp_obj_t GalacticUnicorn_get_volume(mp_obj_t self_in); +extern mp_obj_t GalacticUnicorn_adjust_volume(mp_obj_t self_in, mp_obj_t delta); + +extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +//extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in); + +extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); + +extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); \ No newline at end of file diff --git a/micropython/modules/galactic_unicorn/micropython.cmake b/micropython/modules/galactic_unicorn/micropython.cmake new file mode 100644 index 00000000..a87ced4b --- /dev/null +++ b/micropython/modules/galactic_unicorn/micropython.cmake @@ -0,0 +1,22 @@ +set(MOD_NAME galactic_unicorn) +string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER) +add_library(usermod_${MOD_NAME} INTERFACE) + +target_sources(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/galactic_unicorn.cpp +) +pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/galactic_unicorn.pio) +pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/audio_i2s.pio) + +target_include_directories(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/ +) + +target_compile_definitions(usermod_${MOD_NAME} INTERFACE + MODULE_GALATIC_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) \ No newline at end of file diff --git a/micropython/modules/micropython-common.cmake b/micropython/modules/micropython-common.cmake index 29ec616d..b1d0bb08 100644 --- a/micropython/modules/micropython-common.cmake +++ b/micropython/modules/micropython-common.cmake @@ -44,6 +44,8 @@ include(pcf85063a/micropython) include(picographics/micropython) include(jpegdec/micropython) +include(galactic_unicorn/micropython) + include(modules_py/modules_py) diff --git a/micropython/modules/micropython-picow.cmake b/micropython/modules/micropython-picow.cmake index 14449723..3041e730 100644 --- a/micropython/modules/micropython-picow.cmake +++ b/micropython/modules/micropython-picow.cmake @@ -47,6 +47,7 @@ include(adcfft/micropython) # LEDs & Matrices include(plasma/micropython) include(hub75/micropython) +include(galactic_unicorn/micropython) # Packs include(pico_unicorn/micropython) From 7fd175abc531052b24a6839441e60d09e750bd37 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Wed, 27 Jul 2022 18:09:27 +0100 Subject: [PATCH 17/42] Galactic Unicorn: More MicroPython bringup. --- .../examples/galactic_unicorn/feature_test.py | 50 +++++++ .../examples/galactic_unicorn/fire_effect.py | 134 ++++++++++++++++++ .../galactic_unicorn/galactic_unicorn.c | 12 +- .../galactic_unicorn/galactic_unicorn.cpp | 106 ++++++++++++-- .../galactic_unicorn/galactic_unicorn.h | 3 +- .../galactic_unicorn/micropython.cmake | 3 +- .../modules/picographics/picographics.c | 2 + .../modules/picographics/picographics.cpp | 18 ++- .../modules/picographics/picographics.h | 9 +- 9 files changed, 309 insertions(+), 28 deletions(-) create mode 100644 micropython/examples/galactic_unicorn/feature_test.py create mode 100644 micropython/examples/galactic_unicorn/fire_effect.py diff --git a/micropython/examples/galactic_unicorn/feature_test.py b/micropython/examples/galactic_unicorn/feature_test.py new file mode 100644 index 00000000..3f11d41b --- /dev/null +++ b/micropython/examples/galactic_unicorn/feature_test.py @@ -0,0 +1,50 @@ +import time +from galactic import GalacticUnicorn + +gu = GalacticUnicorn() + +def gradient(r, g, b): + for y in range(0, 11): + for x in range(0, 53): + # graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); + gu.set_pixel(x, y, x) + + +def grid(ms, x, y) { + v = (x + y + (ms / 1000)) % 2 + if v == 0: + gu.set_pixel(x, y, 255) + else: + gu.set_pixel(x, y, 0) +} + +void shader_fill(int ms, shader_func_t f) { + for(int y = 0; y < 12; y++) { + for(int x = 0; x < 53; x++) { + f(ms, x, y); + } + } +} + +void outline_text(std::string text) { + uint ms = to_ms_since_boot(get_absolute_time()); + + graphics.set_font("bitmap8"); + uint8_t v = (sin(ms / 100.0f) + 1.0f) * 127.0f; + uint w = graphics.measure_text(text, 1); + + int x = 53 / 2 - w / 2 + 1, y = 2; + + graphics.set_pen(0, 0, 0); + graphics.text(text, Point(x - 1, y - 1), -1, 1); + graphics.text(text, Point(x , y - 1), -1, 1); + graphics.text(text, Point(x + 1, y - 1), -1, 1); + graphics.text(text, Point(x - 1, y ), -1, 1); + graphics.text(text, Point(x + 1, y ), -1, 1); + graphics.text(text, Point(x - 1, y + 1), -1, 1); + graphics.text(text, Point(x , y + 1), -1, 1); + graphics.text(text, Point(x + 1, y + 1), -1, 1); + + graphics.set_pen(v, v, v); + graphics.text(text, Point(x, y), -1, 1); +} \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/fire_effect.py b/micropython/examples/galactic_unicorn/fire_effect.py new file mode 100644 index 00000000..f47ed8ff --- /dev/null +++ b/micropython/examples/galactic_unicorn/fire_effect.py @@ -0,0 +1,134 @@ +import time +import random +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN +from galactic import GalacticUnicorn +from ulab import numpy as np + +graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN) +gu = GalacticUnicorn() + +width = 53 +height = 15 + +heat = [0.0] * 1000 +#heat = np.full((width + 5, height + 5), 0.0) + +@micropython.native +def set(x, y, v): + global heat + heat[x + y * width] = v + #heat[x, y] = v + +@micropython.native +def get(x, y): + global heat + x = x if x >= 0 else 0 + x = x if x < width else width - 1 + #try: + #return heat[x, y] + return heat[x + y * width] + #except IndexError: + # pass + +@micropython.native +def select_colour(x, y): + #value = heat[x, y] + value = heat[x + y * width] + if value > 0.5: + return 255, 255, 180 + elif value > 0.4: + return 220, 160, 0 + elif value > 0.3: + return 180, 30, 0 + elif value > 0.22: + return 20, 20, 20 + else: + return 0, 0, 0 + + +@micropython.native +def calc_average(x, y): + #if x > 0: + # return (heat[x, y] + heat[x, y + 2] + heat[x, y + 1] + heat[x - 1, y + 1] + heat[x + 1, y + 1]) / 5.0 + return (heat[x + (y * width)] + heat[x + ((y + 2) * width)] + heat[x + ((y + 1) * width)] + heat[(x - 1 if x >= 0 else 0) + ((y + 1) * width)] + heat[(x + 1) + ((y + 1) * width)]) / 5.0 + #else: + #return (heat[x, y] + heat[x, y + 2] + heat[x, y + 1] + heat[x - 0, y + 1] + heat[x + 1, y + 1]) / 5.0 + #return (heat[x + (y * width)] + heat[x + ((y + 2) * width)] + heat[x + ((y + 1) * width)] + heat[(x) + ((y + 1) * width)] + heat[(x + 1) + ((y + 1) * width)]) / 5.0 + + +gu.set_brightness(0.3) + +# heat[x-1:x+2, y:y+3] +#weights = np.array([[0.0, 0.0, 0.0], + #[0.0, 0.0, 0.0], + #[0.0, 0.0, 0.0]]) + +landscape = True + +while True: + start = time.ticks_ms() + if gu.is_pressed(21): + gu.adjust_brightness(+0.01) + if gu.is_pressed(26): + gu.adjust_brightness(-0.01) + + if gu.is_pressed(0): + landscape = True + width = 53 + height = 15 + for i in range(0, len(heat)): + heat[i] = 0.0 + + if gu.is_pressed(1): + landscape = False + width = 11 + height = 55 + for i in range(0, len(heat)): + heat[i] = 0.0 + + #for y, row in enumerate(heat): + #for x, val in enumerate(row): + # print(x, y, row, val) + + for y in range(0, height): + for x in range(0, width): + r, g, b = select_colour(x, y) + + if landscape: + gu.set_pixel(x, y, r, g, b) + #graphics.pixel(x, y) + else: + gu.set_pixel(y, x, r, g, b) + #graphics.pixel(y, x) + + # update this pixel by averaging the below pixels + #average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0 + average = calc_average(x, y) + + # damping factor to ensure flame tapers out towards the top of the displays + average *= 0.95 if landscape else 0.99 + + # update the heat map with our newly averaged value + set(x, y, average) + + #gu.update(graphics) + + # clear the bottom row and then add a new fire seed to it + for x in range(0, width): + set(x, height - 1, 0.0) + + # add a new random heat source + source_count = 5 if landscape else 1 + + for c in range(0, source_count): + px = random.randint(0, width - 4) + 2 + set(px , height - 2, 1.0) + set(px + 1, height - 2, 1.0) + set(px - 1, height - 2, 1.0) + set(px , height - 1, 1.0) + set(px + 1, height - 1, 1.0) + set(px - 1, height - 1, 1.0) + + end = time.ticks_ms() + print("Time:", end - start) + #time.sleep(0.02) \ No newline at end of file diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 9028a19e..c46a2ad0 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -3,23 +3,23 @@ /***** Methods *****/ MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn___del___obj, GalacticUnicorn___del__); -/*MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear); -MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_update_obj, 1, GalacticUnicorn_update); +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_update_obj, GalacticUnicorn_update); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_set_brightness_obj, GalacticUnicorn_set_brightness); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_brightness_obj, GalacticUnicorn_get_brightness); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_brightness_obj, GalacticUnicorn_adjust_brightness); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_set_volume_obj, GalacticUnicorn_set_volume); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_volume_obj, GalacticUnicorn_get_volume); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adjust_volume); -MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_set_pixel_obj, 1, GalacticUnicorn_set_pixel); +MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_set_pixel_obj, 4, GalacticUnicorn_set_pixel); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); -MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_play_sample_obj, 1, GalacticUnicorn_play_sample);*/ +//MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_play_sample_obj, 1, GalacticUnicorn_play_sample); /***** Binding of Methods *****/ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&GalacticUnicorn___del___obj) }, - /*{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&GalacticUnicorn_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&GalacticUnicorn_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&GalacticUnicorn_update_obj) }, { MP_ROM_QSTR(MP_QSTR_set_brightness), MP_ROM_PTR(&GalacticUnicorn_set_brightness_obj) }, { MP_ROM_QSTR(MP_QSTR_get_brightness), MP_ROM_PTR(&GalacticUnicorn_get_brightness_obj) }, @@ -30,7 +30,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&GalacticUnicorn_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) }, { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, - { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) },*/ + //{ MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 0cc0f6d3..34c0cd51 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -1,4 +1,5 @@ #include "libraries/galactic_unicorn/galactic_unicorn.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" #include "micropython/modules/util.hpp" #include #include @@ -17,8 +18,15 @@ extern "C" { typedef struct _GalacticUnicorn_obj_t { mp_obj_base_t base; GalacticUnicorn* galactic; + //PicoGraphics_PenRGB888* graphics; } _GalacticUnicorn_obj_t; +typedef struct _ModPicoGraphics_obj_t { + mp_obj_base_t base; + PicoGraphics *graphics; + DisplayDriver *display; + void *buffer; +} ModPicoGraphics_obj_t; /***** Print *****/ void GalacticUnicorn_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -60,10 +68,22 @@ mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size //m_del_class(GalacticUnicorn, galactic); //mp_raise_msg(&mp_type_RuntimeError, "unable to allocate the hardware resources needed to initialise this GalacticUnicorn. Try running `import gc` followed by `gc.collect()` before creating it"); //} + //PicoGraphics_PenRGB888 *graphics = m_new_class(PicoGraphics_PenRGB888, 53, 11, m_new(uint8_t, PicoGraphics_PenRGB888::buffer_size(53, 11))); + + /*for(int y = 0; y < 11; y++) { + for(int x = 0; x < 53; x++) { +// graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); + graphics->set_pen(x, x, x); + graphics->pixel(Point(x, y)); + } + }*/ + + //galactic->update(*graphics); self = m_new_obj_with_finaliser(_GalacticUnicorn_obj_t); self->base.type = &GalacticUnicorn_type; self->galactic = galactic; + //self->graphics = graphics; return MP_OBJ_FROM_PTR(self); } @@ -73,54 +93,110 @@ mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); m_del_class(GalacticUnicorn, self->galactic); + //m_del_class(PicoGraphics_PenRGB888, self->graphics); return mp_const_none; } /***** Methods *****/ extern mp_obj_t GalacticUnicorn_clear(mp_obj_t self_in) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - //self->galactic->clear(); + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->clear(); return mp_const_none; } -extern mp_obj_t GalacticUnicorn_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); +extern mp_obj_t GalacticUnicorn_update(mp_obj_t self_in, mp_obj_t graphics_in) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t); + + self->galactic->update(*((PicoGraphics_PenRGB888 *)picographics->graphics)); + return mp_const_none; } extern mp_obj_t GalacticUnicorn_set_brightness(mp_obj_t self_in, mp_obj_t value) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->set_brightness(mp_obj_get_float(value)); return mp_const_none; } extern mp_obj_t GalacticUnicorn_get_brightness(mp_obj_t self_in) { -//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - return mp_const_none; + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_obj_new_float(self->galactic->get_brightness()); } extern mp_obj_t GalacticUnicorn_adjust_brightness(mp_obj_t self_in, mp_obj_t delta) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->adjust_brightness(mp_obj_get_float(delta)); return mp_const_none; } extern mp_obj_t GalacticUnicorn_set_volume(mp_obj_t self_in, mp_obj_t value) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->set_volume(mp_obj_get_float(value)); return mp_const_none; } extern mp_obj_t GalacticUnicorn_get_volume(mp_obj_t self_in) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - return mp_const_none; + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_obj_new_float(self->galactic->get_volume()); } extern mp_obj_t GalacticUnicorn_adjust_volume(mp_obj_t self_in, mp_obj_t delta) { -//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->adjust_volume(mp_obj_get_float(delta)); return mp_const_none; } extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { -//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + if(n_args <= 4) { + enum { ARG_self, ARG_x, ARG_y, ARG_v }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_v, MP_ARG_REQUIRED | MP_ARG_INT } + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + int v = args[ARG_v].u_int; + + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t); + //self->graphics->set_pen(v, v, v); + //self->graphics->set_pixel(Point(x, y)); + self->galactic->set_pixel(x, y, v); + } + else { + enum { ARG_self, ARG_x, ARG_y, ARG_r, ARG_g, ARG_b }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_g, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_b, MP_ARG_REQUIRED | MP_ARG_INT } + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + int r = args[ARG_r].u_int; + int g = args[ARG_g].u_int; + int b = args[ARG_b].u_int; + + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t); + //self->graphics->set_pen(r, g, b); + //self->graphics->set_pixel(Point(x, y)); + self->galactic->set_pixel(x, y, r, g, b); + } return mp_const_none; } @@ -130,8 +206,8 @@ extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in) { } extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button) { -//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - return mp_const_none; + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_obj_new_bool(self->galactic->is_pressed((uint8_t)mp_obj_get_int(button))); } extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 009c02dc..8f147e05 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -10,8 +10,7 @@ extern mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_arg extern mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_clear(mp_obj_t self_in); -extern mp_obj_t GalacticUnicorn_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -//extern mp_obj_t GalacticUnicorn_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t GalacticUnicorn_update(mp_obj_t self_in, mp_obj_t graphics_in); extern mp_obj_t GalacticUnicorn_set_brightness(mp_obj_t self_in, mp_obj_t value); extern mp_obj_t GalacticUnicorn_get_brightness(mp_obj_t self_in); diff --git a/micropython/modules/galactic_unicorn/micropython.cmake b/micropython/modules/galactic_unicorn/micropython.cmake index a87ced4b..cdb3bf49 100644 --- a/micropython/modules/galactic_unicorn/micropython.cmake +++ b/micropython/modules/galactic_unicorn/micropython.cmake @@ -6,6 +6,7 @@ target_sources(usermod_${MOD_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/galactic_unicorn.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_rgb888.cpp ) pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/galactic_unicorn.pio) pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/audio_i2s.pio) @@ -16,7 +17,7 @@ target_include_directories(usermod_${MOD_NAME} INTERFACE ) target_compile_definitions(usermod_${MOD_NAME} INTERFACE - MODULE_GALATIC_ENABLED=1 + MODULE_GALACTIC_ENABLED=1 ) target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) \ No newline at end of file diff --git a/micropython/modules/picographics/picographics.c b/micropython/modules/picographics/picographics.c index 9c67df17..2e0f3b8b 100644 --- a/micropython/modules/picographics/picographics.c +++ b/micropython/modules/picographics/picographics.c @@ -125,12 +125,14 @@ STATIC const mp_map_elem_t picographics_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_PACK), MP_ROM_INT(DISPLAY_INKY_PACK) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME), MP_ROM_INT(DISPLAY_INKY_FRAME) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME_4), MP_ROM_INT(DISPLAY_INKY_FRAME_4) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_GALACTIC_UNICORN), MP_ROM_INT(DISPLAY_GALACTIC_UNICORN) }, { MP_ROM_QSTR(MP_QSTR_PEN_1BIT), MP_ROM_INT(PEN_1BIT) }, { MP_ROM_QSTR(MP_QSTR_PEN_P4), MP_ROM_INT(PEN_P4) }, { MP_ROM_QSTR(MP_QSTR_PEN_P8), MP_ROM_INT(PEN_P8) }, { MP_ROM_QSTR(MP_QSTR_PEN_RGB332), MP_ROM_INT(PEN_RGB332) }, { MP_ROM_QSTR(MP_QSTR_PEN_RGB565), MP_ROM_INT(PEN_RGB565) }, + { MP_ROM_QSTR(MP_QSTR_PEN_RGB888), MP_ROM_INT(PEN_RGB888) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_picographics_globals, picographics_globals_table); diff --git a/micropython/modules/picographics/picographics.cpp b/micropython/modules/picographics/picographics.cpp index 7dfaf4ba..dbe8e052 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -112,6 +112,14 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height, if(rotate == -1) rotate = (int)Rotation::ROTATE_0; if(pen_type == -1) pen_type = PEN_P4; break; + case DISPLAY_GALACTIC_UNICORN: + width = 53; + height = 11; + bus_type = BUS_PIO; + // Portrait to match labelling + if(rotate == -1) rotate = (int)Rotation::ROTATE_0; + if(pen_type == -1) pen_type = PEN_RGB888; + break; default: return false; } @@ -132,6 +140,8 @@ size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint h return PicoGraphics_PenRGB332::buffer_size(width, height); case PEN_RGB565: return PicoGraphics_PenRGB565::buffer_size(width, height); + case PEN_RGB888: + return PicoGraphics_PenRGB888::buffer_size(width, height); default: return 0; } @@ -223,7 +233,10 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size } else if (display == DISPLAY_INKY_PACK) { self->display = m_new_class(UC8151, width, height, (Rotation)rotate, spi_bus); - } else { + } else if (display == DISPLAY_GALACTIC_UNICORN) { + self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate); + } + else { self->display = m_new_class(ST7789, width, height, (Rotation)rotate, round, spi_bus); } @@ -267,6 +280,9 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size case PEN_RGB565: self->graphics = m_new_class(PicoGraphics_PenRGB565, self->display->width, self->display->height, self->buffer); break; + case PEN_RGB888: + self->graphics = m_new_class(PicoGraphics_PenRGB888, self->display->width, self->display->height, self->buffer); + break; default: break; } diff --git a/micropython/modules/picographics/picographics.h b/micropython/modules/picographics/picographics.h index 43b68dc0..b2c1e93f 100644 --- a/micropython/modules/picographics/picographics.h +++ b/micropython/modules/picographics/picographics.h @@ -13,7 +13,8 @@ enum PicoGraphicsDisplay { DISPLAY_I2C_OLED_128X128, DISPLAY_INKY_PACK, DISPLAY_INKY_FRAME, - DISPLAY_INKY_FRAME_4 + DISPLAY_INKY_FRAME_4, + DISPLAY_GALACTIC_UNICORN }; enum PicoGraphicsPenType { @@ -23,13 +24,15 @@ enum PicoGraphicsPenType { PEN_P4, PEN_P8, PEN_RGB332, - PEN_RGB565 + PEN_RGB565, + PEN_RGB888 }; enum PicoGraphicsBusType { BUS_I2C, BUS_SPI, - BUS_PARALLEL + BUS_PARALLEL, + BUS_PIO }; // Type From 82b51106918fb610d4c20283a44c373ceb347236 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 28 Jul 2022 18:20:11 +0100 Subject: [PATCH 18/42] Fixed colour order and added working MP examples --- .../galactic_unicorn/galactic_unicorn.cpp | 18 +- .../examples/galactic_unicorn/fire_effect.py | 207 +++++++++--------- .../examples/galactic_unicorn/lava_lamp.py | 137 ++++++++++++ .../galactic_unicorn/galactic_unicorn.c | 10 + 4 files changed, 252 insertions(+), 120 deletions(-) create mode 100644 micropython/examples/galactic_unicorn/lava_lamp.py diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 4b205d73..4f1e637d 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -320,6 +320,10 @@ namespace pimoroni { x = (WIDTH - 1) - x; y = (HEIGHT - 1) - y; + r = (r * this->brightness) >> 8; + g = (g * this->brightness) >> 8; + b = (b * this->brightness) >> 8; + uint16_t gamma_r = r_gamma_lut[r]; uint16_t gamma_g = g_gamma_lut[g]; uint16_t gamma_b = b_gamma_lut[b]; @@ -342,7 +346,7 @@ namespace pimoroni { uint8_t green_bit = gamma_g & 0b1; uint8_t blue_bit = gamma_b & 0b1; - *p = (blue_bit << 2) | (green_bit << 1) | (red_bit << 0); + *p = (blue_bit << 0) | (green_bit << 1) | (red_bit << 2); gamma_r >>= 1; gamma_g >>= 1; @@ -395,11 +399,7 @@ namespace pimoroni { uint8_t b = (col & 0b0000000000011111) << 3; p++; - r = (r * this->brightness) >> 8; - g = (g * this->brightness) >> 8; - b = (b * this->brightness) >> 8; - - set_pixel(x, y, b, g, r); + set_pixel(x, y, r, g, b); } } @@ -415,11 +415,7 @@ namespace pimoroni { uint8_t b = (col & 0x0000ff) >> 0; p++; - r = (r * this->brightness) >> 8; - g = (g * this->brightness) >> 8; - b = (b * this->brightness) >> 8; - - set_pixel(x, y, b, g, r); + set_pixel(x, y, r, g, b); } } diff --git a/micropython/examples/galactic_unicorn/fire_effect.py b/micropython/examples/galactic_unicorn/fire_effect.py index f47ed8ff..72084d4b 100644 --- a/micropython/examples/galactic_unicorn/fire_effect.py +++ b/micropython/examples/galactic_unicorn/fire_effect.py @@ -1,134 +1,123 @@ import time import random -from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN from galactic import GalacticUnicorn -from ulab import numpy as np -graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN) gu = GalacticUnicorn() -width = 53 -height = 15 - -heat = [0.0] * 1000 -#heat = np.full((width + 5, height + 5), 0.0) @micropython.native -def set(x, y, v): - global heat - heat[x + y * width] = v - #heat[x, y] = v - -@micropython.native -def get(x, y): - global heat - x = x if x >= 0 else 0 - x = x if x < width else width - 1 - #try: - #return heat[x, y] - return heat[x + y * width] - #except IndexError: - # pass - -@micropython.native -def select_colour(x, y): - #value = heat[x, y] - value = heat[x + y * width] - if value > 0.5: - return 255, 255, 180 - elif value > 0.4: - return 220, 160, 0 - elif value > 0.3: - return 180, 30, 0 - elif value > 0.22: - return 20, 20, 20 - else: - return 0, 0, 0 +def setup_landscape(): + global width, height, heat, fire_spawns, damping_factor + width = GalacticUnicorn.WIDTH + 2 + height = GalacticUnicorn.HEIGHT + 4 + heat = [[0.0 for y in range(height)] for x in range(width)] + fire_spawns = 5 + damping_factor = 0.97 @micropython.native -def calc_average(x, y): - #if x > 0: - # return (heat[x, y] + heat[x, y + 2] + heat[x, y + 1] + heat[x - 1, y + 1] + heat[x + 1, y + 1]) / 5.0 - return (heat[x + (y * width)] + heat[x + ((y + 2) * width)] + heat[x + ((y + 1) * width)] + heat[(x - 1 if x >= 0 else 0) + ((y + 1) * width)] + heat[(x + 1) + ((y + 1) * width)]) / 5.0 - #else: - #return (heat[x, y] + heat[x, y + 2] + heat[x, y + 1] + heat[x - 0, y + 1] + heat[x + 1, y + 1]) / 5.0 - #return (heat[x + (y * width)] + heat[x + ((y + 2) * width)] + heat[x + ((y + 1) * width)] + heat[(x) + ((y + 1) * width)] + heat[(x + 1) + ((y + 1) * width)]) / 5.0 +def setup_portrait(): + global width, height, heat, fire_spawns, damping_factor + width = GalacticUnicorn.HEIGHT + 2 + height = GalacticUnicorn.WIDTH + 4 + heat = [[0.0 for y in range(height)] for x in range(width)] + fire_spawns = 2 + damping_factor = 0.99 -gu.set_brightness(0.3) +@micropython.native +def update(): + # clear the bottom row and then add a new fire seed to it + for x in range(width): + heat[x][height - 1] = 0.0 + heat[x][height - 2] = 0.0 -# heat[x-1:x+2, y:y+3] -#weights = np.array([[0.0, 0.0, 0.0], - #[0.0, 0.0, 0.0], - #[0.0, 0.0, 0.0]]) - -landscape = True - -while True: - start = time.ticks_ms() - if gu.is_pressed(21): - gu.adjust_brightness(+0.01) - if gu.is_pressed(26): - gu.adjust_brightness(-0.01) - - if gu.is_pressed(0): - landscape = True - width = 53 - height = 15 - for i in range(0, len(heat)): - heat[i] = 0.0 - - if gu.is_pressed(1): - landscape = False - width = 11 - height = 55 - for i in range(0, len(heat)): - heat[i] = 0.0 - - #for y, row in enumerate(heat): - #for x, val in enumerate(row): - # print(x, y, row, val) - - for y in range(0, height): - for x in range(0, width): - r, g, b = select_colour(x, y) - - if landscape: - gu.set_pixel(x, y, r, g, b) - #graphics.pixel(x, y) - else: - gu.set_pixel(y, x, r, g, b) - #graphics.pixel(y, x) + for c in range(fire_spawns): + x = random.randint(0, width - 4) + 2 + heat[x + 0][height - 1] = 1.0 + heat[x + 1][height - 1] = 1.0 + heat[x - 1][height - 1] = 1.0 + heat[x + 0][height - 2] = 1.0 + heat[x + 1][height - 2] = 1.0 + heat[x - 1][height - 2] = 1.0 + for y in range(0, height - 2): + for x in range(1, width - 1): # update this pixel by averaging the below pixels - #average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0 - average = calc_average(x, y) + average = ( + heat[x][y] + heat[x][y + 1] + heat[x][y + 2] + heat[x - 1][y + 1] + heat[x + 1][y + 1] + ) / 5.0 # damping factor to ensure flame tapers out towards the top of the displays - average *= 0.95 if landscape else 0.99 + average *= damping_factor # update the heat map with our newly averaged value - set(x, y, average) + heat[x][y] = average - #gu.update(graphics) - # clear the bottom row and then add a new fire seed to it - for x in range(0, width): - set(x, height - 1, 0.0) +@micropython.native +def draw_landscape(): + for y in range(GalacticUnicorn.HEIGHT): + for x in range(GalacticUnicorn.WIDTH): + value = heat[x + 1][y] - # add a new random heat source - source_count = 5 if landscape else 1 + if value < 0.15: + gu.set_pixel(x, y, 0, 0, 0) + elif value < 0.25: + gu.set_pixel(x, y, 20, 20, 20) + elif value < 0.35: + gu.set_pixel(x, y, 180, 30, 0) + elif value < 0.45: + gu.set_pixel(x, y, 220, 160, 0) + else: + gu.set_pixel(x, y, 255, 255, 180) - for c in range(0, source_count): - px = random.randint(0, width - 4) + 2 - set(px , height - 2, 1.0) - set(px + 1, height - 2, 1.0) - set(px - 1, height - 2, 1.0) - set(px , height - 1, 1.0) - set(px + 1, height - 1, 1.0) - set(px - 1, height - 1, 1.0) - end = time.ticks_ms() - print("Time:", end - start) - #time.sleep(0.02) \ No newline at end of file +@micropython.native +def draw_portrait(): + for y in range(GalacticUnicorn.WIDTH): + for x in range(GalacticUnicorn.HEIGHT): + value = heat[x + 1][y] + + if value < 0.15: + gu.set_pixel(y, x, 0, 0, 0) + elif value < 0.25: + gu.set_pixel(y, x, 20, 20, 20) + elif value < 0.35: + gu.set_pixel(y, x, 180, 30, 0) + elif value < 0.45: + gu.set_pixel(y, x, 220, 160, 0) + else: + gu.set_pixel(y, x, 255, 255, 180) + + +landscape = True +setup_landscape() + +gu.set_brightness(0.5) + +while True: + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + landscape = True + setup_landscape() + + if gu.is_pressed(GalacticUnicorn.SWITCH_B): + landscape = False + setup_portrait() + + start = time.ticks_ms() + + update() + if landscape: + draw_landscape() + else: + draw_portrait() + + print("total took: {} ms".format(time.ticks_ms() - start)) diff --git a/micropython/examples/galactic_unicorn/lava_lamp.py b/micropython/examples/galactic_unicorn/lava_lamp.py new file mode 100644 index 00000000..276be4c3 --- /dev/null +++ b/micropython/examples/galactic_unicorn/lava_lamp.py @@ -0,0 +1,137 @@ +import time +import random +import math +from galactic import GalacticUnicorn + +gu = GalacticUnicorn() + +blob_count = 10 + + +class Blob(): + def __init__(self): + self.x = float(random.randint(0, width - 1)) + self.y = float(random.randint(0, height - 1)) + self.r = (float(random.randint(0, 40)) / 10.0) + 5.0 + self.dx = (float(random.randint(0, 2)) / 10.0) - 0.1 + self.dy = (float(random.randint(0, 2)) / 10.0) - 0.05 # positive bias + + +@micropython.native +def setup_portrait(): + global width, height, liquid, blobs + width = GalacticUnicorn.HEIGHT + height = GalacticUnicorn.WIDTH + liquid = [[0.0 for y in range(height)] for x in range(width)] + blobs = [Blob() for i in range(blob_count)] + + +hue = 0.0 + + +@micropython.native +def from_hsv(h, s, v): + i = math.floor(h * 6.0) + f = h * 6.0 - i + v *= 255.0 + p = v * (1.0 - s) + q = v * (1.0 - f * s) + t = v * (1.0 - (1.0 - f) * s) + + i = int(i) % 6 + if i == 0: + return int(v), int(t), int(p) + if i == 1: + return int(q), int(v), int(p) + if i == 2: + return int(p), int(v), int(t) + if i == 3: + return int(p), int(q), int(v) + if i == 4: + return int(t), int(p), int(v) + if i == 5: + return int(v), int(p), int(q) + + +@micropython.native +def update_liquid(): + for y in range(height): + for x in range(width): + liquid[x][y] = 0.0 + + for blob in blobs: + r_sq = blob.r * blob.r + blob_y_range = range(max(math.floor(blob.y - blob.r), 0), + min(math.ceil(blob.y + blob.r), height)) + blob_x_range = range(max(math.floor(blob.x - blob.r), 0), + min(math.ceil(blob.x + blob.r), width)) + + for y in blob_y_range: + for x in blob_x_range: + x_diff = x - blob.x + y_diff = y - blob.y + d_sq = x_diff * x_diff + y_diff * y_diff + if d_sq <= r_sq: + liquid[x][y] += 1.0 - (d_sq / r_sq) + + +@micropython.native +def move_blobs(): + for blob in blobs: + blob.x += blob.dx + blob.y += blob.dy + + if blob.x < 0.0 or blob.x >= float(width): + blob.dx = 0.0 - blob.dx + + if blob.y < 0.0 or blob.y >= float(height): + blob.dy = 0.0 - blob.dy + + +@micropython.native +def draw_portrait(): + global hue + hue += 0.001 + + dark_r, dark_g, dark_b = from_hsv(hue, 1.0, 0.3) + mid_r, mid_g, mid_b = from_hsv(hue, 1.0, 0.6) + bright_r, bright_g, bright_b = from_hsv(hue, 1.0, 1.0) + + for y in range(height): + for x in range(width): + v = liquid[x][y] + + # select a colour for this pixel based on how much + # "blobfluence" there is at this position in the liquid + if v >= 1.5: + gu.set_pixel(y, x, bright_r, bright_g, bright_b) + elif v >= 1.25: + gu.set_pixel(y, x, mid_r, mid_g, mid_b) + elif v >= 1.0: + gu.set_pixel(y, x, dark_r, dark_g, dark_b) + else: + gu.set_pixel(y, x, 0, 0, 0) + + +setup_portrait() + +gu.set_brightness(0.5) + +while True: + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + setup_portrait() + + start = time.ticks_ms() + + update_liquid() + move_blobs() + draw_portrait() + + print("total took: {} ms".format(time.ticks_ms() - start)) diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index c46a2ad0..1e2a8a82 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -34,6 +34,16 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, + + { MP_ROM_QSTR(MP_QSTR_SWITCH_A), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_B), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_C), MP_ROM_INT(3) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_D), MP_ROM_INT(6) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_SLEEP), MP_ROM_INT(27) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_VOLUME_UP), MP_ROM_INT(7) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_VOLUME_DOWN), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_UP), MP_ROM_INT(21) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_DOWN), MP_ROM_INT(26) }, }; STATIC MP_DEFINE_CONST_DICT(GalacticUnicorn_locals_dict, GalacticUnicorn_locals_dict_table); From 34a1a54cd1a661ed96d7a44f65007469925f3eb5 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Fri, 29 Jul 2022 12:08:17 +0100 Subject: [PATCH 19/42] Added nostalgia prompt example, and fixed linting --- .../examples/galactic_unicorn/feature_test.py | 36 +----- .../galactic_unicorn/nostalgia_prompt.py | 103 ++++++++++++++++++ 2 files changed, 105 insertions(+), 34 deletions(-) create mode 100644 micropython/examples/galactic_unicorn/nostalgia_prompt.py diff --git a/micropython/examples/galactic_unicorn/feature_test.py b/micropython/examples/galactic_unicorn/feature_test.py index 3f11d41b..616a06c8 100644 --- a/micropython/examples/galactic_unicorn/feature_test.py +++ b/micropython/examples/galactic_unicorn/feature_test.py @@ -1,8 +1,8 @@ -import time from galactic import GalacticUnicorn gu = GalacticUnicorn() + def gradient(r, g, b): for y in range(0, 11): for x in range(0, 53): @@ -10,41 +10,9 @@ def gradient(r, g, b): gu.set_pixel(x, y, x) -def grid(ms, x, y) { +def grid(ms, x, y): v = (x + y + (ms / 1000)) % 2 if v == 0: gu.set_pixel(x, y, 255) else: gu.set_pixel(x, y, 0) -} - -void shader_fill(int ms, shader_func_t f) { - for(int y = 0; y < 12; y++) { - for(int x = 0; x < 53; x++) { - f(ms, x, y); - } - } -} - -void outline_text(std::string text) { - uint ms = to_ms_since_boot(get_absolute_time()); - - graphics.set_font("bitmap8"); - uint8_t v = (sin(ms / 100.0f) + 1.0f) * 127.0f; - uint w = graphics.measure_text(text, 1); - - int x = 53 / 2 - w / 2 + 1, y = 2; - - graphics.set_pen(0, 0, 0); - graphics.text(text, Point(x - 1, y - 1), -1, 1); - graphics.text(text, Point(x , y - 1), -1, 1); - graphics.text(text, Point(x + 1, y - 1), -1, 1); - graphics.text(text, Point(x - 1, y ), -1, 1); - graphics.text(text, Point(x + 1, y ), -1, 1); - graphics.text(text, Point(x - 1, y + 1), -1, 1); - graphics.text(text, Point(x , y + 1), -1, 1); - graphics.text(text, Point(x + 1, y + 1), -1, 1); - - graphics.set_pen(v, v, v); - graphics.text(text, Point(x, y), -1, 1); -} \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/nostalgia_prompt.py b/micropython/examples/galactic_unicorn/nostalgia_prompt.py new file mode 100644 index 00000000..3900d289 --- /dev/null +++ b/micropython/examples/galactic_unicorn/nostalgia_prompt.py @@ -0,0 +1,103 @@ +import time +from galactic import GalacticUnicorn + +gu = GalacticUnicorn() + + +c64 = [ + " ", + " ", + " OOOOO OOOOOO OO OOOO OO OO XXXXXXX ", + " OO OO OO OOOO OO OO OO OO XXXXXXX ", + " OO OO OO OO OO OO OO OO OO XXXXXXX ", + " OOOOO OOOO OOOOOO OO OO OOOO XXXXXXX ", + " OOOO OO OO OO OO OO OO XXXXXXX ", + " OO OO OO OO OO OO OO OO OO XXXXXXX ", + " OO OO OOOOOO OO OO OOOO OO OO XXXXXXX ", + " XXXXXXX ", + " " +] +FOREGROUND_C64 = (230, 210, 250) +BACKGROUND_C64 = (20, 20, 120) + +spectrum = [ + " ", + " ", + " O OOOO OOOO OOOOO O O O O XXXXXXXX ", + " O O O O O O O O O O O X XXXXXX ", + " O O O O O O O X XXXXXX ", + " O O O OOOOOO O O X XXXXXX ", + " O O O O O O O X XXXXXX ", + " OOOOOO OOOO O O OOOOO X XXXXXX ", + " X X ", + " XXXXXXXX ", + " " +] +FOREGROUND_SPECTRUM = (0, 0, 0) +BACKGROUND_SPECTRUM = (180, 150, 150) + +bbc_micro = [ + " ", + " ", + " OOOOO OO OOOO OOO OOOO O ", + " O O O O O O O O O O ", + " O O O O O O O O ", + " OOOOO O O OOOO O O O ", + " O O OOOOOO O O O O ", + " O O O O O O O O O O ", + " OOOOO O O OOOO OOO OOOO O ", + " XXXXXXX ", + " " +] +FOREGROUND_BBC_MICRO = (255, 255, 255) +BACKGROUND_BBC_MICRO = (0, 0, 0) + +PROMPT_C64 = 0 +PROMPT_SPECTRUM = 1 +PROMPT_BBC_MICRO = 2 +prompt = 0 + + +@micropython.native +def draw(image, fg, bg, time_ms): + for y in range(len(image)): + row = image[y] + for x in range(len(row)): + pixel = row[x] + # draw the prompt text + if pixel == 'O': + gu.set_pixel(x, y, fg[0], fg[1], fg[2]) + + # draw the caret blinking + elif pixel == 'X' and (time_ms // 300) % 2: + gu.set_pixel(x, y, fg[0], fg[1], fg[2]) + + else: + gu.set_pixel(x, y, bg[0], bg[1], bg[2]) + + +gu.set_brightness(0.5) + +while True: + + time_ms = time.ticks_ms() + prompt = (time_ms // 3000) % 3 + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + start = time.ticks_ms() + + if prompt == PROMPT_C64: + draw(c64, FOREGROUND_C64, BACKGROUND_C64, time_ms) + + elif prompt == PROMPT_SPECTRUM: + draw(spectrum, FOREGROUND_SPECTRUM, BACKGROUND_SPECTRUM, time_ms) + + elif prompt == PROMPT_BBC_MICRO: + draw(bbc_micro, FOREGROUND_BBC_MICRO, BACKGROUND_BBC_MICRO, time_ms) + + print("total took: {} ms".format(time.ticks_ms() - start)) From 2283e7336886a0dab082df022744b58acdb07dbe Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Fri, 29 Jul 2022 12:16:45 +0100 Subject: [PATCH 20/42] Fix for native comments raising linting errors --- micropython/examples/galactic_unicorn/fire_effect.py | 10 +++++----- micropython/examples/galactic_unicorn/lava_lamp.py | 10 +++++----- .../examples/galactic_unicorn/nostalgia_prompt.py | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/micropython/examples/galactic_unicorn/fire_effect.py b/micropython/examples/galactic_unicorn/fire_effect.py index 72084d4b..9ca4e89c 100644 --- a/micropython/examples/galactic_unicorn/fire_effect.py +++ b/micropython/examples/galactic_unicorn/fire_effect.py @@ -5,7 +5,7 @@ from galactic import GalacticUnicorn gu = GalacticUnicorn() -@micropython.native +@micropython.native # noqa: F821 def setup_landscape(): global width, height, heat, fire_spawns, damping_factor width = GalacticUnicorn.WIDTH + 2 @@ -15,7 +15,7 @@ def setup_landscape(): damping_factor = 0.97 -@micropython.native +@micropython.native # noqa: F821 def setup_portrait(): global width, height, heat, fire_spawns, damping_factor width = GalacticUnicorn.HEIGHT + 2 @@ -25,7 +25,7 @@ def setup_portrait(): damping_factor = 0.99 -@micropython.native +@micropython.native # noqa: F821 def update(): # clear the bottom row and then add a new fire seed to it for x in range(width): @@ -55,7 +55,7 @@ def update(): heat[x][y] = average -@micropython.native +@micropython.native # noqa: F821 def draw_landscape(): for y in range(GalacticUnicorn.HEIGHT): for x in range(GalacticUnicorn.WIDTH): @@ -73,7 +73,7 @@ def draw_landscape(): gu.set_pixel(x, y, 255, 255, 180) -@micropython.native +@micropython.native # noqa: F821 def draw_portrait(): for y in range(GalacticUnicorn.WIDTH): for x in range(GalacticUnicorn.HEIGHT): diff --git a/micropython/examples/galactic_unicorn/lava_lamp.py b/micropython/examples/galactic_unicorn/lava_lamp.py index 276be4c3..16e46dc9 100644 --- a/micropython/examples/galactic_unicorn/lava_lamp.py +++ b/micropython/examples/galactic_unicorn/lava_lamp.py @@ -17,7 +17,7 @@ class Blob(): self.dy = (float(random.randint(0, 2)) / 10.0) - 0.05 # positive bias -@micropython.native +@micropython.native # noqa: F821 def setup_portrait(): global width, height, liquid, blobs width = GalacticUnicorn.HEIGHT @@ -29,7 +29,7 @@ def setup_portrait(): hue = 0.0 -@micropython.native +@micropython.native # noqa: F821 def from_hsv(h, s, v): i = math.floor(h * 6.0) f = h * 6.0 - i @@ -53,7 +53,7 @@ def from_hsv(h, s, v): return int(v), int(p), int(q) -@micropython.native +@micropython.native # noqa: F821 def update_liquid(): for y in range(height): for x in range(width): @@ -75,7 +75,7 @@ def update_liquid(): liquid[x][y] += 1.0 - (d_sq / r_sq) -@micropython.native +@micropython.native # noqa: F821 def move_blobs(): for blob in blobs: blob.x += blob.dx @@ -88,7 +88,7 @@ def move_blobs(): blob.dy = 0.0 - blob.dy -@micropython.native +@micropython.native # noqa: F821 def draw_portrait(): global hue hue += 0.001 diff --git a/micropython/examples/galactic_unicorn/nostalgia_prompt.py b/micropython/examples/galactic_unicorn/nostalgia_prompt.py index 3900d289..679ad62b 100644 --- a/micropython/examples/galactic_unicorn/nostalgia_prompt.py +++ b/micropython/examples/galactic_unicorn/nostalgia_prompt.py @@ -58,7 +58,7 @@ PROMPT_BBC_MICRO = 2 prompt = 0 -@micropython.native +@micropython.native # noqa: F821 def draw(image, fg, bg, time_ms): for y in range(len(image)): row = image[y] From c8b5ffff8c9b40c47e8ef507c2f85d32f0e1a740 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Fri, 29 Jul 2022 15:48:48 +0100 Subject: [PATCH 21/42] More MP examples for GU --- .../eighties_super_computer.py | 62 +++++++++++ .../examples/galactic_unicorn/rainbow.py | 105 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 micropython/examples/galactic_unicorn/eighties_super_computer.py create mode 100644 micropython/examples/galactic_unicorn/rainbow.py diff --git a/micropython/examples/galactic_unicorn/eighties_super_computer.py b/micropython/examples/galactic_unicorn/eighties_super_computer.py new file mode 100644 index 00000000..4fdbc48a --- /dev/null +++ b/micropython/examples/galactic_unicorn/eighties_super_computer.py @@ -0,0 +1,62 @@ +import time +import random +from galactic import GalacticUnicorn + +gu = GalacticUnicorn() + +colour = (230, 150, 0) + + +@micropython.native # noqa: F821 +def setup(): + global width, height, lifetime, age + width = GalacticUnicorn.WIDTH + height = GalacticUnicorn.HEIGHT + lifetime = [[0.0 for y in range(height)] for x in range(width)] + age = [[0.0 for y in range(height)] for x in range(width)] + for y in range(height): + for x in range(width): + lifetime[x][y] = 1.0 + random.uniform(0.0, 0.1) + age[x][y] = random.uniform(0.0, 1.0) * lifetime[x][y] + + +@micropython.native # noqa: F821 +def draw(): + for y in range(height): + for x in range(width): + if age[x][y] < lifetime[x][y] * 0.3: + gu.set_pixel(x, y, colour[0], colour[1], colour[2]) + elif age[x][y] < lifetime[x][y] * 0.5: + decay = (lifetime[x][y] * 0.5 - age[x][y]) * 5.0 + gu.set_pixel(x, y, int(decay * colour[0]), int(decay * colour[1]), int(decay * colour[2])) + + +@micropython.native # noqa: F821 +def update(): + for y in range(height): + for x in range(width): + if age[x][y] >= lifetime[x][y]: + age[x][y] = 0.0 + lifetime[x][y] = 1.0 + random.uniform(0.0, 0.1) + + age[x][y] += 0.025 + + +setup() + +gu.set_brightness(0.5) + +while True: + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + start = time.ticks_ms() + + draw() + update() + + print("total took: {} ms".format(time.ticks_ms() - start)) diff --git a/micropython/examples/galactic_unicorn/rainbow.py b/micropython/examples/galactic_unicorn/rainbow.py new file mode 100644 index 00000000..c0ec6826 --- /dev/null +++ b/micropython/examples/galactic_unicorn/rainbow.py @@ -0,0 +1,105 @@ +import time +import math +from galactic import GalacticUnicorn + +gu = GalacticUnicorn() + +width = GalacticUnicorn.WIDTH +height = GalacticUnicorn.HEIGHT + + +@micropython.native # noqa: F821 +def from_hsv(h, s, v): + i = math.floor(h * 6.0) + f = h * 6.0 - i + v *= 255.0 + p = v * (1.0 - s) + q = v * (1.0 - f * s) + t = v * (1.0 - (1.0 - f) * s) + + i = int(i) % 6 + if i == 0: + return int(v), int(t), int(p) + if i == 1: + return int(q), int(v), int(p) + if i == 2: + return int(p), int(v), int(t) + if i == 3: + return int(p), int(q), int(v) + if i == 4: + return int(t), int(p), int(v) + if i == 5: + return int(v), int(p), int(q) + + +@micropython.native # noqa: F821 +def draw(): + global hue_offset, phase + phase_percent = phase / 15 + for x in range(width): + colour = hue_map[int((x + (hue_offset * width)) % width)] + for y in range(height): + v = ((math.sin((x + y) / stripe_width + phase_percent) + 1.5) / 2.5) + + r = int(colour[0] * v) + g = int(colour[1] * v) + b = int(colour[2] * v) + + gu.set_pixel(x, y, r, g, b) + + +hue_map = [from_hsv(x / width, 1.0, 1.0) for x in range(width)] +hue_offset = 0.0 + +animate = True +stripe_width = 3.0 +speed = 1.0 + +gu.set_brightness(0.5) + +phase = 0 +while True: + + if animate: + phase += speed + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): + hue_offset += 0.01 + hue_offset = 1.0 if hue_offset > 1.0 else hue_offset + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): + hue_offset -= 0.01 + hue_offset = 0.0 if hue_offset < 0.0 else hue_offset + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): + animate = False + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + speed += 0.05 + speed = 10.0 if speed > 10.0 else speed + animate = True + + if gu.is_pressed(GalacticUnicorn.SWITCH_B): + speed -= 0.05 + speed = 0.0 if speed < 0.0 else speed + animate = True + + if gu.is_pressed(GalacticUnicorn.SWITCH_C): + stripe_width += 0.05 + stripe_width = 10.0 if stripe_width > 10.0 else stripe_width + + if gu.is_pressed(GalacticUnicorn.SWITCH_D): + stripe_width -= 0.05 + stripe_width = 1.0 if stripe_width < 1.0 else stripe_width + + start = time.ticks_ms() + + draw() + + print("total took: {} ms".format(time.ticks_ms() - start)) From b35ed5d5ba0a7fa355f1af77eac3d3fa0b3d92ba Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Mon, 1 Aug 2022 17:07:38 +0100 Subject: [PATCH 22/42] Moved MP examples over to PicoGraphics --- .../galactic_unicorn/galactic_unicorn.cpp | 33 +++++++++++++++++ .../galactic_unicorn/galactic_unicorn.hpp | 1 + .../pico_graphics_pen_rgb888.cpp | 5 +-- .../eighties_super_computer.py | 11 ++++-- .../examples/galactic_unicorn/fire_effect.py | 36 ++++++++++++------- .../examples/galactic_unicorn/lava_lamp.py | 31 +++++++++------- .../galactic_unicorn/nostalgia_prompt.py | 14 ++++++-- .../examples/galactic_unicorn/rainbow.py | 9 ++--- .../galactic_unicorn/galactic_unicorn.cpp | 8 +++-- 9 files changed, 110 insertions(+), 38 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 4f1e637d..a5ccae51 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -387,6 +387,39 @@ namespace pimoroni { } + void GalacticUnicorn::update(PicoGraphics *graphics) { + if(graphics->pen_type == PicoGraphics::PEN_RGB888) { + uint32_t *p = (uint32_t *)graphics->frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + p++; + + set_pixel(x, y, r, g, b); + } + } + else if(graphics->pen_type == PicoGraphics::PEN_RGB565) { + uint16_t *p = (uint16_t *)graphics->frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint16_t col = __builtin_bswap16(*p); + uint8_t r = (col & 0b1111100000000000) >> 8; + uint8_t g = (col & 0b0000011111100000) >> 3; + uint8_t b = (col & 0b0000000000011111) << 3; + p++; + + set_pixel(x, y, r, g, b); + } + } + } + void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t j = 0; j < 53 * 11; j++) { diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index b9d8e2f6..c9c8010b 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -76,6 +76,7 @@ namespace pimoroni { void clear(); + void update(PicoGraphics *graphics); void update(PicoGraphics_PenRGB565 &graphics); void update(PicoGraphics_PenRGB888 &graphics); diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp index 311829f0..89713f93 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp @@ -9,10 +9,11 @@ namespace pimoroni { } } void PicoGraphics_PenRGB888::set_pen(uint c) { - color = RGB(c, c, c).to_rgb888(); + color = c; } void PicoGraphics_PenRGB888::set_pen(uint8_t r, uint8_t g, uint8_t b) { - color = RGB(r, g, b).to_rgb888(); + src_color = {r, g, b}; + color = src_color.to_rgb888(); } int PicoGraphics_PenRGB888::create_pen(uint8_t r, uint8_t g, uint8_t b) { return RGB(r, g, b).to_rgb888(); diff --git a/micropython/examples/galactic_unicorn/eighties_super_computer.py b/micropython/examples/galactic_unicorn/eighties_super_computer.py index 4fdbc48a..ebeedf8e 100644 --- a/micropython/examples/galactic_unicorn/eighties_super_computer.py +++ b/micropython/examples/galactic_unicorn/eighties_super_computer.py @@ -1,8 +1,10 @@ import time import random from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) colour = (230, 150, 0) @@ -25,10 +27,15 @@ def draw(): for y in range(height): for x in range(width): if age[x][y] < lifetime[x][y] * 0.3: - gu.set_pixel(x, y, colour[0], colour[1], colour[2]) + graphics.set_pen(graphics.create_pen(colour[0], colour[1], colour[2])) elif age[x][y] < lifetime[x][y] * 0.5: decay = (lifetime[x][y] * 0.5 - age[x][y]) * 5.0 - gu.set_pixel(x, y, int(decay * colour[0]), int(decay * colour[1]), int(decay * colour[2])) + graphics.set_pen(graphics.create_pen(int(decay * colour[0]), int(decay * colour[1]), int(decay * colour[2]))) + else: + graphics.set_pen(0) + graphics.pixel(x, y) + + gu.update(graphics) @micropython.native # noqa: F821 diff --git a/micropython/examples/galactic_unicorn/fire_effect.py b/micropython/examples/galactic_unicorn/fire_effect.py index 9ca4e89c..6a7944ab 100644 --- a/micropython/examples/galactic_unicorn/fire_effect.py +++ b/micropython/examples/galactic_unicorn/fire_effect.py @@ -1,8 +1,16 @@ import time import random from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) + +fire_colours = [graphics.create_pen(0, 0, 0), + graphics.create_pen(20, 20, 20), + graphics.create_pen(180, 30, 0), + graphics.create_pen(220, 160, 0), + graphics.create_pen(255, 255, 180)] @micropython.native # noqa: F821 @@ -60,17 +68,19 @@ def draw_landscape(): for y in range(GalacticUnicorn.HEIGHT): for x in range(GalacticUnicorn.WIDTH): value = heat[x + 1][y] - if value < 0.15: - gu.set_pixel(x, y, 0, 0, 0) + graphics.set_pen(fire_colours[0]) elif value < 0.25: - gu.set_pixel(x, y, 20, 20, 20) + graphics.set_pen(fire_colours[1]) elif value < 0.35: - gu.set_pixel(x, y, 180, 30, 0) + graphics.set_pen(fire_colours[2]) elif value < 0.45: - gu.set_pixel(x, y, 220, 160, 0) + graphics.set_pen(fire_colours[3]) else: - gu.set_pixel(x, y, 255, 255, 180) + graphics.set_pen(fire_colours[4]) + graphics.pixel(x, y) + + gu.update(graphics) @micropython.native # noqa: F821 @@ -78,17 +88,19 @@ def draw_portrait(): for y in range(GalacticUnicorn.WIDTH): for x in range(GalacticUnicorn.HEIGHT): value = heat[x + 1][y] - if value < 0.15: - gu.set_pixel(y, x, 0, 0, 0) + graphics.set_pen(fire_colours[0]) elif value < 0.25: - gu.set_pixel(y, x, 20, 20, 20) + graphics.set_pen(fire_colours[1]) elif value < 0.35: - gu.set_pixel(y, x, 180, 30, 0) + graphics.set_pen(fire_colours[2]) elif value < 0.45: - gu.set_pixel(y, x, 220, 160, 0) + graphics.set_pen(fire_colours[3]) else: - gu.set_pixel(y, x, 255, 255, 180) + graphics.set_pen(fire_colours[4]) + graphics.pixel(y, x) + + gu.update(graphics) landscape = True diff --git a/micropython/examples/galactic_unicorn/lava_lamp.py b/micropython/examples/galactic_unicorn/lava_lamp.py index 16e46dc9..04590df9 100644 --- a/micropython/examples/galactic_unicorn/lava_lamp.py +++ b/micropython/examples/galactic_unicorn/lava_lamp.py @@ -2,8 +2,10 @@ import time import random import math from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) blob_count = 10 @@ -40,17 +42,17 @@ def from_hsv(h, s, v): i = int(i) % 6 if i == 0: - return int(v), int(t), int(p) + return graphics.create_pen(int(v), int(t), int(p)) if i == 1: - return int(q), int(v), int(p) + return graphics.create_pen(int(q), int(v), int(p)) if i == 2: - return int(p), int(v), int(t) + return graphics.create_pen(int(p), int(v), int(t)) if i == 3: - return int(p), int(q), int(v) + return graphics.create_pen(int(p), int(q), int(v)) if i == 4: - return int(t), int(p), int(v) + return graphics.create_pen(int(t), int(p), int(v)) if i == 5: - return int(v), int(p), int(q) + return graphics.create_pen(int(v), int(p), int(q)) @micropython.native # noqa: F821 @@ -93,9 +95,9 @@ def draw_portrait(): global hue hue += 0.001 - dark_r, dark_g, dark_b = from_hsv(hue, 1.0, 0.3) - mid_r, mid_g, mid_b = from_hsv(hue, 1.0, 0.6) - bright_r, bright_g, bright_b = from_hsv(hue, 1.0, 1.0) + dark = from_hsv(hue, 1.0, 0.3) + mid = from_hsv(hue, 1.0, 0.6) + bright = from_hsv(hue, 1.0, 1.0) for y in range(height): for x in range(width): @@ -104,13 +106,16 @@ def draw_portrait(): # select a colour for this pixel based on how much # "blobfluence" there is at this position in the liquid if v >= 1.5: - gu.set_pixel(y, x, bright_r, bright_g, bright_b) + graphics.set_pen(bright) elif v >= 1.25: - gu.set_pixel(y, x, mid_r, mid_g, mid_b) + graphics.set_pen(mid) elif v >= 1.0: - gu.set_pixel(y, x, dark_r, dark_g, dark_b) + graphics.set_pen(dark) else: - gu.set_pixel(y, x, 0, 0, 0) + graphics.set_pen(0) + graphics.pixel(y, x) + + gu.update(graphics) setup_portrait() diff --git a/micropython/examples/galactic_unicorn/nostalgia_prompt.py b/micropython/examples/galactic_unicorn/nostalgia_prompt.py index 679ad62b..d66d1cf4 100644 --- a/micropython/examples/galactic_unicorn/nostalgia_prompt.py +++ b/micropython/examples/galactic_unicorn/nostalgia_prompt.py @@ -1,7 +1,9 @@ import time from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) c64 = [ @@ -60,20 +62,26 @@ prompt = 0 @micropython.native # noqa: F821 def draw(image, fg, bg, time_ms): + fg_pen = graphics.create_pen(fg[0], fg[1], fg[2]) + bg_pen = graphics.create_pen(bg[0], bg[1], bg[2]) for y in range(len(image)): row = image[y] for x in range(len(row)): pixel = row[x] # draw the prompt text if pixel == 'O': - gu.set_pixel(x, y, fg[0], fg[1], fg[2]) + graphics.set_pen(fg_pen) # draw the caret blinking elif pixel == 'X' and (time_ms // 300) % 2: - gu.set_pixel(x, y, fg[0], fg[1], fg[2]) + graphics.set_pen(fg_pen) else: - gu.set_pixel(x, y, bg[0], bg[1], bg[2]) + graphics.set_pen(bg_pen) + + graphics.pixel(x, y) + + gu.update(graphics) gu.set_brightness(0.5) diff --git a/micropython/examples/galactic_unicorn/rainbow.py b/micropython/examples/galactic_unicorn/rainbow.py index c0ec6826..818ee0a1 100644 --- a/micropython/examples/galactic_unicorn/rainbow.py +++ b/micropython/examples/galactic_unicorn/rainbow.py @@ -1,8 +1,10 @@ import time import math from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) width = GalacticUnicorn.WIDTH height = GalacticUnicorn.HEIGHT @@ -41,11 +43,10 @@ def draw(): for y in range(height): v = ((math.sin((x + y) / stripe_width + phase_percent) + 1.5) / 2.5) - r = int(colour[0] * v) - g = int(colour[1] * v) - b = int(colour[2] * v) + graphics.set_pen(graphics.create_pen(int(colour[0] * v), int(colour[1] * v), int(colour[2] * v))) + graphics.pixel(x, y) - gu.set_pixel(x, y, r, g, b) + gu.update(graphics) hue_map = [from_hsv(x / width, 1.0, 1.0) for x in range(width)] diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 34c0cd51..4a6e9efa 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -9,6 +9,7 @@ using namespace pimoroni; extern "C" { #include "galactic_unicorn.h" +#include "micropython/modules/pimoroni_i2c/pimoroni_i2c.h" #include "py/builtin.h" @@ -25,7 +26,10 @@ typedef struct _ModPicoGraphics_obj_t { mp_obj_base_t base; PicoGraphics *graphics; DisplayDriver *display; + void *spritedata; void *buffer; + _PimoroniI2C_obj_t *i2c; + //mp_obj_t scanline_callback; // Not really feasible in MicroPython } ModPicoGraphics_obj_t; /***** Print *****/ @@ -107,9 +111,9 @@ extern mp_obj_t GalacticUnicorn_clear(mp_obj_t self_in) { extern mp_obj_t GalacticUnicorn_update(mp_obj_t self_in, mp_obj_t graphics_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t); + ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(graphics_in, ModPicoGraphics_obj_t); - self->galactic->update(*((PicoGraphics_PenRGB888 *)picographics->graphics)); + self->galactic->update(picographics->graphics); return mp_const_none; } From fbc6737f1eaafe27804358dbc5256d0f61f2c2f3 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Mon, 1 Aug 2022 20:29:19 +0100 Subject: [PATCH 23/42] Finished feature_test.py --- .../examples/galactic_unicorn/feature_test.py | 119 ++++++++++++++++-- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/micropython/examples/galactic_unicorn/feature_test.py b/micropython/examples/galactic_unicorn/feature_test.py index 616a06c8..462a94a4 100644 --- a/micropython/examples/galactic_unicorn/feature_test.py +++ b/micropython/examples/galactic_unicorn/feature_test.py @@ -1,18 +1,117 @@ +import time +import math from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) + +width = GalacticUnicorn.WIDTH +height = GalacticUnicorn.HEIGHT def gradient(r, g, b): - for y in range(0, 11): - for x in range(0, 53): - # graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); - gu.set_pixel(x, y, x) + for y in range(0, height): + for x in range(0, width): + graphics.set_pen(graphics.create_pen(int((r * x) / 52), int((g * x) / 52), int((b * x) / 52))) + graphics.pixel(x, y) -def grid(ms, x, y): - v = (x + y + (ms / 1000)) % 2 - if v == 0: - gu.set_pixel(x, y, 255) - else: - gu.set_pixel(x, y, 0) +def grid(r, g, b): + for y in range(0, height): + for x in range(0, width): + if (x + y) % 2 == 0: + graphics.set_pen(graphics.create_pen(r, g, b)) + else: + graphics.set_pen(0) + graphics.pixel(x, y) + + +def outline_text(text): + ms = time.ticks_ms() + + graphics.set_font("bitmap8") + v = int((math.sin(ms / 100.0) + 1.0) * 127.0) + w = graphics.measure_text(text, 1) + + x = int(53 / 2 - w / 2 + 1) + y = 2 + + graphics.set_pen(0) + graphics.text(text, x - 1, y - 1, -1, 1) + graphics.text(text, x, y - 1, -1, 1) + graphics.text(text, x + 1, y - 1, -1, 1) + graphics.text(text, x - 1, y, -1, 1) + graphics.text(text, x + 1, y, -1, 1) + graphics.text(text, x - 1, y + 1, -1, 1) + graphics.text(text, x, y + 1, -1, 1) + graphics.text(text, x + 1, y + 1, -1, 1) + + graphics.set_pen(graphics.create_pen(v, v, v)) + graphics.text(text, x, y, -1, 1) + + +gu.set_brightness(0.5) + +while True: + + time_ms = time.ticks_ms() + test = (time_ms // 1000) % 5 + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + graphics.set_pen(graphics.create_pen(0, 0, 0)) + graphics.clear() + + if test == 0: + print("grid pattern") + grid(255, 255, 255) + elif test == 1: + print("red gradient") + gradient(255, 0, 0) + elif test == 2: + print("green gradient") + gradient(0, 255, 0) + elif test == 3: + print("blue gradient") + gradient(0, 0, 255) + elif test == 4: + print("white gradient") + gradient(255, 255, 255) + + text = "" + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + text = "Button A" + + if gu.is_pressed(GalacticUnicorn.SWITCH_B): + text = "Button B" + + if gu.is_pressed(GalacticUnicorn.SWITCH_C): + text = "Button C" + + if gu.is_pressed(GalacticUnicorn.SWITCH_D): + text = "Button D" + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): + text = "Louder!" + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): + text = "Quieter" + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + text = "Brighter!" + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + text = "Darker" + + if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): + text = "Zzz... zzz..." + + outline_text(text) + + gu.update(graphics) From bb91d9e75b9fcb8d413741e72955a5657b00bf5d Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 2 Aug 2022 12:21:56 +0100 Subject: [PATCH 24/42] WIP improvements to GU hardware reuse (temp disabled audio) --- .../galactic_unicorn/galactic_unicorn.cpp | 580 +++++++++++------- .../galactic_unicorn/galactic_unicorn.hpp | 9 +- 2 files changed, 351 insertions(+), 238 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index a5ccae51..9683cb0d 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -48,6 +48,9 @@ static uint32_t audio_dma_channel; namespace pimoroni { GalacticUnicorn* GalacticUnicorn::unicorn = nullptr; + PIO GalacticUnicorn::bitstream_pio = pio0; + uint GalacticUnicorn::bitstream_sm = 0; + uint GalacticUnicorn::bitstream_sm_offset = 0; // once the dma transfer of the scanline is complete we move to the // next scanline (or quit if we're finished) @@ -66,19 +69,76 @@ namespace pimoroni { } GalacticUnicorn::~GalacticUnicorn() { - // stop and release the dma channel - irq_set_enabled(DMA_IRQ_0, false); - dma_channel_set_irq0_enabled(dma_channel, false); - irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); - irq_remove_handler(DMA_IRQ_0, dma_complete); + // if(unicorn == this) { + // // stop and release the dma channel + // irq_set_enabled(DMA_IRQ_0, false); + // dma_channel_set_irq0_enabled(dma_channel, false); + // irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); + // irq_remove_handler(DMA_IRQ_0, dma_complete); - dma_channel_wait_for_finish_blocking(dma_channel); - dma_channel_unclaim(dma_channel); + // dma_channel_wait_for_finish_blocking(dma_channel); + // dma_channel_unclaim(dma_channel); + + // // release the pio and sm + // pio_sm_unclaim(bitstream_pio, bitstream_sm); + // pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); + // //pio_sm_restart(bitstream_pio, bitstream_sm); + + // unicorn = nullptr; + // } + + if(unicorn == this) { + teardown(); + /*pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); + + // Tear down the DMA channel. + // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc + uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); + hw_clear_bits(&dma_hw->inte0, irq0_save); + + dma_hw->abort = 1u << dma_channel; + + // To fence off on in-flight transfers, the BUSY bit should be polled + // rather than the ABORT bit, because the ABORT bit can clear prematurely. + while (dma_hw->ch[dma_channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); + + // Clear the interrupt (if any) and restore the interrupt masks. + dma_hw->ints0 = 1u << dma_channel; + hw_set_bits(&dma_hw->inte0, irq0_save); + + dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly + unicorn = nullptr; + + pio_sm_unclaim(bitstream_pio, bitstream_sm); + pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); + irq_remove_handler(DMA_IRQ_0, dma_complete);*/ + } + } + + void GalacticUnicorn::teardown() { + pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); + + // Tear down the DMA channel. + // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc + uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); + hw_clear_bits(&dma_hw->inte0, irq0_save); + + dma_hw->abort = 1u << dma_channel; + + // To fence off on in-flight transfers, the BUSY bit should be polled + // rather than the ABORT bit, because the ABORT bit can clear prematurely. + while (dma_hw->ch[dma_channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); + + // Clear the interrupt (if any) and restore the interrupt masks. + dma_hw->ints0 = 1u << dma_channel; + hw_set_bits(&dma_hw->inte0, irq0_save); + + dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly + unicorn = nullptr; - // release the pio and sm pio_sm_unclaim(bitstream_pio, bitstream_sm); - pio_clear_instruction_memory(bitstream_pio); - pio_sm_restart(bitstream_pio, bitstream_sm); + pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); + irq_remove_handler(DMA_IRQ_0, dma_complete); } uint16_t GalacticUnicorn::light() { @@ -87,230 +147,274 @@ namespace pimoroni { } void GalacticUnicorn::init() { - // todo: shouldn't need to do this if things were cleaned up properly but without - // this any attempt to run a micropython script twice will fail - static bool already_init = false; - // create 14-bit gamma luts - for(uint16_t v = 0; v < 256; v++) { - // gamma correct the provided 0-255 brightness value onto a - // 0-65535 range for the pwm counter - float r_gamma = 1.8f; - r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float g_gamma = 1.8f; - g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float b_gamma = 1.8f; - b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + if(unicorn != nullptr) { + // Tear down the old GU instance's hardware resources + teardown(); } - - // for each row: - // for each bcd frame: - // 0: 00110110 // row pixel count (minus one) - // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data - // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align - // 56: xxxxrrrr // row select bits - // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) - // - // .. and back to the start + if(unicorn == nullptr) { + // todo: shouldn't need to do this if things were cleaned up properly but without + // this any attempt to run a micropython script twice will fail + //static bool already_init = false; - // initialise the bcd timing values and row selects in the bitstream - for(uint8_t row = 0; row < HEIGHT; row++) { - for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { - // find the offset of this row and frame in the bitstream - uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; - - p[ 0] = WIDTH - 1; // row pixel count - p[56] = row; // row select - - // set the number of bcd ticks for this frame - uint32_t bcd_ticks = (1 << frame); - p[57] = (bcd_ticks & 0xff) >> 0; - p[58] = (bcd_ticks & 0xff00) >> 8; - p[59] = (bcd_ticks & 0xff0000) >> 16; + // create 14-bit gamma luts + for(uint16_t v = 0; v < 256; v++) { + // gamma correct the provided 0-255 brightness value onto a + // 0-65535 range for the pwm counter + float r_gamma = 1.8f; + r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float g_gamma = 1.8f; + g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float b_gamma = 1.8f; + b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); } - } + + // for each row: + // for each bcd frame: + // 0: 00110110 // row pixel count (minus one) + // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data + // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align + // 56: xxxxrrrr // row select bits + // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) + // + // .. and back to the start - // setup light sensor adc - adc_init(); - adc_gpio_init(LIGHT_SENSOR); - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); + // initialise the bcd timing values and row selects in the bitstream + for(uint8_t row = 0; row < HEIGHT; row++) { + for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { + // find the offset of this row and frame in the bitstream + uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; - gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); - gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); - gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); - - sleep_ms(100); + p[ 0] = WIDTH - 1; // row pixel count + p[56] = row; // row select - // configure full output current in register 2 + // set the number of bcd ticks for this frame + uint32_t bcd_ticks = (1 << frame); + p[57] = (bcd_ticks & 0xff) >> 0; + p[58] = (bcd_ticks & 0xff00) >> 8; + p[59] = (bcd_ticks & 0xff0000) >> 16; + } + } - uint16_t reg1 = 0b1111111111001110; + // setup light sensor adc + adc_init(); + adc_gpio_init(LIGHT_SENSOR); - // clock the register value to the first 9 driver chips - for(int j = 0; j < 9; j++) { + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + + gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); + gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); + gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); + + sleep_ms(100); + + // configure full output current in register 2 + + uint16_t reg1 = 0b1111111111001110; + + // clock the register value to the first 9 driver chips + for(int j = 0; j < 9; j++) { + for(int i = 0; i < 16; i++) { + if(reg1 & (1U << (15 - i))) { + gpio_put(COLUMN_DATA, true); + }else{ + gpio_put(COLUMN_DATA, false); + } + sleep_us(10); + gpio_put(COLUMN_CLOCK, true); + sleep_us(10); + gpio_put(COLUMN_CLOCK, false); + } + } + + // clock the last chip and latch the value for(int i = 0; i < 16; i++) { if(reg1 & (1U << (15 - i))) { gpio_put(COLUMN_DATA, true); }else{ gpio_put(COLUMN_DATA, false); } + sleep_us(10); gpio_put(COLUMN_CLOCK, true); sleep_us(10); gpio_put(COLUMN_CLOCK, false); + + if(i == 4) { + gpio_put(COLUMN_LATCH, true); + } } + gpio_put(COLUMN_LATCH, false); + + + gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); + + // setup button inputs + gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); + gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); + gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); + gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); + + gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); + + gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); + gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); + + gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); + gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); + + // if(already_init) { + // // stop and release the dma channel + // irq_set_enabled(DMA_IRQ_0, false); + // dma_channel_abort(dma_channel); + // dma_channel_wait_for_finish_blocking(dma_channel); + + // dma_channel_set_irq0_enabled(dma_channel, false); + // irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); + // irq_remove_handler(DMA_IRQ_0, dma_complete); + + // dma_channel_unclaim(dma_channel); + + // // release the pio and sm + // pio_sm_unclaim(bitstream_pio, bitstream_sm); + // pio_clear_instruction_memory(bitstream_pio); + // pio_sm_restart(bitstream_pio, bitstream_sm); + // //return; + // } + + + // setup the pio if it has not previously been set up + + bitstream_pio = pio0; + bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); + bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); + + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + pio_gpio_init(bitstream_pio, COLUMN_BLANK); + + pio_gpio_init(bitstream_pio, ROW_BIT_0); + pio_gpio_init(bitstream_pio, ROW_BIT_1); + pio_gpio_init(bitstream_pio, ROW_BIT_2); + pio_gpio_init(bitstream_pio, ROW_BIT_3); + + // set all led driving pins as outputs + pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); + + pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); + + // osr shifts right, autopull on, autopull threshold 8 + sm_config_set_out_shift(&c, true, true, 32); + + // configure out, set, and sideset pins + sm_config_set_out_pins(&c, ROW_BIT_0, 4); + sm_config_set_set_pins(&c, COLUMN_DATA, 3); + sm_config_set_sideset_pins(&c, COLUMN_CLOCK); + + // join fifos as only tx needed (gives 8 deep fifo instead of 4) + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + // setup dma transfer for pixel data to the pio + dma_channel = dma_claim_unused_channel(true); + dma_channel_config config = dma_channel_get_default_config(dma_channel); + channel_config_set_transfer_data_size(&config, DMA_SIZE_32); + channel_config_set_bswap(&config, false); // byte swap to reverse little endian + channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true)); + + dma_channel_configure( + dma_channel, + &config, + &bitstream_pio->txf[bitstream_sm], + NULL, + 0, + false); + + dma_channel_set_irq0_enabled(dma_channel, true); + + pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); + pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); + + irq_add_shared_handler(DMA_IRQ_0, dma_complete, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + irq_set_enabled(DMA_IRQ_0, true); + //irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), true); + //irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); + //irq_set_enabled(DMA_IRQ_0, true); + + unicorn = this; + + next_dma_sequence(); + //dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); + //dma_channel_set_read_addr(dma_channel, bitstream, true); + + //already_init = true; + + // TODO Add audio back in + // setup audio pio program + /*audio_pio = pio0; + audio_sm = pio_claim_unused_sm(audio_pio, true); + audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); + + pio_gpio_init(audio_pio, I2S_DATA); + pio_gpio_init(audio_pio, I2S_BCLK); + pio_gpio_init(audio_pio, I2S_LRCLK); + + audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); + uint32_t system_clock_frequency = clock_get_hz(clk_sys); + uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow + pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); + pio_sm_set_enabled(audio_pio, audio_sm, true); + + + audio_dma_channel = dma_claim_unused_channel(true); + dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); + channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); + //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian + channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); + dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); + //dma_channel_set_irq0_enabled(audio_dma_channel, true); + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ } + // else { + // pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); - // clock the last chip and latch the value - for(int i = 0; i < 16; i++) { - if(reg1 & (1U << (15 - i))) { - gpio_put(COLUMN_DATA, true); - }else{ - gpio_put(COLUMN_DATA, false); - } + // // stop and release the dma channel + // irq_set_enabled(DMA_IRQ_0, false); + // dma_channel_abort(dma_channel); + // dma_channel_wait_for_finish_blocking(dma_channel); - sleep_us(10); - gpio_put(COLUMN_CLOCK, true); - sleep_us(10); - gpio_put(COLUMN_CLOCK, false); - - if(i == 4) { - gpio_put(COLUMN_LATCH, true); - } - } - gpio_put(COLUMN_LATCH, false); - - - gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); - - // setup button inputs - gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); - gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); - gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); - gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); - - gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); - - gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); - gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); - - gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); - gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); - - if(already_init) { - // stop and release the dma channel - irq_set_enabled(DMA_IRQ_0, false); - dma_channel_abort(dma_channel); - dma_channel_wait_for_finish_blocking(dma_channel); - - dma_channel_set_irq0_enabled(dma_channel, false); - irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); - irq_remove_handler(DMA_IRQ_0, dma_complete); - - dma_channel_unclaim(dma_channel); - - // release the pio and sm - pio_sm_unclaim(bitstream_pio, bitstream_sm); - pio_clear_instruction_memory(bitstream_pio); - pio_sm_restart(bitstream_pio, bitstream_sm); - //return; - } - - // setup the pio - bitstream_pio = pio0; - bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); - bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); - - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); - pio_gpio_init(bitstream_pio, COLUMN_BLANK); - - pio_gpio_init(bitstream_pio, ROW_BIT_0); - pio_gpio_init(bitstream_pio, ROW_BIT_1); - pio_gpio_init(bitstream_pio, ROW_BIT_2); - pio_gpio_init(bitstream_pio, ROW_BIT_3); - - // set all led driving pins as outputs - pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); - - pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); - - // osr shifts right, autopull on, autopull threshold 8 - sm_config_set_out_shift(&c, true, true, 32); - - // configure out, set, and sideset pins - sm_config_set_out_pins(&c, ROW_BIT_0, 4); - sm_config_set_set_pins(&c, COLUMN_DATA, 3); - sm_config_set_sideset_pins(&c, COLUMN_CLOCK); - - // join fifos as only tx needed (gives 8 deep fifo instead of 4) - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - - pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); - pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); + // dma_channel_set_irq0_enabled(dma_channel, false); - // setup dma transfer for pixel data to the pio - dma_channel = dma_claim_unused_channel(true); - dma_channel_config config = dma_channel_get_default_config(dma_channel); - channel_config_set_transfer_data_size(&config, DMA_SIZE_32); - channel_config_set_bswap(&config, false); // byte swap to reverse little endian - channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true)); - dma_channel_configure(dma_channel, &config, &bitstream_pio->txf[bitstream_sm], NULL, 0, false); - dma_channel_set_irq0_enabled(dma_channel, true); - irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), true); - irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); - irq_set_enabled(DMA_IRQ_0, true); + // pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); - unicorn = this; + // // setup dma transfer for pixel data to the pio + // irq_set_enabled(DMA_IRQ_0, true); - dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); - dma_channel_set_read_addr(dma_channel, bitstream, true); - - already_init = true; - - - // setup audio pio program - audio_pio = pio0; - audio_sm = pio_claim_unused_sm(audio_pio, true); - audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); - - pio_gpio_init(audio_pio, I2S_DATA); - pio_gpio_init(audio_pio, I2S_BCLK); - pio_gpio_init(audio_pio, I2S_LRCLK); - - audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); - uint32_t system_clock_frequency = clock_get_hz(clk_sys); - uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow - pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - pio_sm_set_enabled(audio_pio, audio_sm, true); - - - audio_dma_channel = dma_claim_unused_channel(true); - dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); - channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); - //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian - channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); - dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); - //dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true); + // dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); + // dma_channel_set_read_addr(dma_channel, bitstream, true); + // } } void GalacticUnicorn::clear() { - for(uint8_t y = 0; y < HEIGHT; y++) { - for(uint8_t x = 0; x < WIDTH; x++) { - set_pixel(x, y, 0); + if(unicorn == this) { + for(uint8_t y = 0; y < HEIGHT; y++) { + for(uint8_t x = 0; x < WIDTH; x++) { + set_pixel(x, y, 0); + } } } } void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { - dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); + if(unicorn == this) { + dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); + } } void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { @@ -388,23 +492,43 @@ namespace pimoroni { void GalacticUnicorn::update(PicoGraphics *graphics) { - if(graphics->pen_type == PicoGraphics::PEN_RGB888) { - uint32_t *p = (uint32_t *)graphics->frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; + if(unicorn == this) { + if(graphics->pen_type == PicoGraphics::PEN_RGB888) { + uint32_t *p = (uint32_t *)graphics->frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; - uint32_t col = *p; - uint8_t r = (col & 0xff0000) >> 16; - uint8_t g = (col & 0x00ff00) >> 8; - uint8_t b = (col & 0x0000ff) >> 0; - p++; + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + p++; - set_pixel(x, y, r, g, b); + set_pixel(x, y, r, g, b); + } + } + else if(graphics->pen_type == PicoGraphics::PEN_RGB565) { + uint16_t *p = (uint16_t *)graphics->frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; + + uint16_t col = __builtin_bswap16(*p); + uint8_t r = (col & 0b1111100000000000) >> 8; + uint8_t g = (col & 0b0000011111100000) >> 3; + uint8_t b = (col & 0b0000000000011111) << 3; + p++; + + set_pixel(x, y, r, g, b); + } } } - else if(graphics->pen_type == PicoGraphics::PEN_RGB565) { - uint16_t *p = (uint16_t *)graphics->frame_buffer; + } + + void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { + if(unicorn == this) { + uint16_t *p = (uint16_t *)graphics.frame_buffer; for(size_t j = 0; j < 53 * 11; j++) { int x = j % 53; int y = j / 53; @@ -420,35 +544,21 @@ namespace pimoroni { } } - void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { - uint16_t *p = (uint16_t *)graphics.frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; - - uint16_t col = __builtin_bswap16(*p); - uint8_t r = (col & 0b1111100000000000) >> 8; - uint8_t g = (col & 0b0000011111100000) >> 3; - uint8_t b = (col & 0b0000000000011111) << 3; - p++; - - set_pixel(x, y, r, g, b); - } - } - void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { - uint32_t *p = (uint32_t *)graphics.frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; + if(unicorn == this) { + uint32_t *p = (uint32_t *)graphics.frame_buffer; + for(size_t j = 0; j < 53 * 11; j++) { + int x = j % 53; + int y = j / 53; - uint32_t col = *p; - uint8_t r = (col & 0xff0000) >> 16; - uint8_t g = (col & 0x00ff00) >> 8; - uint8_t b = (col & 0x0000ff) >> 0; - p++; + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + p++; - set_pixel(x, y, r, g, b); + set_pixel(x, y, r, g, b); + } } } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index c9c8010b..11c28017 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -52,9 +52,9 @@ namespace pimoroni { static const uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); private: - PIO bitstream_pio = pio0; - uint bitstream_sm = 0; - uint bitstream_sm_offset = 0; + static PIO bitstream_pio; + static uint bitstream_sm; + static uint bitstream_sm_offset; PIO audio_pio = pio0; uint audio_sm = 0; @@ -68,6 +68,9 @@ namespace pimoroni { static GalacticUnicorn* unicorn; static void dma_complete(); + private: + void teardown(); + public: ~GalacticUnicorn(); From 739ca71f69def570be842e2ad865ef11097ea8b3 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 4 Aug 2022 13:08:36 +0100 Subject: [PATCH 25/42] Added partial tear down --- .../galactic_unicorn/galactic_unicorn.cpp | 439 +++++++++--------- .../galactic_unicorn/galactic_unicorn.hpp | 1 + 2 files changed, 224 insertions(+), 216 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 9683cb0d..f3d28584 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -141,6 +141,32 @@ namespace pimoroni { irq_remove_handler(DMA_IRQ_0, dma_complete); } + void GalacticUnicorn::partial_teardown() { + pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); + + // Tear down the DMA channel. + // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc + uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); + hw_clear_bits(&dma_hw->inte0, irq0_save); + + dma_hw->abort = 1u << dma_channel; + + // To fence off on in-flight transfers, the BUSY bit should be polled + // rather than the ABORT bit, because the ABORT bit can clear prematurely. + while (dma_hw->ch[dma_channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); + + // Clear the interrupt (if any) and restore the interrupt masks. + dma_hw->ints0 = 1u << dma_channel; + hw_set_bits(&dma_hw->inte0, irq0_save); + + //dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly + //unicorn = nullptr; + + //pio_sm_unclaim(bitstream_pio, bitstream_sm); + //pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); + //irq_remove_handler(DMA_IRQ_0, dma_complete); + } + uint16_t GalacticUnicorn::light() { adc_select_input(2); return adc_read(); @@ -150,255 +176,236 @@ namespace pimoroni { if(unicorn != nullptr) { // Tear down the old GU instance's hardware resources - teardown(); + partial_teardown(); } - if(unicorn == nullptr) { - // todo: shouldn't need to do this if things were cleaned up properly but without - // this any attempt to run a micropython script twice will fail - //static bool already_init = false; + + // todo: shouldn't need to do this if things were cleaned up properly but without + // this any attempt to run a micropython script twice will fail + //static bool already_init = false; - // create 14-bit gamma luts - for(uint16_t v = 0; v < 256; v++) { - // gamma correct the provided 0-255 brightness value onto a - // 0-65535 range for the pwm counter - float r_gamma = 1.8f; - r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float g_gamma = 1.8f; - g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); - float b_gamma = 1.8f; - b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + // create 14-bit gamma luts + for(uint16_t v = 0; v < 256; v++) { + // gamma correct the provided 0-255 brightness value onto a + // 0-65535 range for the pwm counter + float r_gamma = 1.8f; + r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float g_gamma = 1.8f; + g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + float b_gamma = 1.8f; + b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f); + } + + // for each row: + // for each bcd frame: + // 0: 00110110 // row pixel count (minus one) + // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data + // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align + // 56: xxxxrrrr // row select bits + // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) + // + // .. and back to the start + + + // initialise the bcd timing values and row selects in the bitstream + for(uint8_t row = 0; row < HEIGHT; row++) { + for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { + // find the offset of this row and frame in the bitstream + uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; + + p[ 0] = WIDTH - 1; // row pixel count + p[56] = row; // row select + + // set the number of bcd ticks for this frame + uint32_t bcd_ticks = (1 << frame); + p[57] = (bcd_ticks & 0xff) >> 0; + p[58] = (bcd_ticks & 0xff00) >> 8; + p[59] = (bcd_ticks & 0xff0000) >> 16; } - - // for each row: - // for each bcd frame: - // 0: 00110110 // row pixel count (minus one) - // 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data - // 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align - // 56: xxxxrrrr // row select bits - // 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536) - // - // .. and back to the start + } + // setup light sensor adc + adc_init(); + adc_gpio_init(LIGHT_SENSOR); - // initialise the bcd timing values and row selects in the bitstream - for(uint8_t row = 0; row < HEIGHT; row++) { - for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) { - // find the offset of this row and frame in the bitstream - uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)]; + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); - p[ 0] = WIDTH - 1; // row pixel count - p[56] = row; // row select + gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); + gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); + gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); + + sleep_ms(100); - // set the number of bcd ticks for this frame - uint32_t bcd_ticks = (1 << frame); - p[57] = (bcd_ticks & 0xff) >> 0; - p[58] = (bcd_ticks & 0xff00) >> 8; - p[59] = (bcd_ticks & 0xff0000) >> 16; - } - } + // configure full output current in register 2 - // setup light sensor adc - adc_init(); - adc_gpio_init(LIGHT_SENSOR); + uint16_t reg1 = 0b1111111111001110; - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); - - gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); - gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); - gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); - - sleep_ms(100); - - // configure full output current in register 2 - - uint16_t reg1 = 0b1111111111001110; - - // clock the register value to the first 9 driver chips - for(int j = 0; j < 9; j++) { - for(int i = 0; i < 16; i++) { - if(reg1 & (1U << (15 - i))) { - gpio_put(COLUMN_DATA, true); - }else{ - gpio_put(COLUMN_DATA, false); - } - sleep_us(10); - gpio_put(COLUMN_CLOCK, true); - sleep_us(10); - gpio_put(COLUMN_CLOCK, false); - } - } - - // clock the last chip and latch the value + // clock the register value to the first 9 driver chips + for(int j = 0; j < 9; j++) { for(int i = 0; i < 16; i++) { if(reg1 & (1U << (15 - i))) { gpio_put(COLUMN_DATA, true); }else{ gpio_put(COLUMN_DATA, false); } - sleep_us(10); gpio_put(COLUMN_CLOCK, true); sleep_us(10); gpio_put(COLUMN_CLOCK, false); - - if(i == 4) { - gpio_put(COLUMN_LATCH, true); - } } - gpio_put(COLUMN_LATCH, false); - - - gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); - - // setup button inputs - gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); - gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); - gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); - gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); - - gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); - - gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); - gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); - - gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); - gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); - - // if(already_init) { - // // stop and release the dma channel - // irq_set_enabled(DMA_IRQ_0, false); - // dma_channel_abort(dma_channel); - // dma_channel_wait_for_finish_blocking(dma_channel); - - // dma_channel_set_irq0_enabled(dma_channel, false); - // irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); - // irq_remove_handler(DMA_IRQ_0, dma_complete); - - // dma_channel_unclaim(dma_channel); - - // // release the pio and sm - // pio_sm_unclaim(bitstream_pio, bitstream_sm); - // pio_clear_instruction_memory(bitstream_pio); - // pio_sm_restart(bitstream_pio, bitstream_sm); - // //return; - // } - - - // setup the pio if it has not previously been set up - - bitstream_pio = pio0; - bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); - bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); - - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); - pio_gpio_init(bitstream_pio, COLUMN_BLANK); - - pio_gpio_init(bitstream_pio, ROW_BIT_0); - pio_gpio_init(bitstream_pio, ROW_BIT_1); - pio_gpio_init(bitstream_pio, ROW_BIT_2); - pio_gpio_init(bitstream_pio, ROW_BIT_3); - - // set all led driving pins as outputs - pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); - - pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); - - // osr shifts right, autopull on, autopull threshold 8 - sm_config_set_out_shift(&c, true, true, 32); - - // configure out, set, and sideset pins - sm_config_set_out_pins(&c, ROW_BIT_0, 4); - sm_config_set_set_pins(&c, COLUMN_DATA, 3); - sm_config_set_sideset_pins(&c, COLUMN_CLOCK); - - // join fifos as only tx needed (gives 8 deep fifo instead of 4) - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - - // setup dma transfer for pixel data to the pio - dma_channel = dma_claim_unused_channel(true); - dma_channel_config config = dma_channel_get_default_config(dma_channel); - channel_config_set_transfer_data_size(&config, DMA_SIZE_32); - channel_config_set_bswap(&config, false); // byte swap to reverse little endian - channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true)); - - dma_channel_configure( - dma_channel, - &config, - &bitstream_pio->txf[bitstream_sm], - NULL, - 0, - false); - - dma_channel_set_irq0_enabled(dma_channel, true); - - pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); - pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); - - irq_add_shared_handler(DMA_IRQ_0, dma_complete, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); - irq_set_enabled(DMA_IRQ_0, true); - //irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), true); - //irq_set_exclusive_handler(DMA_IRQ_0, dma_complete); - //irq_set_enabled(DMA_IRQ_0, true); - - unicorn = this; - - next_dma_sequence(); - //dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); - //dma_channel_set_read_addr(dma_channel, bitstream, true); - - //already_init = true; - - // TODO Add audio back in - // setup audio pio program - /*audio_pio = pio0; - audio_sm = pio_claim_unused_sm(audio_pio, true); - audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); - - pio_gpio_init(audio_pio, I2S_DATA); - pio_gpio_init(audio_pio, I2S_BCLK); - pio_gpio_init(audio_pio, I2S_LRCLK); - - audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); - uint32_t system_clock_frequency = clock_get_hz(clk_sys); - uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow - pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - pio_sm_set_enabled(audio_pio, audio_sm, true); - - - audio_dma_channel = dma_claim_unused_channel(true); - dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); - channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); - //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian - channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); - dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); - //dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ } - // else { - // pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); + // clock the last chip and latch the value + for(int i = 0; i < 16; i++) { + if(reg1 & (1U << (15 - i))) { + gpio_put(COLUMN_DATA, true); + }else{ + gpio_put(COLUMN_DATA, false); + } + + sleep_us(10); + gpio_put(COLUMN_CLOCK, true); + sleep_us(10); + gpio_put(COLUMN_CLOCK, false); + + if(i == 4) { + gpio_put(COLUMN_LATCH, true); + } + } + gpio_put(COLUMN_LATCH, false); + + + gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); + + // setup button inputs + gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A); + gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B); + gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C); + gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D); + + gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP); + + gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP); + gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN); + + gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); + gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); + + // if(already_init) { // // stop and release the dma channel // irq_set_enabled(DMA_IRQ_0, false); // dma_channel_abort(dma_channel); // dma_channel_wait_for_finish_blocking(dma_channel); // dma_channel_set_irq0_enabled(dma_channel, false); + // irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); + // irq_remove_handler(DMA_IRQ_0, dma_complete); + // dma_channel_unclaim(dma_channel); - // pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); - - // // setup dma transfer for pixel data to the pio - // irq_set_enabled(DMA_IRQ_0, true); - - // dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); - // dma_channel_set_read_addr(dma_channel, bitstream, true); + // // release the pio and sm + // pio_sm_unclaim(bitstream_pio, bitstream_sm); + // pio_clear_instruction_memory(bitstream_pio); + // pio_sm_restart(bitstream_pio, bitstream_sm); + // //return; // } + + // setup the pio if it has not previously been set up + bitstream_pio = pio0; + if(unicorn == nullptr) { + bitstream_sm = pio_claim_unused_sm(bitstream_pio, true); + bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program); + } + + pio_gpio_init(bitstream_pio, COLUMN_CLOCK); + pio_gpio_init(bitstream_pio, COLUMN_DATA); + pio_gpio_init(bitstream_pio, COLUMN_LATCH); + pio_gpio_init(bitstream_pio, COLUMN_BLANK); + + pio_gpio_init(bitstream_pio, ROW_BIT_0); + pio_gpio_init(bitstream_pio, ROW_BIT_1); + pio_gpio_init(bitstream_pio, ROW_BIT_2); + pio_gpio_init(bitstream_pio, ROW_BIT_3); + + // set all led driving pins as outputs + pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); + + pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); + + // osr shifts right, autopull on, autopull threshold 8 + sm_config_set_out_shift(&c, true, true, 32); + + // configure out, set, and sideset pins + sm_config_set_out_pins(&c, ROW_BIT_0, 4); + sm_config_set_set_pins(&c, COLUMN_DATA, 3); + sm_config_set_sideset_pins(&c, COLUMN_CLOCK); + + // join fifos as only tx needed (gives 8 deep fifo instead of 4) + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + // setup dma transfer for pixel data to the pio + if(unicorn == nullptr) { + dma_channel = dma_claim_unused_channel(true); + } + dma_channel_config config = dma_channel_get_default_config(dma_channel); + channel_config_set_transfer_data_size(&config, DMA_SIZE_32); + channel_config_set_bswap(&config, false); // byte swap to reverse little endian + channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true)); + + dma_channel_configure( + dma_channel, + &config, + &bitstream_pio->txf[bitstream_sm], + NULL, + 0, + false); + + dma_channel_set_irq0_enabled(dma_channel, true); + + pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); + + pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); + + if(unicorn == nullptr) { + irq_add_shared_handler(DMA_IRQ_0, dma_complete, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + irq_set_enabled(DMA_IRQ_0, true); + } + + unicorn = this; + + next_dma_sequence(); + + //already_init = true; + + // TODO Add audio back in + // setup audio pio program + /*audio_pio = pio0; + audio_sm = pio_claim_unused_sm(audio_pio, true); + audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); + + pio_gpio_init(audio_pio, I2S_DATA); + pio_gpio_init(audio_pio, I2S_BCLK); + pio_gpio_init(audio_pio, I2S_LRCLK); + + audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); + uint32_t system_clock_frequency = clock_get_hz(clk_sys); + uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow + pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); + pio_sm_set_enabled(audio_pio, audio_sm, true); + + + audio_dma_channel = dma_claim_unused_channel(true); + dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); + channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_16); + //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian + channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); + dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); + //dma_channel_set_irq0_enabled(audio_dma_channel, true); + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ + } void GalacticUnicorn::clear() { diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 11c28017..e1a3f2ef 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -70,6 +70,7 @@ namespace pimoroni { private: void teardown(); + void partial_teardown(); public: ~GalacticUnicorn(); From b2e4e16fab97ffa3cc69cb1444f328abdb1766dd Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 9 Aug 2022 20:32:14 +0100 Subject: [PATCH 26/42] Cleanup of GU and fix for flashes on MP soft reset --- examples/galactic_unicorn/balls.cpp | 5 +- examples/galactic_unicorn/demo.cpp | 5 +- .../eighties_super_computer.cpp | 5 +- examples/galactic_unicorn/feature_test.cpp | 25 ++- examples/galactic_unicorn/fire_effect.cpp | 11 +- examples/galactic_unicorn/lava_lamp.cpp | 4 +- .../galactic_unicorn/nostalgia_prompt.cpp | 10 +- examples/galactic_unicorn/rainbow.cpp | 18 +- examples/galactic_unicorn/scroll_text.cpp | 6 +- .../galactic_unicorn/galactic_unicorn.cpp | 168 +++--------------- .../galactic_unicorn/galactic_unicorn.hpp | 14 +- .../galactic_unicorn/galactic_unicorn.c | 2 - .../galactic_unicorn/galactic_unicorn.cpp | 73 +------- .../galactic_unicorn/galactic_unicorn.h | 2 - 14 files changed, 74 insertions(+), 274 deletions(-) diff --git a/examples/galactic_unicorn/balls.cpp b/examples/galactic_unicorn/balls.cpp index 2012d4fe..65c2aad4 100644 --- a/examples/galactic_unicorn/balls.cpp +++ b/examples/galactic_unicorn/balls.cpp @@ -32,7 +32,6 @@ int main() { graphics.set_pen(0, 0, 0); graphics.clear(); - for(int y = 0; y < 12; y++) { for(int x = 0; x < 53; x++) { if(heat[x][y] > 0.5f) { @@ -63,7 +62,7 @@ int main() { } } - galactic_unicorn.update(graphics); + galactic_unicorn.update(&graphics); // clear the bottom row and then add a new fire seed to it for(int x = 0; x < 53; x++) { @@ -80,7 +79,7 @@ int main() { heat[px + 1][12] = 1.0f; heat[px - 1][12] = 1.0f; } - + sleep_ms(50); } diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp index f65b15e5..aecad0f6 100644 --- a/examples/galactic_unicorn/demo.cpp +++ b/examples/galactic_unicorn/demo.cpp @@ -185,14 +185,15 @@ gpio_set_function(28, GPIO_FUNC_SIO); } }*/ - galactic_unicorn.set_pixel(x, y, 255, 255, 255); + graphics.set_pen(255, 255, 255); + graphics.pixel(Point(x, y)); + galactic_unicorn.update(&graphics); /*i++; graphics.set_pen(0, 0, 0); if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} graphics.clear(); - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} diff --git a/examples/galactic_unicorn/eighties_super_computer.cpp b/examples/galactic_unicorn/eighties_super_computer.cpp index fd6271ae..0ad62580 100644 --- a/examples/galactic_unicorn/eighties_super_computer.cpp +++ b/examples/galactic_unicorn/eighties_super_computer.cpp @@ -39,7 +39,6 @@ int main() { graphics.set_pen(0, 0, 0); graphics.clear(); - for(int y = 0; y < 11; y++) { for(int x = 0; x < 53; x++) { if(age[x][y] < lifetime[x][y] * 0.3f) { @@ -60,8 +59,8 @@ int main() { } } - galactic_unicorn.update(graphics); - + galactic_unicorn.update(&graphics); + sleep_ms(10); } diff --git a/examples/galactic_unicorn/feature_test.cpp b/examples/galactic_unicorn/feature_test.cpp index c2016afb..c406f8b9 100644 --- a/examples/galactic_unicorn/feature_test.cpp +++ b/examples/galactic_unicorn/feature_test.cpp @@ -72,7 +72,6 @@ int main() { galactic_unicorn.init(); - //galactic_unicorn.set_brightness(0.5f); while(true) { @@ -113,7 +112,7 @@ int main() { } printf("%d\n", galactic_unicorn.light()); - + std::string text = ""; static bool was_a_pressed = false; @@ -127,37 +126,37 @@ int main() { } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_A)) { - text = "Button A"; + text = "Button A"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_B)) { - text = "Button B"; + text = "Button B"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_C)) { - text = "Button C"; + text = "Button C"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_D)) { - text = "Button D"; + text = "Button D"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_VOLUME_UP)) { - text = "Louder!"; + text = "Louder!"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_VOLUME_DOWN)) { - text = "quieter"; + text = "quieter"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_BRIGHTNESS_UP)) { - text = "Brighter!"; + text = "Brighter!"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_BRIGHTNESS_DOWN)) { - text = "Darker"; + text = "Darker"; } if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_SLEEP)) { - text = "Zzz... zzz..."; + text = "Zzz... zzz..."; } outline_text(text); - galactic_unicorn.update(graphics); - + galactic_unicorn.update(&graphics); + sleep_ms(50); } diff --git a/examples/galactic_unicorn/fire_effect.cpp b/examples/galactic_unicorn/fire_effect.cpp index b5ee4bfd..4cda71a0 100644 --- a/examples/galactic_unicorn/fire_effect.cpp +++ b/examples/galactic_unicorn/fire_effect.cpp @@ -63,7 +63,7 @@ int main() { height = 55; memset(heat, 0, sizeof(heat)); } - + for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { float value = get(x, y); @@ -78,13 +78,12 @@ int main() { }else if(value > 0.22f) { graphics.set_pen(20, 20, 20); } - + if(landscape) { - graphics.pixel(Point(x, y)); + graphics.pixel(Point(x, y)); }else{ - graphics.pixel(Point(y, x)); + graphics.pixel(Point(y, x)); } - // update this pixel by averaging the below pixels float average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0f; @@ -97,7 +96,7 @@ int main() { } } - galactic_unicorn.update(graphics); + galactic_unicorn.update(&graphics); // clear the bottom row and then add a new fire seed to it for(int x = 0; x < width; x++) { diff --git a/examples/galactic_unicorn/lava_lamp.cpp b/examples/galactic_unicorn/lava_lamp.cpp index 0b5819c1..f4b5dc75 100644 --- a/examples/galactic_unicorn/lava_lamp.cpp +++ b/examples/galactic_unicorn/lava_lamp.cpp @@ -66,7 +66,7 @@ int main() { if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { galactic_unicorn.adjust_brightness(-0.01); } - + uint start_ms = to_ms_since_boot(get_absolute_time()); // calculate the influence of each blob on the liquid based @@ -141,7 +141,7 @@ int main() { printf("rendering took %dms\n", end_ms - start_ms); - galactic_unicorn.update(graphics); + galactic_unicorn.update(&graphics); } return 0; diff --git a/examples/galactic_unicorn/nostalgia_prompt.cpp b/examples/galactic_unicorn/nostalgia_prompt.cpp index e36e85e1..0bc70f66 100644 --- a/examples/galactic_unicorn/nostalgia_prompt.cpp +++ b/examples/galactic_unicorn/nostalgia_prompt.cpp @@ -88,7 +88,7 @@ int main() { }else if(prompt == PROMPT_BBC_MICRO){ graphics.set_pen(0, 0, 0); } - + graphics.clear(); if(prompt == PROMPT_C64) { @@ -103,18 +103,18 @@ int main() { for(size_t x = 0; x < image[y].length(); x++) { // draw the prompt text if(image[y][x] == 'O') { - graphics.pixel(Point(x, y + 1)); + graphics.pixel(Point(x, y + 1)); } // draw the caret blinking if(image[y][x] == 'X' && (time_ms / 300) % 2) { - graphics.pixel(Point(x, y + 1)); + graphics.pixel(Point(x, y + 1)); } } } - galactic_unicorn.update(graphics); - + galactic_unicorn.update(&graphics); + sleep_ms(10); } diff --git a/examples/galactic_unicorn/rainbow.cpp b/examples/galactic_unicorn/rainbow.cpp index 52cc4e59..8ae3e30a 100644 --- a/examples/galactic_unicorn/rainbow.cpp +++ b/examples/galactic_unicorn/rainbow.cpp @@ -86,8 +86,8 @@ int main() { stars[i].a = i; } -gpio_set_function(28, GPIO_FUNC_SIO); - gpio_set_dir(28, GPIO_OUT); + gpio_set_function(28, GPIO_FUNC_SIO); + gpio_set_dir(28, GPIO_OUT); for(int i = 0; i < 10; i++) { gpio_put(28, !gpio_get(28)); @@ -105,7 +105,7 @@ gpio_set_function(28, GPIO_FUNC_SIO); bool x_pressed = false; bool y_pressed = false; */ -graphics.set_font("bitmap8"); + graphics.set_font("bitmap8"); @@ -122,8 +122,8 @@ graphics.set_font("bitmap8"); while(true) { if(animate) { - i += speed; - } + i += speed; + } if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { curve += 0.05; @@ -156,7 +156,6 @@ graphics.set_font("bitmap8"); animate = true; } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) { stripe_width += 0.05f; stripe_width = stripe_width >= 10.0f ? 10.0f : stripe_width; @@ -178,19 +177,16 @@ graphics.set_font("bitmap8"); for(int x = 0; x < 53; x++) { for(int y = 0; y < 11; y++) { int v = ((sin((x + y) / stripe_width + (sin((y * 3.1415927f * 2.0f) / 11.0f) * curve) + i / 15.0f) + 1.5f) / 2.5f) * 255.0f; - uint8_t r = (hue_map[x][0] * v) / 256; uint8_t g = (hue_map[x][1] * v) / 256; uint8_t b = (hue_map[x][2] * v) / 256; graphics.set_pen(r, g, b); - graphics.pixel(Point(x, y)); + graphics.pixel(Point(x, y)); } } - - galactic_unicorn.update(graphics); - + galactic_unicorn.update(&graphics); printf("%d\n", galactic_unicorn.light()); sleep_ms(20); diff --git a/examples/galactic_unicorn/scroll_text.cpp b/examples/galactic_unicorn/scroll_text.cpp index d90e6f77..2d302670 100644 --- a/examples/galactic_unicorn/scroll_text.cpp +++ b/examples/galactic_unicorn/scroll_text.cpp @@ -41,7 +41,7 @@ int main() { graphics.set_pen(0, 0, 0); graphics.clear(); - + ok_color::HSL hsl{scroll / 100.0f, 1.0f, 0.5f}; ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); graphics.set_pen(rgb.r * 255, rgb.g * 255, rgb.b * 255); @@ -59,8 +59,8 @@ int main() { } }*/ - galactic_unicorn.update(graphics); - + galactic_unicorn.update(&graphics); + sleep_ms(10); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index f3d28584..37cde4c8 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -69,81 +69,26 @@ namespace pimoroni { } GalacticUnicorn::~GalacticUnicorn() { - // if(unicorn == this) { - // // stop and release the dma channel - // irq_set_enabled(DMA_IRQ_0, false); - // dma_channel_set_irq0_enabled(dma_channel, false); - // irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); - // irq_remove_handler(DMA_IRQ_0, dma_complete); - - // dma_channel_wait_for_finish_blocking(dma_channel); - // dma_channel_unclaim(dma_channel); - - // // release the pio and sm - // pio_sm_unclaim(bitstream_pio, bitstream_sm); - // pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); - // //pio_sm_restart(bitstream_pio, bitstream_sm); - - // unicorn = nullptr; - // } - if(unicorn == this) { - teardown(); - /*pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); - - // Tear down the DMA channel. - // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc - uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); - hw_clear_bits(&dma_hw->inte0, irq0_save); - - dma_hw->abort = 1u << dma_channel; - - // To fence off on in-flight transfers, the BUSY bit should be polled - // rather than the ABORT bit, because the ABORT bit can clear prematurely. - while (dma_hw->ch[dma_channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); - - // Clear the interrupt (if any) and restore the interrupt masks. - dma_hw->ints0 = 1u << dma_channel; - hw_set_bits(&dma_hw->inte0, irq0_save); + partial_teardown(); dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly unicorn = nullptr; pio_sm_unclaim(bitstream_pio, bitstream_sm); pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); - irq_remove_handler(DMA_IRQ_0, dma_complete);*/ + irq_remove_handler(DMA_IRQ_0, dma_complete); } } - void GalacticUnicorn::teardown() { - pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); - - // Tear down the DMA channel. - // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc - uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); - hw_clear_bits(&dma_hw->inte0, irq0_save); - - dma_hw->abort = 1u << dma_channel; - - // To fence off on in-flight transfers, the BUSY bit should be polled - // rather than the ABORT bit, because the ABORT bit can clear prematurely. - while (dma_hw->ch[dma_channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); - - // Clear the interrupt (if any) and restore the interrupt masks. - dma_hw->ints0 = 1u << dma_channel; - hw_set_bits(&dma_hw->inte0, irq0_save); - - dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly - unicorn = nullptr; - - pio_sm_unclaim(bitstream_pio, bitstream_sm); - pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); - irq_remove_handler(DMA_IRQ_0, dma_complete); - } - void GalacticUnicorn::partial_teardown() { + pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); + // Make sure the display is off and switch it to an invisible row, to be safe + const uint pins_to_set = 1 << COLUMN_BLANK | 0b1111 << ROW_BIT_0; + pio_sm_set_pins_with_mask(bitstream_pio, bitstream_sm, pins_to_set, pins_to_set); + // Tear down the DMA channel. // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); @@ -158,13 +103,6 @@ namespace pimoroni { // Clear the interrupt (if any) and restore the interrupt masks. dma_hw->ints0 = 1u << dma_channel; hw_set_bits(&dma_hw->inte0, irq0_save); - - //dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly - //unicorn = nullptr; - - //pio_sm_unclaim(bitstream_pio, bitstream_sm); - //pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); - //irq_remove_handler(DMA_IRQ_0, dma_complete); } uint16_t GalacticUnicorn::light() { @@ -179,10 +117,6 @@ namespace pimoroni { partial_teardown(); } - - // todo: shouldn't need to do this if things were cleaned up properly but without - // this any attempt to run a micropython script twice will fail - //static bool already_init = false; // create 14-bit gamma luts for(uint16_t v = 0; v < 256; v++) { @@ -228,14 +162,17 @@ namespace pimoroni { adc_init(); adc_gpio_init(LIGHT_SENSOR); - pio_gpio_init(bitstream_pio, COLUMN_CLOCK); - pio_gpio_init(bitstream_pio, COLUMN_DATA); - pio_gpio_init(bitstream_pio, COLUMN_LATCH); - gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false); gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false); gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false); - + gpio_init(COLUMN_BLANK); gpio_set_dir(COLUMN_BLANK, GPIO_OUT); gpio_put(COLUMN_BLANK, true); + + // initialise the row select, and set them to a non-visible row to avoid flashes during setup + gpio_init(ROW_BIT_0); gpio_set_dir(ROW_BIT_0, GPIO_OUT); gpio_put(ROW_BIT_0, true); + gpio_init(ROW_BIT_1); gpio_set_dir(ROW_BIT_1, GPIO_OUT); gpio_put(ROW_BIT_1, true); + gpio_init(ROW_BIT_2); gpio_set_dir(ROW_BIT_2, GPIO_OUT); gpio_put(ROW_BIT_2, true); + gpio_init(ROW_BIT_3); gpio_set_dir(ROW_BIT_3, GPIO_OUT); gpio_put(ROW_BIT_3, true); + sleep_ms(100); // configure full output current in register 2 @@ -276,6 +213,11 @@ namespace pimoroni { } gpio_put(COLUMN_LATCH, false); + // reapply the blank as the above seems to cause a slight glow. + // Note, this will produce a brief flash if a visible row is selected (which it shouldn't be) + gpio_put(COLUMN_BLANK, false); + sleep_us(10); + gpio_put(COLUMN_BLANK, true); gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true); @@ -293,26 +235,6 @@ namespace pimoroni { gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP); gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN); - // if(already_init) { - // // stop and release the dma channel - // irq_set_enabled(DMA_IRQ_0, false); - // dma_channel_abort(dma_channel); - // dma_channel_wait_for_finish_blocking(dma_channel); - - // dma_channel_set_irq0_enabled(dma_channel, false); - // irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false); - // irq_remove_handler(DMA_IRQ_0, dma_complete); - - // dma_channel_unclaim(dma_channel); - - // // release the pio and sm - // pio_sm_unclaim(bitstream_pio, bitstream_sm); - // pio_clear_instruction_memory(bitstream_pio); - // pio_sm_restart(bitstream_pio, bitstream_sm); - // //return; - // } - - // setup the pio if it has not previously been set up bitstream_pio = pio0; if(unicorn == nullptr) { @@ -330,7 +252,10 @@ namespace pimoroni { pio_gpio_init(bitstream_pio, ROW_BIT_2); pio_gpio_init(bitstream_pio, ROW_BIT_3); - // set all led driving pins as outputs + // set the blank and row pins to be high, then set all led driving pins as outputs. + // This order is important to avoid a momentary flash + const uint pins_to_set = 1 << COLUMN_BLANK | 0b1111 << ROW_BIT_0; + pio_sm_set_pins_with_mask(bitstream_pio, bitstream_sm, pins_to_set, pins_to_set); pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true); pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset); @@ -378,8 +303,6 @@ namespace pimoroni { next_dma_sequence(); - //already_init = true; - // TODO Add audio back in // setup audio pio program /*audio_pio = pio0; @@ -412,7 +335,7 @@ namespace pimoroni { if(unicorn == this) { for(uint8_t y = 0; y < HEIGHT; y++) { for(uint8_t x = 0; x < WIDTH; x++) { - set_pixel(x, y, 0); + set_pixel(x, y, 0, 0, 0); } } } @@ -465,10 +388,6 @@ namespace pimoroni { } } - void GalacticUnicorn::set_pixel(int x, int y, uint8_t v) { - set_pixel(x, y, v, v, v); - } - void GalacticUnicorn::set_brightness(float value) { value = value < 0.0f ? 0.0f : value; value = value > 1.0f ? 1.0f : value; @@ -497,7 +416,6 @@ namespace pimoroni { this->set_volume(this->get_volume() + delta); } - void GalacticUnicorn::update(PicoGraphics *graphics) { if(unicorn == this) { if(graphics->pen_type == PicoGraphics::PEN_RGB888) { @@ -533,42 +451,6 @@ namespace pimoroni { } } - void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) { - if(unicorn == this) { - uint16_t *p = (uint16_t *)graphics.frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; - - uint16_t col = __builtin_bswap16(*p); - uint8_t r = (col & 0b1111100000000000) >> 8; - uint8_t g = (col & 0b0000011111100000) >> 3; - uint8_t b = (col & 0b0000000000011111) << 3; - p++; - - set_pixel(x, y, r, g, b); - } - } - } - - void GalacticUnicorn::update(PicoGraphics_PenRGB888 &graphics) { - if(unicorn == this) { - uint32_t *p = (uint32_t *)graphics.frame_buffer; - for(size_t j = 0; j < 53 * 11; j++) { - int x = j % 53; - int y = j / 53; - - uint32_t col = *p; - uint8_t r = (col & 0xff0000) >> 16; - uint8_t g = (col & 0x00ff00) >> 8; - uint8_t b = (col & 0x0000ff) >> 0; - p++; - - set_pixel(x, y, r, g, b); - } - } - } - bool GalacticUnicorn::is_pressed(uint8_t button) { return !gpio_get(button); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index e1a3f2ef..bc012fd1 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -68,10 +68,6 @@ namespace pimoroni { static GalacticUnicorn* unicorn; static void dma_complete(); - private: - void teardown(); - void partial_teardown(); - public: ~GalacticUnicorn(); @@ -81,8 +77,8 @@ namespace pimoroni { void clear(); void update(PicoGraphics *graphics); - void update(PicoGraphics_PenRGB565 &graphics); - void update(PicoGraphics_PenRGB888 &graphics); + //void update(PicoGraphics_PenRGB565 &graphics); + //void update(PicoGraphics_PenRGB888 &graphics); void set_brightness(float value); float get_brightness(); @@ -92,9 +88,10 @@ namespace pimoroni { float get_volume(); void adjust_volume(float delta); - + private: void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b); - void set_pixel(int x, int y, uint8_t v); + //void set_pixel(int x, int y, uint8_t v); + public: uint16_t light(); @@ -104,6 +101,7 @@ namespace pimoroni { private: void next_dma_sequence(); + void partial_teardown(); }; } \ No newline at end of file diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 1e2a8a82..6a6273da 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -11,7 +11,6 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_brightness_obj, GalacticUnicorn MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_set_volume_obj, GalacticUnicorn_set_volume); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_volume_obj, GalacticUnicorn_get_volume); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adjust_volume); -MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_set_pixel_obj, 4, GalacticUnicorn_set_pixel); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); //MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_play_sample_obj, 1, GalacticUnicorn_play_sample); @@ -27,7 +26,6 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_volume), MP_ROM_PTR(&GalacticUnicorn_set_volume_obj) }, { MP_ROM_QSTR(MP_QSTR_get_volume), MP_ROM_PTR(&GalacticUnicorn_get_volume_obj) }, { MP_ROM_QSTR(MP_QSTR_adjust_volume), MP_ROM_PTR(&GalacticUnicorn_adjust_volume_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&GalacticUnicorn_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) }, { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, //{ MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 4a6e9efa..e758017c 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -19,7 +19,6 @@ extern "C" { typedef struct _GalacticUnicorn_obj_t { mp_obj_base_t base; GalacticUnicorn* galactic; - //PicoGraphics_PenRGB888* graphics; } _GalacticUnicorn_obj_t; typedef struct _ModPicoGraphics_obj_t { @@ -68,26 +67,10 @@ mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size GalacticUnicorn *galactic = m_new_class(GalacticUnicorn); galactic->init(); - //if(!galactic->init()) { - //m_del_class(GalacticUnicorn, galactic); - //mp_raise_msg(&mp_type_RuntimeError, "unable to allocate the hardware resources needed to initialise this GalacticUnicorn. Try running `import gc` followed by `gc.collect()` before creating it"); - //} - //PicoGraphics_PenRGB888 *graphics = m_new_class(PicoGraphics_PenRGB888, 53, 11, m_new(uint8_t, PicoGraphics_PenRGB888::buffer_size(53, 11))); - - /*for(int y = 0; y < 11; y++) { - for(int x = 0; x < 53; x++) { -// graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52); - graphics->set_pen(x, x, x); - graphics->pixel(Point(x, y)); - } - }*/ - - //galactic->update(*graphics); self = m_new_obj_with_finaliser(_GalacticUnicorn_obj_t); self->base.type = &GalacticUnicorn_type; self->galactic = galactic; - //self->graphics = graphics; return MP_OBJ_FROM_PTR(self); } @@ -97,7 +80,6 @@ mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); m_del_class(GalacticUnicorn, self->galactic); - //m_del_class(PicoGraphics_PenRGB888, self->graphics); return mp_const_none; } @@ -152,61 +134,10 @@ extern mp_obj_t GalacticUnicorn_adjust_volume(mp_obj_t self_in, mp_obj_t delta) return mp_const_none; } -extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - if(n_args <= 4) { - enum { ARG_self, ARG_x, ARG_y, ARG_v }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_v, MP_ARG_REQUIRED | MP_ARG_INT } - }; - - // Parse args. - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - int x = args[ARG_x].u_int; - int y = args[ARG_y].u_int; - int v = args[ARG_v].u_int; - - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t); - //self->graphics->set_pen(v, v, v); - //self->graphics->set_pixel(Point(x, y)); - self->galactic->set_pixel(x, y, v); - } - else { - enum { ARG_self, ARG_x, ARG_y, ARG_r, ARG_g, ARG_b }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_g, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_b, MP_ARG_REQUIRED | MP_ARG_INT } - }; - - // Parse args. - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - int x = args[ARG_x].u_int; - int y = args[ARG_y].u_int; - int r = args[ARG_r].u_int; - int g = args[ARG_g].u_int; - int b = args[ARG_b].u_int; - - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t); - //self->graphics->set_pen(r, g, b); - //self->graphics->set_pixel(Point(x, y)); - self->galactic->set_pixel(x, y, r, g, b); - } - return mp_const_none; -} extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in) { -//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - return mp_const_none; + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + return mp_obj_new_float(self->galactic->light()); } extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button) { diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 8f147e05..8c4aa2be 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -20,8 +20,6 @@ extern mp_obj_t GalacticUnicorn_set_volume(mp_obj_t self_in, mp_obj_t value); extern mp_obj_t GalacticUnicorn_get_volume(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_adjust_volume(mp_obj_t self_in, mp_obj_t delta); -extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -//extern mp_obj_t GalacticUnicorn_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); From 4551c991fbe7ecb8356ff7cced9eb11918666244 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 11 Aug 2022 14:18:33 +0100 Subject: [PATCH 27/42] Re-added audio PIO and made it's restart cleaner --- .../galactic_unicorn/galactic_unicorn.cpp | 56 ++++++++++++------- .../galactic_unicorn/galactic_unicorn.hpp | 4 +- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 37cde4c8..6f85a0f3 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -82,27 +82,15 @@ namespace pimoroni { } void GalacticUnicorn::partial_teardown() { - + // Stop the bitstream SM pio_sm_set_enabled(bitstream_pio, bitstream_sm, false); // Make sure the display is off and switch it to an invisible row, to be safe const uint pins_to_set = 1 << COLUMN_BLANK | 0b1111 << ROW_BIT_0; pio_sm_set_pins_with_mask(bitstream_pio, bitstream_sm, pins_to_set, pins_to_set); - // Tear down the DMA channel. - // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc - uint32_t irq0_save = dma_hw->inte0 & (1u << dma_channel); - hw_clear_bits(&dma_hw->inte0, irq0_save); - - dma_hw->abort = 1u << dma_channel; - - // To fence off on in-flight transfers, the BUSY bit should be polled - // rather than the ABORT bit, because the ABORT bit can clear prematurely. - while (dma_hw->ch[dma_channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); - - // Clear the interrupt (if any) and restore the interrupt masks. - dma_hw->ints0 = 1u << dma_channel; - hw_set_bits(&dma_hw->inte0, irq0_save); + // Abort any in-progress DMA transfer + dma_safe_abort(dma_channel); } uint16_t GalacticUnicorn::light() { @@ -303,9 +291,9 @@ namespace pimoroni { next_dma_sequence(); - // TODO Add audio back in + // TODO Made audio tear down cleanly // setup audio pio program - /*audio_pio = pio0; + audio_pio = pio0; audio_sm = pio_claim_unused_sm(audio_pio, true); audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); @@ -317,7 +305,7 @@ namespace pimoroni { uint32_t system_clock_frequency = clock_get_hz(clk_sys); uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - pio_sm_set_enabled(audio_pio, audio_sm, true); + //pio_sm_set_enabled(audio_pio, audio_sm, true); // No need to enable the SM until audio is playing audio_dma_channel = dma_claim_unused_channel(true); @@ -327,8 +315,7 @@ namespace pimoroni { channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); //dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/ - + irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true); } void GalacticUnicorn::clear() { @@ -341,8 +328,37 @@ namespace pimoroni { } } + void GalacticUnicorn::dma_safe_abort(uint channel) { + // Tear down the DMA channel. + // This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc + uint32_t irq0_save = dma_hw->inte0 & (1u << channel); + hw_clear_bits(&dma_hw->inte0, irq0_save); + + dma_hw->abort = 1u << channel; + + // To fence off on in-flight transfers, the BUSY bit should be polled + // rather than the ABORT bit, because the ABORT bit can clear prematurely. + while (dma_hw->ch[channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents(); + + // Clear the interrupt (if any) and restore the interrupt masks. + dma_hw->ints0 = 1u << channel; + hw_set_bits(&dma_hw->inte0, irq0_save); + } + void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { if(unicorn == this) { + // Stop the audio SM + pio_sm_set_enabled(audio_pio, audio_sm, false); + + // Reset the I2S pins to avoid popping when audio is suddenly stopped + const uint pins_to_set = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK; + pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_set); + + // Abort any in-progress DMA transfer + dma_safe_abort(audio_dma_channel); + + // Restart the audio SM and start a new DMA transfer + pio_sm_set_enabled(audio_pio, audio_sm, true); dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); } } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index bc012fd1..fa4756ea 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -77,8 +77,6 @@ namespace pimoroni { void clear(); void update(PicoGraphics *graphics); - //void update(PicoGraphics_PenRGB565 &graphics); - //void update(PicoGraphics_PenRGB888 &graphics); void set_brightness(float value); float get_brightness(); @@ -90,7 +88,6 @@ namespace pimoroni { private: void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b); - //void set_pixel(int x, int y, uint8_t v); public: uint16_t light(); @@ -102,6 +99,7 @@ namespace pimoroni { private: void next_dma_sequence(); void partial_teardown(); + void dma_safe_abort(uint channel); }; } \ No newline at end of file From e08ddd98370a9d0b19676954b6e99616b35cd745 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 11 Aug 2022 17:49:57 +0100 Subject: [PATCH 28/42] Exposed audio to MP, and made it teardown cleanly --- libraries/galactic_unicorn/audio_i2s.pio | 2 +- .../galactic_unicorn/galactic_unicorn.cpp | 45 +++++++++++++------ .../galactic_unicorn/galactic_unicorn.hpp | 6 +-- .../galactic_unicorn/galactic_unicorn.c | 4 +- .../galactic_unicorn/galactic_unicorn.cpp | 13 +++++- .../galactic_unicorn/galactic_unicorn.h | 2 +- 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/libraries/galactic_unicorn/audio_i2s.pio b/libraries/galactic_unicorn/audio_i2s.pio index 1c306f4f..d0f99d49 100644 --- a/libraries/galactic_unicorn/audio_i2s.pio +++ b/libraries/galactic_unicorn/audio_i2s.pio @@ -55,7 +55,7 @@ static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint da uint pin_mask = (1u << data_pin) | (3u << clock_pin_base); pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask); - pio_sm_set_pins(pio, sm, 0); // clear pins + pio_sm_set_pins_with_mask(pio, sm, 0, pin_mask); // clear pins pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point)); } diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 6f85a0f3..510509bb 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -51,6 +51,9 @@ namespace pimoroni { PIO GalacticUnicorn::bitstream_pio = pio0; uint GalacticUnicorn::bitstream_sm = 0; uint GalacticUnicorn::bitstream_sm_offset = 0; + PIO GalacticUnicorn::audio_pio = pio0; + uint GalacticUnicorn::audio_sm = 0; + uint GalacticUnicorn::audio_sm_offset = 0; // once the dma transfer of the scanline is complete we move to the // next scanline (or quit if we're finished) @@ -73,11 +76,15 @@ namespace pimoroni { partial_teardown(); dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly - unicorn = nullptr; - pio_sm_unclaim(bitstream_pio, bitstream_sm); pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); irq_remove_handler(DMA_IRQ_0, dma_complete); + + dma_channel_unclaim(audio_dma_channel); // This works now the teardown behaves correctly + pio_sm_unclaim(audio_pio, audio_sm); + pio_remove_program(audio_pio, &audio_i2s_program, audio_sm_offset); + + unicorn = nullptr; } } @@ -91,6 +98,17 @@ namespace pimoroni { // Abort any in-progress DMA transfer dma_safe_abort(dma_channel); + + + // Stop the audio SM + pio_sm_set_enabled(audio_pio, audio_sm, false); + + // Reset the I2S pins to avoid popping when audio is suddenly stopped + const uint pins_to_clear = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK; + pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_clear); + + // Abort any in-progress DMA transfer + dma_safe_abort(audio_dma_channel); } uint16_t GalacticUnicorn::light() { @@ -287,15 +305,13 @@ namespace pimoroni { irq_set_enabled(DMA_IRQ_0, true); } - unicorn = this; - - next_dma_sequence(); - // TODO Made audio tear down cleanly // setup audio pio program audio_pio = pio0; - audio_sm = pio_claim_unused_sm(audio_pio, true); - audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); + if(unicorn == nullptr) { + audio_sm = pio_claim_unused_sm(audio_pio, true); + audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program); + } pio_gpio_init(audio_pio, I2S_DATA); pio_gpio_init(audio_pio, I2S_BCLK); @@ -305,8 +321,6 @@ namespace pimoroni { uint32_t system_clock_frequency = clock_get_hz(clk_sys); uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); - //pio_sm_set_enabled(audio_pio, audio_sm, true); // No need to enable the SM until audio is playing - audio_dma_channel = dma_claim_unused_channel(true); dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel); @@ -314,8 +328,11 @@ namespace pimoroni { //channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); - //dma_channel_set_irq0_enabled(audio_dma_channel, true); - irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true); + + + unicorn = this; + + next_dma_sequence(); } void GalacticUnicorn::clear() { @@ -351,8 +368,8 @@ namespace pimoroni { pio_sm_set_enabled(audio_pio, audio_sm, false); // Reset the I2S pins to avoid popping when audio is suddenly stopped - const uint pins_to_set = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK; - pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_set); + const uint pins_to_clear = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK; + pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_clear); // Abort any in-progress DMA transfer dma_safe_abort(audio_dma_channel); diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index fa4756ea..5530d8f9 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -56,9 +56,9 @@ namespace pimoroni { static uint bitstream_sm; static uint bitstream_sm_offset; - PIO audio_pio = pio0; - uint audio_sm = 0; - uint audio_sm_offset = 0; + static PIO audio_pio; + static uint audio_sm; + static uint audio_sm_offset; uint16_t brightness = 256; uint16_t volume = 127; diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 6a6273da..6bd7b571 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -13,7 +13,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_volume_obj, GalacticUnicorn_get_vo MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adjust_volume); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); -//MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_play_sample_obj, 1, GalacticUnicorn_play_sample); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample); /***** Binding of Methods *****/ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { @@ -28,7 +28,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_adjust_volume), MP_ROM_PTR(&GalacticUnicorn_adjust_volume_obj) }, { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) }, { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index e758017c..09920079 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -145,8 +145,17 @@ extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button) { return mp_obj_new_bool(self->galactic->is_pressed((uint8_t)mp_obj_get_int(button))); } -extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - //_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); +extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_RW); + if(bufinfo.len < 1) { + mp_raise_ValueError("Supplied buffer is too small!"); + } + + self->galactic->play_sample((uint8_t *)bufinfo.buf, bufinfo.len); + return mp_const_none; } } diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 8c4aa2be..c5f02f83 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -24,4 +24,4 @@ extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); -extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); \ No newline at end of file +extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); \ No newline at end of file From f809db6434a11fd38af26ade8a05765cd5a73c50 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Mon, 15 Aug 2022 17:41:27 +0100 Subject: [PATCH 29/42] Added play_tone support to GU C++ and MP --- .../galactic_unicorn/galactic_unicorn.cpp | 81 +- .../galactic_unicorn/galactic_unicorn.hpp | 7 + .../feature_test_with_audio.py | 751 ++++++++++++++++++ .../galactic_unicorn/galactic_unicorn.c | 4 + .../galactic_unicorn/galactic_unicorn.cpp | 14 + .../galactic_unicorn/galactic_unicorn.h | 4 +- 6 files changed, 849 insertions(+), 12 deletions(-) create mode 100644 micropython/examples/galactic_unicorn/feature_test_with_audio.py diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 510509bb..ea7fa2a5 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -58,8 +58,16 @@ namespace pimoroni { // once the dma transfer of the scanline is complete we move to the // next scanline (or quit if we're finished) void __isr GalacticUnicorn::dma_complete() { - if(dma_channel_get_irq0_status(dma_channel) && unicorn != nullptr) { - unicorn->next_dma_sequence(); + if(unicorn != nullptr) { + uint mask = (1u << dma_channel) | (1u << audio_dma_channel); + while(dma_hw->ints0 & mask) { + if(dma_channel_get_irq0_status(dma_channel)) { + unicorn->next_dma_sequence(); + } + if(dma_channel_get_irq0_status(audio_dma_channel)) { + unicorn->loop_tone(); + } + } } } @@ -300,12 +308,7 @@ namespace pimoroni { pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); - if(unicorn == nullptr) { - irq_add_shared_handler(DMA_IRQ_0, dma_complete, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); - irq_set_enabled(DMA_IRQ_0, true); - } - // TODO Made audio tear down cleanly // setup audio pio program audio_pio = pio0; if(unicorn == nullptr) { @@ -329,6 +332,12 @@ namespace pimoroni { channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true)); dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false); + dma_channel_set_irq0_enabled(audio_dma_channel, true); + + if(unicorn == nullptr) { + irq_add_shared_handler(DMA_IRQ_0, dma_complete, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + irq_set_enabled(DMA_IRQ_0, true); + } unicorn = this; @@ -363,6 +372,58 @@ namespace pimoroni { } void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) { + stop_playing(); + + if(unicorn == this) { + // Restart the audio SM and start a new DMA transfer + pio_sm_set_enabled(audio_pio, audio_sm, true); + dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); + } + } + + void GalacticUnicorn::play_tone(float frequency) { + stop_playing(); + + const uint system_freq = 22050; + + if(unicorn == this) { + uint wraps = 1; + uint rounded_freq = (int)roundf(frequency); + if(system_freq % rounded_freq != 0) { + while((rounded_freq * wraps) < (system_freq / 5)) { + if((system_freq * wraps) % rounded_freq != 0) { + wraps += 1; + } + else { + break; + } + } + } + + uint samples_for_full_wave = (uint)((system_freq * wraps) / rounded_freq); + buffer_length = samples_for_full_wave; + for(uint i = 0; i < buffer_length; i++) { + int16_t val = roundf(sinf(((float)(i * wraps) / (float)samples_for_full_wave) * 2 * M_PI) * 0x1fff); + tone_buffer[(i * 2)] = (uint8_t)(val & 0xff); + tone_buffer[(i * 2) + 1] = (uint8_t)((val >> 8) & 0xff); + } + + // Restart the audio SM and start a new DMA transfer + pio_sm_set_enabled(audio_pio, audio_sm, true); + + loop_tone(); + } + } + + void GalacticUnicorn::loop_tone() { + // Clear any interrupt request caused by our channel + dma_channel_acknowledge_irq0(audio_dma_channel); + + if(buffer_length > 0) + dma_channel_transfer_from_buffer_now(audio_dma_channel, tone_buffer, buffer_length); + } + + void GalacticUnicorn::stop_playing() { if(unicorn == this) { // Stop the audio SM pio_sm_set_enabled(audio_pio, audio_sm, false); @@ -371,12 +432,10 @@ namespace pimoroni { const uint pins_to_clear = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK; pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_clear); + buffer_length = 0; + // Abort any in-progress DMA transfer dma_safe_abort(audio_dma_channel); - - // Restart the audio SM and start a new DMA transfer - pio_sm_set_enabled(audio_pio, audio_sm, true); - dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); } } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 5530d8f9..281cb431 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -68,6 +68,10 @@ namespace pimoroni { static GalacticUnicorn* unicorn; static void dma_complete(); + static const uint TONE_BUFFER_SIZE = 22050 / 2; + uint8_t tone_buffer[TONE_BUFFER_SIZE * 2] = {0}; + uint buffer_length = 0; + public: ~GalacticUnicorn(); @@ -95,11 +99,14 @@ namespace pimoroni { bool is_pressed(uint8_t button); void play_sample(uint8_t *data, uint32_t length); + void play_tone(float frequency); + void stop_playing(); private: void next_dma_sequence(); void partial_teardown(); void dma_safe_abort(uint channel); + void loop_tone(); }; } \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py new file mode 100644 index 00000000..89976648 --- /dev/null +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -0,0 +1,751 @@ +import gc +import time +import math +from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY + +gc.collect() + +gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) + +width = GalacticUnicorn.WIDTH +height = GalacticUnicorn.HEIGHT + +left_channel = bytearray(( + 0xfe, 0xff, 0xfb, 0xff, 0xf9, 0xff, 0xf6, 0xff, 0xee, 0xff, 0xed, 0xff, + 0xec, 0xff, 0xed, 0xff, 0xec, 0xff, 0xed, 0xff, 0xef, 0xff, 0xf3, 0xff, + 0x01, 0x00, 0x04, 0x00, 0xe8, 0xff, 0xf6, 0xff, 0x08, 0x00, 0x06, 0x00, + 0x09, 0x00, 0x10, 0x00, 0x39, 0x00, 0x5c, 0x00, 0x6e, 0x00, 0x65, 0x00, + 0x6e, 0x00, 0x88, 0x00, 0x80, 0x00, 0x70, 0x00, 0x78, 0x00, 0xab, 0x00, + 0xa1, 0x00, 0xa9, 0x00, 0xab, 0x00, 0xe1, 0x00, 0x21, 0x01, 0x3c, 0x01, + 0x3a, 0x01, 0x3f, 0x01, 0x55, 0x01, 0x88, 0x01, 0xe4, 0x01, 0x02, 0x02, + 0xeb, 0x01, 0xef, 0x01, 0x1c, 0x02, 0x1a, 0x02, 0x3d, 0x02, 0x45, 0x02, + 0x3f, 0x02, 0x1e, 0x02, 0x1b, 0x02, 0x5d, 0x02, 0xb7, 0x02, 0x3c, 0x03, + 0x01, 0x03, 0x31, 0x03, 0x5e, 0x03, 0x47, 0x03, 0x8d, 0x03, 0xf2, 0x03, + 0xe4, 0x03, 0xc7, 0x03, 0x2d, 0x03, 0x32, 0x03, 0xba, 0x03, 0x3e, 0x03, + 0xb3, 0x02, 0x54, 0x02, 0x14, 0x02, 0xd5, 0x01, 0x4e, 0x01, 0xcc, 0x00, + 0xee, 0xff, 0xeb, 0xfe, 0x97, 0xfe, 0x08, 0xfe, 0x83, 0xfd, 0xe7, 0xfc, + 0x52, 0xfc, 0x0b, 0xfc, 0x78, 0xfc, 0xc0, 0xfb, 0xe2, 0xfa, 0x3a, 0xfb, + 0x57, 0xfb, 0x07, 0xfb, 0x9b, 0xfa, 0x09, 0xfa, 0x18, 0xfa, 0xee, 0xfa, + 0xb7, 0xfa, 0x1e, 0xfa, 0x4e, 0xf9, 0x39, 0xf9, 0x7d, 0xf9, 0x21, 0xfa, + 0xcb, 0xfa, 0x9e, 0xfa, 0xa1, 0xfa, 0x92, 0xfa, 0x52, 0xfb, 0x8e, 0xfb, + 0xa4, 0xfb, 0x5e, 0xfb, 0x03, 0xfc, 0x0c, 0xfd, 0xc3, 0xfd, 0xfe, 0xfd, + 0xda, 0xfd, 0x6e, 0xfe, 0x1d, 0xff, 0xf6, 0xff, 0x02, 0x00, 0xfc, 0xff, + 0x4b, 0x00, 0xcc, 0x00, 0x40, 0x01, 0x87, 0x01, 0xf0, 0x01, 0x2e, 0x02, + 0xf6, 0x02, 0x78, 0x03, 0xa4, 0x03, 0x3f, 0x04, 0x8f, 0x04, 0xdf, 0x04, + 0x11, 0x05, 0x97, 0x04, 0x05, 0x05, 0x57, 0x05, 0xae, 0x05, 0xb2, 0x05, + 0x84, 0x05, 0xc2, 0x05, 0x86, 0x05, 0x9f, 0x05, 0xfb, 0x05, 0x0e, 0x06, + 0x10, 0x06, 0xec, 0x05, 0xc4, 0x05, 0xc1, 0x05, 0xa1, 0x05, 0xa2, 0x06, + 0xba, 0x06, 0xbd, 0x05, 0xe9, 0x05, 0xf0, 0x05, 0x9a, 0x06, 0xfd, 0x06, + 0x45, 0x06, 0x3b, 0x06, 0x8d, 0x05, 0x69, 0x05, 0x8e, 0x05, 0x09, 0x05, + 0xbd, 0x04, 0x5f, 0x04, 0xcd, 0x03, 0xd7, 0x03, 0x74, 0x03, 0x81, 0x02, + 0x6e, 0x01, 0x21, 0x00, 0x1a, 0xff, 0xe3, 0xfe, 0x4b, 0xfe, 0x3f, 0xfd, + 0xc3, 0xfb, 0x0d, 0xfb, 0x8a, 0xf9, 0x15, 0xf8, 0x6a, 0xf7, 0x92, 0xf7, + 0xb3, 0xf7, 0xe6, 0xf7, 0xc3, 0xf6, 0xce, 0xf5, 0xc4, 0xf5, 0xe1, 0xf5, + 0xdd, 0xf5, 0x0e, 0xf5, 0xa4, 0xf4, 0xe5, 0xf4, 0xe9, 0xf4, 0x60, 0xf4, + 0xac, 0xf4, 0xba, 0xf4, 0xb2, 0xf5, 0xad, 0xf6, 0xf7, 0xf6, 0x4a, 0xf7, + 0x63, 0xf7, 0xad, 0xf7, 0xe4, 0xf8, 0x89, 0xf9, 0xc0, 0xf9, 0x80, 0xfa, + 0x93, 0xfb, 0xac, 0xfc, 0xae, 0xfd, 0x51, 0xfe, 0xf3, 0xfe, 0x91, 0x00, + 0x12, 0x02, 0x4a, 0x03, 0x60, 0x03, 0x84, 0x03, 0x6a, 0x04, 0xdd, 0x04, + 0xa3, 0x05, 0x45, 0x06, 0xeb, 0x06, 0xd6, 0x07, 0x74, 0x08, 0xaa, 0x08, + 0xdd, 0x08, 0x17, 0x09, 0xb8, 0x09, 0x27, 0x0a, 0x60, 0x0a, 0x7e, 0x0a, + 0xff, 0x0a, 0x18, 0x0b, 0x08, 0x0b, 0x3a, 0x0b, 0x97, 0x0b, 0xfe, 0x0b, + 0xd7, 0x0b, 0x1c, 0x0b, 0xc8, 0x0a, 0x85, 0x0a, 0x4f, 0x0a, 0x8c, 0x0a, + 0x4a, 0x0a, 0xc0, 0x09, 0x80, 0x09, 0xf5, 0x08, 0xc0, 0x08, 0xe4, 0x08, + 0x10, 0x08, 0x4a, 0x06, 0x89, 0x05, 0x51, 0x05, 0x7a, 0x04, 0xd6, 0x02, + 0x2a, 0x01, 0x5d, 0x00, 0x20, 0x00, 0xb6, 0xff, 0x24, 0xfe, 0xc6, 0xfa, + 0x8e, 0xf9, 0xfc, 0xf9, 0xe8, 0xf9, 0x67, 0xf8, 0x84, 0xf5, 0x67, 0xf5, + 0xc7, 0xf6, 0x4c, 0xf6, 0xb9, 0xf5, 0x47, 0xf4, 0x12, 0xf3, 0xa4, 0xf3, + 0xdd, 0xf3, 0x8f, 0xf3, 0x5f, 0xf2, 0x14, 0xf1, 0xa3, 0xf0, 0xb7, 0xf0, + 0xa1, 0xf1, 0x89, 0xf2, 0x7a, 0xf2, 0xa5, 0xf2, 0xea, 0xf2, 0xa1, 0xf3, + 0x5d, 0xf4, 0x01, 0xf5, 0x7a, 0xf5, 0x8a, 0xf5, 0x03, 0xf6, 0x4e, 0xf7, + 0xe7, 0xf8, 0x41, 0xf9, 0xa7, 0xf9, 0x0b, 0xfb, 0x03, 0xfd, 0x2f, 0xff, + 0x30, 0x00, 0xfd, 0x00, 0x2c, 0x01, 0xf8, 0x01, 0xa2, 0x03, 0xa6, 0x04, + 0x55, 0x05, 0xaa, 0x05, 0x00, 0x07, 0x3f, 0x08, 0xd0, 0x08, 0xb4, 0x09, + 0x30, 0x0a, 0xbc, 0x0a, 0xf0, 0x0b, 0x24, 0x0c, 0xe7, 0x0b, 0x00, 0x0c, + 0x7a, 0x0c, 0x30, 0x0d, 0xe2, 0x0c, 0x01, 0x0d, 0x4a, 0x0d, 0x9f, 0x0d, + 0xa8, 0x0d, 0x36, 0x0d, 0x0c, 0x0d, 0x97, 0x0c, 0xad, 0x0c, 0xce, 0x0c, + 0xe5, 0x0b, 0xb0, 0x0b, 0x59, 0x0b, 0xe7, 0x0a, 0xc0, 0x0a, 0x38, 0x0a, + 0xb0, 0x09, 0x08, 0x09, 0xbe, 0x08, 0x6d, 0x08, 0xf0, 0x06, 0xbf, 0x05, + 0xd7, 0x04, 0x0d, 0x05, 0x20, 0x04, 0xe4, 0x02, 0x00, 0x02, 0x35, 0x00, + 0xd0, 0xfd, 0x28, 0xfd, 0x2d, 0xfc, 0x24, 0xfa, 0xc7, 0xf8, 0xde, 0xf6, + 0x2c, 0xf6, 0x5d, 0xf6, 0x74, 0xf5, 0x3f, 0xf5, 0x33, 0xf4, 0xb4, 0xf2, + 0xf9, 0xf2, 0xe3, 0xf2, 0xd6, 0xf2, 0x04, 0xf2, 0xf9, 0xef, 0xf7, 0xee, + 0xc8, 0xef, 0x12, 0xf1, 0x74, 0xf0, 0xbf, 0xee, 0x3c, 0xf0, 0x79, 0xf1, + 0x40, 0xf1, 0x5c, 0xf1, 0xd9, 0xf1, 0xf3, 0xf2, 0xdf, 0xf3, 0xcf, 0xf3, + 0xcb, 0xf3, 0x90, 0xf4, 0x9f, 0xf5, 0x5c, 0xf7, 0x3c, 0xf9, 0x02, 0xfa, + 0x60, 0xfb, 0xcc, 0xfc, 0x7d, 0xfe, 0x11, 0x00, 0x3e, 0x01, 0x67, 0x02, + 0x33, 0x03, 0xbf, 0x04, 0x4a, 0x06, 0x2d, 0x07, 0x49, 0x08, 0x43, 0x09, + 0xb9, 0x0a, 0x54, 0x0c, 0x23, 0x0d, 0xc0, 0x0d, 0x6a, 0x0e, 0x0d, 0x0f, + 0x1c, 0x0f, 0x48, 0x0f, 0x62, 0x0f, 0xcb, 0x0e, 0xfb, 0x0e, 0x83, 0x0f, + 0x99, 0x0f, 0x48, 0x0f, 0x30, 0x0f, 0x28, 0x0f, 0x02, 0x0f, 0x6f, 0x0e, + 0xb5, 0x0d, 0x78, 0x0c, 0xd0, 0x0b, 0x34, 0x0b, 0xc1, 0x0a, 0x18, 0x0a, + 0x12, 0x09, 0x5b, 0x08, 0x8d, 0x07, 0x72, 0x06, 0x17, 0x05, 0xf9, 0x03, + 0xae, 0x03, 0xcf, 0x02, 0xd0, 0x00, 0xf5, 0xfe, 0x4c, 0xfe, 0xb3, 0xfd, + 0x1b, 0xfd, 0x63, 0xfb, 0x9a, 0xf7, 0x62, 0xf6, 0xd7, 0xf7, 0xc8, 0xf7, + 0x15, 0xf6, 0x6e, 0xf4, 0x22, 0xf3, 0x5f, 0xf3, 0xb8, 0xf3, 0xe3, 0xf2, + 0x15, 0xf2, 0x3c, 0xf2, 0x19, 0xf1, 0x8c, 0xf1, 0x98, 0xf1, 0x65, 0xef, + 0xfc, 0xef, 0x7b, 0xf0, 0x76, 0xf1, 0xac, 0xf2, 0x59, 0xf2, 0xb7, 0xf1, + 0x9e, 0xf2, 0xda, 0xf3, 0x33, 0xf4, 0xca, 0xf4, 0x9d, 0xf4, 0x16, 0xf5, + 0x21, 0xf6, 0x9e, 0xf7, 0xfd, 0xf7, 0xb8, 0xf8, 0x85, 0xfa, 0x31, 0xfc, + 0x01, 0xfe, 0x32, 0xff, 0x49, 0x00, 0x8e, 0x01, 0x75, 0x02, 0x74, 0x03, + 0xa8, 0x04, 0x59, 0x05, 0xaa, 0x06, 0xf9, 0x07, 0x16, 0x09, 0x55, 0x0a, + 0x5a, 0x0b, 0xa9, 0x0c, 0x2c, 0x0d, 0xee, 0x0d, 0x32, 0x0e, 0x64, 0x0e, + 0xa0, 0x0e, 0x40, 0x0e, 0xb2, 0x0e, 0x9e, 0x0e, 0xfa, 0x0d, 0xed, 0x0d, + 0x2e, 0x0e, 0xf5, 0x0e, 0xe1, 0x0e, 0xd1, 0x0d, 0xda, 0x0c, 0x96, 0x0c, + 0xa2, 0x0c, 0xd7, 0x0b, 0xaf, 0x0a, 0xdd, 0x09, 0x7e, 0x09, 0x19, 0x09, + 0x23, 0x08, 0x0d, 0x07, 0xb5, 0x06, 0xea, 0x06, 0x21, 0x06, 0x62, 0x04, + 0x92, 0x02, 0x6d, 0x01, 0xee, 0x00, 0x2b, 0x00, 0x62, 0xfe, 0x5a, 0xfc, + 0xeb, 0xfa, 0x63, 0xfa, 0xb5, 0xf9, 0xd0, 0xf7, 0xad, 0xf5, 0xaf, 0xf4, + 0x16, 0xf5, 0x35, 0xf5, 0xf6, 0xf3, 0xc7, 0xf2, 0xea, 0xf1, 0x5b, 0xf2, + 0xf7, 0xf2, 0x8c, 0xf3, 0xc3, 0xf1, 0x53, 0xef, 0xc9, 0xef, 0x79, 0xf0, + 0xc7, 0xf0, 0xbb, 0xf0, 0xfa, 0xef, 0x94, 0xef, 0xae, 0xf0, 0x3b, 0xf2, + 0x3e, 0xf3, 0xe9, 0xf2, 0x05, 0xf3, 0xc9, 0xf3, 0xa7, 0xf4, 0x79, 0xf4, + 0xe6, 0xf4, 0x56, 0xf6, 0xe7, 0xf7, 0x8c, 0xf9, 0xcd, 0xfa, 0x59, 0xfb, + 0x4d, 0xfd, 0xd8, 0xff, 0x8d, 0x01, 0x16, 0x02, 0xdf, 0x02, 0x3f, 0x04, + 0xf0, 0x05, 0x71, 0x07, 0xc6, 0x07, 0x1b, 0x09, 0xa0, 0x0a, 0xd1, 0x0b, + 0x15, 0x0d, 0x6b, 0x0d, 0x4d, 0x0e, 0x59, 0x0f, 0x33, 0x10, 0xe5, 0x0f, + 0x4d, 0x0f, 0x1e, 0x10, 0x0d, 0x11, 0x52, 0x11, 0x90, 0x11, 0xf1, 0x10, + 0xf2, 0x0f, 0x95, 0x0f, 0x45, 0x10, 0x25, 0x10, 0x78, 0x0e, 0xf8, 0x0c, + 0x90, 0x0c, 0x34, 0x0c, 0x80, 0x0b, 0x40, 0x0a, 0xee, 0x08, 0x5d, 0x08, + 0x2e, 0x08, 0x32, 0x07, 0x55, 0x05, 0xdc, 0x03, 0x14, 0x03, 0x6e, 0x02, + 0x5c, 0x00, 0x05, 0xfe, 0x32, 0xfc, 0xe6, 0xfb, 0x39, 0xfb, 0x73, 0xf9, + 0x14, 0xf7, 0xbe, 0xf4, 0x88, 0xf4, 0x5d, 0xf4, 0xfb, 0xf3, 0x1b, 0xf3, + 0xa8, 0xf1, 0x3b, 0xf2, 0x5c, 0xf2, 0x18, 0xf2, 0x2e, 0xf1, 0x97, 0xef, + 0xd2, 0xef, 0x8c, 0xf0, 0x3c, 0xef, 0xd8, 0xed, 0x69, 0xed, 0xc5, 0xee, + 0x19, 0xf0, 0x67, 0xf0, 0xa4, 0xef, 0x08, 0xf0, 0x46, 0xf1, 0x7b, 0xf2, + 0x83, 0xf2, 0x6e, 0xf2, 0x99, 0xf2, 0x60, 0xf4, 0xf2, 0xf5, 0xd2, 0xf5, + 0x34, 0xf6, 0xfc, 0xf7, 0x89, 0xfa, 0x07, 0xfd, 0x6e, 0xfe, 0xec, 0xfe, + 0xaa, 0xff, 0xb4, 0x00, 0xf7, 0x02, 0x54, 0x04, 0x49, 0x05, 0xe2, 0x05, + 0xdc, 0x06, 0xb3, 0x08, 0x46, 0x0a, 0xf6, 0x0b, 0x58, 0x0d, 0xff, 0x0d, + 0x86, 0x0f, 0x67, 0x10, 0x62, 0x10, 0xab, 0x0f, 0xdd, 0x0f, 0x00, 0x11, + 0x03, 0x12, 0x50, 0x12, 0xd7, 0x11, 0xb9, 0x11, 0x53, 0x12, 0x99, 0x12, + 0xd9, 0x12, 0x53, 0x11, 0x4a, 0x0f, 0x97, 0x0e, 0x47, 0x0e, 0x7b, 0x0d, + 0x07, 0x0c, 0xdd, 0x0a, 0xfe, 0x09, 0x9c, 0x09, 0x00, 0x09, 0x09, 0x08, + 0xfc, 0x06, 0xa6, 0x05, 0xdd, 0x03, 0xfd, 0x01, 0x55, 0x00, 0x0d, 0xff, + 0x05, 0xfe, 0x91, 0xfc, 0x46, 0xfb, 0x79, 0xf9, 0x92, 0xf7, 0x52, 0xf6, + 0xaa, 0xf4, 0xd8, 0xf3, 0x8d, 0xf3, 0xe6, 0xf2, 0xb4, 0xf1, 0xc5, 0xf0, + 0xc6, 0xf0, 0xd8, 0xf0, 0x1a, 0xf1, 0xc7, 0xf0, 0x47, 0xef, 0xf7, 0xee, + 0xc7, 0xee, 0x47, 0xee, 0x83, 0xee, 0x8a, 0xed, 0x7f, 0xee, 0x57, 0xef, + 0x94, 0xef, 0x4b, 0xf0, 0x5e, 0xf0, 0xc4, 0xf1, 0x7c, 0xf2, 0xbc, 0xf1, + 0x90, 0xf2, 0x1b, 0xf4, 0x00, 0xf5, 0x56, 0xf6, 0xa1, 0xf6, 0x54, 0xf7, + 0x66, 0xf9, 0x83, 0xfb, 0xfc, 0xfd, 0xb3, 0xff, 0xd0, 0xff, 0xe3, 0x00, + 0x1a, 0x03, 0xa6, 0x04, 0xba, 0x05, 0xaa, 0x06, 0x1f, 0x08, 0xa6, 0x09, + 0xae, 0x0a, 0xd1, 0x0b, 0xbb, 0x0d, 0x2e, 0x0f, 0xfc, 0x0f, 0x55, 0x10, + 0xb5, 0x10, 0x05, 0x11, 0xb8, 0x11, 0x6d, 0x12, 0x14, 0x12, 0xb1, 0x11, + 0x56, 0x11, 0xaf, 0x11, 0xe0, 0x12, 0x9a, 0x12, 0x3b, 0x11, 0x0f, 0x10, + 0xeb, 0x0f, 0xcb, 0x0f, 0x94, 0x0e, 0xce, 0x0c, 0x8a, 0x0b, 0x36, 0x0b, + 0xb8, 0x0a, 0xf9, 0x09, 0x35, 0x09, 0xbd, 0x07, 0xb8, 0x06, 0x45, 0x06, + 0xd4, 0x04, 0x19, 0x03, 0x0e, 0x01, 0x59, 0xff, 0x98, 0xfe, 0x4b, 0xfd, + 0x97, 0xfb, 0x85, 0xfa, 0x56, 0xf8, 0xc6, 0xf6, 0xe6, 0xf5, 0x5c, 0xf4, + 0xf2, 0xf2, 0x07, 0xf4, 0xb8, 0xf3, 0x79, 0xf1, 0x64, 0xf0, 0x2e, 0xef, + 0xf8, 0xef, 0x38, 0xf1, 0x86, 0xf0, 0xde, 0xee, 0x24, 0xed, 0x7d, 0xed, + 0xad, 0xee, 0x7c, 0xee, 0xb8, 0xed, 0x47, 0xed, 0xfa, 0xed, 0x36, 0xf0, + 0x1d, 0xf1, 0x47, 0xf0, 0xca, 0xef, 0xd8, 0xf0, 0x80, 0xf3, 0x71, 0xf4, + 0x77, 0xf4, 0x92, 0xf3, 0xe3, 0xf3, 0x52, 0xf7, 0xd6, 0xf9, 0x5b, 0xfb, + 0xe9, 0xfb, 0x63, 0xfc, 0x52, 0xff, 0xdf, 0x01, 0xaf, 0x03, 0x8c, 0x04, + 0xec, 0x03, 0xd6, 0x05, 0x6b, 0x08, 0x95, 0x0a, 0x20, 0x0c, 0x72, 0x0c, + 0xb4, 0x0d, 0x74, 0x0f, 0x08, 0x11, 0xc4, 0x11, 0x1a, 0x12, 0x4c, 0x12, + 0x79, 0x12, 0xf7, 0x12, 0x0a, 0x13, 0xa1, 0x12, 0xe6, 0x12, 0xed, 0x12, + 0x48, 0x13, 0x8a, 0x13, 0x10, 0x13, 0xcf, 0x12, 0xd2, 0x11, 0x97, 0x10, + 0xb8, 0x0f, 0xe2, 0x0e, 0xaf, 0x0d, 0x3a, 0x0c, 0x3e, 0x0c, 0x71, 0x0a, + 0x81, 0x08, 0x28, 0x08, 0xc3, 0x07, 0xc2, 0x06, 0x81, 0x04, 0x3a, 0x02, + 0x85, 0xff, 0x36, 0xfe, 0x15, 0xfd, 0x98, 0xfb, 0xab, 0xf9, 0xb5, 0xf8, + 0x8e, 0xf6, 0xfa, 0xf4, 0x85, 0xf3, 0x51, 0xf2, 0x59, 0xf1, 0x7e, 0xef, + 0x44, 0xef, 0xe3, 0xed, 0x0b, 0xee, 0xc2, 0xee, 0x7a, 0xee, 0xd3, 0xed, + 0x61, 0xed, 0x7f, 0xed, 0xb9, 0xee, 0x4e, 0xee, 0x7e, 0xec, 0xae, 0xeb, + 0xdd, 0xeb, 0x38, 0xed, 0x2e, 0xef, 0xef, 0xef, 0x21, 0xf0, 0x52, 0xf1, + 0x7a, 0xf2, 0x16, 0xf4, 0x2d, 0xf5, 0x7a, 0xf5, 0x0f, 0xf6, 0x8a, 0xf7, + 0xbb, 0xf8, 0x93, 0xf9, 0x43, 0xfb, 0x55, 0xfd, 0xfb, 0xfe, 0xa3, 0x00, + 0xe9, 0x02, 0x2f, 0x05, 0x8f, 0x06, 0x1f, 0x08, 0xe4, 0x08, 0xb4, 0x09, + 0x96, 0x0a, 0xbc, 0x0b, 0x64, 0x0d, 0x2d, 0x0f, 0x23, 0x10, 0x72, 0x10, + 0x7b, 0x11, 0xee, 0x11, 0x16, 0x13, 0x35, 0x14, 0xfc, 0x13, 0x4f, 0x13, + 0x10, 0x13, 0xe2, 0x12, 0x73, 0x12, 0x45, 0x12, 0x74, 0x12, 0x4d, 0x12, + 0x01, 0x12, 0xc3, 0x10, 0x5d, 0x0f, 0xfd, 0x0e, 0x74, 0x0e, 0x55, 0x0d, + 0x17, 0x0b, 0x72, 0x09, 0x01, 0x09, 0x8d, 0x08, 0x8a, 0x08, 0x29, 0x07, + 0x05, 0x05, 0xbf, 0x03, 0xc5, 0x02, 0x02, 0x02, 0x33, 0x00, 0x67, 0xfd, + 0x2b, 0xfb, 0x09, 0xfa, 0xbd, 0xf8, 0x7f, 0xf7, 0x7a, 0xf5, 0x62, 0xf2, + 0x65, 0xf0, 0x64, 0xef, 0x80, 0xef, 0x98, 0xef, 0xed, 0xed, 0x18, 0xec, + 0x43, 0xeb, 0xe7, 0xeb, 0xc9, 0xed, 0xed, 0xed, 0x2a, 0xec, 0x16, 0xea, + 0x8a, 0xea, 0xec, 0xec, 0x4b, 0xec, 0x45, 0xed, 0x2b, 0xec, 0x62, 0xeb, + 0xdb, 0xee, 0xcc, 0xef, 0x6b, 0xf1, 0x53, 0xf1, 0xac, 0xf1, 0x7e, 0xf3, + 0x9c, 0xf4, 0x04, 0xf6, 0x5b, 0xf7, 0xd6, 0xf8, 0xfc, 0xf9, 0xfa, 0xfa, + 0xe8, 0xfc, 0x92, 0xff, 0x52, 0x02, 0x2e, 0x04, 0x07, 0x05, 0xaf, 0x06, + 0x1d, 0x08, 0x94, 0x0a, 0x3b, 0x0c, 0x21, 0x0c, 0x65, 0x0d, 0x28, 0x0f, + 0xbe, 0x0f, 0x6b, 0x11, 0xf0, 0x11, 0xfe, 0x11, 0x04, 0x14, 0xf8, 0x14, + 0xdf, 0x14, 0xde, 0x14, 0x2c, 0x14, 0xdd, 0x13, 0xb8, 0x14, 0x01, 0x14, + 0xe0, 0x12, 0x03, 0x12, 0xb7, 0x11, 0xa0, 0x11, 0x60, 0x11, 0x14, 0x10, + 0x43, 0x0e, 0x6f, 0x0d, 0x85, 0x0c, 0x89, 0x0b, 0x2d, 0x0a, 0x61, 0x08, + 0xea, 0x07, 0x4c, 0x07, 0x14, 0x06, 0xe3, 0x04, 0x7d, 0x03, 0x37, 0x02, + 0x0f, 0x00, 0xc6, 0xff, 0xba, 0xfd, 0x61, 0xfb, 0x69, 0xfa, 0x4f, 0xf8, + 0x4e, 0xf8, 0x70, 0xf6, 0x6f, 0xf3, 0xc0, 0xf1, 0x47, 0xef, 0x03, 0xef, + 0x1e, 0xef, 0xa1, 0xed, 0x55, 0xec, 0x8c, 0xeb, 0xa4, 0xec, 0xe9, 0xec, + 0x89, 0xed, 0xb0, 0xed, 0x23, 0xed, 0xa5, 0xee, 0xaa, 0xef, 0x46, 0xee, + 0x94, 0xeb, 0x0a, 0xeb, 0xc7, 0xec, 0xed, 0xef, 0x33, 0xf1, 0xb8, 0xef, + 0xfe, 0xee, 0xf6, 0xf0, 0x2e, 0xf4, 0xac, 0xf6, 0x14, 0xf7, 0xa6, 0xf6, + 0x5d, 0xf7, 0xba, 0xf8, 0x9c, 0xfa, 0x9e, 0xfb, 0xd6, 0xfc, 0x83, 0xff, + 0x88, 0x01, 0x1f, 0x03, 0x78, 0x05, 0xe3, 0x06, 0x75, 0x09, 0x26, 0x0b, + 0x99, 0x0b, 0x1c, 0x0d, 0xfa, 0x0d, 0xc1, 0x0f, 0xc5, 0x10, 0x58, 0x11, + 0xdd, 0x11, 0x08, 0x13, 0x41, 0x15, 0x4e, 0x16, 0x56, 0x16, 0xd7, 0x15, + 0xc6, 0x15, 0xda, 0x15, 0x69, 0x14, 0x9f, 0x13, 0x1f, 0x14, 0x6b, 0x13, + 0xc3, 0x12, 0xbd, 0x11, 0x81, 0x10, 0xf5, 0x10, 0xbe, 0x10, 0x7a, 0x0f, + 0x15, 0x0d, 0x45, 0x0c, 0x50, 0x0b, 0xbe, 0x09, 0x9c, 0x08, 0xa5, 0x06, + 0x28, 0x05, 0xcb, 0x03, 0x92, 0x03, 0x3d, 0x02, 0x3e, 0xff, 0xe9, 0xfc, + 0x75, 0xfb, 0xbb, 0xfa, 0xf1, 0xf8, 0x5d, 0xf6, 0xb1, 0xf3, 0xaa, 0xf1, + 0xeb, 0xf0, 0x56, 0xef, 0xa7, 0xec, 0x60, 0xea, 0x00, 0xe9, 0xfc, 0xe9, + 0xe8, 0xee, 0x84, 0xec, 0x46, 0xe8, 0x58, 0xe7, 0x35, 0xe9, 0xa7, 0xef, + 0x9a, 0xf1, 0x71, 0xec, 0x51, 0xe8, 0xe5, 0xe8, 0x3d, 0xec, 0x40, 0xf0, + 0xfd, 0xee, 0xc9, 0xea, 0x54, 0xed, 0x90, 0xf1, 0x65, 0xf6, 0xc9, 0xf6, + 0x2e, 0xf3, 0xd1, 0xf4, 0xf8, 0xf7, 0x3d, 0xfb, 0x9d, 0xfc, 0xe9, 0xfa, + 0x9c, 0xfb, 0xae, 0xfe, 0x14, 0x02, 0x02, 0x05, 0x13, 0x05, 0xc6, 0x06, + 0xf9, 0x08, 0x45, 0x0b, 0xc4, 0x0c, 0xdf, 0x0c, 0x18, 0x0e, 0x61, 0x10, + 0x16, 0x11, 0x58, 0x11, 0xae, 0x10, 0x54, 0x12, 0x1d, 0x15, 0x39, 0x16, + 0xb0, 0x15, 0xb9, 0x14, 0x30, 0x15, 0x2d, 0x16, 0xc8, 0x15, 0xce, 0x14, + 0x3f, 0x13, 0x08, 0x12, 0x00, 0x12, 0x50, 0x11, 0xaa, 0x10, 0x7f, 0x10, + 0xa2, 0x0f, 0x2f, 0x0f, 0xb6, 0x0d, 0x39, 0x0c, 0x4e, 0x0b, 0xfe, 0x09, + 0x27, 0x09, 0x8a, 0x07, 0x7e, 0x05, 0x0b, 0x04, 0x90, 0x03, 0xf7, 0x02, + 0x34, 0x01, 0xca, 0xfe, 0x8d, 0xfd, 0x68, 0xfc, 0xb6, 0xfb, 0x25, 0xf9, + 0x10, 0xf6, 0x14, 0xf4, 0xf5, 0xf1, 0x6a, 0xf0, 0x31, 0xee, 0xe9, 0xeb, + 0x41, 0xea, 0xe8, 0xea, 0xd6, 0xea, 0xc4, 0xea, 0x24, 0xea, 0xaa, 0xe9, + 0x44, 0xeb, 0x84, 0xeb, 0xe7, 0xec, 0xc8, 0xed, 0xe5, 0xeb, 0xa1, 0xeb, + 0x0f, 0xeb, 0x06, 0xeb, 0xd2, 0xec, 0x8a, 0xee, 0x43, 0xef, 0xe1, 0xef, + 0x59, 0xf1, 0xdf, 0xf2, 0xaa, 0xf5, 0xe9, 0xf6, 0xa5, 0xf6, 0xc2, 0xf7, + 0x30, 0xf9, 0x1b, 0xfb, 0x08, 0xfd, 0x95, 0xfd, 0x22, 0xfe, 0x1d, 0x00, + 0x4c, 0x04, 0x76, 0x06, 0x67, 0x07, 0xcb, 0x08, 0x8b, 0x0a, 0x79, 0x0c, + 0x42, 0x0d, 0xfe, 0x0d, 0x99, 0x0e, 0xab, 0x0f, 0x43, 0x11, 0x6e, 0x11, + 0xb3, 0x10, 0xea, 0x12, 0x1f, 0x15, 0xb5, 0x15, 0xd3, 0x15, 0x8d, 0x14, + 0x2a, 0x15, 0xa1, 0x15, 0x11, 0x15, 0x54, 0x14, 0x35, 0x13, 0xb9, 0x12, + 0xec, 0x12, 0xcd, 0x12, 0x5b, 0x11, 0x8f, 0x10, 0xf5, 0x0f, 0x89, 0x0e, + 0x29, 0x0e, 0x13, 0x0d, 0xad, 0x0b, 0x6a, 0x0a, 0x3e, 0x09, 0xab, 0x07, + 0xc9, 0x05, 0xc9, 0x04, 0xc7, 0x03, 0x0a, 0x02, 0xa0, 0x01, 0xf1, 0xfe, + 0xe7, 0xfa, 0xff, 0xf9, 0xb2, 0xf8, 0x43, 0xf7, 0x7f, 0xf5, 0x1d, 0xf1, + 0xbc, 0xee, 0x4a, 0xed, 0x18, 0xec, 0x2f, 0xe9, 0xdb, 0xe8, 0x00, 0xe8, + 0xd1, 0xe8, 0xb7, 0xe9, 0x5f, 0xe7, 0x64, 0xe7, 0x65, 0xe8, 0xa7, 0xea, + 0xc2, 0xeb, 0xd2, 0xea, 0xfc, 0xe8, 0x76, 0xe8, 0x7a, 0xea, 0x65, 0xec, + 0x29, 0xed, 0x82, 0xed, 0x36, 0xee, 0xff, 0xef, 0xbb, 0xf2, 0xc8, 0xf4, + 0xe3, 0xf5, 0x3d, 0xf6, 0xe1, 0xf7, 0x25, 0xfb, 0x80, 0xfc, 0xc1, 0xfc, + 0x09, 0xfd, 0x0f, 0xff, 0xc0, 0x01, 0x3f, 0x05, 0xb4, 0x06, 0xa2, 0x07, + 0xc0, 0x08, 0xa1, 0x0b, 0xb7, 0x0d, 0xf6, 0x0f, 0x16, 0x10, 0xf8, 0x0e, + 0x42, 0x10, 0xb8, 0x11, 0xbe, 0x13, 0xbb, 0x14, 0x71, 0x14, 0x07, 0x15, + 0xfa, 0x15, 0x1f, 0x16, 0x0a, 0x16, 0xf6, 0x15, 0x3e, 0x17, 0x04, 0x17, + 0x1f, 0x15, 0x34, 0x13, 0x34, 0x12, 0xe8, 0x12, 0x9f, 0x12, 0x08, 0x12, + 0x85, 0x10, 0x28, 0x0e, 0xa4, 0x0d, 0x2b, 0x0d, 0x25, 0x0c, 0xc1, 0x0a, + 0xed, 0x08, 0xa9, 0x07, 0xab, 0x06, 0xed, 0x04, 0xbe, 0x02, 0x3d, 0x01, + 0x40, 0x00, 0x87, 0xfe, 0x9b, 0xfc, 0x5f, 0xfa, 0x73, 0xf7, 0x56, 0xf6, + 0xa5, 0xf5, 0x6c, 0xf3, 0x3b, 0xf0, 0xc1, 0xec, 0x53, 0xea, 0x3f, 0xea, + 0xfb, 0xe8, 0x1c, 0xe8, 0x79, 0xe7, 0xed, 0xe6, 0xf5, 0xe5, 0xde, 0xe6, + 0x47, 0xe9, 0x79, 0xeb, 0xff, 0xec, 0x14, 0xec, 0xf2, 0xe9, 0x25, 0xe9, + 0xa3, 0xea, 0xf3, 0xec, 0x36, 0xee, 0x28, 0xee, 0x8b, 0xee, 0xf2, 0xee, + 0x4f, 0xf2, 0x2d, 0xf5, 0x7e, 0xf7, 0x4c, 0xf9, 0x53, 0xfa, 0x02, 0xfc, + 0x3c, 0xfc, 0xf9, 0xfb, 0x98, 0xfe, 0x88, 0x00, 0xf5, 0x02, 0x04, 0x05, + 0x99, 0x05, 0x50, 0x07, 0xe3, 0x09, 0x62, 0x0d, 0xa0, 0x0e, 0xf4, 0x0e, + 0x9b, 0x0f, 0x1f, 0x11, 0x50, 0x12, 0x2b, 0x12, 0x6b, 0x11, 0xb6, 0x11, + 0xc2, 0x13, 0x45, 0x15, 0x8a, 0x15, 0x57, 0x15, 0x35, 0x15, 0x1c, 0x16, + 0x84, 0x16, 0x12, 0x15, 0xf0, 0x12, 0xf7, 0x11, 0x54, 0x12, 0x49, 0x12, + 0x78, 0x11, 0xd4, 0x0f, 0x4f, 0x0e, 0xcb, 0x0d, 0xc7, 0x0d, 0x35, 0x0d, + 0x3b, 0x0c, 0x73, 0x0b, 0x9c, 0x09, 0xe5, 0x06, 0x16, 0x05, 0xea, 0x03, + 0x68, 0x03, 0xa9, 0x02, 0x55, 0x00, 0x80, 0xfd, 0x20, 0xfb, 0xf6, 0xf8, + 0xff, 0xf8, 0xcd, 0xf7, 0x6a, 0xf5, 0x46, 0xf2, 0xcd, 0xee, 0x3e, 0xec, + 0x49, 0xea, 0xd4, 0xe8, 0x99, 0xe7, 0x82, 0xe5, 0xd9, 0xe5, 0x48, 0xe6, + 0x35, 0xe6, 0x30, 0xe8, 0xd4, 0xe7, 0xbf, 0xe8, 0xe4, 0xe9, 0xd7, 0xea, + 0x72, 0xeb, 0x6f, 0xea, 0x5b, 0xe9, 0xed, 0xe9, 0x74, 0xeb, 0xfa, 0xed, + 0xc4, 0xef, 0x91, 0xf0, 0x66, 0xf2, 0xa4, 0xf4, 0x07, 0xf7, 0xaf, 0xfb, + 0x2b, 0xfd, 0xf6, 0xfc, 0x9f, 0xfe, 0x65, 0xff, 0xcc, 0xff, 0x51, 0x02, + 0x3d, 0x04, 0x18, 0x06, 0xea, 0x08, 0x1c, 0x0a, 0x44, 0x0b, 0xdb, 0x0d, + 0x1b, 0x10, 0x76, 0x11, 0xcb, 0x12, 0x69, 0x12, 0xac, 0x11, 0x73, 0x12, + 0x1f, 0x13, 0x78, 0x13, 0x2b, 0x15, 0x08, 0x15, 0xd4, 0x14, 0xb1, 0x14, + 0xbe, 0x14, 0x15, 0x16, 0x19, 0x16, 0x0d, 0x14, 0xc1, 0x12, 0x9d, 0x11, + 0xaf, 0x11, 0xd3, 0x10, 0x15, 0x10, 0xd8, 0x0e, 0x75, 0x0d, 0xa3, 0x0d, + 0xeb, 0x0c, 0x90, 0x0b, 0x56, 0x0a, 0x34, 0x09, 0x6e, 0x08, 0x14, 0x07, + 0x87, 0x04, 0x27, 0x02, 0xed, 0x00, 0xcd, 0xff, 0x46, 0xfe, 0x7f, 0xfc, + 0xae, 0xf9, 0x13, 0xf7, 0x2f, 0xf7, 0xf1, 0xf5, 0x27, 0xf3, 0xe5, 0xef, + 0x2c, 0xec, 0x52, 0xea, 0x8f, 0xe9, 0x30, 0xe7, 0x56, 0xe5, 0x16, 0xe5, + 0x45, 0xe5, 0xbf, 0xe6, 0xf9, 0xe6, 0x96, 0xe6, 0x8e, 0xe8, 0x51, 0xec, + 0xed, 0xec, 0x1d, 0xeb, 0xdd, 0xe8, 0x4c, 0xe9, 0xfb, 0xec, 0x8f, 0xee, + 0x0b, 0xee, 0xca, 0xed, 0xfc, 0xef, 0x97, 0xf4, 0xc2, 0xf8, 0x21, 0xf9, + 0xb9, 0xf8, 0xe8, 0xfa, 0x0f, 0x00, 0x90, 0x03, 0x9a, 0x01, 0xfd, 0xff, + 0xeb, 0x00, 0xd4, 0x03, 0x8e, 0x07, 0xda, 0x08, 0xa0, 0x08, 0xc1, 0x0a, + 0xfc, 0x0d, 0x50, 0x10, 0x82, 0x12, 0x43, 0x12, 0xcf, 0x10, 0xdb, 0x11, + 0x80, 0x11, 0x41, 0x12, 0xe2, 0x12, 0x8d, 0x12, 0x2c, 0x13, 0xe6, 0x13, + 0x25, 0x14, 0x2d, 0x14, 0x7b, 0x14, 0xb2, 0x14, 0x29, 0x14, 0x60, 0x13, + 0xb7, 0x11, 0xf1, 0x10, 0x4d, 0x11, 0x57, 0x10, 0xe0, 0x0e, 0x3c, 0x0e, + 0x21, 0x0e, 0x23, 0x0d, 0x8c, 0x0c, 0xf8, 0x0b, 0x20, 0x0b, 0xf3, 0x09, + 0xd7, 0x07, 0xd8, 0x04, 0xf2, 0x02, 0x8b, 0x01, 0x94, 0xff, 0xa4, 0xfd, + 0xc3, 0xfa, 0x15, 0xf9, 0x9d, 0xf8, 0x51, 0xf7, 0x07, 0xf5, 0xd6, 0xf1, + 0x3f, 0xee, 0xce, 0xeb, 0x36, 0xe9, 0x51, 0xe6, 0x4c, 0xe4, 0x1e, 0xe4, + 0x56, 0xe2, 0x03, 0xe2, 0x40, 0xe3, 0xde, 0xe3, 0x29, 0xe7, 0x20, 0xeb, + 0xa4, 0xea, 0x51, 0xea, 0x99, 0xea, 0xba, 0xe9, 0x56, 0xec, 0x92, 0xed, + 0x11, 0xec, 0x0f, 0xee, 0x43, 0xf1, 0x96, 0xf3, 0x23, 0xf6, 0xd3, 0xf7, + 0xd9, 0xf9, 0x86, 0xfd, 0x31, 0x00, 0xd9, 0x01, 0xda, 0x03, 0xc7, 0x04, + 0x2f, 0x05, 0xb0, 0x05, 0x99, 0x06, 0xef, 0x08, 0x4e, 0x0c, 0x17, 0x0e, + 0x4e, 0x0f, 0xa9, 0x0f, 0x32, 0x10, 0xc0, 0x11, 0x42, 0x13, 0x10, 0x14, + 0xfa, 0x12, 0x9b, 0x11, 0x88, 0x10, 0xb3, 0x10, 0xb0, 0x11, 0xe4, 0x12, + 0x0c, 0x13, 0xcb, 0x12, 0xdb, 0x11, 0xd0, 0x11, 0x15, 0x13, 0xb9, 0x12, + 0x1c, 0x12, 0x2e, 0x11, 0x37, 0x10, 0x5f, 0x0f, 0x85, 0x0e, 0xe0, 0x0d, + 0x30, 0x0e, 0xff, 0x0d, 0xe4, 0x0d, 0x5a, 0x0c, 0x12, 0x0b, 0x09, 0x0a, + 0x2c, 0x09, 0x2b, 0x08, 0xac, 0x05, 0xe2, 0x02, 0x51, 0x00, 0x0f, 0xfe, + 0xb1, 0xfc, 0x1e, 0xfb, 0x95, 0xf8, 0xd4, 0xf5, 0x1d, 0xf3, 0xaf, 0xf0, + 0xaa, 0xed, 0x78, 0xea, 0x98, 0xe6, 0xa9, 0xe4, 0x0f, 0xe4, 0x41, 0xe3, + 0x98, 0xe3, 0xf5, 0xe1, 0xd2, 0xe2, 0x21, 0xe6, 0x2b, 0xe7, 0x71, 0xe8, + 0x8c, 0xe9, 0x4a, 0xea, 0xe6, 0xeb, 0xeb, 0xeb, 0xe8, 0xeb, 0xfb, 0xea, + 0xf0, 0xea, 0x6a, 0xed, 0x96, 0xef, 0xb5, 0xf4, 0xaf, 0xf7, 0x0c, 0xf9, + 0xd7, 0xfc, 0x87, 0xfd, 0x2f, 0x00, 0x6e, 0x02, 0x30, 0x03, 0x6c, 0x04, + 0xcf, 0x05, 0x9b, 0x05, 0xbc, 0x07, 0xae, 0x09, 0xc4, 0x0b, 0xd3, 0x0e, + 0x1e, 0x10, 0xc0, 0x11, 0x8f, 0x12, 0x2d, 0x12, 0x54, 0x13, 0xcf, 0x12, + 0x1a, 0x12, 0xee, 0x10, 0x70, 0x0f, 0x42, 0x10, 0xe7, 0x10, 0x99, 0x11, + 0x8a, 0x11, 0x26, 0x12, 0xb4, 0x12, 0x71, 0x13, 0xaa, 0x12, 0xd9, 0x11, + 0x19, 0x10, 0x4d, 0x10, 0x84, 0x10, 0xc1, 0x0f, 0x61, 0x0f, 0xc9, 0x0e, + 0xaf, 0x0e, 0x41, 0x0f, 0x66, 0x0f, 0xc7, 0x0e, 0x12, 0x0e, 0x1d, 0x0c, + 0xc3, 0x09, 0x93, 0x07, 0x5c, 0x06, 0x68, 0x04, 0x6e, 0x01, 0x6b, 0xfd, + 0x1d, 0xfa, 0x52, 0xfa, 0x39, 0xf8, 0x3e, 0xf5, 0x19, 0xf1, 0x19, 0xee, + 0x0d, 0xeb, 0x14, 0xe8, 0x4e, 0xe5, 0xc2, 0xe2, 0x9c, 0xe2, 0xfc, 0xe2, + 0x7f, 0xe2, 0x02, 0xe3, 0x41, 0xe4, 0x31, 0xe8, 0xeb, 0xea, 0x21, 0xeb, + 0xd0, 0xe9, 0xf5, 0xe8, 0xf7, 0xe9, 0x8b, 0xed, 0x94, 0xed, 0x61, 0xec, + 0x75, 0xed, 0x5c, 0xef, 0x27, 0xf4, 0xf2, 0xf6, 0xd2, 0xf8, 0x8f, 0xfb, + 0x6b, 0xfe, 0x1d, 0x01, 0x42, 0x02, 0x4c, 0x02, 0x7c, 0x03, 0x3f, 0x04, + 0xb6, 0x05, 0x0e, 0x07, 0xc9, 0x07, 0xef, 0x09, 0x6e, 0x0c, 0xd7, 0x0e, + 0x21, 0x10, 0xf1, 0x0f, 0x23, 0x10, 0x37, 0x10, 0xc6, 0x11, 0xcd, 0x10, + 0x3d, 0x0f, 0xf0, 0x0e, 0xda, 0x0e, 0x24, 0x0f, 0xb6, 0x0f, 0x30, 0x10, + 0x2d, 0x0f, 0x6d, 0x10, 0x60, 0x11, 0x04, 0x11, 0xa1, 0x10, 0xd9, 0x0f, + 0x0b, 0x10, 0x4e, 0x10, 0x6d, 0x10, 0xdc, 0x10, 0x96, 0x10, 0x9a, 0x10, + 0xfb, 0x11, 0x11, 0x12, 0xc7, 0x11, 0x0b, 0x11, 0x56, 0x0f, 0xa4, 0x0c, + 0x8d, 0x0a, 0x8a, 0x07, 0xaf, 0x04, 0xc4, 0x00, 0x7b, 0xfd, 0x25, 0xfb, + 0x97, 0xf8, 0x93, 0xf5, 0xe3, 0xf2, 0x2c, 0xef, 0xcc, 0xea, 0x98, 0xe6, + 0xb3, 0xe3, 0xea, 0xe2, 0x0b, 0xe3, 0xb6, 0xe2, 0x56, 0xe1, 0xfe, 0xdf, + 0xf6, 0xe1, 0x1c, 0xe5, 0x62, 0xe8, 0x4d, 0xe9, 0x4d, 0xe8, 0x4f, 0xe8, + 0x64, 0xe9, 0xcf, 0xeb, 0x17, 0xed, 0x13, 0xee, 0xcf, 0xec, 0x0b, 0xee, + 0xd0, 0xf2, 0xca, 0xf6, 0x9f, 0xf9, 0x6f, 0xfc, 0x14, 0xff, 0x46, 0x02, + 0x08, 0x04, 0x72, 0x02, 0x21, 0x04, 0x1d, 0x05, 0xb1, 0x06, 0xd4, 0x09, + 0x75, 0x09, 0x9a, 0x09, 0xe3, 0x0a, 0x12, 0x0d, 0x34, 0x0f, 0x26, 0x0f, + 0xe5, 0x0e, 0x59, 0x0f, 0xdc, 0x0f, 0x8d, 0x0e, 0x2c, 0x0c, 0xce, 0x0a, + 0x2b, 0x0b, 0x63, 0x0d, 0x5a, 0x0e, 0x93, 0x0d, 0x35, 0x0c, 0x60, 0x0d, + 0xa0, 0x0f, 0xbe, 0x10, 0xd8, 0x0e, 0xfa, 0x0c, 0x34, 0x0d, 0xa3, 0x0e, + 0x49, 0x0f, 0x98, 0x0e, 0xa2, 0x0d, 0x3b, 0x0f, 0xc5, 0x11, 0xcd, 0x12, + 0x45, 0x12, 0x70, 0x10, 0x08, 0x0f, 0x87, 0x0e, 0x17, 0x0d, 0x26, 0x0a, + 0x57, 0x05, 0xf5, 0xff, 0x1b, 0xfe, 0xa4, 0xfc, 0xef, 0xfa, 0x5f, 0xf6, + 0xf6, 0xf1, 0xae, 0xee, 0x0d, 0xea, 0x02, 0xe8, 0x03, 0xe6, 0x9d, 0xe5, + 0xd3, 0xe5, 0xf9, 0xe4, 0x04, 0xe5, 0x7e, 0xe6, 0x29, 0xe7, 0x51, 0xe9, + 0x73, 0xe9, 0x00, 0xeb, 0xad, 0xeb, 0xf8, 0xe8, 0x59, 0xe8, 0x07, 0xe8, + 0x23, 0xeb, 0x63, 0xef, 0x44, 0xf1, 0x52, 0xf1, 0xbe, 0xf2, 0xed, 0xf6, + 0x22, 0xfb, 0x2c, 0xff, 0xcf, 0xfe, 0xf6, 0xfe, 0x15, 0x01, 0xaf, 0x02, + 0xf1, 0x03, 0xe8, 0x04, 0x87, 0x04, 0x6e, 0x06, 0xb1, 0x08, 0x56, 0x09, + 0xfe, 0x0a, 0x71, 0x09, 0x2c, 0x0a, 0xb5, 0x0b, 0x37, 0x0c, 0x18, 0x0c, + 0xb5, 0x0a, 0x4e, 0x0a, 0x61, 0x0a, 0x72, 0x0a, 0x9e, 0x09, 0x15, 0x09, + 0x2c, 0x0a, 0x8b, 0x0c, 0x46, 0x0e, 0xfc, 0x0c, 0xed, 0x0a, 0xc8, 0x0a, + 0x01, 0x0e, 0x99, 0x0f, 0x2f, 0x0f, 0x97, 0x0c, 0x9d, 0x0c, 0x20, 0x0f, + 0xbb, 0x11, 0xbe, 0x12, 0x4b, 0x12, 0xe5, 0x11, 0x9b, 0x12, 0x7f, 0x13, + 0x56, 0x11, 0x84, 0x0c, 0xd1, 0x08, 0x6a, 0x08, 0xd9, 0x05, 0x72, 0x01, + 0xc5, 0xfc, 0x1f, 0xf9, 0xe9, 0xf9, 0xf5, 0xf6, 0xa0, 0xf0, 0x27, 0xeb, + 0xcf, 0xe5, 0x11, 0xe6, 0x27, 0xea, 0x4b, 0xe9, 0xc2, 0xe7, 0x49, 0xe7, + 0xd2, 0xe5, 0x7b, 0xe9, 0x65, 0xeb, 0xb1, 0xe8, 0xde, 0xe7, 0x33, 0xe9, + 0x1e, 0xea, 0x7e, 0xec, 0x60, 0xed, 0x21, 0xea, 0x25, 0xee, 0xad, 0xf1, + 0x27, 0xf5, 0x4b, 0xf9, 0xf1, 0xf9, 0xa6, 0xfc, 0x6a, 0x00, 0x3e, 0x00, + 0x9f, 0x01, 0x5e, 0x02, 0xac, 0x03, 0xa5, 0x05, 0x6d, 0x05, 0xb9, 0x04, + 0xfd, 0x05, 0xd3, 0x07, 0xcd, 0x08, 0xbf, 0x09, 0x34, 0x09, 0x42, 0x09, + 0xda, 0x07, 0x4f, 0x08, 0x35, 0x09, 0xd5, 0x08, 0x83, 0x08, 0xfe, 0x08, + 0xcc, 0x07, 0x5b, 0x07, 0x58, 0x07, 0x6f, 0x08, 0x83, 0x0a, 0xd1, 0x0a, + 0x20, 0x09, 0x1e, 0x0b, 0x1c, 0x0d, 0x16, 0x0d, 0x62, 0x0e, 0x71, 0x0e, + 0xa1, 0x0d, 0xdd, 0x0f, 0x69, 0x11, 0x4a, 0x14, 0x03, 0x15, 0xbc, 0x13, + 0xb2, 0x12, 0x15, 0x12, 0x9a, 0x10, 0x04, 0x0f, 0x0e, 0x0c, 0x0b, 0x06, + 0x3b, 0x02, 0x7f, 0xfe, 0x85, 0xfb, 0x4e, 0xf8, 0xc4, 0xf4, 0xe0, 0xed, + 0x09, 0xe8, 0x75, 0xe4, 0xb4, 0xe2, 0x62, 0xe5, 0x8c, 0xe8, 0x98, 0xe7, + 0xe3, 0xe5, 0x03, 0xe8, 0x9e, 0xea, 0xc6, 0xf0, 0xf6, 0xf2, 0x95, 0xf1, + 0xad, 0xef, 0x91, 0xf0, 0xbe, 0xf1, 0x58, 0xf4, 0x02, 0xf5, 0x1d, 0xf6, + 0xb0, 0xfa, 0xfa, 0xfe, 0x10, 0x04, 0x95, 0x06, 0x0f, 0x09, 0xf4, 0x0a, + 0xd6, 0x0b, 0xcb, 0x0b, 0x91, 0x09, 0xf6, 0x07, 0xc8, 0x06, 0xeb, 0x07, + 0xeb, 0x06, 0xb6, 0x03, 0xde, 0x01, 0x84, 0xff, 0x4d, 0x01, 0xc5, 0x02, + 0x03, 0x01, 0x2e, 0xfe, 0x1e, 0xfb, 0x01, 0xfa, 0xc1, 0xf9, 0xb1, 0xfa, + 0xd2, 0xf8, 0x03, 0xf8, 0x76, 0xf9, 0x25, 0xfb, 0x31, 0xfe, 0xa9, 0x01, + 0xea, 0x03, 0x19, 0x07, 0xe6, 0x08, 0xf9, 0x0a, 0x8c, 0x0c, 0x50, 0x0e, + 0x52, 0x10, 0xe4, 0x12, 0x0f, 0x15, 0xa1, 0x16, 0x19, 0x1a, 0xf2, 0x1b, + 0x3d, 0x1d, 0x2f, 0x1d, 0xd4, 0x19, 0xa5, 0x15, 0xad, 0x11, 0x2c, 0x0d, + 0x71, 0x08, 0x3e, 0x05, 0x7f, 0x01, 0xb4, 0xfb, 0xf3, 0xf6, 0x38, 0xed, + 0x46, 0xe8, 0x22, 0xe2, 0x9d, 0xdf, 0x01, 0xdd, 0x06, 0xdc, 0x08, 0xdc, + 0xe9, 0xdd, 0xe2, 0xe1, 0x7c, 0xe8, 0xf7, 0xee, 0xb5, 0xf4, 0x42, 0xf7, + 0xf9, 0xf7, 0x34, 0xfb, 0xd5, 0xfc, 0x9b, 0xff, 0xa8, 0x01, 0x5f, 0x02, + 0xe6, 0x02, 0x35, 0x05, 0xe2, 0x08, 0x42, 0x0e, 0xf1, 0x14, 0x1d, 0x17, + 0xd0, 0x16, 0x27, 0x13, 0x62, 0x0e, 0xe2, 0x08, 0xa5, 0x03, 0xc6, 0xfe, + 0x7f, 0xf9, 0x63, 0xf7, 0xe5, 0xf5, 0x23, 0xf5, 0xdb, 0xf3, 0xcf, 0xf2, + 0x45, 0xf1, 0x44, 0xf0, 0x36, 0xf0, 0x63, 0xee, 0xaf, 0xec, 0x50, 0xe8, + 0x4b, 0xe7, 0xa7, 0xe8, 0xff, 0xec, 0xff, 0xf3, 0xca, 0xf7, 0x01, 0x00, + 0x75, 0x07, 0xd9, 0x0e, 0x43, 0x15, 0x22, 0x19, 0x89, 0x1d, 0xa6, 0x20, + 0x44, 0x22, 0x45, 0x24, 0x5e, 0x26, 0x83, 0x29, 0x4a, 0x2b, 0xbc, 0x2b, + 0xba, 0x29, 0x84, 0x25, 0x57, 0x20, 0x6d, 0x18, 0x73, 0x11, 0xad, 0x08, + 0x4d, 0xfd, 0xa3, 0xf7, 0xa7, 0xf0, 0x98, 0xed, 0x85, 0xea, 0x54, 0xe4, + 0xa5, 0xdd, 0x29, 0xd4, 0x9d, 0xcb, 0xc2, 0xc4, 0x9f, 0xc5, 0x4c, 0xc8, + 0x69, 0xd0, 0x13, 0xd7, 0x36, 0xdd, 0x3d, 0xe9, 0x62, 0xf5, 0xf1, 0x02, + 0x07, 0x0c, 0x37, 0x11, 0x3f, 0x17, 0xb6, 0x1b, 0x73, 0x1f, 0x91, 0x20, + 0x45, 0x20, 0x61, 0x22, 0xcf, 0x23, 0x3f, 0x26, 0xa5, 0x26, 0x33, 0x27, + 0xd9, 0x1e, 0xb8, 0x15, 0x25, 0x0b, 0x14, 0xfe, 0xeb, 0xf3, 0x80, 0xec, + 0xdf, 0xe0, 0x6b, 0xd8, 0x45, 0xd6, 0x52, 0xd3, 0x55, 0xd7, 0x2d, 0xd8, + 0xab, 0xd5, 0x7b, 0xd7, 0x5c, 0xda, 0x76, 0xdf, 0xd4, 0xe3, 0xec, 0xe2, + 0x38, 0xe8, 0x94, 0xed, 0x00, 0xf8, 0xf0, 0x02, 0x62, 0x0b, 0x80, 0x16, + 0xfb, 0x1f, 0x9a, 0x28, 0xc0, 0x30, 0x64, 0x34, 0x0e, 0x32, 0x46, 0x33, + 0x8d, 0x33, 0x66, 0x35, 0xe8, 0x32, 0x50, 0x2f, 0x78, 0x2a, 0xfa, 0x26, + 0xc7, 0x20, 0xf3, 0x19, 0x30, 0x11, 0xb9, 0x09, 0x92, 0x02, 0xb1, 0xfa, + 0x80, 0xee, 0x49, 0xe3, 0xbe, 0xdd, 0x62, 0xd8, 0x21, 0xd5, 0xc3, 0xcc, + 0xf9, 0xc2, 0x3e, 0xb5, 0xdf, 0xb0, 0xb7, 0xae, 0x95, 0xb4, 0xa8, 0xc5, + 0x6f, 0xd4, 0x19, 0xe9, 0xa5, 0xfc, 0xc6, 0x10, 0x6d, 0x23, 0xfa, 0x32, + 0x5c, 0x3b, 0x69, 0x3d, 0xac, 0x3f, 0x62, 0x3b, 0x95, 0x39, 0xb9, 0x32, + 0xff, 0x2e, 0xb1, 0x2b, 0x60, 0x28, 0xb1, 0x23, 0x24, 0x1c, 0xef, 0x0f, + 0x29, 0xff, 0x3a, 0xef, 0x03, 0xdf, 0x7f, 0xd2, 0xab, 0xca, 0xf5, 0xc5, + 0x0f, 0xc3, 0xb0, 0xc3, 0xb8, 0xc4, 0x71, 0xc8, 0xb2, 0xcd, 0x24, 0xd3, + 0xdb, 0xdc, 0x59, 0xe5, 0xd0, 0xeb, 0xb8, 0xf1, 0x0a, 0xf8, 0xbb, 0x00, + 0x58, 0x0c, 0x3e, 0x17, 0x42, 0x1e, 0xdc, 0x25, 0x6d, 0x2b, 0xe9, 0x2f, + 0xa2, 0x33, 0xa6, 0x32, 0x54, 0x33, 0xa8, 0x31, 0x7d, 0x2d, 0xd7, 0x28, + 0xe7, 0x23, 0x8d, 0x1e, 0x00, 0x1b, 0x38, 0x16, 0x4c, 0x0d, 0xa9, 0x05, + 0xb6, 0xff, 0x2e, 0xfb, 0x75, 0xf5, 0x4e, 0xef, 0x68, 0xea, 0xf0, 0xe5, + 0x29, 0xe2, 0xa9, 0xdc, 0x44, 0xd6, 0xd8, 0xd0, 0x2e, 0xcc, 0x82, 0xc5, + 0xb6, 0xbe, 0x15, 0xb8, 0x98, 0xb8, 0xd2, 0xc4, 0x84, 0xd7, 0xc5, 0xeb, + 0xfa, 0xff, 0x15, 0x15, 0x7c, 0x28, 0x37, 0x3c, 0x60, 0x46, 0x79, 0x45, + 0x3c, 0x43, 0x37, 0x3e, 0xf5, 0x3a, 0xf3, 0x36, 0x24, 0x2d, 0xed, 0x24, + 0xcb, 0x1e, 0x3c, 0x19, 0x61, 0x0f, 0xbd, 0x03, 0x31, 0xf5, 0xb2, 0xe8, + 0x11, 0xdd, 0x58, 0xd3, 0x62, 0xcb, 0xe0, 0xc6, 0xc3, 0xc3, 0x00, 0xc2, + 0xd3, 0xc4, 0xb2, 0xc9, 0x2a, 0xd2, 0xe6, 0xd9, 0xf2, 0xe3, 0x75, 0xec, + 0x4a, 0xf6, 0xf8, 0xfe, 0x49, 0x06, 0x5c, 0x0c, 0xf2, 0x10, 0x6e, 0x18, + 0x24, 0x1f, 0x81, 0x25, 0xff, 0x28, 0xba, 0x2a, 0x67, 0x2c, 0xe1, 0x2d, + 0x97, 0x27, 0x14, 0x21, 0xf8, 0x1b, 0x53, 0x18, 0xdf, 0x19, 0x62, 0x16, + 0xe4, 0x11, 0x77, 0x0e, 0x61, 0x09, 0x89, 0x05, 0xed, 0x02, 0x7c, 0xfe, + 0x57, 0xf9, 0x48, 0xf7, 0xa9, 0xf2, 0xec, 0xed, 0xca, 0xe9, 0x51, 0xe5, + 0x0f, 0xe0, 0x99, 0xda, 0x12, 0xd3, 0xb0, 0xcb, 0x44, 0xc5, 0x46, 0xc0, + 0x91, 0xbd, 0xe9, 0xbf, 0x97, 0xcb, 0xa0, 0xdf, 0x56, 0xf9, 0x1e, 0x13, + 0x35, 0x22, 0xf2, 0x32, 0xd0, 0x3d, 0xc4, 0x45, 0x55, 0x49, 0x99, 0x43, + 0x34, 0x3d, 0x9b, 0x35, 0x06, 0x2f, 0xe1, 0x26, 0x5b, 0x23, 0x70, 0x19, + 0x44, 0x10, 0xf4, 0x04, 0x6d, 0xf7, 0x46, 0xe5, 0x9a, 0xd7, 0xf7, 0xcd, + 0xde, 0xc9, 0x45, 0xc6, 0x42, 0xc2, 0x13, 0xc4, 0x27, 0xc9, 0x87, 0xd3, + 0x06, 0xdc, 0x42, 0xe4, 0x0e, 0xed, 0xf7, 0xf5, 0xf9, 0xfd, 0xae, 0x05, + 0x7e, 0x0a, 0x1f, 0x0f, 0xad, 0x16, 0x55, 0x1c, 0xec, 0x20, 0xa3, 0x22, + 0x74, 0x21, 0x58, 0x21, 0x9f, 0x20, 0x02, 0x22, 0x59, 0x1e, 0xe9, 0x17, + 0x5f, 0x12, 0x5b, 0x0d, 0x47, 0x0d, 0xb2, 0x0d, 0xb6, 0x0d, 0xfc, 0x0c, + 0xde, 0x0c, 0x00, 0x0a, 0x6f, 0x04, 0x7e, 0x01, 0x66, 0xfd, 0xb6, 0xfa, + 0x36, 0xf7, 0xb0, 0xf0, 0x90, 0xeb, 0xf2, 0xe3, 0x9d, 0xdd, 0x85, 0xd9, + 0x15, 0xcf, 0x33, 0xc9, 0x0a, 0xc2, 0x5f, 0xbc, 0x26, 0xbc, 0x4b, 0xc5, + 0xdd, 0xd4, 0xe2, 0xf0, 0xfe, 0x0a, 0xd4, 0x1b, 0x16, 0x2d, 0xbc, 0x39, + 0xd1, 0x45, 0x70, 0x4a, 0xab, 0x46, 0x25, 0x3b, 0x47, 0x35, 0x8a, 0x30, + 0x54, 0x29, 0xd5, 0x1e, 0x34, 0x13, 0xa7, 0x0a, 0x02, 0x05, 0x83, 0xfc, + 0xde, 0xef, 0xd8, 0xe1, 0x61, 0xd6, 0xfb, 0xcb, 0x55, 0xc5, 0x52, 0xc3, + 0x99, 0xc5, 0x10, 0xcd, 0x65, 0xd7, 0xc6, 0xe3, 0xd5, 0xed, 0xb5, 0xf5, + 0x52, 0x00, 0x1e, 0x09, 0xe6, 0x0c, 0xae, 0x0d, 0x76, 0x0c, 0xf9, 0x0a, + 0x2e, 0x11, 0x9a, 0x17, 0x17, 0x1b, 0x71, 0x20, 0xd9, 0x22, 0x8d, 0x20, + 0xbd, 0x1a, 0x6e, 0x13, 0x8c, 0x0b, 0xe8, 0x08, 0x39, 0x07, 0x39, 0x06, + 0xbc, 0x08, 0x9b, 0x0b, 0x19, 0x10, 0x56, 0x12, 0x20, 0x12, 0x9e, 0x10, + 0xa9, 0x0b, 0x78, 0x05, 0x00, 0xff, 0xf6, 0xf6, 0xc9, 0xf0, 0x15, 0xe9, + 0xad, 0xe2, 0xa0, 0xdb, 0xcc, 0xd2, 0x03, 0xcc, 0x9d, 0xc4, 0x8a, 0xc2, + 0x60, 0xbd, 0x26, 0xbb, 0x26, 0xc2, 0xcd, 0xd5, 0x4b, 0xf0, 0x59, 0x0b, + 0xc8, 0x20, 0xe9, 0x32, 0xdc, 0x41, 0x5b, 0x47, 0x3f, 0x47, 0xc1, 0x42, + 0x30, 0x3e, 0x0d, 0x38, 0x81, 0x2d, 0xce, 0x22, 0x8e, 0x18, 0xd9, 0x11, + 0x94, 0x0a, 0x92, 0x03, 0xb6, 0xf6, 0x94, 0xe9, 0xe3, 0xdb, 0x78, 0xd2, + 0xf9, 0xcd, 0x19, 0xc9, 0x4e, 0xc7, 0x70, 0xcb, 0x3f, 0xd3, 0x24, 0xde, + 0x3b, 0xe9, 0x83, 0xf2, 0xfc, 0xfd, 0xa0, 0x0b, 0x60, 0x12, 0x53, 0x13, + 0x4c, 0x10, 0xd2, 0x10, 0x1f, 0x17, 0xfb, 0x19, 0x53, 0x1b, 0x51, 0x1a, + 0x21, 0x1b, 0x28, 0x19, 0x56, 0x15, 0xaf, 0x0e, 0x52, 0x05, 0x40, 0x01, + 0xe6, 0xff, 0x28, 0xff, 0x7c, 0x01, 0x81, 0x05, 0x90, 0x09, 0x1d, 0x12, + 0x40, 0x16, 0x51, 0x16, 0x81, 0x14, 0x24, 0x0f, 0x8b, 0x09, 0x5f, 0x02, + 0xa5, 0xf8, 0xc1, 0xef, 0x97, 0xe7, 0x83, 0xda, 0x4f, 0xd0, 0xb1, 0xc5, + 0xfa, 0xbd, 0x44, 0xb9, 0xdd, 0xb5, 0x5f, 0xb6, 0x9b, 0xc3, 0x7e, 0xda, + 0xda, 0xf7, 0x63, 0x13, 0x05, 0x26, 0xc1, 0x34, 0xd3, 0x3f, 0x02, 0x45, + 0x88, 0x46, 0x44, 0x42, 0x06, 0x3d, 0x67, 0x36, 0x4d, 0x2c, 0x93, 0x21, + 0x00, 0x16, 0x38, 0x0e, 0x03, 0x0b, 0x6b, 0x01, 0x11, 0xf1, 0x50, 0xe1, + 0x23, 0xd6, 0xf1, 0xcd, 0x1b, 0xcc, 0xe3, 0xc9, 0xcb, 0xc8, 0x3c, 0xd0, + 0xf6, 0xd9, 0x44, 0xe7, 0x2a, 0xf4, 0x65, 0xfe, 0x4f, 0x09, 0x45, 0x12, + 0x33, 0x16, 0xa5, 0x15, 0x57, 0x15, 0x83, 0x14, 0xd5, 0x16, 0xd1, 0x18, + 0x0a, 0x14, 0xf1, 0x12, 0xdf, 0x0f, 0x3d, 0x0c, 0xca, 0x09, 0x0c, 0x05, + 0x70, 0xfe, 0x26, 0xfa, 0xfa, 0xf9, 0x92, 0xfb, 0x88, 0x01, 0xfd, 0x08, + 0x67, 0x12, 0x56, 0x18, 0x44, 0x1a, 0xfa, 0x19, 0xaa, 0x16, 0x15, 0x11, + 0x00, 0x0c, 0x89, 0x05, 0x26, 0xfd, 0x2e, 0xf3, 0x01, 0xe5, 0xd2, 0xd6, + 0xe1, 0xcb, 0x76, 0xc1, 0x7c, 0xb6, 0xb2, 0xae, 0xb6, 0xaf, 0xc0, 0xbc, + 0x10, 0xd4, 0x4a, 0xf0, 0x21, 0x08, 0xdb, 0x19, 0xb4, 0x27, 0xbe, 0x34, + 0x17, 0x40, 0x22, 0x42, 0x17, 0x42, 0x34, 0x3d, 0x03, 0x36, 0x27, 0x2e, + 0x39, 0x24, 0xba, 0x1b, 0x19, 0x18, 0x0b, 0x12, 0x1e, 0x04, 0x34, 0xf2, + 0xf5, 0xe2, 0x19, 0xda, 0xe7, 0xd4, 0x30, 0xd1, 0x98, 0xce, 0x56, 0xd1, + 0x76, 0xd6, 0xf3, 0xde, 0x42, 0xe9, 0x55, 0xf3, 0x50, 0xfe, 0x35, 0x09, + 0x69, 0x0f, 0x05, 0x13, 0xd5, 0x14, 0xab, 0x17, 0x03, 0x1a, 0x75, 0x1a, + 0xf3, 0x16, 0x53, 0x11, 0x6f, 0x0c, 0xce, 0x09, 0xcf, 0x05, 0x5e, 0xff, + 0x47, 0xf9, 0x8b, 0xf4, 0xe7, 0xf3, 0x62, 0xf5, 0x39, 0xf9, 0x2c, 0x00, + 0x37, 0x0d, 0x52, 0x16, 0x6f, 0x1a, 0x6f, 0x1d, 0x64, 0x1c, 0x1d, 0x19, + 0xe4, 0x16, 0xbc, 0x11, 0x6f, 0x09, 0x2b, 0x01, 0x6e, 0xf3, 0x09, 0xe5, + 0xda, 0xd5, 0x23, 0xc7, 0xc9, 0xbd, 0x99, 0xb5, 0x14, 0xaf, 0x4a, 0xb2, + 0x4f, 0xbf, 0x82, 0xd7, 0x5c, 0xf4, 0x46, 0x0d, 0x93, 0x1c, 0xc0, 0x2b, + 0xe5, 0x37, 0xc8, 0x38, 0x85, 0x39, 0x39, 0x3b, 0xe5, 0x38, 0x1a, 0x35, + 0x41, 0x2f, 0xed, 0x24, 0xab, 0x1c, 0x59, 0x16, 0xe6, 0x0a, 0xee, 0xfb, + 0x97, 0xed, 0x9e, 0xe0, 0x8a, 0xd8, 0x03, 0xd4, 0x92, 0xd2, 0xfc, 0xd4, + 0xc2, 0xd7, 0x04, 0xe0, 0x5e, 0xe8, 0x11, 0xf0, 0x19, 0xf9, 0xb3, 0x01, + 0x3f, 0x0b, 0xd6, 0x10, 0x9a, 0x12, 0x4b, 0x15, 0x42, 0x15, 0x69, 0x16, + 0x44, 0x13, 0xd9, 0x0d, 0x26, 0x0b, 0x1f, 0x06, 0x13, 0xff, 0x09, 0xfb, + 0x6b, 0xf8, 0x71, 0xf6, 0x95, 0xf5, 0x88, 0xf6, 0x12, 0xf9, 0xbf, 0xff, + 0x9f, 0x08, 0x6d, 0x12, 0x4a, 0x1b, 0xef, 0x20, 0xac, 0x22, 0x06, 0x21, + 0x4a, 0x1b, 0x82, 0x14, 0x17, 0x0d, 0xe7, 0x02, 0x8c, 0xf6, 0x7d, 0xe6, + 0x7b, 0xd6, 0x7f, 0xc8, 0x04, 0xbb, 0x32, 0xb1, 0xe1, 0xac, 0xe0, 0xaf, + 0x3f, 0xc0, 0x79, 0xda, 0x08, 0xf4, 0x07, 0x0b, 0xa2, 0x1a, 0x31, 0x28, + 0x62, 0x34, 0x48, 0x39, 0xde, 0x3b, 0x58, 0x3a, 0xc1, 0x37, 0x22, 0x31, + 0xcf, 0x2d, 0xa5, 0x23, 0x6b, 0x1c, 0xb5, 0x11, 0xe6, 0x05, 0x71, 0xfb, + 0x92, 0xe9, 0x67, 0xdc, 0xe2, 0xd1, 0x0e, 0xd0, 0xf5, 0xd1, 0xe8, 0xd6, + 0x80, 0xde, 0xb4, 0xe6, 0x54, 0xf0, 0x6d, 0xfa, 0x1a, 0x02, 0x56, 0x06, + 0x52, 0x0b, 0x12, 0x10, 0xfc, 0x12, 0x2a, 0x14, 0xe5, 0x12, 0x3a, 0x11, + 0x96, 0x10, 0xad, 0x0d, 0x71, 0x07, 0xe0, 0x00, 0x9c, 0xfc, 0x6a, 0xf7, + 0x77, 0xf5, 0x45, 0xf5, 0xf4, 0xf5, 0x87, 0xf8, 0x85, 0xfd, 0x71, 0x04, + 0x64, 0x0b, 0x63, 0x16, 0xff, 0x1c, 0x5f, 0x1f, 0x6f, 0x20, 0x71, 0x1d, + 0x73, 0x1b, 0x45, 0x12, 0xd4, 0x09, 0x6a, 0xfe, 0xcb, 0xed, 0x8f, 0xdc, + 0xd0, 0xcc, 0xa4, 0xbd, 0xe6, 0xb5, 0x32, 0xb0, 0x4c, 0xb3, 0xea, 0xbb, + 0xe1, 0xd0, 0xb2, 0xee, 0x3e, 0x09, 0x3e, 0x1c, 0xf4, 0x25, 0x54, 0x2f, + 0x0b, 0x33, 0xb0, 0x39, 0x16, 0x3a, 0x72, 0x36, 0x12, 0x33, 0xbb, 0x2c, + 0x21, 0x24, 0x3d, 0x1a, 0xd9, 0x10, 0x09, 0x07, 0x2f, 0xfc, 0x88, 0xef, + 0x90, 0xe0, 0x3c, 0xd4, 0x4b, 0xcd, 0xd3, 0xd1, 0x2f, 0xdb, 0xb1, 0xe2, + 0xc1, 0xea, 0x8a, 0xf3, 0x5d, 0xfd, 0x68, 0x06, 0x23, 0x09, 0xa4, 0x0b, + 0x7d, 0x10, 0x50, 0x15, 0x8e, 0x15, 0xfc, 0x11, 0xea, 0x0d, 0x74, 0x0d, + 0x88, 0x0b, 0x07, 0x08, 0x7d, 0x00, 0xf6, 0xf9, 0xef, 0xf2, 0x2d, 0xf2, + 0xce, 0xf4, 0x94, 0xf4, 0xe1, 0xf7, 0x5e, 0xfd, 0x20, 0x04, 0xe8, 0x0d, + 0x1e, 0x15, 0xc4, 0x1a, 0xd6, 0x1f, 0x7a, 0x20, 0xfc, 0x1c, 0x72, 0x1d, + 0x78, 0x16, 0x80, 0x0d, 0x24, 0x03, 0x87, 0xef, 0xc6, 0xde, 0x64, 0xcc, + 0x62, 0xbf, 0x2a, 0xb6, 0x7c, 0xaf, 0xc9, 0xb0, 0xbe, 0xbb, 0xe0, 0xd1, + 0x9d, 0xed, 0x1c, 0x06, 0x3f, 0x18, 0x6b, 0x22, 0x32, 0x2d, 0xf7, 0x32, + 0x51, 0x36, 0xf4, 0x3b, 0x87, 0x39, 0xcf, 0x33, 0xa6, 0x2b, 0x20, 0x22, + 0x7d, 0x1c, 0xbe, 0x13, 0xba, 0x09, 0x73, 0xfb, 0x96, 0xec, 0x06, 0xdd, + 0x22, 0xd6, 0x9a, 0xd3, 0x8d, 0xda, 0x0b, 0xe1, 0xc8, 0xe6, 0x78, 0xeb, + 0xa6, 0xf1, 0x68, 0xf7, 0x34, 0x02, 0x52, 0x0a, 0x21, 0x0e, 0x65, 0x13, + 0xcf, 0x13, 0xea, 0x12, 0xce, 0x11, 0x27, 0x0e, 0xd1, 0x0b, 0x82, 0x0a, + 0x38, 0x05, 0x0e, 0xff, 0x1e, 0xf7, 0xc4, 0xf2, 0x23, 0xf2, 0x7c, 0xf4, + 0x43, 0xf7, 0xc7, 0xfa, 0x5e, 0xff, 0x89, 0x04, 0xab, 0x0d, 0xef, 0x14, + 0x26, 0x1d, 0x4d, 0x21, 0x0b, 0x21, 0xc6, 0x1c, 0x54, 0x16, 0x12, 0x0f, + 0xd6, 0x06, 0xab, 0xf9, 0xe2, 0xe7, 0x37, 0xd8, 0x46, 0xc9, 0xc4, 0xbe, + 0x3c, 0xb6, 0x8e, 0xb2, 0xb9, 0xb6, 0x41, 0xc8, 0x13, 0xe0, 0xd4, 0xf8, + 0x7b, 0x0e, 0xe1, 0x1c, 0x7d, 0x23, 0x07, 0x2c, 0x3a, 0x2f, 0x15, 0x32, + 0xd3, 0x30, 0xc1, 0x2f, 0x44, 0x2c, 0x64, 0x27, 0xc7, 0x20, 0x04, 0x18, + 0xb3, 0x10, 0x20, 0x05, 0x09, 0xfa, 0x86, 0xee, 0x9f, 0xe1, 0xee, 0xda, + 0x6f, 0xd9, 0x7c, 0xdd, 0x19, 0xe6, 0xb5, 0xf0, 0x1e, 0xf6, 0x21, 0xfb, + 0xba, 0xfe, 0x68, 0x01, 0x45, 0x07, 0x5e, 0x09, 0xbb, 0x0c, 0x61, 0x0c, + 0xda, 0x0c, 0xac, 0x0e, 0x3e, 0x0d, 0xb1, 0x09, 0x03, 0x05, 0xe9, 0xfe, + 0xcb, 0xf9, 0x21, 0xf6, 0xc3, 0xf2, 0x6f, 0xf2, 0xbf, 0xf5, 0x56, 0xfa, + 0x85, 0x00, 0x88, 0x07, 0x3a, 0x0d, 0x78, 0x15, 0xfd, 0x1b, 0x5c, 0x20, + 0x30, 0x21, 0x79, 0x1d, 0xce, 0x19, 0x84, 0x13, 0x1e, 0x0a, 0x0c, 0xfe, + 0x89, 0xed, 0x63, 0xd9, 0x5f, 0xca, 0x4a, 0xbd, 0xc9, 0xb5, 0x59, 0xb3, + 0xbb, 0xb8, 0x68, 0xc4, 0xfa, 0xdb, 0x7c, 0xf3, 0x11, 0x05, 0xc6, 0x17, + 0x18, 0x21, 0x47, 0x2f, 0x1a, 0x31, 0x7f, 0x30, 0xd8, 0x31, 0xb6, 0x30, + 0xd2, 0x2d, 0xe0, 0x27, 0x12, 0x21, 0x58, 0x19, 0x25, 0x11, 0x06, 0x08, + 0x84, 0xf7, 0xad, 0xe9, 0xe5, 0xdb, 0xb0, 0xd8, 0x15, 0xdc, 0x07, 0xe0, + 0x10, 0xe8, 0x9e, 0xef, 0xc6, 0xf7, 0xef, 0xff, 0xab, 0x05, 0xd8, 0x0a, + 0xbf, 0x0e, 0x0d, 0x11, 0x32, 0x10, 0xb1, 0x10, 0xc0, 0x0f, 0x81, 0x0d, + 0xe2, 0x0c, 0xaf, 0x07, 0x2a, 0x04, 0x2d, 0xfe, 0x29, 0xf7, 0x9b, 0xf2, + 0x1d, 0xf0, 0x00, 0xef, 0xbe, 0xf2, 0x4a, 0xf5, 0x6a, 0xf9, 0x9d, 0x01, + 0x6e, 0x0a, 0x44, 0x11, 0x35, 0x1a, 0x52, 0x1e, 0xa5, 0x1e, 0xf4, 0x1c, + 0x36, 0x18, 0xd3, 0x10, 0xa7, 0x09, 0x3b, 0xfa, 0x47, 0xeb, 0xa8, 0xdd, + 0x85, 0xcd, 0x45, 0xc4, 0x04, 0xbc, 0x7b, 0xb8, 0x3b, 0xbf, 0x26, 0xcb, + 0x2e, 0xe1, 0x54, 0xf7, 0xf8, 0x07, 0x0b, 0x18, 0x1f, 0x1f, 0xd0, 0x24, + 0xbf, 0x2a, 0x2e, 0x2d, 0x89, 0x2e, 0x55, 0x2d, 0xa2, 0x26, 0x49, 0x21, + 0x63, 0x1e, 0x3e, 0x17, 0x0b, 0x11, 0xf6, 0x05, 0x71, 0xf8, 0x95, 0xed, + 0x3c, 0xe6, 0x97, 0xe2, 0xbe, 0xe3, 0xf3, 0xe5, 0xae, 0xed, 0x09, 0xf7, + 0x73, 0xfc, 0x14, 0x02, 0xbf, 0x09, 0x06, 0x0b, 0xab, 0x0d, 0x4d, 0x0f, + 0x59, 0x0e, 0x99, 0x0d, 0x11, 0x0c, 0xa6, 0x08, 0x0d, 0x06, 0x7d, 0x02, + 0xeb, 0xfd, 0xd5, 0xfa, 0x6b, 0xf7, 0x0a, 0xf4, 0x6e, 0xf1, 0x7d, 0xef, + 0xfa, 0xf0, 0x1a, 0xf7, 0xf7, 0xfa, 0x20, 0x01, 0x60, 0x09, 0x59, 0x12, + 0xff, 0x16, 0x46, 0x1d, 0x81, 0x1c, 0x27, 0x1a, 0x26, 0x12, 0x42, 0x07, + 0xbd, 0xf9, 0x07, 0xf1, 0xb7, 0xe6, 0x9c, 0xd9, 0x29, 0xce, 0xc8, 0xc7, + 0x8f, 0xc1, 0x04, 0xc4, 0xb4, 0xd0, 0xc0, 0xe0, 0x9c, 0xf3, 0xb1, 0xff, + 0x64, 0x0b, 0x5c, 0x15, 0xf5, 0x1b, 0x82, 0x20, 0x1b, 0x2a, 0x9e, 0x28, + 0xd5, 0x2a, 0xb9, 0x28, 0xb9, 0x21, 0xc1, 0x1a, 0x27, 0x14, 0x4d, 0x0d, + 0x1f, 0x07, 0x9f, 0x01, 0x7f, 0xf6, 0x8b, 0xee, 0xaf, 0xe8, 0x15, 0xe7, + 0xd2, 0xec, 0x70, 0xf1, 0xff, 0xf5, 0xf1, 0xfb, 0x4a, 0xff, 0x0e, 0x02, + 0xf5, 0x05, 0xfc, 0x05, 0xf2, 0x0a, 0xf4, 0x0d, 0x57, 0x0e, 0x81, 0x0c, + 0xfb, 0x0a, 0xe8, 0x06, 0x6d, 0x03, 0x6e, 0xff, 0x8f, 0xfb, 0x77, 0xf8, + 0x8f, 0xf3, 0x48, 0xee, 0x89, 0xee, 0x36, 0xf0, 0x17, 0xf5, 0xe0, 0xfc, + 0x53, 0x02, 0xde, 0x07, 0x75, 0x0e, 0xce, 0x12, 0xaf, 0x16, 0xc0, 0x16, + 0x8a, 0x14, 0xd6, 0x12, 0x2a, 0x0a, 0xe7, 0x00, 0x03, 0xf7, 0x6c, 0xe9, + 0x69, 0xdc, 0x08, 0xd1, 0xd8, 0xc5, 0xf8, 0xc3, 0x6d, 0xc8, 0x71, 0xd6, + 0xb5, 0xe7, 0x0b, 0xf3, 0xd1, 0xfd, 0x55, 0x07, 0xd3, 0x0d, 0x57, 0x18, + 0x10, 0x19, 0xea, 0x1d, 0x23, 0x23, 0x62, 0x25, 0x34, 0x28, 0xb5, 0x23, + 0x48, 0x20, 0x6d, 0x1b, 0xc5, 0x13, 0xd1, 0x0a, 0xc9, 0x02, 0xfb, 0xfa, + 0x67, 0xf2, 0xc2, 0xed, 0x64, 0xea, 0x29, 0xed, 0x8a, 0xf0, 0xe8, 0xf3, + 0x95, 0xf8, 0x87, 0xfd, 0x1b, 0x02, 0x1f, 0x07, 0xd0, 0x0a, 0xb3, 0x0d, + 0x2c, 0x0f, 0x34, 0x0e, 0x7c, 0x0b, 0xc1, 0x0b, 0xfe, 0x09, 0x7a, 0x08, + 0xd9, 0x04, 0x31, 0xff, 0x4d, 0xf9, 0x23, 0xf3, 0x06, 0xef, 0x26, 0xec, + 0x46, 0xee, 0x18, 0xf0, 0xea, 0xf3, 0x0f, 0xfb, 0xa7, 0x01, 0x96, 0x07, + 0xcb, 0x0b, 0x39, 0x0f, 0x19, 0x12, 0x1e, 0x12, 0x1c, 0x0d, 0xfc, 0x07, + 0xb0, 0xff, 0x84, 0xf6, 0x35, 0xea, 0x44, 0xdc, 0x9f, 0xcf, 0xbf, 0xc8, + 0xcc, 0xcb, 0x41, 0xd5, 0x4c, 0xe0, 0x77, 0xee, 0xb4, 0xfa, 0x2e, 0x07, + 0xc7, 0x0f, 0x82, 0x15, 0x64, 0x16, 0xb9, 0x19, 0xaa, 0x1c, 0x51, 0x1b, + 0x74, 0x1f, 0x76, 0x1d, 0x52, 0x1c, 0x47, 0x1a, 0x1b, 0x14, 0xec, 0x0e, + 0xe9, 0x05, 0xb6, 0xfc, 0x48, 0xf7, 0x42, 0xf2, 0xcb, 0xee, 0x38, 0xee, + 0x03, 0xef, 0xcb, 0xee, 0x42, 0xf5, 0x83, 0xf9, 0xed, 0xff, 0x16, 0x08, + 0x18, 0x0d, 0x4b, 0x0f, 0x87, 0x13, 0x4f, 0x12, 0x72, 0x10, 0xf6, 0x12, + 0x3e, 0x10, 0x1a, 0x0f, 0xcb, 0x0a, 0x85, 0x03, 0x3d, 0xfd, 0xc9, 0xf8, + 0x81, 0xf3, 0xab, 0xf1, 0xe5, 0xef, 0xe3, 0xee, 0x96, 0xf1, 0xb7, 0xf4, + 0x6d, 0xf9, 0xd6, 0x01, 0x6f, 0x06, 0xdd, 0x0a, 0xc1, 0x0c, 0xd7, 0x0b, + 0xd8, 0x08, 0xdf, 0x03, 0x27, 0xfe, 0x5b, 0xf7, 0x7e, 0xef, 0x49, 0xe6, + 0x6a, 0xdf, 0xe3, 0xd8, 0xd8, 0xd5, 0xa3, 0xda, 0x57, 0xe3, 0x59, 0xea, + 0x4a, 0xf3, 0xc0, 0xfa, 0x49, 0x01, 0x40, 0x09, 0x31, 0x11, 0x20, 0x16, + 0xce, 0x17, 0x79, 0x19, 0x14, 0x1c, 0x5c, 0x1c, 0x1a, 0x1b, 0xfe, 0x15, + 0xcb, 0x13, 0x74, 0x12, 0x5b, 0x0e, 0xeb, 0x08, 0x79, 0x01, 0x6e, 0xfb, + 0x1f, 0xf7, 0x31, 0xf4, 0x0d, 0xf3, 0x58, 0xf3, 0xb5, 0xf6, 0xff, 0xf5, + 0x25, 0xf9, 0x82, 0xfb, 0x38, 0xff, 0xb0, 0x03, 0x83, 0x08, 0xfb, 0x0c, + 0x94, 0x11, 0x40, 0x14, 0x00, 0x14, 0x3b, 0x11, 0x3e, 0x0c, 0x17, 0x0a, + 0xfd, 0x05, 0x31, 0x01, 0x97, 0xfb, 0xdb, 0xf5, 0xc7, 0xf1, 0x0e, 0xf1, + 0x94, 0xf1, 0x2b, 0xf5, 0x99, 0xf9, 0x68, 0xfa, 0xf0, 0xfb, 0x3b, 0xfe, + 0xb7, 0x00, 0xa0, 0x03, 0x64, 0x06, 0x92, 0x05, 0xe5, 0x03, 0xbf, 0xfd, + 0x81, 0xf9, 0xde, 0xf0, 0xb2, 0xe7, 0x36, 0xdf, 0xa8, 0xd6, 0x0a, 0xd3, + 0x1d, 0xd9, 0x4d, 0xe2, 0x6d, 0xed, 0x82, 0xf5, 0xf0, 0xfb, 0x30, 0x03, + 0x16, 0x0a, 0x12, 0x0f, 0x2f, 0x13, 0x54, 0x17, 0x51, 0x17, 0xfe, 0x1d, + 0x22, 0x22, 0x7f, 0x21, 0xcb, 0x21, 0x4b, 0x1d, 0x79, 0x15, 0xd3, 0x0d, + 0xa6, 0x06, 0x12, 0xff, 0xc6, 0xfb, 0xef, 0xf6, 0x4d, 0xf3, 0x1d, 0xf2, + 0xf8, 0xef, 0x5d, 0xf2, 0xcc, 0xf6, 0xff, 0xf9, 0xd7, 0xfc, 0x82, 0x00, + 0xb2, 0x02, 0x04, 0x07, 0x0b, 0x0d, 0x55, 0x0f, 0x43, 0x11, 0x83, 0x12, + 0x19, 0x0d, 0x77, 0x0a, 0xf3, 0x05, 0xd1, 0x02, 0x48, 0xff, 0x59, 0xf9, + 0xd4, 0xf3, 0x73, 0xf0, 0x20, 0xf2, 0x46, 0xf4, 0x2b, 0xf8, 0x90, 0xfb, + 0xa4, 0xfc, 0x2b, 0xfe, 0x16, 0x03, 0xb0, 0x07, 0x2d, 0x0b, 0xee, 0x08, + 0xdd, 0x08, 0xc9, 0x06, 0x91, 0xff, 0xc1, 0xfa, 0x1e, 0xf1, 0x3d, 0xeb, + 0x39, 0xe4, 0x0d, 0xdf, 0x75, 0xd8, 0x1d, 0xd7, 0x25, 0xd7, 0x03, 0xde, + 0xb4, 0xe8, 0x24, 0xf1, 0x10, 0xfb, 0x9c, 0x06, 0x52, 0x0b, 0x8e, 0x12, + 0xa8, 0x16, 0xc5, 0x1b, 0x89, 0x20, 0xb8, 0x21, 0x03, 0x21, 0x51, 0x1d, + 0xc8, 0x17, 0x63, 0x14, 0x7f, 0x12, 0xa8, 0x0d, 0xa9, 0x09, 0x9e, 0x02, + 0x9b, 0xfa, 0xfb, 0xf6, 0x1b, 0xf2, 0x6d, 0xef, 0x15, 0xf1, 0x80, 0xf3, + 0x3f, 0xf6, 0xb6, 0xfc, 0x25, 0x00, 0x86, 0x05, 0x78, 0x0a, 0x4b, 0x0e, + 0x2d, 0x11, 0x02, 0x11, 0x49, 0x0f, 0x8d, 0x0d, 0x37, 0x08, 0x81, 0x03, + 0x15, 0xff, 0x92, 0xf8, 0xa2, 0xf5, 0x0a, 0xf3, 0x6f, 0xef, 0x19, 0xee, + 0xa9, 0xf1, 0xf2, 0xf3, 0x44, 0xfc, 0x01, 0x02, 0x32, 0x05, 0x34, 0x08, + 0xaf, 0x08, 0xc2, 0x07, 0x8a, 0x0b, 0xdc, 0x0a, 0x36, 0x08, 0xc4, 0x04, + 0xb8, 0xff, 0xc4, 0xfa, 0x8b, 0xf5, 0xbb, 0xef, 0x25, 0xe8, 0xdc, 0xde, + 0x56, 0xd9, 0x4f, 0xd4, 0xc4, 0xd8, 0xee, 0xdf, 0xc4, 0xe9, 0x1b, 0xf5, + 0xb5, 0xfe, 0xc5, 0x05, 0x33, 0x09, 0xbb, 0x0a, 0x88, 0x0d, 0xb7, 0x0d, + 0xcc, 0x12, 0xf3, 0x1a, 0xbc, 0x1a, 0xf2, 0x1a, 0x12, 0x1b, 0x96, 0x17, + 0x2c, 0x16, 0x94, 0x11, 0xb1, 0x0a, 0xf2, 0x04, 0x84, 0x01, 0xff, 0xff, + 0xa0, 0xfe, 0x6c, 0xfb, 0x59, 0xf8, 0x5a, 0xf8, 0xd0, 0xf8, 0xba, 0xfd, +)) + + +def gradient(r, g, b): + for y in range(0, height): + for x in range(0, width): + graphics.set_pen(graphics.create_pen(int((r * x) / 52), int((g * x) / 52), int((b * x) / 52))) + graphics.pixel(x, y) + + +def grid(r, g, b): + for y in range(0, height): + for x in range(0, width): + if (x + y) % 2 == 0: + graphics.set_pen(graphics.create_pen(r, g, b)) + else: + graphics.set_pen(0) + graphics.pixel(x, y) + + +def outline_text(text): + ms = time.ticks_ms() + + graphics.set_font("bitmap8") + v = int((math.sin(ms / 100.0) + 1.0) * 127.0) + w = graphics.measure_text(text, 1) + + x = int(53 / 2 - w / 2 + 1) + y = 2 + + graphics.set_pen(0) + graphics.text(text, x - 1, y - 1, -1, 1) + graphics.text(text, x, y - 1, -1, 1) + graphics.text(text, x + 1, y - 1, -1, 1) + graphics.text(text, x - 1, y, -1, 1) + graphics.text(text, x + 1, y, -1, 1) + graphics.text(text, x - 1, y + 1, -1, 1) + graphics.text(text, x, y + 1, -1, 1) + graphics.text(text, x + 1, y + 1, -1, 1) + + graphics.set_pen(graphics.create_pen(v, v, v)) + graphics.text(text, x, y, -1, 1) + + +gu.set_brightness(0.5) +was_a_pressed = False +was_b_pressed = False +was_c_pressed = False +was_d_pressed = False + +while True: + + time_ms = time.ticks_ms() + test = (time_ms // 1000) % 5 + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + if not was_a_pressed: + gu.play_sample(left_channel) + was_a_pressed = True + else: + was_a_pressed = False + + if gu.is_pressed(GalacticUnicorn.SWITCH_B): + if not was_b_pressed: + gu.play_tone(1000) + was_b_pressed = True + else: + was_b_pressed = False + + if gu.is_pressed(GalacticUnicorn.SWITCH_C): + if not was_c_pressed: + gu.play_tone(2000) + was_c_pressed = True + else: + was_c_pressed = False + + if gu.is_pressed(GalacticUnicorn.SWITCH_D): + if not was_d_pressed: + gu.stop_playing() + was_d_pressed = True + else: + was_d_pressed = False + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + graphics.set_pen(graphics.create_pen(0, 0, 0)) + graphics.clear() + + if test == 0: + print("grid pattern") + grid(255, 255, 255) + elif test == 1: + print("red gradient") + gradient(255, 0, 0) + elif test == 2: + print("green gradient") + gradient(0, 255, 0) + elif test == 3: + print("blue gradient") + gradient(0, 0, 255) + elif test == 4: + print("white gradient") + gradient(255, 255, 255) + + text = "" + + if gu.is_pressed(GalacticUnicorn.SWITCH_A): + text = "Button A" + + if gu.is_pressed(GalacticUnicorn.SWITCH_B): + text = "Button B" + + if gu.is_pressed(GalacticUnicorn.SWITCH_C): + text = "Button C" + + if gu.is_pressed(GalacticUnicorn.SWITCH_D): + text = "Button D" + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): + text = "Louder!" + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): + text = "Quieter" + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): + text = "Brighter!" + + if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): + text = "Darker" + + if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): + text = "Zzz... zzz..." + + outline_text(text) + + gu.update(graphics) diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 6bd7b571..2049f63f 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -14,6 +14,8 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adj MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_tone_obj, GalacticUnicorn_play_tone); +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing); /***** Binding of Methods *****/ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { @@ -29,6 +31,8 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) }, { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&GalacticUnicorn_play_tone_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_playing), MP_ROM_PTR(&GalacticUnicorn_stop_playing_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 09920079..549e6644 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -158,4 +158,18 @@ extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data) { return mp_const_none; } + +extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->play_tone(mp_obj_get_float(freq)); + + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->stop_playing(); + + return mp_const_none; +} } diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index c5f02f83..616181ab 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -24,4 +24,6 @@ extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); -extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); \ No newline at end of file +extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); +extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq); +extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in); \ No newline at end of file From 12ea527f4454ea572de5007eae9507c083acbdcc Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Fri, 19 Aug 2022 12:43:02 +0100 Subject: [PATCH 30/42] Audio performance improvements and bugfixes --- .../galactic_unicorn/galactic_unicorn.cpp | 123 ++++++++++++------ .../galactic_unicorn/galactic_unicorn.hpp | 22 +++- .../feature_test_with_audio.py | 45 +++++-- .../galactic_unicorn/galactic_unicorn.c | 2 + .../galactic_unicorn/galactic_unicorn.cpp | 7 + .../galactic_unicorn/galactic_unicorn.h | 1 + 6 files changed, 147 insertions(+), 53 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index ea7fa2a5..5bb2c1b2 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -45,6 +45,8 @@ static uint16_t b_gamma_lut[256] = {0}; static uint32_t dma_channel; static uint32_t audio_dma_channel; +static const int16_t sine_waveform[256] = {-32768,-32758,-32729,-32679,-32610,-32522,-32413,-32286,-32138,-31972,-31786,-31581,-31357,-31114,-30853,-30572,-30274,-29957,-29622,-29269,-28899,-28511,-28106,-27684,-27246,-26791,-26320,-25833,-25330,-24812,-24279,-23732,-23170,-22595,-22006,-21403,-20788,-20160,-19520,-18868,-18205,-17531,-16846,-16151,-15447,-14733,-14010,-13279,-12540,-11793,-11039,-10279,-9512,-8740,-7962,-7180,-6393,-5602,-4808,-4011,-3212,-2411,-1608,-804,0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32767,32758,32729,32679,32610,32522,32413,32286,32138,31972,31786,31581,31357,31114,30853,30572,30274,29957,29622,29269,28899,28511,28106,27684,27246,26791,26320,25833,25330,24812,24279,23732,23170,22595,22006,21403,20788,20160,19520,18868,18205,17531,16846,16151,15447,14733,14010,13279,12540,11793,11039,10279,9512,8740,7962,7180,6393,5602,4808,4011,3212,2411,1608,804,0,-804,-1608,-2411,-3212,-4011,-4808,-5602,-6393,-7180,-7962,-8740,-9512,-10279,-11039,-11793,-12540,-13279,-14010,-14733,-15447,-16151,-16846,-17531,-18205,-18868,-19520,-20160,-20788,-21403,-22006,-22595,-23170,-23732,-24279,-24812,-25330,-25833,-26320,-26791,-27246,-27684,-28106,-28511,-28899,-29269,-29622,-29957,-30274,-30572,-30853,-31114,-31357,-31581,-31786,-31972,-32138,-32286,-32413,-32522,-32610,-32679,-32729,-32758}; + namespace pimoroni { GalacticUnicorn* GalacticUnicorn::unicorn = nullptr; @@ -59,21 +61,26 @@ namespace pimoroni { // next scanline (or quit if we're finished) void __isr GalacticUnicorn::dma_complete() { if(unicorn != nullptr) { - uint mask = (1u << dma_channel) | (1u << audio_dma_channel); - while(dma_hw->ints0 & mask) { - if(dma_channel_get_irq0_status(dma_channel)) { - unicorn->next_dma_sequence(); - } - if(dma_channel_get_irq0_status(audio_dma_channel)) { - unicorn->loop_tone(); - } + if(dma_channel_get_irq0_status(dma_channel)) { + gpio_put(I2C_SCL, true); + unicorn->next_dma_sequence(); + gpio_put(I2C_SCL, false); + } + if(dma_channel_get_irq0_status(audio_dma_channel)) { + gpio_put(I2C_SDA, true); + unicorn->loop_tone(); + gpio_put(I2C_SDA, false); + } } } void GalacticUnicorn::next_dma_sequence() { // Clear any interrupt request caused by our channel - dma_channel_acknowledge_irq0(dma_channel); + //dma_channel_acknowledge_irq0(dma_channel); + // NOTE Temporary replacement of the above until this reaches pico-sdk main: + // https://github.com/raspberrypi/pico-sdk/issues/974 + dma_hw->ints0 = 1u << dma_channel; dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); dma_channel_set_read_addr(dma_channel, bitstream, true); @@ -172,6 +179,10 @@ namespace pimoroni { } } + // temp for debugging + gpio_init(I2C_SDA); gpio_set_dir(I2C_SDA, GPIO_OUT); gpio_put(I2C_SDA, false); + gpio_init(I2C_SCL); gpio_set_dir(I2C_SCL, GPIO_OUT); gpio_put(I2C_SCL, false); + // setup light sensor adc adc_init(); adc_gpio_init(LIGHT_SENSOR); @@ -322,7 +333,7 @@ namespace pimoroni { audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK); uint32_t system_clock_frequency = clock_get_hz(clk_sys); - uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow + uint32_t divider = system_clock_frequency * 4 / SYSTEM_FREQ; // avoid arithmetic overflow pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu); audio_dma_channel = dma_claim_unused_channel(true); @@ -378,49 +389,79 @@ namespace pimoroni { // Restart the audio SM and start a new DMA transfer pio_sm_set_enabled(audio_pio, audio_sm, true); dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 2); + play_mode = PLAYING_BUFFER; } } void GalacticUnicorn::play_tone(float frequency) { - stop_playing(); + play_dual_tone(frequency, 0.0f); + } - const uint system_freq = 22050; + void GalacticUnicorn::play_dual_tone(float freq_a, float freq_b) { + if(play_mode != PLAYING_TONE) { + stop_playing(); + } if(unicorn == this) { - uint wraps = 1; - uint rounded_freq = (int)roundf(frequency); - if(system_freq % rounded_freq != 0) { - while((rounded_freq * wraps) < (system_freq / 5)) { - if((system_freq * wraps) % rounded_freq != 0) { - wraps += 1; - } - else { - break; - } - } + + tone_frequency_a = MAX(freq_a, 0.0f); + tone_frequency_b = MAX(freq_b, 0.0f); + + if(play_mode == NOT_PLAYING) { + // Nothing is playing, so we can set up the first buffer straight away + current_buffer = 0; + + populate_next_buffer(); + + // Restart the audio SM and start a new DMA transfer + pio_sm_set_enabled(audio_pio, audio_sm, true); + + play_mode = PLAYING_TONE; + + loop_tone(); } - - uint samples_for_full_wave = (uint)((system_freq * wraps) / rounded_freq); - buffer_length = samples_for_full_wave; - for(uint i = 0; i < buffer_length; i++) { - int16_t val = roundf(sinf(((float)(i * wraps) / (float)samples_for_full_wave) * 2 * M_PI) * 0x1fff); - tone_buffer[(i * 2)] = (uint8_t)(val & 0xff); - tone_buffer[(i * 2) + 1] = (uint8_t)((val >> 8) & 0xff); - } - - // Restart the audio SM and start a new DMA transfer - pio_sm_set_enabled(audio_pio, audio_sm, true); - - loop_tone(); } } void GalacticUnicorn::loop_tone() { // Clear any interrupt request caused by our channel - dma_channel_acknowledge_irq0(audio_dma_channel); + //dma_channel_acknowledge_irq0(audio_dma_channel); + // NOTE Temporary replacement of the above until this reaches pico-sdk main: + // https://github.com/raspberrypi/pico-sdk/issues/974 + dma_hw->ints0 = 1u << audio_dma_channel; - if(buffer_length > 0) - dma_channel_transfer_from_buffer_now(audio_dma_channel, tone_buffer, buffer_length); + if(play_mode == PLAYING_TONE) { + + dma_channel_transfer_from_buffer_now(audio_dma_channel, tone_buffers[current_buffer], TONE_BUFFER_SIZE); + current_buffer = (current_buffer + 1) % NUM_TONE_BUFFERS; + + populate_next_buffer(); + } + else { + play_mode = NOT_PLAYING; + } + } + + void GalacticUnicorn::populate_next_buffer() { + float percent_along_a, percent_along_b; + int16_t val; + int16_t* buffer = tone_buffers[current_buffer]; + + //sine_waveform + for(uint i = 0; i < TONE_BUFFER_SIZE; i++) { + percent_along_a = (((float)i * tone_frequency_a) / SYSTEM_FREQ) + wave_start_a; + val = (sine_waveform[(int)(percent_along_a * 256.0f) % 256] * 0x0fff) >> 16; + //val = sinf(percent_along_a * 2 * M_PI) * 0x0fff; + + percent_along_b = (((float)i * tone_frequency_b) / SYSTEM_FREQ) + wave_start_b; + val += (sine_waveform[(int)(percent_along_b * 256.0f) % 256] * 0x0fff) >> 16; + //val += sinf(percent_along_b * 2 * M_PI) * 0x0fff; + + buffer[i] = val; + } + + wave_start_a = fmodf((((float)TONE_BUFFER_SIZE * tone_frequency_a) / SYSTEM_FREQ) + wave_start_a, 1.0f); + wave_start_b = fmodf((((float)TONE_BUFFER_SIZE * tone_frequency_b) / SYSTEM_FREQ) + wave_start_b, 1.0f); } void GalacticUnicorn::stop_playing() { @@ -432,10 +473,10 @@ namespace pimoroni { const uint pins_to_clear = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK; pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_clear); - buffer_length = 0; - // Abort any in-progress DMA transfer dma_safe_abort(audio_dma_channel); + + play_mode = NOT_PLAYING; } } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 281cb431..509ad140 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -50,6 +50,7 @@ namespace pimoroni { static const uint32_t BCD_FRAME_BYTES = 60; static const uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES; static const uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES); + static const uint SYSTEM_FREQ = 22050; private: static PIO bitstream_pio; @@ -68,9 +69,22 @@ namespace pimoroni { static GalacticUnicorn* unicorn; static void dma_complete(); - static const uint TONE_BUFFER_SIZE = 22050 / 2; - uint8_t tone_buffer[TONE_BUFFER_SIZE * 2] = {0}; - uint buffer_length = 0; + static const uint NUM_TONE_BUFFERS = 2; + static const uint TONE_BUFFER_SIZE = 16; + int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0}; + uint current_buffer = 0; + + float tone_frequency_a = 0.0f; + float tone_frequency_b = 0.0f; + float wave_start_a = 0.0f; + float wave_start_b = 0.0f; + + enum PlayMode { + PLAYING_BUFFER, + PLAYING_TONE, + NOT_PLAYING + }; + PlayMode play_mode = NOT_PLAYING; public: ~GalacticUnicorn(); @@ -100,6 +114,7 @@ namespace pimoroni { void play_sample(uint8_t *data, uint32_t length); void play_tone(float frequency); + void play_dual_tone(float freq_a, float freq_b); void stop_playing(); private: @@ -107,6 +122,7 @@ namespace pimoroni { void partial_teardown(); void dma_safe_abort(uint channel); void loop_tone(); + void populate_next_buffer(); }; } \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index 89976648..ceb5de41 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -659,6 +659,10 @@ was_b_pressed = False was_c_pressed = False was_d_pressed = False +bool_playing = False +freq_a = 0 +freq_b = 0 + while True: time_ms = time.ticks_ms() @@ -667,54 +671,77 @@ while True: if gu.is_pressed(GalacticUnicorn.SWITCH_A): if not was_a_pressed: gu.play_sample(left_channel) + bool_playing = False was_a_pressed = True else: was_a_pressed = False if gu.is_pressed(GalacticUnicorn.SWITCH_B): if not was_b_pressed: - gu.play_tone(1000) + freq_a = 400 + gu.play_dual_tone(freq_a, freq_b) + bool_playing = True was_b_pressed = True else: was_b_pressed = False if gu.is_pressed(GalacticUnicorn.SWITCH_C): if not was_c_pressed: - gu.play_tone(2000) + freq_b = 600 + gu.play_dual_tone(freq_a, freq_b) + bool_playing = True was_c_pressed = True else: was_c_pressed = False if gu.is_pressed(GalacticUnicorn.SWITCH_D): if not was_d_pressed: + freq_a = 0 + freq_b = 0 gu.stop_playing() was_d_pressed = True else: was_d_pressed = False if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): - gu.adjust_brightness(+0.01) + # gu.adjust_brightness(+0.01) + if bool_playing: + freq_b += 10 + gu.play_dual_tone(freq_a, freq_b) if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): - gu.adjust_brightness(-0.01) + # gu.adjust_brightness(-0.01) + if bool_playing: + freq_a -= 10 + gu.play_dual_tone(freq_a, freq_b) + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): + if bool_playing: + freq_a += 10 + gu.play_dual_tone(freq_a, freq_b) + + if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): + if bool_playing: + freq_a -= 10 + gu.play_dual_tone(freq_a, freq_b) graphics.set_pen(graphics.create_pen(0, 0, 0)) graphics.clear() if test == 0: - print("grid pattern") + # print("grid pattern") grid(255, 255, 255) elif test == 1: - print("red gradient") + # print("red gradient") gradient(255, 0, 0) elif test == 2: - print("green gradient") + # print("green gradient") gradient(0, 255, 0) elif test == 3: - print("blue gradient") + # print("blue gradient") gradient(0, 0, 255) elif test == 4: - print("white gradient") + # print("white gradient") gradient(255, 255, 255) text = "" diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 2049f63f..c706fe22 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -15,6 +15,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_tone_obj, GalacticUnicorn_play_tone); +MP_DEFINE_CONST_FUN_OBJ_3(GalacticUnicorn_play_dual_tone_obj, GalacticUnicorn_play_dual_tone); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing); /***** Binding of Methods *****/ @@ -32,6 +33,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, { MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&GalacticUnicorn_play_tone_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_dual_tone), MP_ROM_PTR(&GalacticUnicorn_play_dual_tone_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_playing), MP_ROM_PTR(&GalacticUnicorn_stop_playing_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 549e6644..9e1f319b 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -166,6 +166,13 @@ extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq) { return mp_const_none; } +extern mp_obj_t GalacticUnicorn_play_dual_tone(mp_obj_t self_in, mp_obj_t freq_a, mp_obj_t freq_b) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->play_dual_tone(mp_obj_get_float(freq_a), mp_obj_get_float(freq_b)); + + return mp_const_none; +} + extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); self->galactic->stop_playing(); diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 616181ab..76c312db 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -26,4 +26,5 @@ extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq); +extern mp_obj_t GalacticUnicorn_play_dual_tone(mp_obj_t self_in, mp_obj_t freq_a, mp_obj_t freq_b); extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in); \ No newline at end of file From deec835692f070089c95e06209f3bb7a9af7dd2c Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Fri, 19 Aug 2022 17:25:44 +0100 Subject: [PATCH 31/42] First addition of synth to GU --- .../galactic_unicorn/galactic_unicorn.cmake | 1 + .../galactic_unicorn/galactic_unicorn.cpp | 156 ++++++++++++++++- .../galactic_unicorn/galactic_unicorn.hpp | 14 +- libraries/galactic_unicorn/synth.cpp | 160 ++++++++++++++++++ libraries/galactic_unicorn/synth.hpp | 132 +++++++++++++++ .../feature_test_with_audio.py | 26 ++- .../galactic_unicorn/galactic_unicorn.c | 2 + .../galactic_unicorn/galactic_unicorn.cpp | 7 + .../galactic_unicorn/galactic_unicorn.h | 1 + 9 files changed, 484 insertions(+), 15 deletions(-) create mode 100644 libraries/galactic_unicorn/synth.cpp create mode 100644 libraries/galactic_unicorn/synth.hpp diff --git a/libraries/galactic_unicorn/galactic_unicorn.cmake b/libraries/galactic_unicorn/galactic_unicorn.cmake index c99a3473..0df2a35a 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cmake +++ b/libraries/galactic_unicorn/galactic_unicorn.cmake @@ -6,6 +6,7 @@ pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pi target_sources(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp + ${CMAKE_CURRENT_LIST_DIR}/synth.cpp ) target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 5bb2c1b2..b35302b8 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -47,6 +47,40 @@ static uint32_t audio_dma_channel; static const int16_t sine_waveform[256] = {-32768,-32758,-32729,-32679,-32610,-32522,-32413,-32286,-32138,-31972,-31786,-31581,-31357,-31114,-30853,-30572,-30274,-29957,-29622,-29269,-28899,-28511,-28106,-27684,-27246,-26791,-26320,-25833,-25330,-24812,-24279,-23732,-23170,-22595,-22006,-21403,-20788,-20160,-19520,-18868,-18205,-17531,-16846,-16151,-15447,-14733,-14010,-13279,-12540,-11793,-11039,-10279,-9512,-8740,-7962,-7180,-6393,-5602,-4808,-4011,-3212,-2411,-1608,-804,0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32767,32758,32729,32679,32610,32522,32413,32286,32138,31972,31786,31581,31357,31114,30853,30572,30274,29957,29622,29269,28899,28511,28106,27684,27246,26791,26320,25833,25330,24812,24279,23732,23170,22595,22006,21403,20788,20160,19520,18868,18205,17531,16846,16151,15447,14733,14010,13279,12540,11793,11039,10279,9512,8740,7962,7180,6393,5602,4808,4011,3212,2411,1608,804,0,-804,-1608,-2411,-3212,-4011,-4808,-5602,-6393,-7180,-7962,-8740,-9512,-10279,-11039,-11793,-12540,-13279,-14010,-14733,-15447,-16151,-16846,-17531,-18205,-18868,-19520,-20160,-20788,-21403,-22006,-22595,-23170,-23732,-24279,-24812,-25330,-25833,-26320,-26791,-27246,-27684,-28106,-28511,-28899,-29269,-29622,-29957,-30274,-30572,-30853,-31114,-31357,-31581,-31786,-31972,-32138,-32286,-32413,-32522,-32610,-32679,-32729,-32758}; +#define SONG_LENGTH 384 +#define HAT 20000 +#define BASS 500 +#define SNARE 6000 +#define SUB 50 + +static const int16_t notes[5][SONG_LENGTH] = { + { // melody notes + 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 220, 0, 196, 0, 147, 0, 175, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, + 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 220, 0, 196, 0, 147, 0, 175, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, + 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 262, 0, 294, 0, 392, 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { // rhythm notes + 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, + 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, + 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, + }, + { // drum beats + BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, + BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, + BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0 + }, + { // hi-hat + HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, + HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, + HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1 + }, + { // bass notes under bass drum + SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, + SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, + SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0 + }, +}; + namespace pimoroni { GalacticUnicorn* GalacticUnicorn::unicorn = nullptr; @@ -350,6 +384,57 @@ namespace pimoroni { irq_set_enabled(DMA_IRQ_0, true); } + + // configure voices +/* + channels[0].waveforms = Waveform::SINE; + channels[0].attack_ms = 1; + channels[0].decay_ms = 1; + channels[0].sustain = 0xafff; + channels[0].release_ms = 1; + channels[0].volume = 10000; + channels[0].frequency = 1000; +*/ + // melody track + channels[0].waveforms = Waveform::TRIANGLE | Waveform::SQUARE; + channels[0].attack_ms = 16; + channels[0].decay_ms = 168; + channels[0].sustain = 0xafff; + channels[0].release_ms = 168; + channels[0].volume = 10000; + + // rhythm track + channels[1].waveforms = Waveform::SINE | Waveform::SQUARE; + channels[1].attack_ms = 38; + channels[1].decay_ms = 300; + channels[1].sustain = 0; + channels[1].release_ms = 0; + channels[1].volume = 12000; + + // drum track + channels[2].waveforms = Waveform::NOISE; + channels[2].attack_ms = 5; + channels[2].decay_ms = 10; + channels[2].sustain = 16000; + channels[2].release_ms = 100; + channels[2].volume = 18000; + + // hi-hat track + channels[3].waveforms = Waveform::NOISE; + channels[3].attack_ms = 5; + channels[3].decay_ms = 5; + channels[3].sustain = 8000; + channels[3].release_ms = 40; + channels[3].volume = 8000; + + // bass track + channels[4].waveforms = Waveform::SQUARE; + channels[4].attack_ms = 10; + channels[4].decay_ms = 100; + channels[4].sustain = 0; + channels[4].release_ms = 500; + channels[4].volume = 12000; + unicorn = this; next_dma_sequence(); @@ -411,7 +496,7 @@ namespace pimoroni { // Nothing is playing, so we can set up the first buffer straight away current_buffer = 0; - populate_next_buffer(); + populate_next_tone(); // Restart the audio SM and start a new DMA transfer pio_sm_set_enabled(audio_pio, audio_sm, true); @@ -423,6 +508,32 @@ namespace pimoroni { } } + void GalacticUnicorn::play_synth() { + if(play_mode != PLAYING_SYNTH) { + stop_playing(); + } + + if(unicorn == this) { + + if(play_mode == NOT_PLAYING) { + // Nothing is playing, so we can set up the first buffer straight away + current_buffer = 0; + + absolute_time_t at = get_absolute_time(); + synth_start = to_us_since_boot(at) / 1000; + + populate_next_synth(); + + // Restart the audio SM and start a new DMA transfer + pio_sm_set_enabled(audio_pio, audio_sm, true); + + play_mode = PLAYING_SYNTH; + + loop_tone(); + } + } + } + void GalacticUnicorn::loop_tone() { // Clear any interrupt request caused by our channel //dma_channel_acknowledge_irq0(audio_dma_channel); @@ -430,19 +541,28 @@ namespace pimoroni { // https://github.com/raspberrypi/pico-sdk/issues/974 dma_hw->ints0 = 1u << audio_dma_channel; - if(play_mode == PLAYING_TONE) { + if(play_mode == PLAYING_TONE || play_mode == PLAYING_SYNTH) { dma_channel_transfer_from_buffer_now(audio_dma_channel, tone_buffers[current_buffer], TONE_BUFFER_SIZE); current_buffer = (current_buffer + 1) % NUM_TONE_BUFFERS; - populate_next_buffer(); + switch(play_mode) { + case PLAYING_TONE: + populate_next_tone(); + break; + case PLAYING_SYNTH: + populate_next_synth(); + break; + default: + break; + } } else { play_mode = NOT_PLAYING; } } - void GalacticUnicorn::populate_next_buffer() { + void GalacticUnicorn::populate_next_tone() { float percent_along_a, percent_along_b; int16_t val; int16_t* buffer = tone_buffers[current_buffer]; @@ -464,6 +584,34 @@ namespace pimoroni { wave_start_b = fmodf((((float)TONE_BUFFER_SIZE * tone_frequency_b) / SYSTEM_FREQ) + wave_start_b, 1.0f); } + void GalacticUnicorn::populate_next_synth() { + static uint16_t prev_beat = 1; + static uint16_t beat = 0; + + absolute_time_t at = get_absolute_time(); + uint64_t tick_ms = (to_us_since_boot(at) / 1000) - synth_start; + + beat = (tick_ms / 100) % SONG_LENGTH; // 100ms per beat + + if (beat != prev_beat) { + prev_beat = beat; + + for(uint8_t i = 0; i < 5; i++) { + if(notes[i][beat] > 0) { + channels[i].frequency = notes[i][beat]; + channels[i].trigger_attack(); + } else if (notes[i][beat] == -1) { + channels[i].trigger_release(); + } + } + } + + int16_t *samples = tone_buffers[current_buffer]; + for(uint i = 0; i < TONE_BUFFER_SIZE; i++) { + samples[i] = get_audio_frame(channels); + } + } + void GalacticUnicorn::stop_playing() { if(unicorn == this) { // Stop the audio SM diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 509ad140..55631d87 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -2,6 +2,9 @@ #include "hardware/pio.h" #include "pico_graphics.hpp" +#include "synth.hpp" + +using namespace synth; namespace pimoroni { @@ -70,7 +73,7 @@ namespace pimoroni { static void dma_complete(); static const uint NUM_TONE_BUFFERS = 2; - static const uint TONE_BUFFER_SIZE = 16; + static const uint TONE_BUFFER_SIZE = 4; int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0}; uint current_buffer = 0; @@ -79,9 +82,12 @@ namespace pimoroni { float wave_start_a = 0.0f; float wave_start_b = 0.0f; + synth::AudioChannel channels[CHANNEL_COUNT]; + enum PlayMode { PLAYING_BUFFER, PLAYING_TONE, + PLAYING_SYNTH, NOT_PLAYING }; PlayMode play_mode = NOT_PLAYING; @@ -115,14 +121,18 @@ namespace pimoroni { void play_sample(uint8_t *data, uint32_t length); void play_tone(float frequency); void play_dual_tone(float freq_a, float freq_b); + void play_synth(); void stop_playing(); + uint64_t synth_start = 0; + private: void next_dma_sequence(); void partial_teardown(); void dma_safe_abort(uint channel); void loop_tone(); - void populate_next_buffer(); + void populate_next_tone(); + void populate_next_synth(); }; } \ No newline at end of file diff --git a/libraries/galactic_unicorn/synth.cpp b/libraries/galactic_unicorn/synth.cpp new file mode 100644 index 00000000..10097529 --- /dev/null +++ b/libraries/galactic_unicorn/synth.cpp @@ -0,0 +1,160 @@ +#include "synth.hpp" + +namespace synth { + + uint32_t prng_xorshift_state = 0x32B71700; + + uint32_t prng_xorshift_next() { + uint32_t x = prng_xorshift_state; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + prng_xorshift_state = x; + return x; + } + + int32_t prng_normal() { + // rough approximation of a normal distribution + uint32_t r0 = prng_xorshift_next(); + uint32_t r1 = prng_xorshift_next(); + uint32_t n = ((r0 & 0xffff) + (r1 & 0xffff) + (r0 >> 16) + (r1 >> 16)) / 2; + return n - 0xffff; + } + + //uint16_t volume = 0xffff; + const int16_t sine_waveform[256] = {-32768,-32758,-32729,-32679,-32610,-32522,-32413,-32286,-32138,-31972,-31786,-31581,-31357,-31114,-30853,-30572,-30274,-29957,-29622,-29269,-28899,-28511,-28106,-27684,-27246,-26791,-26320,-25833,-25330,-24812,-24279,-23732,-23170,-22595,-22006,-21403,-20788,-20160,-19520,-18868,-18205,-17531,-16846,-16151,-15447,-14733,-14010,-13279,-12540,-11793,-11039,-10279,-9512,-8740,-7962,-7180,-6393,-5602,-4808,-4011,-3212,-2411,-1608,-804,0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32767,32758,32729,32679,32610,32522,32413,32286,32138,31972,31786,31581,31357,31114,30853,30572,30274,29957,29622,29269,28899,28511,28106,27684,27246,26791,26320,25833,25330,24812,24279,23732,23170,22595,22006,21403,20788,20160,19520,18868,18205,17531,16846,16151,15447,14733,14010,13279,12540,11793,11039,10279,9512,8740,7962,7180,6393,5602,4808,4011,3212,2411,1608,804,0,-804,-1608,-2411,-3212,-4011,-4808,-5602,-6393,-7180,-7962,-8740,-9512,-10279,-11039,-11793,-12540,-13279,-14010,-14733,-15447,-16151,-16846,-17531,-18205,-18868,-19520,-20160,-20788,-21403,-22006,-22595,-23170,-23732,-24279,-24812,-25330,-25833,-26320,-26791,-27246,-27684,-28106,-28511,-28899,-29269,-29622,-29957,-30274,-30572,-30853,-31114,-31357,-31581,-31786,-31972,-32138,-32286,-32413,-32522,-32610,-32679,-32729,-32758}; + + bool is_audio_playing(AudioChannel *channels) { + if(volume == 0) { + return false; + } + + bool any_channel_playing = false; + for(int c = 0; c < CHANNEL_COUNT; c++) { + if(channels[c].volume > 0 && channels[c].adsr_phase != ADSRPhase::OFF) { + any_channel_playing = true; + } + } + + return any_channel_playing; + } + + int16_t get_audio_frame(AudioChannel *channels) { + int32_t sample = 0; // used to combine channel output + + for(int c = 0; c < CHANNEL_COUNT; c++) { + + auto &channel = channels[c]; + + // increment the waveform position counter. this provides an + // Q16 fixed point value representing how far through + // the current waveform we are + channel.waveform_offset += ((channel.frequency * 256) << 8) / sample_rate; + + if(channel.adsr_phase == ADSRPhase::OFF) { + continue; + } + + if ((channel.adsr_frame >= channel.adsr_end_frame) && (channel.adsr_phase != ADSRPhase::SUSTAIN)) { + switch (channel.adsr_phase) { + case ADSRPhase::ATTACK: + channel.trigger_decay(); + break; + case ADSRPhase::DECAY: + channel.trigger_sustain(); + break; + case ADSRPhase::RELEASE: + channel.off(); + break; + default: + break; + } + } + + channel.adsr += channel.adsr_step; + channel.adsr_frame++; + + if(channel.waveform_offset & 0x10000) { + // if the waveform offset overflows then generate a new + // random noise sample + channel.noise = prng_normal(); + } + + channel.waveform_offset &= 0xffff; + + // check if any waveforms are active for this channel + if(channel.waveforms) { + uint8_t waveform_count = 0; + int32_t channel_sample = 0; + + if(channel.waveforms & Waveform::NOISE) { + channel_sample += channel.noise; + waveform_count++; + } + + if(channel.waveforms & Waveform::SAW) { + channel_sample += (int32_t)channel.waveform_offset - 0x7fff; + waveform_count++; + } + + // creates a triangle wave of ^ + if (channel.waveforms & Waveform::TRIANGLE) { + if (channel.waveform_offset < 0x7fff) { // initial quarter up slope + channel_sample += int32_t(channel.waveform_offset * 2) - int32_t(0x7fff); + } + else { // final quarter up slope + channel_sample += int32_t(0x7fff) - ((int32_t(channel.waveform_offset) - int32_t(0x7fff)) * 2); + } + waveform_count++; + } + + if (channel.waveforms & Waveform::SQUARE) { + channel_sample += (channel.waveform_offset < channel.pulse_width) ? 0x7fff : -0x7fff; + waveform_count++; + } + + if(channel.waveforms & Waveform::SINE) { + // the sine_waveform sample contains 256 samples in + // total so we'll just use the most significant bits + // of the current waveform position to index into it + channel_sample += sine_waveform[channel.waveform_offset >> 8]; + waveform_count++; + } + + if(channel.waveforms & Waveform::WAVE) { + channel_sample += channel.wave_buffer[channel.wave_buf_pos]; + if (++channel.wave_buf_pos == 64) { + channel.wave_buf_pos = 0; + if(channel.wave_buffer_callback) + channel.wave_buffer_callback(channel); + } + waveform_count++; + } + + channel_sample = channel_sample / waveform_count; + + channel_sample = (int64_t(channel_sample) * int32_t(channel.adsr >> 8)) >> 16; + + // apply channel volume + channel_sample = (int64_t(channel_sample) * int32_t(channel.volume)) >> 16; + + // apply channel filter + //if (channel.filter_enable) { + //float filter_epow = 1 - expf(-(1.0f / 22050.0f) * 2.0f * pi * int32_t(channel.filter_cutoff_frequency)); + //channel_sample += (channel_sample - channel.filter_last_sample) * filter_epow; + //} + + //channel.filter_last_sample = channel_sample; + + // combine channel sample into the final sample + sample += channel_sample; + } + } + + sample = (int64_t(sample) * int32_t(volume)) >> 16; + + // clip result to 16-bit + sample = sample <= -0x8000 ? -0x8000 : (sample > 0x7fff ? 0x7fff : sample); + return sample; + } +} \ No newline at end of file diff --git a/libraries/galactic_unicorn/synth.hpp b/libraries/galactic_unicorn/synth.hpp new file mode 100644 index 00000000..2c5e887b --- /dev/null +++ b/libraries/galactic_unicorn/synth.hpp @@ -0,0 +1,132 @@ +#pragma once + +#include + +namespace synth { + + // The duration a note is played is determined by the amount of attack, + // decay, and release, combined with the length of the note as defined by + // the user. + // + // - Attack: number of milliseconds it takes for a note to hit full volume + // - Decay: number of milliseconds it takes for a note to settle to sustain volume + // - Sustain: percentage of full volume that the note sustains at (duration implied by other factors) + // - Release: number of milliseconds it takes for a note to reduce to zero volume after it has ended + // + // Attack (750ms) - Decay (500ms) -------- Sustain ----- Release (250ms) + // + // + + + + + // | | | | + // | | | | + // | | | | + // v v v v + // 0ms 1000ms 2000ms 3000ms 4000ms + // + // | XXXX | | | | + // | X X|XX | | | + // | X | XXX | | | + // | X | XXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXX| | + // | X | | |X | + // | X | | |X | + // | X | | | X | + // | X | | | X | + // | X | | | X | + // | X | | | X | + // | X | | | X | + // | X | | | X | + // | X + + + | + + + | + + + | + + + | + + // | X | | | | | | | | | | | | | | | | | + // |X | | | | | | | | | | | | | | | | | + // +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---> + + #define CHANNEL_COUNT 8 + + constexpr float pi = 3.14159265358979323846f; + + const uint32_t sample_rate = 22050; + const uint16_t volume = 0x2fff; + + enum Waveform { + NOISE = 128, + SQUARE = 64, + SAW = 32, + TRIANGLE = 16, + SINE = 8, + WAVE = 1 + }; + + enum class ADSRPhase : uint8_t { + ATTACK, + DECAY, + SUSTAIN, + RELEASE, + OFF + }; + + struct AudioChannel { + uint8_t waveforms = 0; // bitmask for enabled waveforms (see AudioWaveform enum for values) + uint16_t frequency = 660; // frequency of the voice (Hz) + uint16_t volume = 0xffff; // channel volume (default 50%) + + uint16_t attack_ms = 2; // attack period + uint16_t decay_ms = 6; // decay period + uint16_t sustain = 0xffff; // sustain volume + uint16_t release_ms = 1; // release period + uint16_t pulse_width = 0x7fff; // duty cycle of square wave (default 50%) + int16_t noise = 0; // current noise value + + uint32_t waveform_offset = 0; // voice offset (Q8) + + int32_t filter_last_sample = 0; + bool filter_enable = false; + uint16_t filter_cutoff_frequency = 0; + + uint32_t adsr_frame = 0; // number of frames into the current ADSR phase + uint32_t adsr_end_frame = 0; // frame target at which the ADSR changes to the next phase + uint32_t adsr = 0; + int32_t adsr_step = 0; + ADSRPhase adsr_phase = ADSRPhase::OFF; + + uint8_t wave_buf_pos = 0; // + int16_t wave_buffer[64]; // buffer for arbitrary waveforms. small as it's filled by user callback + + void *user_data = nullptr; + void (*wave_buffer_callback)(AudioChannel &channel); + + void trigger_attack() { + adsr_frame = 0; + adsr_phase = ADSRPhase::ATTACK; + adsr_end_frame = (attack_ms * sample_rate) / 1000; + adsr_step = (int32_t(0xffffff) - int32_t(adsr)) / int32_t(adsr_end_frame); + } + void trigger_decay() { + adsr_frame = 0; + adsr_phase = ADSRPhase::DECAY; + adsr_end_frame = (decay_ms * sample_rate) / 1000; + adsr_step = (int32_t(sustain << 8) - int32_t(adsr)) / int32_t(adsr_end_frame); + } + void trigger_sustain() { + adsr_frame = 0; + adsr_phase = ADSRPhase::SUSTAIN; + adsr_end_frame = 0; + adsr_step = 0; + } + void trigger_release() { + adsr_frame = 0; + adsr_phase = ADSRPhase::RELEASE; + adsr_end_frame = (release_ms * sample_rate) / 1000; + adsr_step = (int32_t(0) - int32_t(adsr)) / int32_t(adsr_end_frame); + } + void off() { + adsr_frame = 0; + adsr_phase = ADSRPhase::OFF; + adsr_step = 0; + } + }; + + //extern AudioChannel channels[CHANNEL_COUNT]; + + int16_t get_audio_frame(AudioChannel *channels); + bool is_audio_playing(AudioChannel *channels); + +} \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index ceb5de41..f4bddff8 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -658,6 +658,7 @@ was_a_pressed = False was_b_pressed = False was_c_pressed = False was_d_pressed = False +was_z_pressed = False bool_playing = False freq_a = 0 @@ -724,6 +725,13 @@ while True: if bool_playing: freq_a -= 10 gu.play_dual_tone(freq_a, freq_b) + + if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): + if not was_z_pressed: + gu.play_synth() + was_z_pressed = True + else: + was_z_pressed = False graphics.set_pen(graphics.create_pen(0, 0, 0)) graphics.clear() @@ -747,31 +755,31 @@ while True: text = "" if gu.is_pressed(GalacticUnicorn.SWITCH_A): - text = "Button A" + text = "Play Sample" if gu.is_pressed(GalacticUnicorn.SWITCH_B): - text = "Button B" + text = "Tone A" if gu.is_pressed(GalacticUnicorn.SWITCH_C): - text = "Button C" + text = "Tone B" if gu.is_pressed(GalacticUnicorn.SWITCH_D): - text = "Button D" + text = "Stop" if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): - text = "Louder!" + text = "Raise A" if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): - text = "Quieter" + text = "Lower A" if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): - text = "Brighter!" + text = "Raise B" if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): - text = "Darker" + text = "Power B" if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): - text = "Zzz... zzz..." + text = "Play Synth" outline_text(text) diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index c706fe22..9768bd19 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -16,6 +16,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pre MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_tone_obj, GalacticUnicorn_play_tone); MP_DEFINE_CONST_FUN_OBJ_3(GalacticUnicorn_play_dual_tone_obj, GalacticUnicorn_play_dual_tone); +MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_play_synth_obj, GalacticUnicorn_play_synth); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing); /***** Binding of Methods *****/ @@ -34,6 +35,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, { MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&GalacticUnicorn_play_tone_obj) }, { MP_ROM_QSTR(MP_QSTR_play_dual_tone), MP_ROM_PTR(&GalacticUnicorn_play_dual_tone_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_synth), MP_ROM_PTR(&GalacticUnicorn_play_synth_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_playing), MP_ROM_PTR(&GalacticUnicorn_stop_playing_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 9e1f319b..80c8d7b9 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -173,6 +173,13 @@ extern mp_obj_t GalacticUnicorn_play_dual_tone(mp_obj_t self_in, mp_obj_t freq_a return mp_const_none; } +extern mp_obj_t GalacticUnicorn_play_synth(mp_obj_t self_in) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->play_synth(); + + return mp_const_none; +} + extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); self->galactic->stop_playing(); diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 76c312db..8409aee8 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -27,4 +27,5 @@ extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq); extern mp_obj_t GalacticUnicorn_play_dual_tone(mp_obj_t self_in, mp_obj_t freq_a, mp_obj_t freq_b); +extern mp_obj_t GalacticUnicorn_play_synth(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in); \ No newline at end of file From 882f76dcbcdf58226a5b7ed9b05462b69d287890 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 23 Aug 2022 13:59:16 +0100 Subject: [PATCH 32/42] More work on GU synth --- .../galactic_unicorn/galactic_unicorn.cmake | 2 +- .../galactic_unicorn/galactic_unicorn.cpp | 216 ++---------------- .../galactic_unicorn/galactic_unicorn.hpp | 24 +- .../synth.cpp => pico_synth/pico_synth.cpp} | 67 ++++-- .../synth.hpp => pico_synth/pico_synth.hpp} | 91 ++++---- .../feature_test_with_audio.py | 189 ++++++++++++++- .../galactic_unicorn/galactic_unicorn.c | 19 +- .../galactic_unicorn/galactic_unicorn.cpp | 66 ++++-- .../galactic_unicorn/galactic_unicorn.h | 9 +- .../galactic_unicorn/micropython.cmake | 1 + 10 files changed, 366 insertions(+), 318 deletions(-) rename libraries/{galactic_unicorn/synth.cpp => pico_synth/pico_synth.cpp} (63%) rename libraries/{galactic_unicorn/synth.hpp => pico_synth/pico_synth.hpp} (58%) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cmake b/libraries/galactic_unicorn/galactic_unicorn.cmake index 0df2a35a..e6ff85a8 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cmake +++ b/libraries/galactic_unicorn/galactic_unicorn.cmake @@ -6,7 +6,7 @@ pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pi target_sources(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp - ${CMAKE_CURRENT_LIST_DIR}/synth.cpp + ${CMAKE_CURRENT_LIST_DIR}/../pico_synth/pico_synth.cpp ) target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index b35302b8..333debef 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -45,42 +45,6 @@ static uint16_t b_gamma_lut[256] = {0}; static uint32_t dma_channel; static uint32_t audio_dma_channel; -static const int16_t sine_waveform[256] = {-32768,-32758,-32729,-32679,-32610,-32522,-32413,-32286,-32138,-31972,-31786,-31581,-31357,-31114,-30853,-30572,-30274,-29957,-29622,-29269,-28899,-28511,-28106,-27684,-27246,-26791,-26320,-25833,-25330,-24812,-24279,-23732,-23170,-22595,-22006,-21403,-20788,-20160,-19520,-18868,-18205,-17531,-16846,-16151,-15447,-14733,-14010,-13279,-12540,-11793,-11039,-10279,-9512,-8740,-7962,-7180,-6393,-5602,-4808,-4011,-3212,-2411,-1608,-804,0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32767,32758,32729,32679,32610,32522,32413,32286,32138,31972,31786,31581,31357,31114,30853,30572,30274,29957,29622,29269,28899,28511,28106,27684,27246,26791,26320,25833,25330,24812,24279,23732,23170,22595,22006,21403,20788,20160,19520,18868,18205,17531,16846,16151,15447,14733,14010,13279,12540,11793,11039,10279,9512,8740,7962,7180,6393,5602,4808,4011,3212,2411,1608,804,0,-804,-1608,-2411,-3212,-4011,-4808,-5602,-6393,-7180,-7962,-8740,-9512,-10279,-11039,-11793,-12540,-13279,-14010,-14733,-15447,-16151,-16846,-17531,-18205,-18868,-19520,-20160,-20788,-21403,-22006,-22595,-23170,-23732,-24279,-24812,-25330,-25833,-26320,-26791,-27246,-27684,-28106,-28511,-28899,-29269,-29622,-29957,-30274,-30572,-30853,-31114,-31357,-31581,-31786,-31972,-32138,-32286,-32413,-32522,-32610,-32679,-32729,-32758}; - -#define SONG_LENGTH 384 -#define HAT 20000 -#define BASS 500 -#define SNARE 6000 -#define SUB 50 - -static const int16_t notes[5][SONG_LENGTH] = { - { // melody notes - 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 220, 0, 196, 0, 147, 0, 175, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, - 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 220, 0, 196, 0, 147, 0, 175, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, - 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 262, 0, 294, 0, 392, 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, - { // rhythm notes - 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, - 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, - 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, - }, - { // drum beats - BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, - BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, - BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0 - }, - { // hi-hat - HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, - HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, - HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1 - }, - { // bass notes under bass drum - SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, - SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, - SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0 - }, -}; - namespace pimoroni { GalacticUnicorn* GalacticUnicorn::unicorn = nullptr; @@ -96,20 +60,15 @@ namespace pimoroni { void __isr GalacticUnicorn::dma_complete() { if(unicorn != nullptr) { if(dma_channel_get_irq0_status(dma_channel)) { - gpio_put(I2C_SCL, true); - unicorn->next_dma_sequence(); - gpio_put(I2C_SCL, false); + unicorn->next_bitstream_sequence(); } if(dma_channel_get_irq0_status(audio_dma_channel)) { - gpio_put(I2C_SDA, true); - unicorn->loop_tone(); - gpio_put(I2C_SDA, false); - + unicorn->next_audio_sequence(); } } } - void GalacticUnicorn::next_dma_sequence() { + void GalacticUnicorn::next_bitstream_sequence() { // Clear any interrupt request caused by our channel //dma_channel_acknowledge_irq0(dma_channel); // NOTE Temporary replacement of the above until this reaches pico-sdk main: @@ -213,10 +172,6 @@ namespace pimoroni { } } - // temp for debugging - gpio_init(I2C_SDA); gpio_set_dir(I2C_SDA, GPIO_OUT); gpio_put(I2C_SDA, false); - gpio_init(I2C_SCL); gpio_set_dir(I2C_SCL, GPIO_OUT); gpio_put(I2C_SCL, false); - // setup light sensor adc adc_init(); adc_gpio_init(LIGHT_SENSOR); @@ -384,60 +339,9 @@ namespace pimoroni { irq_set_enabled(DMA_IRQ_0, true); } - - // configure voices -/* - channels[0].waveforms = Waveform::SINE; - channels[0].attack_ms = 1; - channels[0].decay_ms = 1; - channels[0].sustain = 0xafff; - channels[0].release_ms = 1; - channels[0].volume = 10000; - channels[0].frequency = 1000; -*/ - // melody track - channels[0].waveforms = Waveform::TRIANGLE | Waveform::SQUARE; - channels[0].attack_ms = 16; - channels[0].decay_ms = 168; - channels[0].sustain = 0xafff; - channels[0].release_ms = 168; - channels[0].volume = 10000; - - // rhythm track - channels[1].waveforms = Waveform::SINE | Waveform::SQUARE; - channels[1].attack_ms = 38; - channels[1].decay_ms = 300; - channels[1].sustain = 0; - channels[1].release_ms = 0; - channels[1].volume = 12000; - - // drum track - channels[2].waveforms = Waveform::NOISE; - channels[2].attack_ms = 5; - channels[2].decay_ms = 10; - channels[2].sustain = 16000; - channels[2].release_ms = 100; - channels[2].volume = 18000; - - // hi-hat track - channels[3].waveforms = Waveform::NOISE; - channels[3].attack_ms = 5; - channels[3].decay_ms = 5; - channels[3].sustain = 8000; - channels[3].release_ms = 40; - channels[3].volume = 8000; - - // bass track - channels[4].waveforms = Waveform::SQUARE; - channels[4].attack_ms = 10; - channels[4].decay_ms = 100; - channels[4].sustain = 0; - channels[4].release_ms = 500; - channels[4].volume = 12000; - unicorn = this; - next_dma_sequence(); + next_bitstream_sequence(); } void GalacticUnicorn::clear() { @@ -478,137 +382,49 @@ namespace pimoroni { } } - void GalacticUnicorn::play_tone(float frequency) { - play_dual_tone(frequency, 0.0f); - } - - void GalacticUnicorn::play_dual_tone(float freq_a, float freq_b) { - if(play_mode != PLAYING_TONE) { - stop_playing(); - } - - if(unicorn == this) { - - tone_frequency_a = MAX(freq_a, 0.0f); - tone_frequency_b = MAX(freq_b, 0.0f); - - if(play_mode == NOT_PLAYING) { - // Nothing is playing, so we can set up the first buffer straight away - current_buffer = 0; - - populate_next_tone(); - - // Restart the audio SM and start a new DMA transfer - pio_sm_set_enabled(audio_pio, audio_sm, true); - - play_mode = PLAYING_TONE; - - loop_tone(); - } - } - } - void GalacticUnicorn::play_synth() { if(play_mode != PLAYING_SYNTH) { stop_playing(); } - if(unicorn == this) { + if(unicorn == this && play_mode == NOT_PLAYING) { + // Nothing is playing, so we can set up the first buffer straight away + current_buffer = 0; - if(play_mode == NOT_PLAYING) { - // Nothing is playing, so we can set up the first buffer straight away - current_buffer = 0; + populate_next_synth(); - absolute_time_t at = get_absolute_time(); - synth_start = to_us_since_boot(at) / 1000; + // Restart the audio SM and start a new DMA transfer + pio_sm_set_enabled(audio_pio, audio_sm, true); - populate_next_synth(); + play_mode = PLAYING_SYNTH; - // Restart the audio SM and start a new DMA transfer - pio_sm_set_enabled(audio_pio, audio_sm, true); - - play_mode = PLAYING_SYNTH; - - loop_tone(); - } + next_audio_sequence(); } } - void GalacticUnicorn::loop_tone() { + void GalacticUnicorn::next_audio_sequence() { // Clear any interrupt request caused by our channel //dma_channel_acknowledge_irq0(audio_dma_channel); // NOTE Temporary replacement of the above until this reaches pico-sdk main: // https://github.com/raspberrypi/pico-sdk/issues/974 dma_hw->ints0 = 1u << audio_dma_channel; - if(play_mode == PLAYING_TONE || play_mode == PLAYING_SYNTH) { + if(play_mode == PLAYING_SYNTH) { dma_channel_transfer_from_buffer_now(audio_dma_channel, tone_buffers[current_buffer], TONE_BUFFER_SIZE); current_buffer = (current_buffer + 1) % NUM_TONE_BUFFERS; - switch(play_mode) { - case PLAYING_TONE: - populate_next_tone(); - break; - case PLAYING_SYNTH: - populate_next_synth(); - break; - default: - break; - } + populate_next_synth(); } else { play_mode = NOT_PLAYING; } } - void GalacticUnicorn::populate_next_tone() { - float percent_along_a, percent_along_b; - int16_t val; - int16_t* buffer = tone_buffers[current_buffer]; - - //sine_waveform - for(uint i = 0; i < TONE_BUFFER_SIZE; i++) { - percent_along_a = (((float)i * tone_frequency_a) / SYSTEM_FREQ) + wave_start_a; - val = (sine_waveform[(int)(percent_along_a * 256.0f) % 256] * 0x0fff) >> 16; - //val = sinf(percent_along_a * 2 * M_PI) * 0x0fff; - - percent_along_b = (((float)i * tone_frequency_b) / SYSTEM_FREQ) + wave_start_b; - val += (sine_waveform[(int)(percent_along_b * 256.0f) % 256] * 0x0fff) >> 16; - //val += sinf(percent_along_b * 2 * M_PI) * 0x0fff; - - buffer[i] = val; - } - - wave_start_a = fmodf((((float)TONE_BUFFER_SIZE * tone_frequency_a) / SYSTEM_FREQ) + wave_start_a, 1.0f); - wave_start_b = fmodf((((float)TONE_BUFFER_SIZE * tone_frequency_b) / SYSTEM_FREQ) + wave_start_b, 1.0f); - } - void GalacticUnicorn::populate_next_synth() { - static uint16_t prev_beat = 1; - static uint16_t beat = 0; - - absolute_time_t at = get_absolute_time(); - uint64_t tick_ms = (to_us_since_boot(at) / 1000) - synth_start; - - beat = (tick_ms / 100) % SONG_LENGTH; // 100ms per beat - - if (beat != prev_beat) { - prev_beat = beat; - - for(uint8_t i = 0; i < 5; i++) { - if(notes[i][beat] > 0) { - channels[i].frequency = notes[i][beat]; - channels[i].trigger_attack(); - } else if (notes[i][beat] == -1) { - channels[i].trigger_release(); - } - } - } - int16_t *samples = tone_buffers[current_buffer]; for(uint i = 0; i < TONE_BUFFER_SIZE; i++) { - samples[i] = get_audio_frame(channels); + samples[i] = synth.get_audio_frame(); } } diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 55631d87..f1d4f9d8 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -2,9 +2,7 @@ #include "hardware/pio.h" #include "pico_graphics.hpp" -#include "synth.hpp" - -using namespace synth; +#include "../pico_synth/pico_synth.hpp" namespace pimoroni { @@ -77,16 +75,13 @@ namespace pimoroni { int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0}; uint current_buffer = 0; - float tone_frequency_a = 0.0f; - float tone_frequency_b = 0.0f; - float wave_start_a = 0.0f; - float wave_start_b = 0.0f; - - synth::AudioChannel channels[CHANNEL_COUNT]; + public: + PicoSynth synth; + private: enum PlayMode { PLAYING_BUFFER, - PLAYING_TONE, + //PLAYING_TONE, PLAYING_SYNTH, NOT_PLAYING }; @@ -119,19 +114,14 @@ namespace pimoroni { bool is_pressed(uint8_t button); void play_sample(uint8_t *data, uint32_t length); - void play_tone(float frequency); - void play_dual_tone(float freq_a, float freq_b); void play_synth(); void stop_playing(); - uint64_t synth_start = 0; - private: - void next_dma_sequence(); + void next_bitstream_sequence(); void partial_teardown(); void dma_safe_abort(uint channel); - void loop_tone(); - void populate_next_tone(); + void next_audio_sequence(); void populate_next_synth(); }; diff --git a/libraries/galactic_unicorn/synth.cpp b/libraries/pico_synth/pico_synth.cpp similarity index 63% rename from libraries/galactic_unicorn/synth.cpp rename to libraries/pico_synth/pico_synth.cpp index 10097529..4fc66cbf 100644 --- a/libraries/galactic_unicorn/synth.cpp +++ b/libraries/pico_synth/pico_synth.cpp @@ -1,6 +1,6 @@ -#include "synth.hpp" +#include "pico_synth.hpp" -namespace synth { +namespace pimoroni { uint32_t prng_xorshift_state = 0x32B71700; @@ -21,16 +21,48 @@ namespace synth { return n - 0xffff; } - //uint16_t volume = 0xffff; - const int16_t sine_waveform[256] = {-32768,-32758,-32729,-32679,-32610,-32522,-32413,-32286,-32138,-31972,-31786,-31581,-31357,-31114,-30853,-30572,-30274,-29957,-29622,-29269,-28899,-28511,-28106,-27684,-27246,-26791,-26320,-25833,-25330,-24812,-24279,-23732,-23170,-22595,-22006,-21403,-20788,-20160,-19520,-18868,-18205,-17531,-16846,-16151,-15447,-14733,-14010,-13279,-12540,-11793,-11039,-10279,-9512,-8740,-7962,-7180,-6393,-5602,-4808,-4011,-3212,-2411,-1608,-804,0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32767,32758,32729,32679,32610,32522,32413,32286,32138,31972,31786,31581,31357,31114,30853,30572,30274,29957,29622,29269,28899,28511,28106,27684,27246,26791,26320,25833,25330,24812,24279,23732,23170,22595,22006,21403,20788,20160,19520,18868,18205,17531,16846,16151,15447,14733,14010,13279,12540,11793,11039,10279,9512,8740,7962,7180,6393,5602,4808,4011,3212,2411,1608,804,0,-804,-1608,-2411,-3212,-4011,-4808,-5602,-6393,-7180,-7962,-8740,-9512,-10279,-11039,-11793,-12540,-13279,-14010,-14733,-15447,-16151,-16846,-17531,-18205,-18868,-19520,-20160,-20788,-21403,-22006,-22595,-23170,-23732,-24279,-24812,-25330,-25833,-26320,-26791,-27246,-27684,-28106,-28511,-28899,-29269,-29622,-29957,-30274,-30572,-30853,-31114,-31357,-31581,-31786,-31972,-32138,-32286,-32413,-32522,-32610,-32679,-32729,-32758}; - bool is_audio_playing(AudioChannel *channels) { + void AudioChannel::trigger_attack() { + adsr_frame = 0; + adsr_phase = ADSRPhase::ATTACK; + adsr_end_frame = (attack_ms * sample_rate) / 1000; + adsr_step = (int32_t(0xffffff) - int32_t(adsr_level)) / int32_t(adsr_end_frame); + } + + void AudioChannel::trigger_decay() { + adsr_frame = 0; + adsr_phase = ADSRPhase::DECAY; + adsr_end_frame = (decay_ms * sample_rate) / 1000; + adsr_step = (int32_t(sustain << 8) - int32_t(adsr_level)) / int32_t(adsr_end_frame); + } + + void AudioChannel::trigger_sustain() { + adsr_frame = 0; + adsr_phase = ADSRPhase::SUSTAIN; + adsr_end_frame = 0; + adsr_step = 0; + } + + void AudioChannel::trigger_release() { + adsr_frame = 0; + adsr_phase = ADSRPhase::RELEASE; + adsr_end_frame = (release_ms * sample_rate) / 1000; + adsr_step = (int32_t(0) - int32_t(adsr_level)) / int32_t(adsr_end_frame); + } + + void AudioChannel::off() { + adsr_frame = 0; + adsr_phase = ADSRPhase::OFF; + adsr_step = 0; + } + + bool PicoSynth::is_audio_playing() { if(volume == 0) { return false; } bool any_channel_playing = false; - for(int c = 0; c < CHANNEL_COUNT; c++) { + for(uint c = 0; c < CHANNEL_COUNT; c++) { if(channels[c].volume > 0 && channels[c].adsr_phase != ADSRPhase::OFF) { any_channel_playing = true; } @@ -39,10 +71,10 @@ namespace synth { return any_channel_playing; } - int16_t get_audio_frame(AudioChannel *channels) { + int16_t PicoSynth::get_audio_frame() { int32_t sample = 0; // used to combine channel output - for(int c = 0; c < CHANNEL_COUNT; c++) { + for(uint c = 0; c < CHANNEL_COUNT; c++) { auto &channel = channels[c]; @@ -55,7 +87,7 @@ namespace synth { continue; } - if ((channel.adsr_frame >= channel.adsr_end_frame) && (channel.adsr_phase != ADSRPhase::SUSTAIN)) { + if((channel.adsr_frame >= channel.adsr_end_frame) && (channel.adsr_phase != ADSRPhase::SUSTAIN)) { switch (channel.adsr_phase) { case ADSRPhase::ATTACK: channel.trigger_decay(); @@ -71,7 +103,7 @@ namespace synth { } } - channel.adsr += channel.adsr_step; + channel.adsr_level += channel.adsr_step; channel.adsr_frame++; if(channel.waveform_offset & 0x10000) { @@ -98,8 +130,8 @@ namespace synth { } // creates a triangle wave of ^ - if (channel.waveforms & Waveform::TRIANGLE) { - if (channel.waveform_offset < 0x7fff) { // initial quarter up slope + if(channel.waveforms & Waveform::TRIANGLE) { + if(channel.waveform_offset < 0x7fff) { // initial quarter up slope channel_sample += int32_t(channel.waveform_offset * 2) - int32_t(0x7fff); } else { // final quarter up slope @@ -108,7 +140,7 @@ namespace synth { waveform_count++; } - if (channel.waveforms & Waveform::SQUARE) { + if(channel.waveforms & Waveform::SQUARE) { channel_sample += (channel.waveform_offset < channel.pulse_width) ? 0x7fff : -0x7fff; waveform_count++; } @@ -123,17 +155,17 @@ namespace synth { if(channel.waveforms & Waveform::WAVE) { channel_sample += channel.wave_buffer[channel.wave_buf_pos]; - if (++channel.wave_buf_pos == 64) { + if(++channel.wave_buf_pos == 64) { channel.wave_buf_pos = 0; if(channel.wave_buffer_callback) - channel.wave_buffer_callback(channel); + channel.wave_buffer_callback(channel); } waveform_count++; } channel_sample = channel_sample / waveform_count; - channel_sample = (int64_t(channel_sample) * int32_t(channel.adsr >> 8)) >> 16; + channel_sample = (int64_t(channel_sample) * int32_t(channel.adsr_level >> 8)) >> 16; // apply channel volume channel_sample = (int64_t(channel_sample) * int32_t(channel.volume)) >> 16; @@ -157,4 +189,5 @@ namespace synth { sample = sample <= -0x8000 ? -0x8000 : (sample > 0x7fff ? 0x7fff : sample); return sample; } -} \ No newline at end of file + +} diff --git a/libraries/galactic_unicorn/synth.hpp b/libraries/pico_synth/pico_synth.hpp similarity index 58% rename from libraries/galactic_unicorn/synth.hpp rename to libraries/pico_synth/pico_synth.hpp index 2c5e887b..f0c48b9a 100644 --- a/libraries/galactic_unicorn/synth.hpp +++ b/libraries/pico_synth/pico_synth.hpp @@ -1,8 +1,15 @@ #pragma once -#include +//#include +//#include +//#include +//#include +//#include +//#include -namespace synth { +#include "common/pimoroni_common.hpp" + +namespace pimoroni { // The duration a note is played is determined by the amount of attack, // decay, and release, combined with the length of the note as defined by @@ -39,13 +46,6 @@ namespace synth { // |X | | | | | | | | | | | | | | | | | // +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---> - #define CHANNEL_COUNT 8 - - constexpr float pi = 3.14159265358979323846f; - - const uint32_t sample_rate = 22050; - const uint16_t volume = 0x2fff; - enum Waveform { NOISE = 128, SQUARE = 64, @@ -63,13 +63,16 @@ namespace synth { OFF }; - struct AudioChannel { - uint8_t waveforms = 0; // bitmask for enabled waveforms (see AudioWaveform enum for values) - uint16_t frequency = 660; // frequency of the voice (Hz) - uint16_t volume = 0xffff; // channel volume (default 50%) + const int16_t sine_waveform[256] = {-32768,-32758,-32729,-32679,-32610,-32522,-32413,-32286,-32138,-31972,-31786,-31581,-31357,-31114,-30853,-30572,-30274,-29957,-29622,-29269,-28899,-28511,-28106,-27684,-27246,-26791,-26320,-25833,-25330,-24812,-24279,-23732,-23170,-22595,-22006,-21403,-20788,-20160,-19520,-18868,-18205,-17531,-16846,-16151,-15447,-14733,-14010,-13279,-12540,-11793,-11039,-10279,-9512,-8740,-7962,-7180,-6393,-5602,-4808,-4011,-3212,-2411,-1608,-804,0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32767,32758,32729,32679,32610,32522,32413,32286,32138,31972,31786,31581,31357,31114,30853,30572,30274,29957,29622,29269,28899,28511,28106,27684,27246,26791,26320,25833,25330,24812,24279,23732,23170,22595,22006,21403,20788,20160,19520,18868,18205,17531,16846,16151,15447,14733,14010,13279,12540,11793,11039,10279,9512,8740,7962,7180,6393,5602,4808,4011,3212,2411,1608,804,0,-804,-1608,-2411,-3212,-4011,-4808,-5602,-6393,-7180,-7962,-8740,-9512,-10279,-11039,-11793,-12540,-13279,-14010,-14733,-15447,-16151,-16846,-17531,-18205,-18868,-19520,-20160,-20788,-21403,-22006,-22595,-23170,-23732,-24279,-24812,-25330,-25833,-26320,-26791,-27246,-27684,-28106,-28511,-28899,-29269,-29622,-29957,-30274,-30572,-30853,-31114,-31357,-31581,-31786,-31972,-32138,-32286,-32413,-32522,-32610,-32679,-32729,-32758}; + const uint32_t sample_rate = 22050; - uint16_t attack_ms = 2; // attack period - uint16_t decay_ms = 6; // decay period + struct AudioChannel { + uint8_t waveforms = 0; // bitmask for enabled waveforms (see Waveform enum for values) + uint16_t frequency = 660; // frequency of the voice (Hz) + uint16_t volume = 0xffff; // channel volume + + uint16_t attack_ms = 2; // attack period (cannot be zero) + uint16_t decay_ms = 6; // decay period (cannot be zero) uint16_t sustain = 0xffff; // sustain volume uint16_t release_ms = 1; // release period uint16_t pulse_width = 0x7fff; // duty cycle of square wave (default 50%) @@ -81,11 +84,11 @@ namespace synth { bool filter_enable = false; uint16_t filter_cutoff_frequency = 0; - uint32_t adsr_frame = 0; // number of frames into the current ADSR phase + uint32_t adsr_frame = 0; // number of frames into the current ADSR phase uint32_t adsr_end_frame = 0; // frame target at which the ADSR changes to the next phase - uint32_t adsr = 0; - int32_t adsr_step = 0; - ADSRPhase adsr_phase = ADSRPhase::OFF; + uint32_t adsr_level = 0; // the output level at the current frame of the ADSR phase + int32_t adsr_step = 0; // the amount to increment the level with each frame + ADSRPhase adsr_phase = ADSRPhase::OFF; uint8_t wave_buf_pos = 0; // int16_t wave_buffer[64]; // buffer for arbitrary waveforms. small as it's filled by user callback @@ -93,40 +96,24 @@ namespace synth { void *user_data = nullptr; void (*wave_buffer_callback)(AudioChannel &channel); - void trigger_attack() { - adsr_frame = 0; - adsr_phase = ADSRPhase::ATTACK; - adsr_end_frame = (attack_ms * sample_rate) / 1000; - adsr_step = (int32_t(0xffffff) - int32_t(adsr)) / int32_t(adsr_end_frame); - } - void trigger_decay() { - adsr_frame = 0; - adsr_phase = ADSRPhase::DECAY; - adsr_end_frame = (decay_ms * sample_rate) / 1000; - adsr_step = (int32_t(sustain << 8) - int32_t(adsr)) / int32_t(adsr_end_frame); - } - void trigger_sustain() { - adsr_frame = 0; - adsr_phase = ADSRPhase::SUSTAIN; - adsr_end_frame = 0; - adsr_step = 0; - } - void trigger_release() { - adsr_frame = 0; - adsr_phase = ADSRPhase::RELEASE; - adsr_end_frame = (release_ms * sample_rate) / 1000; - adsr_step = (int32_t(0) - int32_t(adsr)) / int32_t(adsr_end_frame); - } - void off() { - adsr_frame = 0; - adsr_phase = ADSRPhase::OFF; - adsr_step = 0; - } + void trigger_attack(); + void trigger_decay(); + void trigger_sustain(); + void trigger_release(); + void off(); }; - //extern AudioChannel channels[CHANNEL_COUNT]; + class PicoSynth { + public: + const uint16_t volume = 0x2fff; - int16_t get_audio_frame(AudioChannel *channels); - bool is_audio_playing(AudioChannel *channels); + static const uint CHANNEL_COUNT = 8; + AudioChannel channels[CHANNEL_COUNT]; -} \ No newline at end of file + int16_t get_audio_frame(); + bool is_audio_playing(); + }; + + constexpr float pi = 3.14159265358979323846f; + +} diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index f4bddff8..a83290f7 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -1,6 +1,7 @@ import gc import time import math +from machine import Timer from galactic import GalacticUnicorn from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY @@ -611,6 +612,39 @@ left_channel = bytearray(( 0xa0, 0xfe, 0x6c, 0xfb, 0x59, 0xf8, 0x5a, 0xf8, 0xd0, 0xf8, 0xba, 0xfd, )) +SONG_LENGTH = 384 +HAT = 20000 +BASS = 500 +SNARE = 6000 +SUB = 50 + +melody_notes = ( + 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 220, 0, 196, 0, 147, 0, 175, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, + 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 220, 0, 196, 0, 147, 0, 175, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, + 147, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 247, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 175, 0, 196, 0, 220, 0, 262, 0, 330, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 349, 0, 330, 0, 294, 0, 220, 0, 262, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 247, 0, 262, 0, 294, 0, 392, 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +rhythm_notes = ( + 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, + 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0, + 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 294, 0, 440, 0, 587, 0, 440, 0, 392, 0, 523, 0, 659, 0, 523, 0, 392, 0, 523, 0, 659, 0, 523, 0, 698, 0, 587, 0, 440, 0, 587, 0, 698, 0, 587, 0, 440, 0, 587, 0, 523, 0, 440, 0, 330, 0, 440, 0, 523, 0, 440, 0, 330, 0, 440, 0, 349, 0, 294, 0, 220, 0, 294, 0, 349, 0, 294, 0, 220, 0, 294, 0, 262, 0, 247, 0, 220, 0, 175, 0, 165, 0, 147, 0, 131, 0, 98, 0) + +drum_beats = ( + BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, + BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, + BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, BASS, -1, BASS, -1, 0, 0, 0, 0, 0, 0, SNARE, 0, -1, 0, 0, 0, 0, 0) + +hi_hat = ( + HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, + HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, + HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1, HAT, -1) + +bass_notes = ( + SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, + SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, + SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, SUB, -1, SUB, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0) + +notes = [melody_notes, rhythm_notes, drum_beats, hi_hat, bass_notes] + def gradient(r, g, b): for y in range(0, height): @@ -664,6 +698,30 @@ bool_playing = False freq_a = 0 freq_b = 0 +beat = 0 + + +def next_beat(): + global beat + for i in range(5): + if notes[i][beat] > 0: + gu.channel_freq(i, notes[i][beat]) + gu.channel_trigger_attack(i) + elif notes[i][beat] == -1: + gu.channel_trigger_release(i) + + beat = (beat + 1) % SONG_LENGTH + + +def tick(timer): + next_beat() + + +timer = Timer(-1) + +synthing = False + + while True: time_ms = time.ticks_ms() @@ -671,26 +729,100 @@ while True: if gu.is_pressed(GalacticUnicorn.SWITCH_A): if not was_a_pressed: - gu.play_sample(left_channel) - bool_playing = False + gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE, + 16, + 168, + 0, + 168, + 0) + gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE, + 38, + 300, + 0, + 0, + 12000) + gu.channel_configure(2, gu.WF_NOISE, + 5, + 10, + 16000, + 100, + 0) + gu.channel_configure(3, gu.WF_NOISE, + 5, + 5, + 8000, + 40, + 0) + gu.channel_configure(4, gu.WF_SQUARE, + 10, + 100, + 0, + 500, + 0) + if not synthing: + beat = 0 + next_beat() + gu.play_synth() + synthing = True + timer.init(freq=10, mode=Timer.PERIODIC, callback=tick) + was_a_pressed = True else: was_a_pressed = False if gu.is_pressed(GalacticUnicorn.SWITCH_B): if not was_b_pressed: + timer.deinit() freq_a = 400 - gu.play_dual_tone(freq_a, freq_b) + + gu.channel_freq(0, freq_a) + gu.channel_configure(0, gu.WF_SINE, + 1, + 1, + 0xffff, + 1, + 4000) + gu.channel_configure(1, gu.WF_SINE, + 1, + 1, + 0xffff, + 1, + 4000) + gu.channel_trigger_attack(0) + gu.play_synth() + synthing = False + bool_playing = True + was_b_pressed = True else: was_b_pressed = False if gu.is_pressed(GalacticUnicorn.SWITCH_C): if not was_c_pressed: + timer.deinit() freq_b = 600 - gu.play_dual_tone(freq_a, freq_b) + + gu.channel_freq(1, freq_b) + gu.channel_configure(0, gu.WF_SINE, + 1, + 1, + 0xffff, + 1, + 4000) + gu.channel_configure(1, gu.WF_SINE, + 1, + 1, + 0xffff, + 1, + 4000) + + gu.channel_trigger_attack(1) + gu.play_synth() + synthing = False + bool_playing = True + was_c_pressed = True else: was_c_pressed = False @@ -700,6 +832,8 @@ while True: freq_a = 0 freq_b = 0 gu.stop_playing() + timer.deinit() + synthing = False was_d_pressed = True else: was_d_pressed = False @@ -708,27 +842,62 @@ while True: # gu.adjust_brightness(+0.01) if bool_playing: freq_b += 10 - gu.play_dual_tone(freq_a, freq_b) + gu.channel_freq(1, freq_b) if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): # gu.adjust_brightness(-0.01) if bool_playing: - freq_a -= 10 - gu.play_dual_tone(freq_a, freq_b) + freq_b -= 10 + gu.channel_freq(1, freq_b) if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): if bool_playing: freq_a += 10 - gu.play_dual_tone(freq_a, freq_b) + gu.channel_freq(0, freq_a) if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): if bool_playing: freq_a -= 10 - gu.play_dual_tone(freq_a, freq_b) - + gu.channel_freq(0, freq_a) + if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): if not was_z_pressed: + gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE, + 16, + 168, + 0xafff, + 168, + 10000) + gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE, + 38, + 300, + 0, + 0, + 12000) + gu.channel_configure(2, gu.WF_NOISE, + 5, + 10, + 16000, + 100, + 18000) + gu.channel_configure(3, gu.WF_NOISE, + 5, + 5, + 8000, + 40, + 8000) + gu.channel_configure(4, gu.WF_SQUARE, + 10, + 100, + 0, + 500, + 12000) + if not synthing: + beat = 0 + next_beat() gu.play_synth() + synthing = True + timer.init(freq=10, mode=Timer.PERIODIC, callback=tick) was_z_pressed = True else: was_z_pressed = False diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 9768bd19..8fded8d6 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -14,10 +14,12 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adj MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample); -MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_tone_obj, GalacticUnicorn_play_tone); -MP_DEFINE_CONST_FUN_OBJ_3(GalacticUnicorn_play_dual_tone_obj, GalacticUnicorn_play_dual_tone); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_play_synth_obj, GalacticUnicorn_play_synth); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing); +MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_channel_configure_obj, 7, GalacticUnicorn_channel_configure); +MP_DEFINE_CONST_FUN_OBJ_3(GalacticUnicorn_channel_freq_obj, GalacticUnicorn_channel_freq); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_channel_trigger_attack_obj, GalacticUnicorn_channel_trigger_attack); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_channel_trigger_release_obj, GalacticUnicorn_channel_trigger_release); /***** Binding of Methods *****/ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { @@ -33,10 +35,12 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) }, { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) }, { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, - { MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&GalacticUnicorn_play_tone_obj) }, - { MP_ROM_QSTR(MP_QSTR_play_dual_tone), MP_ROM_PTR(&GalacticUnicorn_play_dual_tone_obj) }, { MP_ROM_QSTR(MP_QSTR_play_synth), MP_ROM_PTR(&GalacticUnicorn_play_synth_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_playing), MP_ROM_PTR(&GalacticUnicorn_stop_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel_configure), MP_ROM_PTR(&GalacticUnicorn_channel_configure_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel_freq), MP_ROM_PTR(&GalacticUnicorn_channel_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel_trigger_attack), MP_ROM_PTR(&GalacticUnicorn_channel_trigger_attack_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel_trigger_release), MP_ROM_PTR(&GalacticUnicorn_channel_trigger_release_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, @@ -50,6 +54,13 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SWITCH_VOLUME_DOWN), MP_ROM_INT(8) }, { MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_UP), MP_ROM_INT(21) }, { MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_DOWN), MP_ROM_INT(26) }, + + { MP_ROM_QSTR(MP_QSTR_WF_NOISE), MP_ROM_INT(128) }, + { MP_ROM_QSTR(MP_QSTR_WF_SQUARE), MP_ROM_INT(64) }, + { MP_ROM_QSTR(MP_QSTR_WF_SAW), MP_ROM_INT(32) }, + { MP_ROM_QSTR(MP_QSTR_WF_TRIANGLE), MP_ROM_INT(16) }, + { MP_ROM_QSTR(MP_QSTR_WF_SINE), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_WF_WAVE), MP_ROM_INT(1) }, }; STATIC MP_DEFINE_CONST_DICT(GalacticUnicorn_locals_dict, GalacticUnicorn_locals_dict_table); diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 80c8d7b9..34d6e4c3 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -159,20 +159,6 @@ extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data) { return mp_const_none; } -extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq) { - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - self->galactic->play_tone(mp_obj_get_float(freq)); - - return mp_const_none; -} - -extern mp_obj_t GalacticUnicorn_play_dual_tone(mp_obj_t self_in, mp_obj_t freq_a, mp_obj_t freq_b) { - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - self->galactic->play_dual_tone(mp_obj_get_float(freq_a), mp_obj_get_float(freq_b)); - - return mp_const_none; -} - extern mp_obj_t GalacticUnicorn_play_synth(mp_obj_t self_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); self->galactic->play_synth(); @@ -186,4 +172,56 @@ extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) { return mp_const_none; } + +extern mp_obj_t GalacticUnicorn_channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_channel, ARG_waveforms, ARG_attack_ms, ARG_decay_ms, ARG_sustain, ARG_release_ms, ARG_volume }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_channel, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_waveforms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_attack_ms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_decay_ms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_sustain, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_release_ms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_volumes, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t); + + int c = args[ARG_channel].u_int; + self->galactic->synth.channels[c].waveforms = args[ARG_waveforms].u_int; + self->galactic->synth.channels[c].attack_ms = args[ARG_attack_ms].u_int; + self->galactic->synth.channels[c].decay_ms = args[ARG_decay_ms].u_int; + self->galactic->synth.channels[c].sustain = args[ARG_sustain].u_int; + self->galactic->synth.channels[c].release_ms = args[ARG_release_ms].u_int; + self->galactic->synth.channels[c].volume = args[ARG_volume].u_int; + + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_channel_freq(mp_obj_t self_in, mp_obj_t channel, mp_obj_t freq) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + + self->galactic->synth.channels[mp_obj_get_int(channel)].frequency = mp_obj_get_float(freq); + + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_channel_trigger_attack(mp_obj_t self_in, mp_obj_t channel) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->synth.channels[mp_obj_get_int(channel)].trigger_attack(); + + return mp_const_none; +} + +extern mp_obj_t GalacticUnicorn_channel_trigger_release(mp_obj_t self_in, mp_obj_t channel) { + _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); + self->galactic->synth.channels[mp_obj_get_int(channel)].trigger_release(); + + return mp_const_none; +} } diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 8409aee8..69afbd84 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -25,7 +25,10 @@ extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button); extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); -extern mp_obj_t GalacticUnicorn_play_tone(mp_obj_t self_in, mp_obj_t freq); -extern mp_obj_t GalacticUnicorn_play_dual_tone(mp_obj_t self_in, mp_obj_t freq_a, mp_obj_t freq_b); extern mp_obj_t GalacticUnicorn_play_synth(mp_obj_t self_in); -extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in); \ No newline at end of file +extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in); + +extern mp_obj_t GalacticUnicorn_channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);; +extern mp_obj_t GalacticUnicorn_channel_freq(mp_obj_t self_in, mp_obj_t channel, mp_obj_t freq); +extern mp_obj_t GalacticUnicorn_channel_trigger_attack(mp_obj_t self_in, mp_obj_t channel); +extern mp_obj_t GalacticUnicorn_channel_trigger_release(mp_obj_t self_in, mp_obj_t channel); \ No newline at end of file diff --git a/micropython/modules/galactic_unicorn/micropython.cmake b/micropython/modules/galactic_unicorn/micropython.cmake index cdb3bf49..9f00a1b3 100644 --- a/micropython/modules/galactic_unicorn/micropython.cmake +++ b/micropython/modules/galactic_unicorn/micropython.cmake @@ -6,6 +6,7 @@ target_sources(usermod_${MOD_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/galactic_unicorn.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_synth/pico_synth.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_rgb888.cpp ) pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/galactic_unicorn/galactic_unicorn.pio) From 53dfb9866d98c5ac8cd2d16dc93cc4261994c55d Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 25 Aug 2022 17:27:53 +0100 Subject: [PATCH 33/42] Started splitting out synth into separate channel objects --- .../galactic_unicorn/galactic_unicorn.cpp | 5 + .../galactic_unicorn/galactic_unicorn.hpp | 3 +- .../feature_test_with_audio.py | 165 ++++++-------- .../galactic_unicorn/galactic_unicorn.c | 50 +++-- .../galactic_unicorn/galactic_unicorn.cpp | 207 ++++++++++++++---- .../galactic_unicorn/galactic_unicorn.h | 16 +- 6 files changed, 287 insertions(+), 159 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 333debef..66830313 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -444,6 +444,11 @@ namespace pimoroni { } } + AudioChannel& GalacticUnicorn::synth_channel(uint channel) { + assert(channel < PicoSynth::CHANNEL_COUNT); + return synth.channels[channel]; + } + void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return; diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index f1d4f9d8..00e52439 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -75,10 +75,8 @@ namespace pimoroni { int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0}; uint current_buffer = 0; - public: PicoSynth synth; - private: enum PlayMode { PLAYING_BUFFER, //PLAYING_TONE, @@ -116,6 +114,7 @@ namespace pimoroni { void play_sample(uint8_t *data, uint32_t length); void play_synth(); void stop_playing(); + AudioChannel& synth_channel(uint channel); private: void next_bitstream_sequence(); diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index a83290f7..2ded25cc 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -2,7 +2,7 @@ import gc import time import math from machine import Timer -from galactic import GalacticUnicorn +from galactic import GalacticUnicorn, Channel from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY gc.collect() @@ -700,15 +700,22 @@ freq_b = 0 beat = 0 +channel0 = gu.synth_channel(0) +channel1 = gu.synth_channel(1) +channel2 = gu.synth_channel(2) +channel3 = gu.synth_channel(3) +channel4 = gu.synth_channel(7) +channels = [channel0, channel1, channel2, channel3, channel4] + def next_beat(): global beat for i in range(5): if notes[i][beat] > 0: - gu.channel_freq(i, notes[i][beat]) - gu.channel_trigger_attack(i) + channels[i].freq(notes[i][beat]) + channels[i].trigger_attack() elif notes[i][beat] == -1: - gu.channel_trigger_release(i) + channels[i].trigger_release() beat = (beat + 1) % SONG_LENGTH @@ -729,36 +736,36 @@ while True: if gu.is_pressed(GalacticUnicorn.SWITCH_A): if not was_a_pressed: - gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE, - 16, + channel0.configure(Channel.TRIANGLE + Channel.SQUARE, + 16, 168, 0, 168, 0) - gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE, - 38, - 300, - 0, - 0, - 12000) - gu.channel_configure(2, gu.WF_NOISE, - 5, - 10, - 16000, - 100, - 0) - gu.channel_configure(3, gu.WF_NOISE, - 5, - 5, - 8000, - 40, - 0) - gu.channel_configure(4, gu.WF_SQUARE, - 10, - 100, - 0, - 500, - 0) + channel1.configure(Channel.SINE + Channel.SQUARE, + 38, + 300, + 0, + 0, + 12000) + channel2.configure(Channel.NOISE, + 5, + 10, + 16000, + 100, + 0) + channel3.configure(Channel.NOISE, + 5, + 5, + 8000, + 40, + 0) + channel4.configure(Channel.SQUARE, + 10, + 100, + 0, + 500, + 0) if not synthing: beat = 0 next_beat() @@ -774,21 +781,8 @@ while True: if not was_b_pressed: timer.deinit() freq_a = 400 + channel0.play_tone(freq_a, 0.06) - gu.channel_freq(0, freq_a) - gu.channel_configure(0, gu.WF_SINE, - 1, - 1, - 0xffff, - 1, - 4000) - gu.channel_configure(1, gu.WF_SINE, - 1, - 1, - 0xffff, - 1, - 4000) - gu.channel_trigger_attack(0) gu.play_synth() synthing = False @@ -803,21 +797,8 @@ while True: timer.deinit() freq_b = 600 - gu.channel_freq(1, freq_b) - gu.channel_configure(0, gu.WF_SINE, - 1, - 1, - 0xffff, - 1, - 4000) - gu.channel_configure(1, gu.WF_SINE, - 1, - 1, - 0xffff, - 1, - 4000) + channel1.play_tone(freq_b, 0.06, fade_in=0.5) - gu.channel_trigger_attack(1) gu.play_synth() synthing = False @@ -842,56 +823,56 @@ while True: # gu.adjust_brightness(+0.01) if bool_playing: freq_b += 10 - gu.channel_freq(1, freq_b) + channel1.freq(freq_b) if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): # gu.adjust_brightness(-0.01) if bool_playing: freq_b -= 10 - gu.channel_freq(1, freq_b) + channel1.freq(freq_b) if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): if bool_playing: freq_a += 10 - gu.channel_freq(0, freq_a) + channel0.freq(freq_a) if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): if bool_playing: freq_a -= 10 - gu.channel_freq(0, freq_a) + channel0.freq(freq_a) if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): if not was_z_pressed: - gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE, - 16, - 168, - 0xafff, - 168, - 10000) - gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE, - 38, - 300, - 0, - 0, - 12000) - gu.channel_configure(2, gu.WF_NOISE, - 5, - 10, - 16000, - 100, - 18000) - gu.channel_configure(3, gu.WF_NOISE, - 5, - 5, - 8000, - 40, - 8000) - gu.channel_configure(4, gu.WF_SQUARE, - 10, - 100, - 0, - 500, - 12000) + channel0.configure(Channel.TRIANGLE + Channel.SQUARE, + 16, + 168, + 0xafff, + 168, + 10000) + channel1.configure(Channel.SINE + Channel.SQUARE, + 38, + 300, + 0, + 0, + 12000) + channel2.configure(Channel.NOISE, + 5, + 10, + 16000, + 100, + 18000) + channel3.configure(Channel.NOISE, + 5, + 5, + 8000, + 40, + 8000) + channel4.configure(Channel.SQUARE, + 10, + 100, + 0, + 500, + 12000) if not synthing: beat = 0 next_beat() diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index 8fded8d6..e44ca13e 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -2,6 +2,13 @@ /***** Methods *****/ +MP_DEFINE_CONST_FUN_OBJ_1(Channel___del___obj, Channel___del__); +MP_DEFINE_CONST_FUN_OBJ_KW(Channel_configure_obj, 6, Channel_configure); +MP_DEFINE_CONST_FUN_OBJ_2(Channel_freq_obj, Channel_freq); +MP_DEFINE_CONST_FUN_OBJ_1(Channel_trigger_attack_obj, Channel_trigger_attack); +MP_DEFINE_CONST_FUN_OBJ_1(Channel_trigger_release_obj, Channel_trigger_release); +MP_DEFINE_CONST_FUN_OBJ_KW(Channel_play_tone_obj, 2, Channel_play_tone); + MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn___del___obj, GalacticUnicorn___del__); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear); MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_update_obj, GalacticUnicorn_update); @@ -16,12 +23,25 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pre MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_play_synth_obj, GalacticUnicorn_play_synth); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing); -MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_channel_configure_obj, 7, GalacticUnicorn_channel_configure); -MP_DEFINE_CONST_FUN_OBJ_3(GalacticUnicorn_channel_freq_obj, GalacticUnicorn_channel_freq); -MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_channel_trigger_attack_obj, GalacticUnicorn_channel_trigger_attack); -MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_channel_trigger_release_obj, GalacticUnicorn_channel_trigger_release); +MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_synth_channel_obj, GalacticUnicorn_synth_channel); /***** Binding of Methods *****/ +STATIC const mp_rom_map_elem_t Channel_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Channel___del___obj) }, + { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&Channel_configure_obj) }, + { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&Channel_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_trigger_attack), MP_ROM_PTR(&Channel_trigger_attack_obj) }, + { MP_ROM_QSTR(MP_QSTR_trigger_release), MP_ROM_PTR(&Channel_trigger_release_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&Channel_play_tone_obj) }, + + { MP_ROM_QSTR(MP_QSTR_NOISE), MP_ROM_INT(128) }, + { MP_ROM_QSTR(MP_QSTR_SQUARE), MP_ROM_INT(64) }, + { MP_ROM_QSTR(MP_QSTR_SAW), MP_ROM_INT(32) }, + { MP_ROM_QSTR(MP_QSTR_TRIANGLE), MP_ROM_INT(16) }, + { MP_ROM_QSTR(MP_QSTR_SINE), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_WAVE), MP_ROM_INT(1) }, +}; + STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&GalacticUnicorn___del___obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&GalacticUnicorn_clear_obj) }, @@ -37,10 +57,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) }, { MP_ROM_QSTR(MP_QSTR_play_synth), MP_ROM_PTR(&GalacticUnicorn_play_synth_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_playing), MP_ROM_PTR(&GalacticUnicorn_stop_playing_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel_configure), MP_ROM_PTR(&GalacticUnicorn_channel_configure_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel_freq), MP_ROM_PTR(&GalacticUnicorn_channel_freq_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel_trigger_attack), MP_ROM_PTR(&GalacticUnicorn_channel_trigger_attack_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel_trigger_release), MP_ROM_PTR(&GalacticUnicorn_channel_trigger_release_obj) }, + { MP_ROM_QSTR(MP_QSTR_synth_channel), MP_ROM_PTR(&GalacticUnicorn_synth_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, @@ -54,18 +71,20 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SWITCH_VOLUME_DOWN), MP_ROM_INT(8) }, { MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_UP), MP_ROM_INT(21) }, { MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_DOWN), MP_ROM_INT(26) }, - - { MP_ROM_QSTR(MP_QSTR_WF_NOISE), MP_ROM_INT(128) }, - { MP_ROM_QSTR(MP_QSTR_WF_SQUARE), MP_ROM_INT(64) }, - { MP_ROM_QSTR(MP_QSTR_WF_SAW), MP_ROM_INT(32) }, - { MP_ROM_QSTR(MP_QSTR_WF_TRIANGLE), MP_ROM_INT(16) }, - { MP_ROM_QSTR(MP_QSTR_WF_SINE), MP_ROM_INT(8) }, - { MP_ROM_QSTR(MP_QSTR_WF_WAVE), MP_ROM_INT(1) }, }; +STATIC MP_DEFINE_CONST_DICT(Channel_locals_dict, Channel_locals_dict_table); STATIC MP_DEFINE_CONST_DICT(GalacticUnicorn_locals_dict, GalacticUnicorn_locals_dict_table); /***** Class Definition *****/ +const mp_obj_type_t Channel_type = { + { &mp_type_type }, + .name = MP_QSTR_Channel, + .print = Channel_print, + .make_new = Channel_make_new, + .locals_dict = (mp_obj_dict_t*)&Channel_locals_dict, +}; + const mp_obj_type_t GalacticUnicorn_type = { { &mp_type_type }, .name = MP_QSTR_GalacticUnicorn, @@ -77,6 +96,7 @@ const mp_obj_type_t GalacticUnicorn_type = { /***** Globals Table *****/ STATIC const mp_map_elem_t galactic_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_galactic) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Channel), (mp_obj_t)&Channel_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_GalacticUnicorn), (mp_obj_t)&GalacticUnicorn_type }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_galactic_globals, galactic_globals_table); diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 34d6e4c3..8b724e0f 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -13,6 +13,155 @@ extern "C" { #include "py/builtin.h" +/********** Channel **********/ + +/***** Variables Struct *****/ +typedef struct _Channel_obj_t { + mp_obj_base_t base; + AudioChannel* channel; +} _Channel_obj_t; + + +/***** Print *****/ +void Channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; //Unused input parameter + //_Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t); + //AudioChannel* channel = self->channel; + mp_print_str(print, "Channel("); + mp_print_str(print, ")"); +} + + +/***** Constructor *****/ +mp_obj_t Channel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + mp_raise_msg(&mp_type_RuntimeError, "Cannot create Channel objects. They can only be accessed from GalacticUnicorn.synth_channel()"); + return mp_const_none; +} + + +/***** Destructor ******/ +mp_obj_t Channel___del__(mp_obj_t self_in) { + return mp_const_none; +} + + +/***** Methods *****/ +mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_waveforms, ARG_attack_ms, ARG_decay_ms, ARG_sustain, ARG_release_ms, ARG_volume }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_waveforms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_attack_ms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_decay_ms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_sustain, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_release_ms, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_volumes, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Channel_obj_t); + + self->channel->waveforms = args[ARG_waveforms].u_int; + self->channel->attack_ms = args[ARG_attack_ms].u_int; + self->channel->decay_ms = args[ARG_decay_ms].u_int; + self->channel->sustain = args[ARG_sustain].u_int; + self->channel->release_ms = args[ARG_release_ms].u_int; + self->channel->volume = args[ARG_volume].u_int; + + return mp_const_none; +} + +mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t); + + float freq = mp_obj_get_float(freq_in); + if(freq <= 0.0f) { + mp_raise_ValueError("freq out of range. Expected greater than 0.0"); + } + self->channel->frequency = freq; + + return mp_const_none; +} + +mp_obj_t Channel_trigger_attack(mp_obj_t self_in) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t); + self->channel->trigger_attack(); + + return mp_const_none; +} + +mp_obj_t Channel_trigger_release(mp_obj_t self_in) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t); + self->channel->trigger_release(); + + return mp_const_none; +} + +mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_self, ARG_freq, ARG_volume, ARG_fade_in, ARG_fade_out }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_volume, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_fade_in, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_fade_out, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Channel_obj_t); + + float freq = mp_obj_get_float(args[ARG_freq].u_obj); + if(freq <= 0.0f) { + mp_raise_ValueError("freq out of range. Expected greater than 0.0"); + } + + float volume = 1.0f; + if(args[ARG_volume].u_obj != mp_const_none) { + volume = mp_obj_get_float(args[ARG_volume].u_obj); + if(volume < 0.0f || volume > 1.0f) { + mp_raise_ValueError("volume out of range. Expected 0.0 to 1.0"); + } + } + + int fade_in_ms = 1; + if(args[ARG_fade_in].u_obj != mp_const_none) { + float fade_in = mp_obj_get_float(args[ARG_fade_in].u_obj); + if(fade_in <= 0.0f) { + mp_raise_ValueError("fade_in out of range. Expected greater than 0.0"); + } + fade_in_ms = (uint16_t)(fade_in * 1000.0f); + } + + int fade_out_ms = 1; + if(args[ARG_fade_out].u_obj != mp_const_none) { + float fade_out = mp_obj_get_float(args[ARG_fade_out].u_obj); + if(fade_out <= 0.0f) { + mp_raise_ValueError("fade_out out of range. Expected greater than 0.0"); + } + fade_out_ms = (uint16_t)(fade_out * 1000.0f); + } + + + self->channel->frequency = freq; + self->channel->waveforms = Waveform::SINE; + self->channel->attack_ms = MAX(fade_in_ms, 1); + self->channel->decay_ms = 1; + self->channel->sustain = 0xffff; + self->channel->release_ms = MAX(fade_out_ms, 1); + self->channel->volume = (uint16_t)(volume * 0xffff); + + self->channel->trigger_attack(); + + return mp_const_none; +} + + /********** GalacticUnicorn **********/ /***** Variables Struct *****/ @@ -173,55 +322,21 @@ extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) { return mp_const_none; } -extern mp_obj_t GalacticUnicorn_channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_self, ARG_channel, ARG_waveforms, ARG_attack_ms, ARG_decay_ms, ARG_sustain, ARG_release_ms, ARG_volume }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_channel, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_waveforms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_attack_ms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_decay_ms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_sustain, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_release_ms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_volumes, MP_ARG_REQUIRED | MP_ARG_INT }, - }; - - // Parse args. - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t); - - int c = args[ARG_channel].u_int; - self->galactic->synth.channels[c].waveforms = args[ARG_waveforms].u_int; - self->galactic->synth.channels[c].attack_ms = args[ARG_attack_ms].u_int; - self->galactic->synth.channels[c].decay_ms = args[ARG_decay_ms].u_int; - self->galactic->synth.channels[c].sustain = args[ARG_sustain].u_int; - self->galactic->synth.channels[c].release_ms = args[ARG_release_ms].u_int; - self->galactic->synth.channels[c].volume = args[ARG_volume].u_int; - - return mp_const_none; -} - -extern mp_obj_t GalacticUnicorn_channel_freq(mp_obj_t self_in, mp_obj_t channel, mp_obj_t freq) { +extern mp_obj_t GalacticUnicorn_synth_channel(mp_obj_t self_in, mp_obj_t channel_in) { _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - self->galactic->synth.channels[mp_obj_get_int(channel)].frequency = mp_obj_get_float(freq); + // Check that the channel is valid + int channel = mp_obj_get_int(channel_in); + if(channel < 0 || channel >= (int)PicoSynth::CHANNEL_COUNT) { + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("channel out of range. Expected 0 to %d"), PicoSynth::CHANNEL_COUNT - 1); + } - return mp_const_none; -} + // NOTE This seems to work, in that it give MP access to the calibration object + // Could very easily mess up in weird ways once object deletion is considered? + _Channel_obj_t *channel_obj = m_new_obj_with_finaliser(_Channel_obj_t); + channel_obj->base.type = &Channel_type; + channel_obj->channel = &self->galactic->synth_channel(channel); -extern mp_obj_t GalacticUnicorn_channel_trigger_attack(mp_obj_t self_in, mp_obj_t channel) { - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - self->galactic->synth.channels[mp_obj_get_int(channel)].trigger_attack(); - - return mp_const_none; -} - -extern mp_obj_t GalacticUnicorn_channel_trigger_release(mp_obj_t self_in, mp_obj_t channel) { - _GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); - self->galactic->synth.channels[mp_obj_get_int(channel)].trigger_release(); - - return mp_const_none; + return MP_OBJ_FROM_PTR(channel_obj); } } diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 69afbd84..11f0993d 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -2,9 +2,20 @@ #include "py/runtime.h" /***** Extern of Class Definition *****/ +extern const mp_obj_type_t Channel_type; extern const mp_obj_type_t GalacticUnicorn_type; /***** Extern of Class Methods *****/ +extern void Channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +extern mp_obj_t Channel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); +extern mp_obj_t Channel___del__(mp_obj_t self_in); +extern mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +extern mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in); +extern mp_obj_t Channel_trigger_attack(mp_obj_t self_in); +extern mp_obj_t Channel_trigger_release(mp_obj_t self_in); +extern mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + + extern void GalacticUnicorn_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); extern mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); extern mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in); @@ -28,7 +39,4 @@ extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data); extern mp_obj_t GalacticUnicorn_play_synth(mp_obj_t self_in); extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in); -extern mp_obj_t GalacticUnicorn_channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);; -extern mp_obj_t GalacticUnicorn_channel_freq(mp_obj_t self_in, mp_obj_t channel, mp_obj_t freq); -extern mp_obj_t GalacticUnicorn_channel_trigger_attack(mp_obj_t self_in, mp_obj_t channel); -extern mp_obj_t GalacticUnicorn_channel_trigger_release(mp_obj_t self_in, mp_obj_t channel); \ No newline at end of file +extern mp_obj_t GalacticUnicorn_synth_channel(mp_obj_t self_in, mp_obj_t channel_in); \ No newline at end of file From 27e9d467ff0cad0a236479b8adc566a5f1d3d7af Mon Sep 17 00:00:00 2001 From: jon Date: Fri, 29 Jul 2022 10:58:14 +0100 Subject: [PATCH 34/42] Galactic Unicorn: Example tweaks. --- examples/galactic_unicorn/lava_lamp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/galactic_unicorn/lava_lamp.cpp b/examples/galactic_unicorn/lava_lamp.cpp index f4b5dc75..7499b921 100644 --- a/examples/galactic_unicorn/lava_lamp.cpp +++ b/examples/galactic_unicorn/lava_lamp.cpp @@ -45,6 +45,7 @@ int main() { stdio_init_all(); galactic_unicorn.init(); + galactic_unicorn.set_brightness(0.5); // randomise blob start positions, directions, and size std::array blobs; From 8e8299a80bca2c4604da651918615c7735ab8c5e Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 25 Aug 2022 17:37:40 +0100 Subject: [PATCH 35/42] Linting --- .../examples/galactic_unicorn/feature_test_with_audio.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index 2ded25cc..fe4d81b8 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -738,10 +738,10 @@ while True: if not was_a_pressed: channel0.configure(Channel.TRIANGLE + Channel.SQUARE, 16, - 168, - 0, - 168, - 0) + 168, + 0, + 168, + 0) channel1.configure(Channel.SINE + Channel.SQUARE, 38, 300, From 269598218281933249e760d8906626c3b02bc0f7 Mon Sep 17 00:00:00 2001 From: lowfatcode Date: Thu, 25 Aug 2022 17:40:53 +0100 Subject: [PATCH 36/42] Galactic Unicorn: Rainbow text demo. --- examples/galactic_unicorn/CMakeLists.txt | 10 +- examples/galactic_unicorn/demo.cpp | 242 --------------------- examples/galactic_unicorn/rainbow_text.cpp | 106 +++++++++ 3 files changed, 111 insertions(+), 247 deletions(-) delete mode 100644 examples/galactic_unicorn/demo.cpp create mode 100644 examples/galactic_unicorn/rainbow_text.cpp diff --git a/examples/galactic_unicorn/CMakeLists.txt b/examples/galactic_unicorn/CMakeLists.txt index 7b145552..7b879bbe 100644 --- a/examples/galactic_unicorn/CMakeLists.txt +++ b/examples/galactic_unicorn/CMakeLists.txt @@ -1,14 +1,14 @@ add_executable( - galactic_unicorn_demo - demo.cpp + rainbow_text + rainbow_text.cpp ) # Pull in pico libraries that we need -target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) -pico_enable_stdio_usb(galactic_unicorn_demo 1) +target_link_libraries(rainbow_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn) +pico_enable_stdio_usb(rainbow_text 1) # create map/bin/hex file etc. -pico_add_extra_outputs(galactic_unicorn_demo) +pico_add_extra_outputs(rainbow_text) diff --git a/examples/galactic_unicorn/demo.cpp b/examples/galactic_unicorn/demo.cpp deleted file mode 100644 index aecad0f6..00000000 --- a/examples/galactic_unicorn/demo.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include -#include -#include "pico/stdlib.h" - -#include "libraries/pico_graphics/pico_graphics.hpp" -#include "galactic_unicorn.hpp" -#include "okcolor.hpp" - -using namespace pimoroni; - -PicoGraphics_PenRGB888 graphics(53, 11, nullptr); -GalacticUnicorn galactic_unicorn; - -// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel -// Outputs are rgb in the range 0-255 for each channel -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } -} - -void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { - int w = graphics.measure_text(t, s); - p.x += (53 / 2) - (w / 2); - p.y += (11 / 2); - graphics.text(t, Point(p.x, p.y), -1, s, a); - graphics.text(t, Point(p.x + 1, p.y), -1, s, a); - graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); - graphics.text(t, Point(p.x, p.y + 1), -1, s, a); -} - -struct star_t { - float dx, dy, x, y, a; - - uint8_t brightness() { - int b = a / 5; - return b > 15 ? 15 : b; - } -}; - -void init_star(star_t &s) { - s.x = ((rand() % 100) / 5.0f) - 10.0f; - s.y = ((rand() % 100) / 10.0f) - 5.0f; - - s.dx = s.x / 10.0f; - s.dy = s.y / 10.0f; - s.a = 0; -} - -void step_star(star_t &s) { - s.x += s.dx; - s.y += s.dy; - s.a++; - - if(s.a > 100) { - init_star(s); - } -} - - -int main() { - - uint8_t hue_map[53][3]; - for(int i = 0; i < 53; i++) { - from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); - } - - star_t stars[100]; - for(int i = 0; i < 100; i++) { - init_star(stars[i]); - stars[i].a = i; - } - -gpio_set_function(28, GPIO_FUNC_SIO); - gpio_set_dir(28, GPIO_OUT); - - for(int i = 0; i < 10; i++) { - gpio_put(28, !gpio_get(28)); - sleep_ms(100); - } - sleep_ms(1000); - - gpio_put(28,true); - - galactic_unicorn.init(); - -/* - bool a_pressed = false; - bool b_pressed = false; - bool x_pressed = false; - bool y_pressed = false; -*/ - graphics.set_font("sans"); - - - - //uint i = 0; - //int v = 255; - - float hue_offset = 0.0f; - float brightness = 0.5f; - float curve = 4.0f; - - int x = 10; - int y = 5; - - while(true) { - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) { - hue_offset += 0.05; - if(hue_offset > 1.0f) hue_offset = 1.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_DOWN)) { - hue_offset -= 0.05; - if(hue_offset < 0.0f) hue_offset = 0.0f; - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { - brightness += 0.05; - if(brightness > 1.0f) brightness = 1.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { - brightness -= 0.05; - if(brightness < 0.0f) brightness = 0.0f; - } - - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { - curve += 0.5; - if(curve > 100.0f) curve = 100.0f; - } - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { - curve -= 0.5; - if(curve < 0.5) curve = 0.5; - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) { - x -= 1; - sleep_ms(250); - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) { - x += 1; - sleep_ms(250); - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) { - y -= 1; - sleep_ms(250); - } - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_D)) { - y += 1; - sleep_ms(250); - } - -/* - for(int y = 0; y < 11; y++) { - for(int x = 0; x < 53; x++) { - float fx = x / 53.0f; - float fy = (y / 11.0f) - 0.5f; - float twopi = M_PI * 2; - float hue = fy + (sin(fx * twopi / curve)); - float fade = 1.0f; - - hue += hue_offset; - while(hue < 0.0f) {hue += 1.0f;} - while(hue > 1.0f) {hue -= 1.0f;} - hue = 1.0f - hue; - ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade}; - ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); - galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f); - } - }*/ - - graphics.set_pen(255, 255, 255); - graphics.pixel(Point(x, y)); - galactic_unicorn.update(&graphics); - /*i++; - - graphics.set_pen(0, 0, 0); - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);} - graphics.clear(); - - if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;} - - - for(int i = 0; i < 100; i++) { - star_t &star = stars[i]; - step_star(star); - - uint b = star.brightness(); - graphics.set_pen(b, b, b); - graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2))); - } - -graphics.set_pen(255, 255, 255); - float s = 1.0f;//0.65f + (sin(i / 25.0f) * 0.15f); - float a = 1.0f;// (sin(i / 25.0f) * 100.0f); - float x = (sin(i / 25.0f) * 40.0f) * s; - float y = (cos(i / 15.0f) * 10.0f) * s; - text("Galactic", Point(x, y), s, a); - - uint16_t *p = (uint16_t *)graphics.frame_buffer; - for(size_t i = 0; i < 53 * 11; i++) { - int x = i % 53; - int y = i / 53; - uint r = ((*p & 0b1111100000000000) >> 11) << 3; - uint g = ((*p & 0b0000011111100000) >> 5) << 2; - uint b = ((*p & 0b0000000000011111) >> 0) << 3; - p++; - - if(r > 200 && g > 200 && b > 200) { - r = hue_map[x][0]; - g = hue_map[x][1]; - b = hue_map[x][2]; - } - galactic_unicorn.set_pixel(x, y, r, g, b); - } -*/ - - sleep_ms(10); - } - - - - printf("done\n"); - - return 0; -} diff --git a/examples/galactic_unicorn/rainbow_text.cpp b/examples/galactic_unicorn/rainbow_text.cpp new file mode 100644 index 00000000..fa8d6949 --- /dev/null +++ b/examples/galactic_unicorn/rainbow_text.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include "pico/stdlib.h" + +#include "libraries/pico_graphics/pico_graphics.hpp" +#include "galactic_unicorn.hpp" +#include "okcolor.hpp" + +using namespace pimoroni; + +PicoGraphics_PenRGB888 graphics(53, 11, nullptr); +GalacticUnicorn galactic_unicorn; + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) { + int w = graphics.measure_text(t, s); + p.x += (53 / 2) - (w / 2); + p.y += (11 / 2); + graphics.text(t, Point(p.x, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y), -1, s, a); + graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a); + graphics.text(t, Point(p.x, p.y + 1), -1, s, a); +} + + +int main() { + + uint8_t hue_map[53][3]; + for(int i = 0; i < 53; i++) { + from_hsv(i / 53.0f, 1.0f, 0.1f, hue_map[i][0], hue_map[i][1], hue_map[i][2]); + } + + galactic_unicorn.init(); + + graphics.set_font("sans"); + uint i = 0; + + while(true) { + + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) { + galactic_unicorn.adjust_brightness(+0.01); + } + if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) { + galactic_unicorn.adjust_brightness(-0.01); + } + + + i++; + graphics.set_pen(0, 0, 0); + graphics.clear(); + + float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f); + float a = 1.0f;// (sin(i / 25.0f) * 100.0f); + + float x = (sin((i) / 50.0f) * 90.0f); + float y = (cos((i) / 40.0f) * 5.0f); + graphics.set_pen(255, 255, 255); + text("Galactic Unicorn", Point(x, y), s, a); + + uint8_t *p = (uint8_t *)graphics.frame_buffer; + for(size_t i = 0; i < 53 * 11; i++) { + int x = i % 53; + int y = i / 53; + uint r = *p++; + uint g = *p++; + uint b = *p++; + p++; + + if(r > 0) { + r = hue_map[x][0]; + g = hue_map[x][1]; + b = hue_map[x][2]; + } + + galactic_unicorn.set_pixel(x, y, r, g, b); + } + + + } + + + + printf("done\n"); + + return 0; +} From df79caf34e59f9c62fb3a81b6f1a89a6257e27d8 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Fri, 26 Aug 2022 19:32:39 +0100 Subject: [PATCH 37/42] Exposed remaining AudioChannel parameters --- examples/galactic_unicorn/rainbow_text.cpp | 11 +- libraries/pico_synth/pico_synth.cpp | 14 + libraries/pico_synth/pico_synth.hpp | 5 +- .../feature_test_with_audio.py | 140 ++++----- .../galactic_unicorn/galactic_unicorn.c | 23 +- .../galactic_unicorn/galactic_unicorn.cpp | 278 ++++++++++++++---- .../galactic_unicorn/galactic_unicorn.h | 12 +- 7 files changed, 347 insertions(+), 136 deletions(-) diff --git a/examples/galactic_unicorn/rainbow_text.cpp b/examples/galactic_unicorn/rainbow_text.cpp index fa8d6949..bee8ea9b 100644 --- a/examples/galactic_unicorn/rainbow_text.cpp +++ b/examples/galactic_unicorn/rainbow_text.cpp @@ -68,7 +68,7 @@ int main() { i++; graphics.set_pen(0, 0, 0); graphics.clear(); - + float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f); float a = 1.0f;// (sin(i / 25.0f) * 100.0f); @@ -76,7 +76,7 @@ int main() { float y = (cos((i) / 40.0f) * 5.0f); graphics.set_pen(255, 255, 255); text("Galactic Unicorn", Point(x, y), s, a); - + uint8_t *p = (uint8_t *)graphics.frame_buffer; for(size_t i = 0; i < 53 * 11; i++) { int x = i % 53; @@ -92,14 +92,11 @@ int main() { b = hue_map[x][2]; } - galactic_unicorn.set_pixel(x, y, r, g, b); + graphics.set_pen(r, g, b); + graphics.pixel(Point(x, y)); } - - } - - printf("done\n"); return 0; diff --git a/libraries/pico_synth/pico_synth.cpp b/libraries/pico_synth/pico_synth.cpp index 4fc66cbf..4f96ed6f 100644 --- a/libraries/pico_synth/pico_synth.cpp +++ b/libraries/pico_synth/pico_synth.cpp @@ -56,6 +56,20 @@ namespace pimoroni { adsr_step = 0; } + void AudioChannel::restore() { + // Put all the parameters back to their initial values + waveforms = 0; + frequency = 660; + volume = 0xffff; + + attack_ms = 2; + decay_ms = 6; + sustain = 0xffff; + release_ms = 1; + pulse_width = 0x7fff; + noise = 0; + } + bool PicoSynth::is_audio_playing() { if(volume == 0) { return false; diff --git a/libraries/pico_synth/pico_synth.hpp b/libraries/pico_synth/pico_synth.hpp index f0c48b9a..01fe55bc 100644 --- a/libraries/pico_synth/pico_synth.hpp +++ b/libraries/pico_synth/pico_synth.hpp @@ -69,11 +69,11 @@ namespace pimoroni { struct AudioChannel { uint8_t waveforms = 0; // bitmask for enabled waveforms (see Waveform enum for values) uint16_t frequency = 660; // frequency of the voice (Hz) - uint16_t volume = 0xffff; // channel volume + uint16_t volume = UINT16_MAX; // channel volume uint16_t attack_ms = 2; // attack period (cannot be zero) uint16_t decay_ms = 6; // decay period (cannot be zero) - uint16_t sustain = 0xffff; // sustain volume + uint16_t sustain = UINT16_MAX; // sustain volume uint16_t release_ms = 1; // release period uint16_t pulse_width = 0x7fff; // duty cycle of square wave (default 50%) int16_t noise = 0; // current noise value @@ -101,6 +101,7 @@ namespace pimoroni { void trigger_sustain(); void trigger_release(); void off(); + void restore(); }; class PicoSynth { diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index fe4d81b8..4c32afbe 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -712,7 +712,7 @@ def next_beat(): global beat for i in range(5): if notes[i][beat] > 0: - channels[i].freq(notes[i][beat]) + channels[i].frequency(notes[i][beat]) channels[i].trigger_attack() elif notes[i][beat] == -1: channels[i].trigger_release() @@ -736,36 +736,36 @@ while True: if gu.is_pressed(GalacticUnicorn.SWITCH_A): if not was_a_pressed: - channel0.configure(Channel.TRIANGLE + Channel.SQUARE, - 16, - 168, - 0, - 168, - 0) - channel1.configure(Channel.SINE + Channel.SQUARE, - 38, - 300, - 0, - 0, - 12000) - channel2.configure(Channel.NOISE, - 5, - 10, - 16000, - 100, - 0) - channel3.configure(Channel.NOISE, - 5, - 5, - 8000, - 40, - 0) - channel4.configure(Channel.SQUARE, - 10, - 100, - 0, - 500, - 0) + channel0.configure(waveforms=Channel.TRIANGLE + Channel.SQUARE, + attack=0.016, + decay=0.168, + sustain=0, + release=0.168, + volume=0) + channel1.configure(waveforms=Channel.SINE + Channel.SQUARE, + attack=0.038, + decay=0.300, + sustain=0, + release=0, + volume=12000/65535) + channel2.configure(waveforms=Channel.NOISE, + attack=0.005, + decay=0.010, + sustain=16000/65535, + release=0.100, + volume=0) + channel3.configure(waveforms=Channel.NOISE, + attack=0.005, + decay=0.005, + sustain=8000/65535, + release=0.040, + volume=0) + channel4.configure(waveforms=Channel.SQUARE, + attack=0.010, + decay=0.100, + sustain=0, + release=0.500, + volume=0) if not synthing: beat = 0 next_beat() @@ -797,7 +797,7 @@ while True: timer.deinit() freq_b = 600 - channel1.play_tone(freq_b, 0.06, fade_in=0.5) + channel1.play_tone(freq_b, 0.06, attack=0.5) gu.play_synth() synthing = False @@ -822,57 +822,57 @@ while True: if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): # gu.adjust_brightness(+0.01) if bool_playing: - freq_b += 10 - channel1.freq(freq_b) + freq_b = min(freq_b + 10, 20000) + channel1.frequency(freq_b) if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): # gu.adjust_brightness(-0.01) if bool_playing: - freq_b -= 10 - channel1.freq(freq_b) + freq_b = max(freq_b - 10, 10) + channel1.frequency(max(freq_b, 10)) if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): if bool_playing: - freq_a += 10 - channel0.freq(freq_a) + freq_a = min(freq_a + 10, 20000) + channel0.frequency(freq_a) if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): if bool_playing: - freq_a -= 10 - channel0.freq(freq_a) + freq_a = max(freq_a - 10, 10) + channel0.frequency(freq_a) if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): if not was_z_pressed: - channel0.configure(Channel.TRIANGLE + Channel.SQUARE, - 16, - 168, - 0xafff, - 168, - 10000) - channel1.configure(Channel.SINE + Channel.SQUARE, - 38, - 300, - 0, - 0, - 12000) - channel2.configure(Channel.NOISE, - 5, - 10, - 16000, - 100, - 18000) - channel3.configure(Channel.NOISE, - 5, - 5, - 8000, - 40, - 8000) - channel4.configure(Channel.SQUARE, - 10, - 100, - 0, - 500, - 12000) + channel0.configure(waveforms=Channel.TRIANGLE + Channel.SQUARE, + attack=0.016, + decay=0.168, + sustain=0xafff/65535, + release=0.168, + volume=10000/65535) + channel1.configure(waveforms=Channel.SINE + Channel.SQUARE, + attack=0.038, + decay=0.300, + sustain=0, + release=0, + volume=12000/65535) + channel2.configure(waveforms=Channel.NOISE, + attack=0.005, + decay=0.010, + sustain=16000/65535, + release=0.100, + volume=18000/65535) + channel3.configure(waveforms=Channel.NOISE, + attack=0.005, + decay=0.005, + sustain=8000/65535, + release=0.040, + volume=8000/65535) + channel4.configure(waveforms=Channel.SQUARE, + attack=0.010, + decay=0.100, + sustain=0, + release=0.500, + volume=12000/65535) if not synthing: beat = 0 next_beat() diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.c b/micropython/modules/galactic_unicorn/galactic_unicorn.c index e44ca13e..7bb36ffa 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.c +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.c @@ -3,11 +3,20 @@ /***** Methods *****/ MP_DEFINE_CONST_FUN_OBJ_1(Channel___del___obj, Channel___del__); -MP_DEFINE_CONST_FUN_OBJ_KW(Channel_configure_obj, 6, Channel_configure); -MP_DEFINE_CONST_FUN_OBJ_2(Channel_freq_obj, Channel_freq); +MP_DEFINE_CONST_FUN_OBJ_KW(Channel_configure_obj, 1, Channel_configure); +MP_DEFINE_CONST_FUN_OBJ_1(Channel_restore_obj, Channel_restore); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_waveforms_obj, 1, 2, Channel_waveforms); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_frequency_obj, 1, 2, Channel_frequency); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_volume_obj, 1, 2, Channel_volume); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_attack_duration_obj, 1, 2, Channel_attack_duration); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_decay_duration_obj, 1, 2, Channel_decay_duration); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_sustain_level_obj, 1, 2, Channel_sustain_level); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_release_duration_obj, 1, 2, Channel_release_duration); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_pulse_width_obj, 1, 2, Channel_pulse_width); MP_DEFINE_CONST_FUN_OBJ_1(Channel_trigger_attack_obj, Channel_trigger_attack); MP_DEFINE_CONST_FUN_OBJ_1(Channel_trigger_release_obj, Channel_trigger_release); MP_DEFINE_CONST_FUN_OBJ_KW(Channel_play_tone_obj, 2, Channel_play_tone); +//MP_DEFINE_CONST_FUN_OBJ_1(Channel_stop_playing_obj, Channel_stop_playing); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn___del___obj, GalacticUnicorn___del__); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear); @@ -29,7 +38,15 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_synth_channel_obj, GalacticUnicorn_syn STATIC const mp_rom_map_elem_t Channel_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Channel___del___obj) }, { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&Channel_configure_obj) }, - { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&Channel_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_restore), MP_ROM_PTR(&Channel_restore_obj) }, + { MP_ROM_QSTR(MP_QSTR_waveforms), MP_ROM_PTR(&Channel_waveforms_obj) }, + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Channel_frequency_obj) }, + { MP_ROM_QSTR(MP_QSTR_volume), MP_ROM_PTR(&Channel_volume_obj) }, + { MP_ROM_QSTR(MP_QSTR_attack_duration), MP_ROM_PTR(&Channel_attack_duration_obj) }, + { MP_ROM_QSTR(MP_QSTR_decay_duration), MP_ROM_PTR(&Channel_decay_duration_obj) }, + { MP_ROM_QSTR(MP_QSTR_sustain_level), MP_ROM_PTR(&Channel_sustain_level_obj) }, + { MP_ROM_QSTR(MP_QSTR_release_duration), MP_ROM_PTR(&Channel_release_duration_obj) }, + { MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&Channel_pulse_width_obj) }, { MP_ROM_QSTR(MP_QSTR_trigger_attack), MP_ROM_PTR(&Channel_trigger_attack_obj) }, { MP_ROM_QSTR(MP_QSTR_trigger_release), MP_ROM_PTR(&Channel_trigger_release_obj) }, { MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&Channel_play_tone_obj) }, diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp index 8b724e0f..64790e16 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.cpp +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.cpp @@ -45,17 +45,86 @@ mp_obj_t Channel___del__(mp_obj_t self_in) { } +/***** Helper Functions *****/ +void set_channel_waveforms(AudioChannel& channel, mp_obj_t in) { + int waveforms = mp_obj_get_int(in); + const int mask = (NOISE | SQUARE | SAW | TRIANGLE | SINE | WAVE); + if(waveforms < 0 || (waveforms & mask) == 0) { + mp_raise_ValueError("waveforms invalid. Expected a combination of NOISE, SQUARE, SAW, TRIANGLE, SINE, or WAVE"); + } + channel.waveforms = (uint8_t)waveforms; +} + +void set_channel_frequency(AudioChannel& channel, mp_obj_t in) { + int freq = mp_obj_get_int(in); + if(freq <= 0 || freq > UINT16_MAX) { + mp_raise_ValueError("frequency out of range. Expected greater than 0Hz to 65535Hz"); + } + channel.frequency = (uint16_t)freq; +} + +void set_channel_volume(AudioChannel& channel, mp_obj_t in) { + float volume = mp_obj_get_float(in); + if(volume < 0.0f || volume > 1.0f) { + mp_raise_ValueError("volume out of range. Expected 0.0 to 1.0"); + } + channel.volume = (uint16_t)(volume * UINT16_MAX); +} + +void set_channel_attack(AudioChannel& channel, mp_obj_t in) { + int attack_ms = (int)(mp_obj_get_float(in) * 1000.0f); + if(attack_ms < 0 || attack_ms > UINT16_MAX) { + mp_raise_ValueError("attack out of range. Expected 0.0s to 65.5s"); + } + channel.attack_ms = MAX(attack_ms, 1); +} + +void set_channel_decay(AudioChannel& channel, mp_obj_t in) { + int decay_ms = (int)(mp_obj_get_float(in) * 1000.0f); + if(decay_ms < 0 || decay_ms > UINT16_MAX) { + mp_raise_ValueError("decay out of range. Expected 0.0s to 65.5s"); + } + channel.decay_ms = MAX(decay_ms, 1); +} + +void set_channel_sustain(AudioChannel& channel, mp_obj_t in) { + float sustain = mp_obj_get_float(in); + if(sustain < 0.0f || sustain > 1.0f) { + mp_raise_ValueError("sustain out of range. Expected 0.0 to 1.0"); + } + channel.sustain = (uint16_t)(sustain * UINT16_MAX); +} + +void set_channel_release(AudioChannel& channel, mp_obj_t in) { + int release_ms = (int)(mp_obj_get_float(in) * 1000.0f); + if(release_ms < 0 || release_ms > UINT16_MAX) { + mp_raise_ValueError("release out of range. Expected 0.0s to 65.5s"); + } + channel.release_ms = MAX(release_ms, 1); +} + +void set_channel_pulse_width(AudioChannel& channel, mp_obj_t in) { + float pulse_width = mp_obj_get_float(in); + if(pulse_width < 0.0f || pulse_width > 1.0f) { + mp_raise_ValueError("pulse_width out of range. Expected 0.0 to 1.0"); + } + channel.pulse_width = (uint16_t)(pulse_width * UINT16_MAX); +} + + /***** Methods *****/ mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_self, ARG_waveforms, ARG_attack_ms, ARG_decay_ms, ARG_sustain, ARG_release_ms, ARG_volume }; + enum { ARG_self, ARG_waveforms, ARG_frequency, ARG_volume, ARG_attack, ARG_decay, ARG_sustain, ARG_release, ARG_pulse_width }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_waveforms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_attack_ms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_decay_ms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_sustain, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_release_ms, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_volumes, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_waveforms, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_frequency, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_volume, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_attack, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_decay, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_sustain, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_release, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_pulse_width, MP_ARG_OBJ, {.u_obj = mp_const_none} } }; // Parse args. @@ -64,25 +133,140 @@ mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Channel_obj_t); - self->channel->waveforms = args[ARG_waveforms].u_int; - self->channel->attack_ms = args[ARG_attack_ms].u_int; - self->channel->decay_ms = args[ARG_decay_ms].u_int; - self->channel->sustain = args[ARG_sustain].u_int; - self->channel->release_ms = args[ARG_release_ms].u_int; - self->channel->volume = args[ARG_volume].u_int; + mp_obj_t waveforms = args[ARG_waveforms].u_obj; + if(waveforms != mp_const_none) { + set_channel_waveforms(*self->channel, waveforms); + } + + mp_obj_t frequency = args[ARG_frequency].u_obj; + if(frequency != mp_const_none) { + set_channel_frequency(*self->channel, frequency); + } + + mp_obj_t volume = args[ARG_volume].u_obj; + if(volume != mp_const_none) { + set_channel_volume(*self->channel, volume); + } + + mp_obj_t attack = args[ARG_attack].u_obj; + if(attack != mp_const_none) { + set_channel_attack(*self->channel, attack); + } + + mp_obj_t decay = args[ARG_decay].u_obj; + if(decay != mp_const_none) { + set_channel_decay(*self->channel, decay); + } + + mp_obj_t sustain = args[ARG_sustain].u_obj; + if(sustain != mp_const_none) { + set_channel_sustain(*self->channel, sustain); + } + + mp_obj_t release = args[ARG_release].u_obj; + if(release != mp_const_none) { + set_channel_release(*self->channel, release); + } + + mp_obj_t pulse_width = args[ARG_pulse_width].u_obj; + if(pulse_width != mp_const_none) { + set_channel_pulse_width(*self->channel, pulse_width); + } return mp_const_none; } -mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in) { +mp_obj_t Channel_restore(mp_obj_t self_in) { _Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t); + self->channel->restore(); + return mp_const_none; +} - float freq = mp_obj_get_float(freq_in); - if(freq <= 0.0f) { - mp_raise_ValueError("freq out of range. Expected greater than 0.0"); +mp_obj_t Channel_waveforms(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_int(self->channel->waveforms); } - self->channel->frequency = freq; + set_channel_waveforms(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_frequency(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_int(self->channel->frequency); + } + + set_channel_frequency(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_volume(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_float((float)self->channel->volume / UINT16_MAX); + } + + set_channel_volume(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_attack_duration(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_float((float)self->channel->attack_ms / 1000.0f); + } + + set_channel_attack(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_decay_duration(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_float((float)self->channel->decay_ms / 1000.0f); + } + + set_channel_decay(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_sustain_level(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_float((float)self->channel->sustain / UINT16_MAX); + } + + set_channel_sustain(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_release_duration(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_float((float)self->channel->release_ms / 1000.0f); + } + + set_channel_release(*self->channel, args[1]); + return mp_const_none; +} + +mp_obj_t Channel_pulse_width(size_t n_args, const mp_obj_t *args) { + _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t); + + if(n_args == 1) { + return mp_obj_new_float((float)self->channel->pulse_width / 0xffff); + } + + set_channel_pulse_width(*self->channel, args[1]); return mp_const_none; } @@ -104,10 +288,10 @@ mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw enum { ARG_self, ARG_freq, ARG_volume, ARG_fade_in, ARG_fade_out }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_volume, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_fade_in, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_fade_out, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_attack, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_release, MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; // Parse args. @@ -116,45 +300,35 @@ mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw _Channel_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Channel_obj_t); - float freq = mp_obj_get_float(args[ARG_freq].u_obj); - if(freq <= 0.0f) { - mp_raise_ValueError("freq out of range. Expected greater than 0.0"); + set_channel_frequency(*self->channel, args[ARG_freq].u_obj); + + mp_obj_t volume = args[ARG_volume].u_obj; + if(volume != mp_const_none) { + set_channel_volume(*self->channel, volume); + } + else { + self->channel->volume = UINT16_MAX; } - float volume = 1.0f; - if(args[ARG_volume].u_obj != mp_const_none) { - volume = mp_obj_get_float(args[ARG_volume].u_obj); - if(volume < 0.0f || volume > 1.0f) { - mp_raise_ValueError("volume out of range. Expected 0.0 to 1.0"); - } + mp_obj_t attack_ms = args[ARG_fade_in].u_obj; + if(attack_ms != mp_const_none) { + set_channel_attack(*self->channel, attack_ms); + } + else { + self->channel->attack_ms = 1; } - int fade_in_ms = 1; - if(args[ARG_fade_in].u_obj != mp_const_none) { - float fade_in = mp_obj_get_float(args[ARG_fade_in].u_obj); - if(fade_in <= 0.0f) { - mp_raise_ValueError("fade_in out of range. Expected greater than 0.0"); - } - fade_in_ms = (uint16_t)(fade_in * 1000.0f); + mp_obj_t release_ms = args[ARG_fade_out].u_obj; + if(release_ms != mp_const_none) { + set_channel_release(*self->channel, release_ms); + } + else { + self->channel->release_ms = 1; } - int fade_out_ms = 1; - if(args[ARG_fade_out].u_obj != mp_const_none) { - float fade_out = mp_obj_get_float(args[ARG_fade_out].u_obj); - if(fade_out <= 0.0f) { - mp_raise_ValueError("fade_out out of range. Expected greater than 0.0"); - } - fade_out_ms = (uint16_t)(fade_out * 1000.0f); - } - - - self->channel->frequency = freq; self->channel->waveforms = Waveform::SINE; - self->channel->attack_ms = MAX(fade_in_ms, 1); self->channel->decay_ms = 1; - self->channel->sustain = 0xffff; - self->channel->release_ms = MAX(fade_out_ms, 1); - self->channel->volume = (uint16_t)(volume * 0xffff); + self->channel->sustain = UINT16_MAX; self->channel->trigger_attack(); diff --git a/micropython/modules/galactic_unicorn/galactic_unicorn.h b/micropython/modules/galactic_unicorn/galactic_unicorn.h index 11f0993d..21859574 100644 --- a/micropython/modules/galactic_unicorn/galactic_unicorn.h +++ b/micropython/modules/galactic_unicorn/galactic_unicorn.h @@ -10,11 +10,19 @@ extern void Channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki extern mp_obj_t Channel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); extern mp_obj_t Channel___del__(mp_obj_t self_in); extern mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -extern mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in); +extern mp_obj_t Channel_restore(mp_obj_t self_in); +extern mp_obj_t Channel_waveforms(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_frequency(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_volume(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_attack_duration(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_decay_duration(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_sustain_level(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_release_duration(size_t n_args, const mp_obj_t *args); +extern mp_obj_t Channel_pulse_width(size_t n_args, const mp_obj_t *args); extern mp_obj_t Channel_trigger_attack(mp_obj_t self_in); extern mp_obj_t Channel_trigger_release(mp_obj_t self_in); extern mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - +extern mp_obj_t Channel_stop_playing(mp_obj_t self_in); extern void GalacticUnicorn_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); extern mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); From 52a107e6d6a3d0b2a34cd43b2a5c7661fc7f50cc Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 20 Sep 2022 12:42:18 +0100 Subject: [PATCH 38/42] Switched GU over to chained DMA to remove interrupt use --- .../galactic_unicorn/galactic_unicorn.cpp | 61 +++++++++++-------- .../galactic_unicorn/galactic_unicorn.hpp | 2 +- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/libraries/galactic_unicorn/galactic_unicorn.cpp b/libraries/galactic_unicorn/galactic_unicorn.cpp index 66830313..54219239 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.cpp +++ b/libraries/galactic_unicorn/galactic_unicorn.cpp @@ -43,6 +43,7 @@ static uint16_t g_gamma_lut[256] = {0}; static uint16_t b_gamma_lut[256] = {0}; static uint32_t dma_channel; +static uint32_t dma_ctrl_channel; static uint32_t audio_dma_channel; namespace pimoroni { @@ -58,39 +59,24 @@ namespace pimoroni { // once the dma transfer of the scanline is complete we move to the // next scanline (or quit if we're finished) void __isr GalacticUnicorn::dma_complete() { - if(unicorn != nullptr) { - if(dma_channel_get_irq0_status(dma_channel)) { - unicorn->next_bitstream_sequence(); - } - if(dma_channel_get_irq0_status(audio_dma_channel)) { - unicorn->next_audio_sequence(); - } + if(unicorn != nullptr && dma_channel_get_irq0_status(audio_dma_channel)) { + unicorn->next_audio_sequence(); } } - void GalacticUnicorn::next_bitstream_sequence() { - // Clear any interrupt request caused by our channel - //dma_channel_acknowledge_irq0(dma_channel); - // NOTE Temporary replacement of the above until this reaches pico-sdk main: - // https://github.com/raspberrypi/pico-sdk/issues/974 - dma_hw->ints0 = 1u << dma_channel; - - dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false); - dma_channel_set_read_addr(dma_channel, bitstream, true); - } - GalacticUnicorn::~GalacticUnicorn() { if(unicorn == this) { partial_teardown(); + dma_channel_unclaim(dma_ctrl_channel); // This works now the teardown behaves correctly dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly pio_sm_unclaim(bitstream_pio, bitstream_sm); pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset); - irq_remove_handler(DMA_IRQ_0, dma_complete); dma_channel_unclaim(audio_dma_channel); // This works now the teardown behaves correctly pio_sm_unclaim(audio_pio, audio_sm); pio_remove_program(audio_pio, &audio_i2s_program, audio_sm_offset); + irq_remove_handler(DMA_IRQ_0, dma_complete); unicorn = nullptr; } @@ -104,7 +90,13 @@ namespace pimoroni { const uint pins_to_set = 1 << COLUMN_BLANK | 0b1111 << ROW_BIT_0; pio_sm_set_pins_with_mask(bitstream_pio, bitstream_sm, pins_to_set, pins_to_set); + + dma_hw->ch[dma_ctrl_channel].al1_ctrl = (dma_hw->ch[dma_ctrl_channel].al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (dma_ctrl_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB); + dma_hw->ch[dma_channel].al1_ctrl = (dma_hw->ch[dma_channel].al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (dma_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB); // Abort any in-progress DMA transfer + dma_safe_abort(dma_ctrl_channel); + //dma_channel_abort(dma_ctrl_channel); + //dma_channel_abort(dma_channel); dma_safe_abort(dma_channel); @@ -286,28 +278,47 @@ namespace pimoroni { sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); // setup dma transfer for pixel data to the pio - if(unicorn == nullptr) { + //if(unicorn == nullptr) { dma_channel = dma_claim_unused_channel(true); - } + dma_ctrl_channel = dma_claim_unused_channel(true); + //} + dma_channel_config ctrl_config = dma_channel_get_default_config(dma_ctrl_channel); + channel_config_set_transfer_data_size(&ctrl_config, DMA_SIZE_32); + channel_config_set_read_increment(&ctrl_config, false); + channel_config_set_write_increment(&ctrl_config, false); + channel_config_set_chain_to(&ctrl_config, dma_channel); + + dma_channel_configure( + dma_ctrl_channel, + &ctrl_config, + &dma_hw->ch[dma_channel].read_addr, + &bitstream_addr, + 1, + false + ); + + dma_channel_config config = dma_channel_get_default_config(dma_channel); channel_config_set_transfer_data_size(&config, DMA_SIZE_32); channel_config_set_bswap(&config, false); // byte swap to reverse little endian channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true)); + channel_config_set_chain_to(&config, dma_ctrl_channel); dma_channel_configure( dma_channel, &config, &bitstream_pio->txf[bitstream_sm], NULL, - 0, + BITSTREAM_LENGTH / 4, false); - dma_channel_set_irq0_enabled(dma_channel, true); - pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c); pio_sm_set_enabled(bitstream_pio, bitstream_sm, true); + // start the control channel + dma_start_channel_mask(1u << dma_ctrl_channel); + // setup audio pio program audio_pio = pio0; @@ -340,8 +351,6 @@ namespace pimoroni { } unicorn = this; - - next_bitstream_sequence(); } void GalacticUnicorn::clear() { diff --git a/libraries/galactic_unicorn/galactic_unicorn.hpp b/libraries/galactic_unicorn/galactic_unicorn.hpp index 00e52439..79b39fff 100644 --- a/libraries/galactic_unicorn/galactic_unicorn.hpp +++ b/libraries/galactic_unicorn/galactic_unicorn.hpp @@ -67,6 +67,7 @@ namespace pimoroni { // must be aligned for 32bit dma transfer alignas(4) uint8_t bitstream[BITSTREAM_LENGTH] = {0}; + const uint32_t bitstream_addr = (uint32_t)bitstream; static GalacticUnicorn* unicorn; static void dma_complete(); @@ -117,7 +118,6 @@ namespace pimoroni { AudioChannel& synth_channel(uint channel); private: - void next_bitstream_sequence(); void partial_teardown(); void dma_safe_abort(uint channel); void next_audio_sequence(); From 1357cb876d6199616fbc761cd76a1ef593ad6a8b Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 13 Oct 2022 13:47:25 +0100 Subject: [PATCH 39/42] Galactic Unicorn: Fix audio test linting. --- .../feature_test_with_audio.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/micropython/examples/galactic_unicorn/feature_test_with_audio.py b/micropython/examples/galactic_unicorn/feature_test_with_audio.py index 4c32afbe..0bb13ebd 100644 --- a/micropython/examples/galactic_unicorn/feature_test_with_audio.py +++ b/micropython/examples/galactic_unicorn/feature_test_with_audio.py @@ -747,17 +747,17 @@ while True: decay=0.300, sustain=0, release=0, - volume=12000/65535) + volume=12000 / 65535) channel2.configure(waveforms=Channel.NOISE, attack=0.005, decay=0.010, - sustain=16000/65535, + sustain=16000 / 65535, release=0.100, volume=0) channel3.configure(waveforms=Channel.NOISE, attack=0.005, decay=0.005, - sustain=8000/65535, + sustain=8000 / 65535, release=0.040, volume=0) channel4.configure(waveforms=Channel.SQUARE, @@ -846,33 +846,33 @@ while True: channel0.configure(waveforms=Channel.TRIANGLE + Channel.SQUARE, attack=0.016, decay=0.168, - sustain=0xafff/65535, + sustain=0xafff / 65535, release=0.168, - volume=10000/65535) + volume=10000 / 65535) channel1.configure(waveforms=Channel.SINE + Channel.SQUARE, attack=0.038, decay=0.300, sustain=0, release=0, - volume=12000/65535) + volume=12000 / 65535) channel2.configure(waveforms=Channel.NOISE, attack=0.005, decay=0.010, - sustain=16000/65535, + sustain=16000 / 65535, release=0.100, - volume=18000/65535) + volume=18000 / 65535) channel3.configure(waveforms=Channel.NOISE, attack=0.005, decay=0.005, - sustain=8000/65535, + sustain=8000 / 65535, release=0.040, - volume=8000/65535) + volume=8000 / 65535) channel4.configure(waveforms=Channel.SQUARE, attack=0.010, decay=0.100, sustain=0, release=0.500, - volume=12000/65535) + volume=12000 / 65535) if not synthing: beat = 0 next_beat() From a41715a377e24c415f63640bfd648e7e7273c34f Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 13 Oct 2022 14:02:36 +0100 Subject: [PATCH 40/42] PicoGraphics: Include RGB888 pen type for MicroPython. --- micropython/modules/picographics/micropython.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/micropython/modules/picographics/micropython.cmake b/micropython/modules/picographics/micropython.cmake index e8cf8b39..31d8e764 100644 --- a/micropython/modules/picographics/micropython.cmake +++ b/micropython/modules/picographics/micropython.cmake @@ -18,6 +18,7 @@ target_sources(usermod_${MOD_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_p8.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_rgb332.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_rgb565.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_rgb888.cpp ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/types.cpp ) From 70b7d3065d101ad23ddbff9b1382387c518b1bb2 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 13 Oct 2022 14:43:02 +0100 Subject: [PATCH 41/42] Galactic Unicorn: Add dedicated firmware build. --- .github/workflows/micropython-picow.yml | 4 +- micropython/modules/micropython-picow.cmake | 1 - .../micropython-picow_galactic_unicorn.cmake | 52 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 micropython/modules/micropython-picow_galactic_unicorn.cmake diff --git a/.github/workflows/micropython-picow.yml b/.github/workflows/micropython-picow.yml index 98888c20..cf2a5102 100644 --- a/.github/workflows/micropython-picow.yml +++ b/.github/workflows/micropython-picow.yml @@ -61,7 +61,7 @@ jobs: build: needs: deps - name: Build ${{matrix.board}} + name: Build ${{matrix.name}} (${{matrix.board}}) runs-on: ubuntu-20.04 strategy: matrix: @@ -70,6 +70,8 @@ jobs: board: PICO_W - name: picow_enviro board: PICO_W_ENVIRO + - name: picow_galactic_unicorn + board: PICO_W env: # MicroPython version will be contained in github.event.release.tag_name for releases diff --git a/micropython/modules/micropython-picow.cmake b/micropython/modules/micropython-picow.cmake index 3041e730..14449723 100644 --- a/micropython/modules/micropython-picow.cmake +++ b/micropython/modules/micropython-picow.cmake @@ -47,7 +47,6 @@ include(adcfft/micropython) # LEDs & Matrices include(plasma/micropython) include(hub75/micropython) -include(galactic_unicorn/micropython) # Packs include(pico_unicorn/micropython) diff --git a/micropython/modules/micropython-picow_galactic_unicorn.cmake b/micropython/modules/micropython-picow_galactic_unicorn.cmake new file mode 100644 index 00000000..ffec6aaf --- /dev/null +++ b/micropython/modules/micropython-picow_galactic_unicorn.cmake @@ -0,0 +1,52 @@ +include_directories(${CMAKE_CURRENT_LIST_DIR}/../../) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../") + +# Essential +include(pimoroni_i2c/micropython) +include(pimoroni_bus/micropython) + +# Pico Graphics Essential +include(hershey_fonts/micropython) +include(bitmap_fonts/micropython) +include(picographics/micropython) + +# Pico Graphics Extra +include(jpegdec/micropython) +include(qrcode/micropython/micropython) + +# Sensors & Breakouts +include(breakout_dotmatrix/micropython) +include(breakout_encoder/micropython) +include(breakout_ioexpander/micropython) +include(breakout_ltr559/micropython) +include(breakout_as7262/micropython) +include(breakout_rgbmatrix5x5/micropython) +include(breakout_matrix11x7/micropython) +include(breakout_msa301/micropython) +include(breakout_pmw3901/micropython) +include(breakout_mics6814/micropython) +include(breakout_potentiometer/micropython) +include(breakout_rtc/micropython) +include(breakout_trackball/micropython) +include(breakout_sgp30/micropython) +include(breakout_bh1745/micropython) +include(breakout_bme68x/micropython) +include(breakout_bme280/micropython) +include(breakout_bmp280/micropython) +include(breakout_icp10125/micropython) +include(breakout_scd41/micropython) +include(breakout_vl53l5cx/micropython) +include(pcf85063a/micropython) + +# Utility +include(adcfft/micropython) + +# LEDs & Matrices +include(galactic_unicorn/micropython) + +# include(micropython-common) + +include(modules_py/modules_py) \ No newline at end of file From d73634257803fe2258ba66889027f28bd5a16129 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 17 Oct 2022 16:06:28 +0100 Subject: [PATCH 42/42] Galactic Unicorn: Paint app. --- .../galactic_unicorn/galactic_paint/README.md | 11 + .../galactic_paint/galactic_paint.py | 113 ++ .../galactic_paint/galactic_paint/index.html | 54 + .../galactic_paint/static/paint.css | 131 ++ .../galactic_paint/static/paint.js | 214 +++ .../galactic_paint/static/tinycolor.js | 1193 +++++++++++++++++ 6 files changed, 1716 insertions(+) create mode 100644 micropython/examples/galactic_unicorn/galactic_paint/README.md create mode 100644 micropython/examples/galactic_unicorn/galactic_paint/galactic_paint.py create mode 100644 micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/index.html create mode 100644 micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.css create mode 100644 micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.js create mode 100644 micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/tinycolor.js diff --git a/micropython/examples/galactic_unicorn/galactic_paint/README.md b/micropython/examples/galactic_unicorn/galactic_paint/README.md new file mode 100644 index 00000000..c41fe01c --- /dev/null +++ b/micropython/examples/galactic_unicorn/galactic_paint/README.md @@ -0,0 +1,11 @@ +# Galactic Paint + +Galactic Paint lets you paint pixels onto your Galatic Unicorn over WiFi, in realtime! + +## Setting Up + +You'll need `WIFI_CONFIG.py` from the `common` directory to be saved to your Pico W. Open up `WIFI_CONFIG.py` in Thonny to add your wifi details (and save it when you're done). + +You will also have to install `micropython-phew` and `microdot` through Thonny's Tools -> Manage Packages. + +Run the example through Thonny and it should get connected and give you a URL to visit. Open that URL in your browser and start painting! \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint.py b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint.py new file mode 100644 index 00000000..a77ce6ce --- /dev/null +++ b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint.py @@ -0,0 +1,113 @@ +import os +from microdot_asyncio import Microdot, send_file +from microdot_asyncio_websocket import with_websocket +from phew import connect_to_wifi +from galactic import GalacticUnicorn +from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY +from WIFI_CONFIG import SSID, PSK + + +gu = GalacticUnicorn() +graphics = PicoGraphics(DISPLAY) +mv_graphics = memoryview(graphics) +gu.set_brightness(0.5) + +WIDTH, HEIGHT = graphics.get_bounds() + +ip = connect_to_wifi(SSID, PSK) + +print(f"Start painting at: http://{ip}") + + +server = Microdot() + + +@server.route("/", methods=["GET"]) +def route_index(request): + return send_file("galactic_paint/index.html") + + +@server.route("/static/", methods=["GET"]) +def route_static(request, path): + return send_file(f"galactic_paint/static/{path}") + + +def get_pixel(x, y): + if x < WIDTH and y < HEIGHT and x >= 0 and y >= 0: + o = (y * WIDTH + x) * 4 + return tuple(mv_graphics[o:o + 3]) + return None + + +def flood_fill(x, y, r, g, b): + todo = [] + + def fill(x, y, c): + if get_pixel(x, y) != c: + return + + graphics.pixel(x, y) + + up = get_pixel(x, y - 1) + dn = get_pixel(x, y + 1) + lf = get_pixel(x - 1, y) + ri = get_pixel(x + 1, y) + + if up == c: + todo.append((x, y - 1)) + if dn == c: + todo.append((x, y + 1)) + if lf == c: + todo.append((x - 1, y)) + if ri == c: + todo.append((x + 1, y)) + + c = get_pixel(x, y) + + if c is None: + return + + fill(x, y, c) + + while len(todo): + x, y = todo.pop(0) + fill(x, y, c) + + +@server.route('/paint') +@with_websocket +async def echo(request, ws): + while True: + data = await ws.receive() + try: + x, y, r, g, b = [int(n) for n in data[0:5]] + graphics.set_pen(graphics.create_pen(r, g, b)) + graphics.pixel(x, y) + + except ValueError: + if data == "show": + gu.update(graphics) + + if data == "fill": + data = await ws.receive() + x, y, r, g, b = [int(n) for n in data[0:5]] + graphics.set_pen(graphics.create_pen(r, g, b)) + flood_fill(x, y, r, g, b) + + if data == "clear": + graphics.set_pen(graphics.create_pen(0, 0, 0)) + graphics.clear() + + if data == "save": + filename = await ws.receive() + print(f"Saving to {filename}.bin") + try: + os.mkdir("saves") + except OSError: + pass + with open(f"saves/{filename}.bin", "wb") as f: + f.write(graphics) + await ws.send(f"alert: Saved to saves/{filename}.bin") + + +server.run(host="0.0.0.0", port=80) diff --git a/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/index.html b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/index.html new file mode 100644 index 00000000..03b64453 --- /dev/null +++ b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/index.html @@ -0,0 +1,54 @@ + + + + + Galactic Paint + + + + + +
+

Galactic Paint

+ + +
+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+ + +
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
+ + + + + + diff --git a/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.css b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.css new file mode 100644 index 00000000..355d7d26 --- /dev/null +++ b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.css @@ -0,0 +1,131 @@ +body { + background:#333; + padding:20px; + font-family:Arial, Verdana, Sans-Serif; + background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAaUlEQVQYV33Q0Q3AIAgEUBjBFVyBFRzbWVjBEajXBIOVypcJj1NhETG61BiDVJX4Bh211v5hRDiniV+Elx0wQwd0hEatlUop65srMSah23vf8Auz65AWMc8rDHvCCjAQK2KeDcuQDzh+AHEJX8mbbU1BAAAAAElFTkSuQmCC) repeat; +} + +.icons { + position:absolute; + margin:0; + padding:20px; + list-style:none; +} + +.icons li { + margin:20px; + padding:0; + list-style:none; + padding-top:80px; + width:100px; +} + +.icons li span { + background:#FFF; + color:#000; + border:1px solid #000; + line-height:20px; + padding:5px 10px; + text-align:center; + font-size:10px; + line-height:10px; + display:inline-block; +} + +#palette ul, #palette li { + margin:0;padding:0;list-style:none; +} + +#palette { + list-style:none; + position:relative; + height: 122px; + padding:0 8px; +} + +#palette ul { + display:block; + width:456px; + float: left; +} + +#palette li, #palette input { + border: 2px outset; + width:49px; + height:49px; + float:left; + display:block; + margin:2px; +} + +#palette input { + width:110px; + height:110px; +} + +.window { + width: 976px; + position: relative; + background: #0E071A; + box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5); +} + +.tools { + margin:0;padding:0;list-style:none; + clear:both; + display:block; + position:absolute; + top: 50px; + right: 8px; + width: 98px; + background:#999999; + font-size:0; +} +.tools span { + line-height:30px; +} + +.tools li { + font-size:16px; + width: 45px; + height: 40px; + text-align:center; + margin:0; + padding:0; + display:inline-block; + line-height:40px; + border:2px outset #EEEEEE; + background:#F5F5F5; + cursor:pointer; + color:#000; +} + +.tools li.selected { + background:#000; + color:#FFF; +} + +h1 { + color: #FFF; + background: #6D38BB; + height:40px; + margin:0; + padding:0 8px; + line-height:40px; + font-weight:normal; + font-size:24px; +} + +table { + clear:both; + cursor:pointer; + margin:10px; + border:1px solid #333; + background: #000000; +} + +table td { + width:14px; + height:14px; + border:1px solid #333; +} \ No newline at end of file diff --git a/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.js b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.js new file mode 100644 index 00000000..1455d34c --- /dev/null +++ b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/paint.js @@ -0,0 +1,214 @@ +'use strict'; + +var md = false; +var color = tinycolor('#840000'); +var update; + +$(document).ready(function(){ + + var picker = $('#custom'); + var palette = $('#palette'); + + picker.val(color.toHexString()); + + $(document) + .on('mousedown',function(e){md=true;}) + .on('mouseup',function(e){md=false;}); + + $('table').on('dragstart', function(e){ + e.preventDefault(); + return false; + }); + + for (var y = 0; y < 11; y++) { + var row = $(''); + for (var x = 0; x < 53; x++) { + row.append(''); + } + $('tbody').append(row); + } + + $('.tools li').on('click', function(){ + switch($(this).index()){ + case 6: + clear(); + break; + case 7: + save(); + break; + default: + $('.tools li').removeClass('selected'); + $(this).addClass('selected'); + break; + } + }); + + picker.on('change', function(){ + color = tinycolor($(this).val()); + }) + + palette.find('li').on('click', function(){ + pick(this); + }); + + function handle_tool(obj, is_click){ + switch($('.tools li.selected').index()){ + case 0: //'paint': + paint(obj); + break; + case 1: // Fill + if( is_click ) fill(obj); + break; + case 2: // Erase + update_pixel(obj, tinycolor('#000000')); + break; + case 3: //'pick': + pick(obj); + break; + case 4: //'lighten': + lighten(obj); + break; + case 5: //'darken': + darken(obj); + break; + } + } + + var fill_target = null; + var fill_stack = []; + function fill(obj){ + fill_target = tinycolor($(obj).css('background-color')).toRgbString(); + + if( fill_target == color.toRgbString() ){ + return false; + } + + var x = $(obj).index(); + var y = $(obj).parent().index(); + + socket.send("fill"); + socket.send(new Uint8Array([x, y, color.toRgb().r, color.toRgb().g, color.toRgb().b])); + socket.send('show'); + + do_fill(obj); + + while(fill_stack.length > 0){ + var pixel = fill_stack.pop(); + do_fill(pixel); + } + } + + function is_target_color(obj){ + return ( tinycolor($(obj).css('background-color')).toRgbString() == fill_target); + } + + function do_fill(obj){ + var obj = $(obj); + + if( is_target_color(obj) ){ + + $(obj).css('background-color', color.toRgbString()); + + var r = obj.next('td'); // Right + var l = obj.prev('td'); // Left + var u = obj.parent().prev('tr').find('td:eq(' + obj.index() + ')'); // Above + var d = obj.parent().next('tr').find('td:eq(' + obj.index() + ')'); // Below + + if( r.length && is_target_color(r[0]) ) fill_stack.push(r[0]); + if( l.length && is_target_color(l[0]) ) fill_stack.push(l[0]); + if( u.length && is_target_color(u[0]) ) fill_stack.push(u[0]); + if( d.length && is_target_color(d[0]) ) fill_stack.push(d[0]); + } + } + + function save(){ + var filename = prompt('Please enter a filename', 'mypaint'); + filename = filename.replace(/[^a-z0-9]/gi, '_').toLowerCase(); + socket.send('save'); + socket.send(filename); + } + + function clear(){ + $('td').css('background-color','rgb(0,0,0)').data('changed',false); + socket.send('clear'); + socket.send('show'); + } + + function lighten(obj){ + var c = tinycolor($(obj).css('background-color')); + c.lighten(5); + update_pixel(obj, c); + } + + function darken(obj){ + var c = tinycolor($(obj).css('background-color')); + c.darken(5); + update_pixel(obj, c); + } + + function pick(obj){ + color = tinycolor($(obj).css('background-color')); + picker.val(color.toHexString()); + } + + function update_pixel(obj, col){ + var bgcol = tinycolor($(obj).css('background-color')); + + if(col != bgcol){ + $(obj) + .data('changed', true) + .css('background-color', col.toRgbString()); + } + } + + function update_pixels(){ + var changed = false; + + $('td').each(function( index, obj ){ + if($(obj).data('changed')){ + $(obj).data('changed',false); + changed = true; + + var x = $(this).index(); + var y = $(this).parent().index(); + var col = tinycolor($(obj).css('background-color')).toRgb(); + + if(socket) { + socket.send(new Uint8Array([x, y, col.r, col.g, col.b])); + } + } + }); + if(changed){ + socket.send('show'); + } + } + + function paint(obj){ + update_pixel(obj, color); + } + + $('table td').on('click', function(){ + handle_tool(this, true); + }); + $('table td').on('mousemove', function(){ + if(!md) return false; + handle_tool(this, false); + }) + + const socket = new WebSocket('ws://' + window.location.host + '/paint'); + socket.addEventListener('message', ev => { + console.log('<<< ' + ev.data); + + if(ev.data.substring(0, 6) == "alert:") { + alert(ev.data.substring(6)); + } + }); + socket.addEventListener('close', ev => { + console.log('<<< closed'); + }); + + socket.addEventListener('open', ev => { + clear(); + update = setInterval(update_pixels, 50); + }); +}); diff --git a/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/tinycolor.js b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/tinycolor.js new file mode 100644 index 00000000..0d8b0e7f --- /dev/null +++ b/micropython/examples/galactic_unicorn/galactic_paint/galactic_paint/static/tinycolor.js @@ -0,0 +1,1193 @@ +// TinyColor v1.4.2 +// https://github.com/bgrins/TinyColor +// Brian Grinstead, MIT License + +(function(Math) { + + var trimLeft = /^\s+/, + trimRight = /\s+$/, + mathRound = Math.round, + mathMin = Math.min, + mathMax = Math.max, + mathRandom = Math.random; + + function tinycolor (color, opts) { + + color = (color) ? color : ''; + opts = opts || { }; + + // If input is already a tinycolor, return itself + if (color instanceof tinycolor) { + return color; + } + // If we are called as a function, call using new instead + if (!(this instanceof tinycolor)) { + return new tinycolor(color, opts); + } + + var rgb = inputToRGB(color); + this._originalInput = color, + this._r = rgb.r, + this._g = rgb.g, + this._b = rgb.b, + this._a = rgb.a, + this._roundA = mathRound(100*this._a) / 100, + this._format = opts.format || rgb.format; + this._gradientType = opts.gradientType; + + // Don't let the range of [0,255] come back in [0,1]. + // Potentially lose a little bit of precision here, but will fix issues where + // .5 gets interpreted as half of the total, instead of half of 1 + // If it was supposed to be 128, this was already taken care of by `inputToRgb` + if (this._r < 1) { this._r = mathRound(this._r); } + if (this._g < 1) { this._g = mathRound(this._g); } + if (this._b < 1) { this._b = mathRound(this._b); } + + this._ok = rgb.ok; + } + + tinycolor.prototype = { + isDark: function() { + return this.getBrightness() < 128; + }, + isLight: function() { + return !this.isDark(); + }, + isValid: function() { + return this._ok; + }, + getOriginalInput: function() { + return this._originalInput; + }, + getFormat: function() { + return this._format; + }, + getAlpha: function() { + return this._a; + }, + getBrightness: function() { + //http://www.w3.org/TR/AERT#color-contrast + var rgb = this.toRgb(); + return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; + }, + getLuminance: function() { + //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + var rgb = this.toRgb(); + var RsRGB, GsRGB, BsRGB, R, G, B; + RsRGB = rgb.r/255; + GsRGB = rgb.g/255; + BsRGB = rgb.b/255; + + if (RsRGB <= 0.03928) {R = RsRGB / 12.92;} else {R = Math.pow(((RsRGB + 0.055) / 1.055), 2.4);} + if (GsRGB <= 0.03928) {G = GsRGB / 12.92;} else {G = Math.pow(((GsRGB + 0.055) / 1.055), 2.4);} + if (BsRGB <= 0.03928) {B = BsRGB / 12.92;} else {B = Math.pow(((BsRGB + 0.055) / 1.055), 2.4);} + return (0.2126 * R) + (0.7152 * G) + (0.0722 * B); + }, + setAlpha: function(value) { + this._a = boundAlpha(value); + this._roundA = mathRound(100*this._a) / 100; + return this; + }, + toHsv: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; + }, + toHsvString: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); + return (this._a == 1) ? + "hsv(" + h + ", " + s + "%, " + v + "%)" : + "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; + }, + toHsl: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; + }, + toHslString: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); + return (this._a == 1) ? + "hsl(" + h + ", " + s + "%, " + l + "%)" : + "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; + }, + toHex: function(allow3Char) { + return rgbToHex(this._r, this._g, this._b, allow3Char); + }, + toHexString: function(allow3Char) { + return '#' + this.toHex(allow3Char); + }, + toHex8: function(allow4Char) { + return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char); + }, + toHex8String: function(allow4Char) { + return '#' + this.toHex8(allow4Char); + }, + toRgb: function() { + return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; + }, + toRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : + "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; + }, + toPercentageRgb: function() { + return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; + }, + toPercentageRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : + "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; + }, + toName: function() { + if (this._a === 0) { + return "transparent"; + } + + if (this._a < 1) { + return false; + } + + return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; + }, + toFilter: function(secondColor) { + var hex8String = '#' + rgbaToArgbHex(this._r, this._g, this._b, this._a); + var secondHex8String = hex8String; + var gradientType = this._gradientType ? "GradientType = 1, " : ""; + + if (secondColor) { + var s = tinycolor(secondColor); + secondHex8String = '#' + rgbaToArgbHex(s._r, s._g, s._b, s._a); + } + + return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; + }, + toString: function(format) { + var formatSet = !!format; + format = format || this._format; + + var formattedString = false; + var hasAlpha = this._a < 1 && this._a >= 0; + var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); + + if (needsAlphaFormat) { + // Special case for "transparent", all other non-alpha formats + // will return rgba when there is transparency. + if (format === "name" && this._a === 0) { + return this.toName(); + } + return this.toRgbString(); + } + if (format === "rgb") { + formattedString = this.toRgbString(); + } + if (format === "prgb") { + formattedString = this.toPercentageRgbString(); + } + if (format === "hex" || format === "hex6") { + formattedString = this.toHexString(); + } + if (format === "hex3") { + formattedString = this.toHexString(true); + } + if (format === "hex4") { + formattedString = this.toHex8String(true); + } + if (format === "hex8") { + formattedString = this.toHex8String(); + } + if (format === "name") { + formattedString = this.toName(); + } + if (format === "hsl") { + formattedString = this.toHslString(); + } + if (format === "hsv") { + formattedString = this.toHsvString(); + } + + return formattedString || this.toHexString(); + }, + clone: function() { + return tinycolor(this.toString()); + }, + + _applyModification: function(fn, args) { + var color = fn.apply(null, [this].concat([].slice.call(args))); + this._r = color._r; + this._g = color._g; + this._b = color._b; + this.setAlpha(color._a); + return this; + }, + lighten: function() { + return this._applyModification(lighten, arguments); + }, + brighten: function() { + return this._applyModification(brighten, arguments); + }, + darken: function() { + return this._applyModification(darken, arguments); + }, + desaturate: function() { + return this._applyModification(desaturate, arguments); + }, + saturate: function() { + return this._applyModification(saturate, arguments); + }, + greyscale: function() { + return this._applyModification(greyscale, arguments); + }, + spin: function() { + return this._applyModification(spin, arguments); + }, + + _applyCombination: function(fn, args) { + return fn.apply(null, [this].concat([].slice.call(args))); + }, + analogous: function() { + return this._applyCombination(analogous, arguments); + }, + complement: function() { + return this._applyCombination(complement, arguments); + }, + monochromatic: function() { + return this._applyCombination(monochromatic, arguments); + }, + splitcomplement: function() { + return this._applyCombination(splitcomplement, arguments); + }, + triad: function() { + return this._applyCombination(triad, arguments); + }, + tetrad: function() { + return this._applyCombination(tetrad, arguments); + } + }; + + // If input is an object, force 1 into "1.0" to handle ratios properly + // String input requires "1.0" as input, so 1 will be treated as 1 + tinycolor.fromRatio = function(color, opts) { + if (typeof color == "object") { + var newColor = {}; + for (var i in color) { + if (color.hasOwnProperty(i)) { + if (i === "a") { + newColor[i] = color[i]; + } + else { + newColor[i] = convertToPercentage(color[i]); + } + } + } + color = newColor; + } + + return tinycolor(color, opts); + }; + + // Given a string or object, convert that input to RGB + // Possible string inputs: + // + // "red" + // "#f00" or "f00" + // "#ff0000" or "ff0000" + // "#ff000000" or "ff000000" + // "rgb 255 0 0" or "rgb (255, 0, 0)" + // "rgb 1.0 0 0" or "rgb (1, 0, 0)" + // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" + // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" + // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" + // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" + // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" + // + function inputToRGB(color) { + + var rgb = { r: 0, g: 0, b: 0 }; + var a = 1; + var s = null; + var v = null; + var l = null; + var ok = false; + var format = false; + + if (typeof color == "string") { + color = stringInputToObject(color); + } + + if (typeof color == "object") { + if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { + rgb = rgbToRgb(color.r, color.g, color.b); + ok = true; + format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { + s = convertToPercentage(color.s); + v = convertToPercentage(color.v); + rgb = hsvToRgb(color.h, s, v); + ok = true; + format = "hsv"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { + s = convertToPercentage(color.s); + l = convertToPercentage(color.l); + rgb = hslToRgb(color.h, s, l); + ok = true; + format = "hsl"; + } + + if (color.hasOwnProperty("a")) { + a = color.a; + } + } + + a = boundAlpha(a); + + return { + ok: ok, + format: color.format || format, + r: mathMin(255, mathMax(rgb.r, 0)), + g: mathMin(255, mathMax(rgb.g, 0)), + b: mathMin(255, mathMax(rgb.b, 0)), + a: a + }; + } + + + // Conversion Functions + // -------------------- + + // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: + // + + // `rgbToRgb` + // Handle bounds / percentage checking to conform to CSS color spec + // + // *Assumes:* r, g, b in [0, 255] or [0, 1] + // *Returns:* { r, g, b } in [0, 255] + function rgbToRgb(r, g, b){ + return { + r: bound01(r, 255) * 255, + g: bound01(g, 255) * 255, + b: bound01(b, 255) * 255 + }; + } + + // `rgbToHsl` + // Converts an RGB color value to HSL. + // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] + // *Returns:* { h, s, l } in [0,1] + function rgbToHsl(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + + h /= 6; + } + + return { h: h, s: s, l: l }; + } + + // `hslToRgb` + // Converts an HSL color value to RGB. + // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] + // *Returns:* { r, g, b } in the set [0, 255] + function hslToRgb(h, s, l) { + var r, g, b; + + h = bound01(h, 360); + s = bound01(s, 100); + l = bound01(l, 100); + + function hue2rgb(p, q, t) { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + if(s === 0) { + r = g = b = l; // achromatic + } + else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return { r: r * 255, g: g * 255, b: b * 255 }; + } + + // `rgbToHsv` + // Converts an RGB color value to HSV + // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] + // *Returns:* { h, s, v } in [0,1] + function rgbToHsv(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, v = max; + + var d = max - min; + s = max === 0 ? 0 : d / max; + + if(max == min) { + h = 0; // achromatic + } + else { + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h, s: s, v: v }; + } + + // `hsvToRgb` + // Converts an HSV color value to RGB. + // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] + // *Returns:* { r, g, b } in the set [0, 255] + function hsvToRgb(h, s, v) { + + h = bound01(h, 360) * 6; + s = bound01(s, 100); + v = bound01(v, 100); + + var i = Math.floor(h), + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6, + r = [v, q, p, p, t, v][mod], + g = [t, v, v, q, p, p][mod], + b = [p, p, t, v, v, q][mod]; + + return { r: r * 255, g: g * 255, b: b * 255 }; + } + + // `rgbToHex` + // Converts an RGB color to hex + // Assumes r, g, and b are contained in the set [0, 255] + // Returns a 3 or 6 character hex + function rgbToHex(r, g, b, allow3Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + // Return a 3 character hex if possible + if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); + } + + return hex.join(""); + } + + // `rgbaToHex` + // Converts an RGBA color plus alpha transparency to hex + // Assumes r, g, b are contained in the set [0, 255] and + // a in [0, 1]. Returns a 4 or 8 character rgba hex + function rgbaToHex(r, g, b, a, allow4Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)), + pad2(convertDecimalToHex(a)) + ]; + + // Return a 4 character hex if possible + if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); + } + + return hex.join(""); + } + + // `rgbaToArgbHex` + // Converts an RGBA color to an ARGB Hex8 string + // Rarely used, but required for "toFilter()" + function rgbaToArgbHex(r, g, b, a) { + + var hex = [ + pad2(convertDecimalToHex(a)), + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + return hex.join(""); + } + + // `equals` + // Can be called with any tinycolor input + tinycolor.equals = function (color1, color2) { + if (!color1 || !color2) { return false; } + return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); + }; + + tinycolor.random = function() { + return tinycolor.fromRatio({ + r: mathRandom(), + g: mathRandom(), + b: mathRandom() + }); + }; + + + // Modification Functions + // ---------------------- + // Thanks to less.js for some of the basics here + // + + function desaturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s -= amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); + } + + function saturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s += amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); + } + + function greyscale(color) { + return tinycolor(color).desaturate(100); + } + + function lighten (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l += amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); + } + + function brighten(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var rgb = tinycolor(color).toRgb(); + rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); + rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); + rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); + return tinycolor(rgb); + } + + function darken (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l -= amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); + } + + // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. + // Values outside of this range will be wrapped into this range. + function spin(color, amount) { + var hsl = tinycolor(color).toHsl(); + var hue = (hsl.h + amount) % 360; + hsl.h = hue < 0 ? 360 + hue : hue; + return tinycolor(hsl); + } + + // Combination Functions + // --------------------- + // Thanks to jQuery xColor for some of the ideas behind these + // + + function complement(color) { + var hsl = tinycolor(color).toHsl(); + hsl.h = (hsl.h + 180) % 360; + return tinycolor(hsl); + } + + function triad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) + ]; + } + + function tetrad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) + ]; + } + + function splitcomplement(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), + tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) + ]; + } + + function analogous(color, results, slices) { + results = results || 6; + slices = slices || 30; + + var hsl = tinycolor(color).toHsl(); + var part = 360 / slices; + var ret = [tinycolor(color)]; + + for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { + hsl.h = (hsl.h + part) % 360; + ret.push(tinycolor(hsl)); + } + return ret; + } + + function monochromatic(color, results) { + results = results || 6; + var hsv = tinycolor(color).toHsv(); + var h = hsv.h, s = hsv.s, v = hsv.v; + var ret = []; + var modification = 1 / results; + + while (results--) { + ret.push(tinycolor({ h: h, s: s, v: v})); + v = (v + modification) % 1; + } + + return ret; + } + + // Utility Functions + // --------------------- + + tinycolor.mix = function(color1, color2, amount) { + amount = (amount === 0) ? 0 : (amount || 50); + + var rgb1 = tinycolor(color1).toRgb(); + var rgb2 = tinycolor(color2).toRgb(); + + var p = amount / 100; + + var rgba = { + r: ((rgb2.r - rgb1.r) * p) + rgb1.r, + g: ((rgb2.g - rgb1.g) * p) + rgb1.g, + b: ((rgb2.b - rgb1.b) * p) + rgb1.b, + a: ((rgb2.a - rgb1.a) * p) + rgb1.a + }; + + return tinycolor(rgba); + }; + + + // Readability Functions + // --------------------- + // false + // tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false + tinycolor.isReadable = function(color1, color2, wcag2) { + var readability = tinycolor.readability(color1, color2); + var wcag2Parms, out; + + out = false; + + wcag2Parms = validateWCAG2Parms(wcag2); + switch (wcag2Parms.level + wcag2Parms.size) { + case "AAsmall": + case "AAAlarge": + out = readability >= 4.5; + break; + case "AAlarge": + out = readability >= 3; + break; + case "AAAsmall": + out = readability >= 7; + break; + } + return out; + + }; + + // `mostReadable` + // Given a base color and a list of possible foreground or background + // colors for that base, returns the most readable color. + // Optionally returns Black or White if the most readable color is unreadable. + // *Example* + // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" + // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" + // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" + // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" + tinycolor.mostReadable = function(baseColor, colorList, args) { + var bestColor = null; + var bestScore = 0; + var readability; + var includeFallbackColors, level, size ; + args = args || {}; + includeFallbackColors = args.includeFallbackColors ; + level = args.level; + size = args.size; + + for (var i= 0; i < colorList.length ; i++) { + readability = tinycolor.readability(baseColor, colorList[i]); + if (readability > bestScore) { + bestScore = readability; + bestColor = tinycolor(colorList[i]); + } + } + + if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) { + return bestColor; + } + else { + args.includeFallbackColors=false; + return tinycolor.mostReadable(baseColor,["#fff", "#000"],args); + } + }; + + + // Big List of Colors + // ------------------ + // + var names = tinycolor.names = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + burntsienna: "ea7e5d", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "f0f", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + grey: "808080", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + rebeccapurple: "663399", + red: "f00", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32" + }; + + // Make it easy to access colors via `hexNames[hex]` + var hexNames = tinycolor.hexNames = flip(names); + + + // Utilities + // --------- + + // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` + function flip(o) { + var flipped = { }; + for (var i in o) { + if (o.hasOwnProperty(i)) { + flipped[o[i]] = i; + } + } + return flipped; + } + + // Return a valid alpha value [0,1] with all invalid values being set to 1 + function boundAlpha(a) { + a = parseFloat(a); + + if (isNaN(a) || a < 0 || a > 1) { + a = 1; + } + + return a; + } + + // Take input from [0, n] and return it as [0, 1] + function bound01(n, max) { + if (isOnePointZero(n)) { n = "100%"; } + + var processPercent = isPercentage(n); + n = mathMin(max, mathMax(0, parseFloat(n))); + + // Automatically convert percentage into number + if (processPercent) { + n = parseInt(n * max, 10) / 100; + } + + // Handle floating point rounding errors + if ((Math.abs(n - max) < 0.000001)) { + return 1; + } + + // Convert into [0, 1] range if it isn't already + return (n % max) / parseFloat(max); + } + + // Force a number between 0 and 1 + function clamp01(val) { + return mathMin(1, mathMax(0, val)); + } + + // Parse a base-16 hex value into a base-10 integer + function parseIntFromHex(val) { + return parseInt(val, 16); + } + + // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 + // + function isOnePointZero(n) { + return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; + } + + // Check to see if string passed in is a percentage + function isPercentage(n) { + return typeof n === "string" && n.indexOf('%') != -1; + } + + // Force a hex value to have 2 characters + function pad2(c) { + return c.length == 1 ? '0' + c : '' + c; + } + + // Replace a decimal with it's percentage value + function convertToPercentage(n) { + if (n <= 1) { + n = (n * 100) + "%"; + } + + return n; + } + + // Converts a decimal to a hex value + function convertDecimalToHex(d) { + return Math.round(parseFloat(d) * 255).toString(16); + } + // Converts a hex value to a decimal + function convertHexToDecimal(h) { + return (parseIntFromHex(h) / 255); + } + + var matchers = (function() { + + // + var CSS_INTEGER = "[-\\+]?\\d+%?"; + + // + var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; + + // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. + var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; + + // Actual matching. + // Parentheses and commas are optional, but not required. + // Whitespace can take the place of commas or opening paren + var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + + return { + CSS_UNIT: new RegExp(CSS_UNIT), + rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), + rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), + hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), + hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), + hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), + hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), + hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ + }; + })(); + + // `isValidCSSUnit` + // Take in a single string / number and check to see if it looks like a CSS unit + // (see `matchers` above for definition). + function isValidCSSUnit(color) { + return !!matchers.CSS_UNIT.exec(color); + } + + // `stringInputToObject` + // Permissive string parsing. Take in a number of formats, and output an object + // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` + function stringInputToObject(color) { + + color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); + var named = false; + if (names[color]) { + color = names[color]; + named = true; + } + else if (color == 'transparent') { + return { r: 0, g: 0, b: 0, a: 0, format: "name" }; + } + + // Try to match string input using regular expressions. + // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] + // Just return an object and let the conversion functions handle that. + // This way the result will be the same whether the tinycolor is initialized with string or object. + var match; + if ((match = matchers.rgb.exec(color))) { + return { r: match[1], g: match[2], b: match[3] }; + } + if ((match = matchers.rgba.exec(color))) { + return { r: match[1], g: match[2], b: match[3], a: match[4] }; + } + if ((match = matchers.hsl.exec(color))) { + return { h: match[1], s: match[2], l: match[3] }; + } + if ((match = matchers.hsla.exec(color))) { + return { h: match[1], s: match[2], l: match[3], a: match[4] }; + } + if ((match = matchers.hsv.exec(color))) { + return { h: match[1], s: match[2], v: match[3] }; + } + if ((match = matchers.hsva.exec(color))) { + return { h: match[1], s: match[2], v: match[3], a: match[4] }; + } + if ((match = matchers.hex8.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + a: convertHexToDecimal(match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex6.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + format: named ? "name" : "hex" + }; + } + if ((match = matchers.hex4.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + a: convertHexToDecimal(match[4] + '' + match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex3.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + format: named ? "name" : "hex" + }; + } + + return false; + } + + function validateWCAG2Parms(parms) { + // return valid WCAG2 parms for isReadable. + // If input parms are invalid, return {"level":"AA", "size":"small"} + var level, size; + parms = parms || {"level":"AA", "size":"small"}; + level = (parms.level || "AA").toUpperCase(); + size = (parms.size || "small").toLowerCase(); + if (level !== "AA" && level !== "AAA") { + level = "AA"; + } + if (size !== "small" && size !== "large") { + size = "small"; + } + return {"level":level, "size":size}; + } + + // Node: Export function + if (typeof module !== "undefined" && module.exports) { + module.exports = tinycolor; + } + // AMD/requirejs: Define the module + else if (typeof define === 'function' && define.amd) { + define(function () {return tinycolor;}); + } + // Browser: Expose to window + else { + window.tinycolor = tinycolor; + } + + })(Math); \ No newline at end of file