diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index ea6fd34..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**", - "${workspaceFolder}/../ch32v003fun/ch32v003fun" - ], - "defines": [], - "compilerPath": "/usr/bin/clang", - "cppStandard": "c++14", - "intelliSenseMode": "linux-clang-x64", - "compilerArgs": [ - "-DCH32V003FUN_BASE" - ], - "configurationProvider": "ms-vscode.makefile-tools" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index fe1d669..0000000 --- a/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# video compressor and player for the ch32v003 with an SSD1306 32x128 OLED display -Put a webm file in `video/` and run `./convert ` to convert the video to a sequence of 32x40 images. - -Run `cd encoder && cargo run` to convert to bytes, this will be exported to `data.h`. - -Tweak framerate or MAX_ERROR in `main.rs` until the total size fits the 16k flash alongside the decoder. - -By default it's tuned for bad apple. - -## building ch32_decoder -If you are not on Linux, good luck. - -You will need [ch32v003fun](https://github.com/cnlohr/ch32v003fun/) in next to the folder for this repository. - -The `gdbinit` file contains the device path for uploading via a Pi Pico with [PicoRVD](https://github.com/aappleby/PicoRVD). This is triggered with `make flash`. - -If you have an official WCH programmer you can probably run `make cv_flash` to use minchlink from ch32v003fun, but I can't test this. - diff --git a/ch32_decoder/Makefile b/ch32_decoder/Makefile deleted file mode 100644 index fad28f2..0000000 --- a/ch32_decoder/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all : flash - -TARGET:=bad_apple -CH32V003FUN:=../../ch32v003fun/ch32v003fun - -include ../../ch32v003fun/ch32v003fun/ch32v003fun.mk - -flash : build - gdb-multiarch -x gdbinit -ex 'load' -ex 'detach' -ex 'quit' $(TARGET).elf -clean : cv_clean - diff --git a/ch32_decoder/bad_apple.c b/ch32_decoder/bad_apple.c deleted file mode 100644 index 7497819..0000000 --- a/ch32_decoder/bad_apple.c +++ /dev/null @@ -1,248 +0,0 @@ - -#define SSD1306_128X32 -#include "ch32v003fun.h" -#include -#include "ssd1306_i2c.h" -#include "ssd1306.h" - -#include "data.h" - -#define PIN_LED PC4 -#define PIN_BTN PC7 - -#define WIDTH 40 -#define HEIGHT 32 -#define X_OFFSET ((128 - WIDTH) / 2) - -void decode_next_frame(); -void refresh_screen(); -u32 reader = 0; - -u32 frame[WIDTH]; - -int main() -{ - SystemInit(); - // funGpioInitAll(); - // funPinMode(PIN_LED, GPIO_CFGLR_OUT_10Mhz_PP); - // funPinMode(PIN_BTN, GPIO_CFGLR_IN_PUPD); - - // initialize OLED - ssd1306_i2c_init(); - // not using ssd1306_init because it does more than i want - uint8_t *cmd_list = (uint8_t *)ssd1306_init_array; - while (*cmd_list != SSD1306_TERMINATE_CMDS) - ssd1306_cmd(*cmd_list++); - - while (1) - { - decode_next_frame(); - refresh_screen(); - Delay_Ms(300); - if (reader >= sizeof(video)) - reader = 0; - } -} - -void refresh_screen() -{ - ssd1306_cmd(SSD1306_COLUMNADDR); - ssd1306_cmd(X_OFFSET); // Column start address (0 = reset) - ssd1306_cmd(X_OFFSET + WIDTH - 1); // Column end address (127 = reset) - - ssd1306_cmd(SSD1306_PAGEADDR); - ssd1306_cmd(0); // Page start address (0 = reset) - ssd1306_cmd(7); // Page end address - - u8 packet[SSD1306_PSZ]; - u8 x; - u8 packet_index; - u8 page = 0; - while (page < 8) - { - /* odd rows are unused so each nybble is expanded */ - packet[packet_index] = expand[(frame[x] >> (page * 4)) & 0xf]; - x++; - packet_index++; - if (x == WIDTH) - { - x = 0; - page++; - } - if (packet_index == SSD1306_PSZ) - { - ssd1306_data(packet, SSD1306_PSZ); - packet_index = 0; - } - } -} - -u8 next_byte() -{ - u8 byte = video[reader]; - reader += 1; - return byte; -} - -void fill_frame(u8 color) -{ - memset(frame, color ? 0xFFFFFFFF : 0x00, sizeof(frame)); -} - -void set_pixel(u8 x, u8 y, u8 color) -{ - if (color) - frame[x] |= (1 << (y & 31)); - else - frame[x] &= ~(1 << (y & 31)); -} - -void rle_horizontal(); -void rle_vertical(); -void bg_strips_h(); -void cell_diff_8v(); - -void decode_next_frame() -{ - Encoding_t encoding = next_byte(); - switch (encoding) - { -#ifdef USE_FillBlack - case Encoding_FillBlack: - fill_frame(0); - break; -#endif -#ifdef USE_FillWhite - case Encoding_FillWhite: - fill_frame(1); - break; -#endif -#ifdef USE_RLEHorizontal - case Encoding_RLEHorizontal: - rle_horizontal(); - break; -#endif -#ifdef USE_RLEVertical - case Encoding_RLEVertical: - rle_vertical(); - break; -#endif -#ifdef USE_BGStripsH - case Encoding_BGStripsH: - bg_strips_h(); - break; -#endif -#ifdef USE_CellDiff8V - case Encoding_CellDiff8V: - cell_diff_8v(); - break; -#endif - default: - memset(frame, 0b10101010, sizeof(frame)); - break; - } -} - -#ifdef USE_RLEHorizontal -void rle_horizontal() -{ - u8 x = 0; - u8 y = 0; - u8 color = 0; - while (y < HEIGHT) - { - u8 run = next_byte(); - for (int i = 0; i < run; i++) - { - set_pixel(x, y, color); - x += 1; - if (x == WIDTH) - { - x = 0; - y += 1; - } - } - color = 1 - color; - } -} -#endif - -#ifdef USE_RLEVertical -void rle_vertical() -{ - u8 x = 0; - u8 y = 0; - u8 color = 0; - while (x < WIDTH) - { - u8 run = next_byte(); - for (int i = 0; i < run; i++) - { - set_pixel(x, y, color); - y += 1; - if (y == HEIGHT) - { - y = 0; - x += 1; - } - } - color = 1 - color; - } -} -#endif - -#ifdef USE_BGStripsH -void bg_strips_h() -{ - u8 head = next_byte(); - u8 bg = head >> 7; - u8 fg = 1 - bg; - fill_frame(bg); - u8 strip_count = head & 127; - for (u8 i = 0; i < strip_count; i++) - { - u16 packed = (next_byte() << 8) | next_byte(); - u8 y = packed >> 11; - u8 x_start = (packed >> 5) & 0x3f; - u8 width = packed & 0x1f; - for (int x = x_start; x < (x_start + width); x++) - { - set_pixel(x, y, fg); - } - } -} -#endif - -#ifdef USE_CellDiff8V -void cell_diff_8v() -{ - u32 bitmap = (next_byte() << 16) | (next_byte() << 8) | next_byte(); - - u8 run_remaining = next_byte(); - u8 color = 0; - for (u8 x = 0; x < WIDTH; x++) - { - u8 cellx = x >> 3; - for (u8 y = 0; y < HEIGHT; y++) - { - u8 celly = y >> 3; - if (bitmap >> (cellx + (WIDTH / 8) * celly) & 1) - { - // advance rle once - if (run_remaining == 0) - { - run_remaining = next_byte(); - color = 1 - color; - if (run_remaining == 0) - { - run_remaining = next_byte(); - color = 1 - color; - } - } - set_pixel(x, y, color); - run_remaining--; - } - } - } -} -#endif diff --git a/ch32_decoder/data.h b/ch32_decoder/data.h deleted file mode 100644 index bad7e89..0000000 --- a/ch32_decoder/data.h +++ /dev/null @@ -1,836 +0,0 @@ -// Generated by the `encoder` rust app -#define USE_FillBlack -#define USE_FillWhite -#define USE_RLEHorizontal -#define USE_RLEVertical -#define USE_BGStripsH -#define USE_CellDiff8V - - -typedef enum Encoding { - Encoding_FillBlack = 0, - Encoding_FillWhite = 1, - Encoding_RLEHorizontal = 2, - Encoding_RLEVertical = 3, - Encoding_BGStripsH = 6, - Encoding_CellDiff8V = 7, -} Encoding_t; - -const unsigned char video[] = { - 0,0,7,8,99,152,57,1,13,3,19,5,18,6,16,8, - 3,1,10,15,9,15,9,16,8,17,7,18,14,19,13,28, - 4,29,3,29,3,30,2,64,3,0,255,0,30,3,27,5, - 19,2,3,8,19,13,15,17,1,3,9,23,8,28,2,255, - 0,49,4,25,9,68,4,25,15,16,18,14,22,10,30,2, - 224,7,13,41,78,0,146,9,6,2,13,5,3,8,1,4, - 9,5,4,9,1,7,3,29,1,7,1,7,1,7,1,39, - 5,23,2,1,7,18,17,15,20,12,23,9,25,7,128,7, - 5,41,206,0,119,8,22,11,18,14,16,16,1,5,1,1, - 5,19,1,15,2,14,2,14,2,14,3,13,3,13,2,14, - 3,4,7,2,3,3,10,16,19,12,193,7,5,41,206,0, - 213,4,10,1,15,9,6,4,9,1,2,5,7,2,2,14, - 2,14,2,14,2,14,1,15,1,15,1,31,1,4,8,19, - 16,16,20,12,22,9,97,3,0,255,0,158,2,28,5,1, - 1,18,1,3,14,10,25,6,81,1,31,1,31,1,31,2, - 30,2,30,1,31,1,22,4,5,1,6,1,2,6,8,9, - 6,11,14,1,4,14,13,22,10,24,8,26,6,28,4,224, - 7,15,123,142,0,85,4,19,6,18,6,3,3,12,12,14, - 10,23,9,24,8,24,8,24,8,8,4,13,7,7,6,11, - 8,6,10,6,9,6,13,3,11,2,30,2,30,2,30,3, - 29,4,28,4,28,4,28,5,39,7,5,4,8,7,1,3, - 1,144,3,0,255,0,180,5,26,7,5,2,18,14,18,14, - 19,13,22,10,8,4,11,9,6,7,12,7,5,10,8,9, - 4,12,7,11,2,16,2,106,1,31,2,30,2,30,2,30, - 3,29,4,28,7,14,8,3,10,11,8,1,31,1,130,3, - 0,255,0,242,5,26,7,4,5,16,16,16,16,7,4,5, - 16,5,7,4,16,4,11,6,10,4,14,5,10,3,17,3, - 9,2,222,1,31,2,30,2,30,4,21,4,3,7,15,9, - 1,10,12,9,1,21,1,8,1,65,3,0,255,0,119,3, - 28,6,25,8,24,8,24,12,20,12,7,6,10,10,4,9, - 10,11,1,10,11,23,10,29,2,59,3,27,3,11,1,18, - 1,12,1,127,1,31,2,30,5,20,1,6,7,14,3,2, - 17,10,171,3,0,177,5,26,7,24,9,23,9,24,8,24, - 7,27,5,28,3,29,5,1,7,18,14,17,15,18,14,18, - 14,18,14,18,14,19,13,19,13,19,13,19,13,19,13,19, - 13,19,13,19,5,3,5,18,5,7,2,17,7,1,7,18, - 14,19,13,18,14,17,15,11,3,3,15,5,10,2,15,4, - 28,3,29,2,30,2,30,6,139,122,131,130,102,138,72,146, - 72,154,42,162,42,170,42,178,42,186,72,194,103,202,132,6, - 142,58,130,66,70,74,40,75,65,82,41,90,10,98,11,106, - 11,114,11,122,11,130,11,138,41,146,71,154,99,6,33,1, - 94,10,86,18,55,26,24,34,24,42,55,50,101,51,140,58, - 100,59,202,66,100,67,233,74,100,76,8,82,100,84,7,90, - 101,92,37,98,102,100,67,106,72,108,98,114,41,122,10,130, - 11,137,236,146,11,154,11,162,11,170,42,178,73,186,134,194, - 194,6,159,2,117,10,179,18,148,26,179,34,210,42,241,50, - 210,58,179,65,225,66,179,74,179,82,179,89,162,90,179,97, - 193,98,179,106,179,114,179,122,179,130,241,136,161,139,233,144, - 130,148,8,152,99,154,164,155,199,160,68,163,3,168,67,176, - 35,3,255,0,97,1,31,3,29,3,29,5,27,6,26,7, - 25,8,10,2,12,9,8,5,10,10,6,7,10,11,4,7, - 10,12,2,9,9,23,9,27,5,31,1,18,5,27,3,1, - 1,255,0,143,2,24,2,255,0,6,3,33,2,1,6,30, - 8,1,2,30,7,34,8,34,7,32,9,30,2,1,8,30, - 10,31,5,2,1,32,9,31,9,31,2,1,7,30,1,2, - 10,11,3,12,1,2,18,4,12,2,2,1,19,7,33,12, - 3,5,20,20,20,25,3,4,8,25,1,1,1,10,2,200, - 6,14,58,66,58,161,66,99,74,131,82,101,90,132,98,132, - 106,164,113,165,114,107,122,1,122,139,130,194,131,99,6,14, - 58,33,58,99,66,36,74,100,82,69,90,100,98,100,106,133, - 107,67,113,146,122,100,123,6,130,162,131,98,6,14,58,65, - 58,161,66,68,74,100,82,100,90,132,98,132,106,164,113,132, - 114,107,121,226,122,108,130,194,131,69,6,19,51,99,59,36, - 67,38,75,100,83,70,91,101,99,99,99,226,107,133,115,133, - 116,101,123,109,130,179,138,226,139,78,147,163,148,39,155,194, - 156,163,3,25,7,25,7,22,10,20,12,20,12,22,10,23, - 9,23,9,25,7,25,7,25,7,25,7,25,7,25,7,26, - 6,22,10,23,9,208,1,23,2,5,2,22,11,21,10,24, - 2,1,7,25,6,27,5,27,5,28,4,255,0,15,3,25, - 7,25,7,21,11,21,11,19,13,20,12,21,11,25,7,22, - 10,23,9,25,7,25,7,25,7,25,7,25,7,25,7,23, - 1,2,6,22,10,170,1,6,2,22,6,1,3,21,11,23, - 9,27,6,27,5,27,5,28,3,255,0,46,3,26,6,26, - 6,22,10,21,11,19,13,19,13,21,11,26,6,25,7,23, - 9,24,8,26,6,26,6,26,6,26,6,26,6,26,6,27, - 5,23,2,2,5,22,10,104,1,6,2,22,6,1,4,20, - 13,21,10,22,2,2,7,26,6,26,6,26,5,28,4,255, - 0,15,6,29,3,233,12,8,68,163,76,132,84,132,90,69, - 92,70,98,40,100,39,105,237,107,233,113,227,114,98,114,210, - 121,196,122,97,122,241,129,194,130,34,131,16,137,228,139,41, - 140,132,146,3,147,100,154,34,162,34,170,34,178,34,6,6, - 114,2,121,228,129,197,137,135,145,132,153,162,6,132,3,39, - 11,70,19,101,27,131,7,1,136,200,0,57,3,10,2,5, - 7,10,2,2,8,12,15,8,15,8,11,2,2,6,8,16, - 6,18,5,20,2,124,7,1,140,194,0,113,4,7,4,5, - 3,4,9,3,8,4,28,3,29,3,29,3,29,4,28,9, - 23,10,6,7,9,3,1,60,7,7,189,206,0,255,0,209, - 1,1,14,5,27,4,28,4,28,4,28,4,28,4,15,3, - 10,7,1,2,8,8,6,11,2,1,4,12,2,15,2,30, - 1,112,3,0,205,1,31,1,31,5,27,4,28,4,28,4, - 28,4,28,4,28,4,28,4,28,3,28,4,22,1,5,6, - 2,2,9,1,5,4,3,10,4,6,3,29,2,30,2,30, - 2,30,1,31,2,30,3,29,4,2,5,21,12,8,24,3, - 30,1,255,0,51,7,15,57,236,0,226,4,19,3,28,6, - 24,9,11,1,10,9,11,1,10,8,9,7,7,13,4,11, - 2,15,4,28,4,28,4,28,4,28,4,28,5,27,6,26, - 10,22,18,14,20,15,61,3,0,255,0,233,1,29,6,2, - 3,21,11,23,2,1,7,26,6,8,2,17,6,1,11,16, - 17,15,17,6,1,8,17,6,3,2,1,2,18,6,26,5, - 27,4,28,4,28,3,29,2,30,4,28,4,28,5,27,6, - 8,8,10,26,6,30,2,96,3,0,255,0,178,5,27,7, - 24,10,22,12,20,13,1,2,13,7,3,9,12,2,11,7, - 9,2,15,6,8,3,15,6,8,4,14,6,7,6,10,9, - 4,28,1,31,1,49,4,29,2,255,0,76,1,31,3,0, - 255,0,86,1,27,6,26,7,23,11,20,14,18,16,16,18, - 5,7,2,18,6,26,7,25,11,21,15,17,16,16,19,13, - 26,6,27,5,28,4,29,3,29,3,30,2,31,1,255,0, - 33,2,0,101,6,3,2,28,12,27,14,26,15,25,13,27, - 13,26,14,25,13,27,13,28,11,30,10,30,11,30,9,33, - 4,24,2,8,7,22,4,6,11,18,6,4,12,17,9,1, - 13,16,25,7,2,5,35,4,5,3,28,16,14,2,8,17, - 12,5,6,17,12,6,2,20,12,28,12,30,9,31,8,31, - 10,30,10,12,2,0,177,5,34,8,32,10,29,12,28,12, - 28,12,27,12,29,10,30,9,31,9,32,8,34,5,20,2, - 12,5,20,5,8,9,9,1,7,7,6,11,6,4,5,9, - 5,11,4,7,4,36,4,2,1,34,3,2,4,6,2,24, - 11,2,4,10,2,1,2,1,4,4,16,10,11,4,14,11, - 14,1,15,10,31,7,32,8,32,9,31,9,31,9,16,2, - 0,177,7,3,2,28,12,27,14,26,14,26,13,26,14,25, - 12,29,11,30,10,30,10,30,10,21,2,8,8,22,2,10, - 4,23,4,6,7,21,7,4,11,12,2,3,9,2,13,9, - 4,2,25,7,6,4,2,2,32,9,1,1,29,12,14,2, - 12,14,12,4,10,14,11,10,1,17,12,29,11,31,9,31, - 8,31,9,31,9,16,6,171,4,39,11,202,19,171,27,140, - 35,109,43,109,51,78,59,47,66,210,74,241,82,241,91,47, - 99,78,107,109,115,109,123,140,131,140,137,39,140,7,145,41, - 147,230,153,73,155,229,161,74,163,105,169,106,171,105,178,5, - 179,44,180,225,186,6,187,13,188,225,194,52,196,194,202,55, - 210,86,218,86,226,117,234,143,236,194,243,72,251,72,6,149, - 2,170,4,70,10,111,12,132,18,20,20,163,25,246,28,225, - 34,8,35,78,42,68,43,140,51,202,59,233,68,39,76,101, - 217,198,225,106,233,75,241,106,249,106,6,142,33,195,41,199, - 49,201,57,204,65,206,73,238,81,236,83,129,89,234,91,129, - 97,237,105,232,113,231,122,67,6,49,24,97,32,100,40,132, - 48,133,56,164,64,227,73,33,138,225,147,2,152,193,155,35, - 160,194,168,194,169,65,170,193,176,229,178,194,179,195,180,65, - 185,6,186,163,187,165,193,39,194,164,195,193,201,133,202,164, - 203,163,209,134,210,133,211,101,217,165,218,165,219,102,225,167, - 226,196,227,98,227,197,233,199,234,197,235,193,236,3,241,199, - 243,4,243,225,244,34,249,228,251,35,252,2,6,9,90,194, - 98,132,106,101,114,101,122,70,130,70,138,36,146,34,154,2, - 6,15,67,65,75,34,83,3,90,226,98,98,98,194,106,69, - 114,69,122,39,130,39,137,233,145,170,153,99,154,37,162,98, - 7,7,57,128,127,1,2,5,11,5,2,14,1,80,1,6, - 2,15,11,13,15,2,22,3,22,3,1,1,21,2,124,7, - 7,56,196,57,1,22,2,22,2,21,3,22,3,11,1,9, - 4,6,6,14,6,3,9,15,17,8,5,1,18,6,26,6, - 26,6,14,2,10,7,10,6,9,8,6,10,3,3,2,8, - 1,119,7,7,57,196,154,5,8,3,6,7,5,4,5,6, - 5,16,4,28,5,27,5,27,5,27,5,27,6,26,7,7, - 1,9,1,7,4,1,3,5,4,6,11,2,6,5,19,3, - 123,3,255,0,255,0,125,1,30,3,8,1,1,3,16,6, - 3,8,15,6,2,10,15,5,2,20,5,5,2,30,2,30, - 2,30,3,29,3,29,3,29,4,9,2,17,6,7,2,17, - 10,1,6,13,20,5,2,5,18,6,3,5,3,4,2,1, - 6,7,16,14,21,10,23,8,15,6,10,107,193,115,162,123, - 162,124,129,130,21,138,103,139,132,140,98,147,162,155,193,3, - 17,10,21,2,2,3,25,2,29,2,30,2,1,3,26,10, - 21,2,1,6,22,2,30,2,31,2,2,5,24,11,22,6, - 27,2,31,2,1,5,25,10,23,5,27,1,32,1,1,4, - 26,9,7,4,1,7,4,1,1,4,9,13,4,1,14,11, - 6,1,7,3,4,9,6,13,3,10,4,15,3,12,2,15, - 2,13,1,16,2,30,2,30,2,30,2,30,2,13,1,16, - 3,10,3,16,4,9,4,15,9,2,7,14,20,9,1,2, - 20,2,30,2,30,2,1,3,26,10,22,8,4,3,15,1, - 31,1,31,1,1,7,23,7,24,2,1,2,27,2,30,1, - 2,1,27,9,23,7,24,2,30,2,31,2,1,7,23,7, - 26,2,32,1,2,7,23,8,25,1,1,1,29,1,21,2, - 9,8,10,4,10,6,5,1,5,6,9,1,6,5,3,9, - 6,14,2,11,4,15,2,13,1,16,2,30,1,31,2,30, - 2,30,2,12,1,17,3,11,2,16,4,9,4,15,9,2, - 8,12,11,1,8,8,24,1,2,2,27,1,31,1,1,2, - 28,8,24,1,1,3,58,6,8,3,240,1,29,3,27,4, - 28,3,30,2,32,2,23,1,6,2,19,2,1,3,5,2, - 14,1,3,8,4,3,9,5,2,10,2,18,2,10,2,18, - 2,30,2,30,2,30,2,30,3,29,3,29,3,9,4,1, - 12,3,4,4,8,4,11,1,5,2,9,3,30,1,31,1, - 30,3,29,2,29,1,31,2,29,3,29,2,30,2,31,3, - 29,3,30,4,28,1,1,3,11,3,18,3,28,4,27,2, - 29,5,26,1,2,2,27,1,32,5,7,1,19,3,9,1, - 30,2,20,1,1,2,5,3,21,4,5,1,30,2,22,1, - 6,2,23,4,2,3,23,1,1,6,15,2,7,7,5,3, - 4,7,4,8,3,6,3,10,1,18,3,10,1,18,3,29, - 3,29,3,10,1,18,3,10,1,18,4,7,4,17,5,8, - 3,2,2,12,5,10,2,1,1,3,3,7,6,8,3,4, - 9,2,17,1,63,4,27,1,1,4,25,1,31,3,28,6, - 26,1,31,4,29,5,28,2,1,1,29,3,30,3,11,3, - 17,6,25,1,3,4,23,3,28,7,25,1,3,3,25,2, - 12,1,18,5,8,1,18,2,1,3,7,1,19,1,9,3, - 20,4,5,3,20,1,1,4,3,2,21,1,7,3,21,5, - 3,2,22,9,15,1,7,1,4,4,11,5,7,8,4,3, - 3,8,4,9,1,7,2,11,1,18,2,11,1,18,2,30, - 2,30,2,11,1,18,2,11,1,18,3,9,3,9,2,6, - 4,5,1,1,6,8,4,3,4,10,3,1,5,3,11,10, - 2,6,1,2,12,2,2,4,3,4,4,2,22,1,7,2, - 22,1,1,4,3,2,21,5,4,2,20,1,9,3,19,1, - 1,1,9,1,18,6,7,1,18,1,30,2,3,3,25,1, - 1,4,27,3,30,1,2,4,26,5,9,3,17,1,30,5, - 26,1,1,6,24,1,31,1,1,3,9,1,18,6,7,2, - 17,1,12,2,18,1,9,3,19,7,3,3,20,4,5,2, - 30,2,21,5,3,2,21,6,2,3,21,1,6,3,12,2, - 8,9,9,8,5,9,4,3,2,10,3,17,1,12,2,17, - 1,12,1,18,1,31,1,31,1,12,1,18,1,12,2,17, - 2,10,3,17,3,8,6,8,4,3,4,9,4,3,2,4, - 9,12,2,1,6,3,9,10,3,6,2,3,22,4,4,2, - 31,2,20,6,4,2,20,6,4,3,18,1,10,3,18,1, - 1,1,10,1,17,7,7,1,17,1,2,1,10,1,16,1, - 31,2,1,5,25,5,28,2,14,3,0,10,5,14,3,9, - 2,1,4,13,3,9,1,5,2,10,5,9,2,1,2,13, - 5,10,6,12,4,10,8,11,3,11,1,17,3,11,7,10, - 4,12,8,7,4,13,1,14,4,13,1,13,4,14,6,6, - 5,15,17,5,3,7,2,1,12,7,4,8,11,6,10,5, - 28,3,30,2,158,2,31,1,30,3,28,3,13,5,8,5, - 2,1,13,5,19,2,7,4,16,9,4,2,15,11,4,2, - 8,1,4,14,4,13,7,9,3,12,6,11,4,11,1,17, - 3,10,1,1,5,12,3,9,7,12,4,9,5,13,5,8, - 2,16,1,1,4,9,1,2,5,11,4,9,6,13,4,2, - 7,1,23,2,7,1,38,2,3,1,30,1,255,0,69,1, - 38,1,80,1,38,2,37,3,9,126,23,1,255,0,70,1, - 39,1,38,2,28,1,9,2,28,1,5,2,79,1,38,2, - 38,2,32,1,5,2,32,1,5,2,33,1,4,2,34,6, - 36,2,111,2,36,4,30,1,4,6,13,26,32,9,34,6, - 35,5,34,6,35,5,35,5,35,5,35,5,35,5,27,2, - 6,5,29,2,4,5,4,3,24,2,1,12,26,11,30,8, - 31,8,27,15,23,19,4,2,11,5,5,4,26,6,4,5, - 27,4,4,6,34,4,1,2,39,2,39,1,60,2,39,3, - 39,2,41,1,3,4,35,6,21,1,13,5,20,2,14,4, - 20,2,14,5,19,3,12,5,1,2,17,3,13,3,21,3, - 13,3,21,3,12,4,1,2,18,3,12,6,19,3,7,4, - 1,4,21,3,10,6,19,4,12,10,28,8,30,3,1,7, - 28,2,3,8,32,9,31,9,30,9,30,2,1,6,31,1, - 7,1,30,2,7,1,15,3,86,1,31,1,25,1,5,1, - 21,11,21,10,26,1,99,1,30,1,31,1,31,1,29,3, - 27,5,2,10,8,2,2,4,2,10,11,20,12,20,11,21, - 11,4,2,4,1,12,9,3,3,3,2,1,2,12,14,2, - 1,1,2,1,1,4,21,3,5,2,23,2,3,1,27,2, - 15,1,31,1,31,3,28,5,27,5,27,5,28,3,30,2, - 219,2,37,3,103,1,35,5,34,6,34,6,34,6,15,1, - 17,7,14,2,18,5,13,2,21,3,13,1,22,8,3,6, - 9,1,11,18,9,3,10,7,1,2,1,1,1,4,10,2, - 11,7,5,3,12,3,9,8,3,3,14,3,4,2,3,1, - 2,4,3,2,16,4,5,1,1,2,1,5,1,3,17,3, - 7,3,1,7,20,2,8,2,1,6,20,3,8,8,21,3, - 8,8,21,3,8,8,21,3,6,11,18,5,4,3,2,9, - 16,1,2,1,3,4,4,11,18,5,5,10,1,2,15,4, - 8,10,3,2,13,1,10,12,4,1,23,12,28,12,21,1, - 6,12,15,2,10,16,23,18,4,2,16,18,3,1,18,18, - 8,3,11,18,2,1,5,2,12,21,5,3,10,22,4,1, - 2,1,10,21,4,2,2,1,10,19,2,1,1,1,4,3, - 9,18,3,2,6,3,7,19,2,1,8,3,7,21,6,6, - 8,19,5,8,7,21,1,3,3,4,7,27,2,2,8,31, - 9,30,9,30,10,30,11,28,12,28,13,19,2,7,12,28, - 13,16,3,8,17,11,4,8,32,7,33,8,32,8,31,9, - 31,9,31,9,31,9,6,2,167,8,31,10,30,11,28,13, - 27,13,27,13,25,15,25,15,25,15,27,14,25,14,26,13, - 26,14,25,16,23,16,26,14,28,12,27,13,27,13,27,14, - 25,15,25,15,25,16,24,15,24,17,18,2,3,17,17,3, - 3,17,15,5,3,17,15,4,2,7,10,148,167,107,1,30, - 3,29,3,5,2,17,15,4,8,4,28,4,4,3,5,3, - 5,2,6,2,6,3,5,3,5,4,4,4,28,5,27,7, - 25,16,4,1,11,25,7,28,4,128,2,51,1,34,6,32, - 9,31,11,28,12,28,13,27,13,26,14,24,16,24,16,25, - 15,27,14,26,13,27,13,26,14,26,15,25,15,25,15,27, - 9,2,2,26,12,26,14,3,7,16,15,1,10,14,15,1, - 12,12,28,12,16,1,10,13,27,13,26,13,18,1,7,14, - 26,14,25,15,25,15,2,15,1,38,2,35,7,32,9,30, - 11,29,12,27,13,27,14,26,14,26,13,25,16,24,16,25, - 15,26,14,26,14,26,14,25,15,25,15,25,15,25,15,27, - 12,28,13,27,13,26,14,26,15,24,16,24,16,24,16,24, - 22,18,25,14,27,12,30,5,2,90,1,38,3,32,8,30, - 11,28,12,28,13,26,14,26,15,25,17,24,15,25,14,27, - 13,12,1,13,13,13,1,13,12,28,12,28,12,27,12,28, - 11,29,14,28,13,27,13,26,14,3,7,17,25,14,28,12, - 29,11,30,10,31,8,32,8,33,8,32,7,2,52,1,39, - 2,34,7,32,9,29,11,28,13,27,16,24,16,24,15,25, - 15,25,15,26,13,27,12,28,12,28,12,29,11,29,11,29, - 8,32,10,30,13,26,14,26,23,17,25,15,27,13,28,12, - 29,11,30,9,32,9,31,9,31,8,13,1,16,6,3,0, - 32,1,31,2,30,3,29,4,28,5,27,6,18,1,7,7, - 16,2,7,8,15,2,7,8,8,1,3,5,7,8,7,11, - 6,8,2,16,6,29,3,202,1,255,0,255,0,151,6,7, - 106,71,114,9,121,233,129,201,137,200,145,230,153,229,6,15, - 89,193,90,33,97,193,98,33,98,229,105,162,106,33,106,107, - 113,208,121,177,129,51,137,50,145,47,153,106,161,132,6,20, - 66,195,74,226,82,226,90,227,99,1,106,227,114,227,122,196, - 123,225,130,165,131,194,137,10,138,202,145,23,153,54,161,84, - 169,207,177,238,186,34,186,226,2,8,3,7,7,24,2,6, - 9,23,1,5,11,22,2,4,11,24,1,4,11,24,1,3, - 12,24,1,3,12,28,11,28,12,14,2,15,9,10,6,19, - 5,6,10,20,3,3,14,19,21,9,255,0,15,1,38,2, - 37,3,36,4,35,5,33,7,31,9,30,12,26,16,21,23, - 10,102,2,3,6,7,8,19,4,2,3,4,8,19,4,5, - 3,1,8,18,4,9,8,19,4,10,6,20,4,10,9,17, - 3,13,6,1,6,11,3,13,6,4,6,8,3,13,6,5, - 10,3,3,13,13,5,4,2,3,12,12,10,1,2,3,12, - 9,16,3,12,6,19,3,13,5,19,3,14,5,18,4,13, - 5,19,3,12,6,19,3,11,8,18,3,9,11,18,2,7, - 13,18,2,6,14,18,1,6,15,18,1,5,16,18,1,4, - 17,18,1,4,18,17,2,3,18,12,1,5,2,2,18,8, - 5,8,18,6,8,7,19,2,12,7,33,9,31,5,35,3, - 43,14,14,21,11,25,8,9,6,9,8,4,15,5,8,2, - 31,1,32,1,31,1,31,1,32,1,31,1,31,1,32,1, - 29,3,18,1,9,5,15,3,7,8,4,2,7,4,6,9, - 2,5,5,5,6,14,1,2,2,7,6,26,6,26,6,26, - 6,5,3,18,8,1,5,18,15,1,2,4,3,7,15,1, - 4,2,5,5,15,1,3,3,6,2,18,1,2,2,27,1, - 2,2,27,5,27,4,28,3,30,1,31,1,31,1,31,2, - 31,1,31,1,31,2,12,2,182,5,34,7,16,3,13,8, - 17,4,10,8,18,7,6,10,16,5,3,3,2,11,16,5, - 6,12,17,5,9,10,16,4,12,10,14,4,12,12,11,5, - 13,9,2,8,3,5,15,8,5,4,3,5,14,9,5,4, - 3,5,14,9,3,5,4,5,13,17,6,4,13,2,1,12, - 8,4,14,11,11,4,15,7,14,4,16,6,14,4,16,7, - 14,3,16,7,14,4,14,8,14,4,12,11,14,4,10,13, - 13,4,8,15,14,3,7,16,14,3,4,19,14,3,3,21, - 6,3,255,0,164,22,7,255,0,234,21,6,255,0,61,3, - 255,0,187,1,30,2,30,6,25,8,23,9,23,9,23,32, - 9,23,9,23,9,24,8,25,6,27,1,31,1,255,0,166, - 7,7,48,128,62,2,1,5,4,8,1,5,1,23,1,47, - 24,1,23,1,23,1,6,3,14,4,3,7,2,112,7,7, - 49,128,76,1,7,4,5,2,3,14,2,5,1,16,2,24, - 22,1,23,1,23,2,7,1,14,2,7,2,13,5,2,10, - 3,20,3,20,3,102,7,7,57,132,103,3,1,2,8,11, - 6,2,9,15,5,27,13,40,11,21,11,22,10,24,1,231, - 7,7,25,198,107,1,28,5,16,10,7,8,10,7,11,3, - 11,7,25,6,26,8,24,9,23,12,1,2,17,13,9,4, - 6,12,4,5,3,5,3,14,2,6,2,22,2,7,2,13, - 2,1,2,11,2,14,2,14,2,72,6,3,116,5,124,8, - 132,194,7,2,115,132,5,3,26,7,3,3,7,10,3,29, - 4,28,4,28,6,26,9,23,11,8,18,4,247,7,7,57, - 198,57,1,29,3,28,4,27,4,28,3,29,2,15,4,11, - 2,13,7,5,7,12,9,1,19,2,30,3,29,5,27,6, - 26,7,25,12,18,1,1,7,10,175,7,3,60,198,49,1, - 7,2,22,2,31,1,31,2,30,2,30,3,30,2,30,2, - 18,2,8,4,15,6,5,5,16,8,1,19,3,29,2,30, - 2,30,4,28,7,25,10,30,2,1,53,3,210,1,27,2, - 2,1,26,6,26,6,27,2,2,2,30,3,29,3,30,2, - 29,3,14,1,11,6,8,3,3,6,4,7,2,1,2,7, - 3,29,3,29,3,29,2,30,2,30,1,31,2,3,2,17, - 1,7,12,12,1,7,14,14,27,4,255,0,166,7,5,125, - 238,118,1,3,1,18,6,25,7,25,5,1,2,27,1,2, - 3,29,3,30,2,28,6,24,7,6,4,9,14,4,21,2, - 22,2,22,3,21,4,20,4,20,3,7,3,9,5,6,6, - 7,6,4,16,6,9,1,20,2,30,3,29,3,30,2,30, - 1,30,2,14,1,59,7,2,125,238,167,1,16,2,1,2, - 2,2,14,11,13,7,1,5,13,5,2,5,20,4,6,3, - 7,7,2,1,3,4,3,23,3,29,3,29,4,28,4,28, - 4,28,3,29,3,3,1,2,1,14,1,7,3,3,8,8, - 20,4,19,5,12,5,2,4,12,10,15,8,17,3,2,2, - 94,7,7,111,255,30,6,17,8,3,2,11,14,8,17,6, - 19,3,23,1,51,5,30,2,64,1,31,1,22,4,37,2, - 1,1,28,6,18,3,2,1,48,3,3,2,13,6,1,4, - 10,14,10,4,6,3,11,3,21,3,188,1,28,4,24,8, - 46,2,19,1,1,3,10,2,5,7,11,2,1,10,11,61, - 1,7,3,156,227,58,1,8,2,19,4,7,5,11,1,3, - 5,6,14,1,2,2,8,6,26,6,29,4,27,10,21,12, - 22,11,18,20,12,24,8,5,5,20,1,4,11,21,12,20, - 5,9,6,4,6,7,9,2,7,4,133,7,3,156,227,46, - 6,16,3,5,8,7,2,7,18,3,4,8,15,3,7,7, - 12,3,10,7,27,7,1,1,23,10,21,12,21,11,19,13, - 19,11,21,2,2,5,22,3,28,4,29,3,22,2,23,1, - 144,3,48,3,27,5,8,2,15,6,8,3,8,1,5,6, - 4,1,2,5,7,13,1,3,2,7,6,15,3,9,6,27, - 5,27,5,26,11,22,11,20,13,2,3,14,22,9,255,0, - 157,3,23,9,14,19,12,20,11,23,4,26,6,28,4,12, - 1,13,6,25,6,1,5,7,3,10,5,1,7,7,4,7, - 15,6,6,5,16,3,30,3,16,3,222,2,28,4,18,4, - 4,6,11,21,8,24,7,25,6,26,6,26,4,11,1,11, - 3,2,5,9,3,10,9,9,7,2,1,3,9,5,1,4, - 7,2,1,2,26,2,1,2,25,6,26,6,28,2,1,2, - 12,2,3,4,7,2,1,2,12,8,7,2,1,3,12,8, - 3,9,12,9,1,11,11,26,6,26,7,25,8,24,11,21, - 26,6,27,5,27,5,27,5,28,4,29,3,30,2,64,3, - 255,0,30,3,27,5,2,1,23,9,2,1,3,23,1,3, - 1,27,2,62,2,1,1,28,4,1,2,21,3,1,8,19, - 15,1,3,9,25,6,26,6,24,9,12,24,12,21,10,26, - 6,26,7,25,7,25,4,1,2,25,4,4,18,6,3,2, - 21,6,4,1,22,5,27,5,28,4,29,3,30,2,128,3, - 10,5,26,7,24,9,22,11,20,14,17,18,13,21,10,24, - 8,26,5,29,2,31,1,10,2,192,1,30,7,25,9,23, - 10,24,8,26,7,27,5,28,4,28,4,28,4,28,4,27, - 5,25,6,9,2,3,3,7,7,10,4,1,16,10,21,10, - 20,2,2,8,19,1,4,7,18,1,6,6,27,5,30,2, - 31,1,31,1,5,2,0,22,18,22,18,22,18,22,18,22, - 18,22,18,22,18,22,17,23,16,24,17,23,17,22,19,21, - 19,21,19,20,20,19,21,18,22,18,22,16,24,15,27,11, - 32,5,229,1,39,1,39,1,38,2,38,2,38,2,3,0, - 13,19,13,19,13,19,13,19,13,19,13,19,13,19,12,20, - 12,20,11,21,10,22,8,24,7,255,0,193,3,19,3,7, - 4,14,7,7,5,1,5,2,12,7,25,7,25,8,24,10, - 22,15,8,1,8,26,6,29,3,128,7,14,115,8,85,1, - 14,2,9,1,3,1,7,5,6,5,4,5,2,10,7,5, - 1,19,7,25,7,25,8,24,11,21,20,4,2,6,28,4, - 22,2,168,7,14,49,204,0,4,4,3,5,2,25,1,8, - 1,7,1,15,2,31,1,31,1,31,1,31,2,29,3,30, - 2,13,4,6,5,2,4,8,7,7,25,7,25,8,24,9, - 23,14,18,15,17,21,4,2,5,29,3,64,7,6,33,200, - 0,4,4,3,5,2,35,1,7,1,7,1,15,2,14,2, - 14,2,14,2,14,2,14,2,6,5,3,3,1,7,7,5, - 1,6,1,12,7,25,7,25,8,24,11,21,15,17,27,5, - 29,3,7,14,115,220,0,4,4,3,5,2,255,0,76,3, - 27,5,25,7,14,5,4,9,10,22,8,24,7,25,7,25, - 7,5,2,18,7,4,5,3,3,10,27,5,160,6,13,1, - 22,9,22,17,22,25,22,33,53,41,52,49,52,57,83,65, - 82,73,112,81,142,89,172,97,232,7,2,19,222,139,2,29, - 4,3,3,3,9,9,23,9,23,10,22,13,19,19,13,31, - 1,128,6,10,8,8,9,7,11,5,11,5,12,4,13,3, - 13,3,7,2,18,144,26,3,20,4,4,15,1,23,1,23, - 2,22,3,21,9,15,16,6,10,8,8,9,7,10,6,11, - 5,12,4,12,4,7,6,51,156,40,2,11,4,14,4,6, - 15,6,8,2,16,5,27,5,27,5,27,5,27,6,26,7, - 25,9,23,255,0,33,6,31,58,133,66,73,74,43,82,12, - 90,13,98,13,106,13,114,13,122,44,130,75,138,43,146,43, - 154,33,154,105,162,12,170,12,177,237,185,238,193,208,201,209, - 209,179,217,149,225,99,225,243,233,68,233,244,241,67,241,246, - 249,36,249,204,251,138,6,18,4,194,12,194,20,225,138,132, - 146,103,154,74,162,44,170,44,178,13,185,238,193,238,201,206, - 209,175,217,175,225,144,233,144,241,113,249,81,1,7,15,128, - 0,0,42,1,3,2,2,6,1,7,2,2,2,2,73,1, - 2,20,4,4,74,3,1,2,1,7,1,7,2,2,2,2, - 40,7,15,220,0,0,11,4,13,3,13,4,12,4,11,5, - 11,1,1,3,5,11,4,12,5,11,14,2,148,12,3,13, - 4,6,2,4,8,3,2,3,9,2,4,1,68,3,1,1, - 5,2,3,13,4,12,5,1,1,9,7,2,6,1,8,2, - 14,2,14,2,6,7,15,255,192,2,11,1,2,2,11,2, - 1,3,10,6,10,3,1,3,9,3,1,3,10,2,1,4, - 10,6,10,1,1,3,1,10,4,1,3,49,8,7,4,4, - 12,3,7,1,15,1,141,1,4,2,16,5,2,2,5,6, - 2,5,5,2,4,14,3,3,5,14,2,4,5,3,14,2, - 5,3,15,1,32,1,23,2,23,1,5,2,6,1,9,2, - 3,4,4,3,7,13,1,3,1,1,2,14,3,5,1,23, - 2,3,1,1,6,2,5,4,120,3,0,12,2,30,2,10, - 2,17,4,9,2,18,3,8,4,17,4,8,4,16,5,8, - 4,14,6,8,5,7,2,3,2,1,5,8,5,5,16,2, - 4,1,4,6,21,2,3,8,1,5,5,2,6,3,1,17, - 2,5,2,141,1,31,3,6,2,21,3,4,5,3,1,16, - 17,13,14,3,3,12,6,3,5,3,3,26,4,252,1,29, - 4,1,4,19,10,2,2,1,2,10,14,2,5,10,22,10, - 7,3,3,7,2,11,2,1,2,15,2,14,2,14,2,14, - 2,15,1,15,1,20,3,0,8,2,3,4,9,4,15,4, - 10,2,15,2,1,3,26,1,2,3,25,2,1,4,13,1, - 11,1,1,4,13,2,11,5,13,3,10,6,11,5,2,5, - 2,7,10,6,2,15,6,9,2,18,2,10,1,63,2,30, - 3,29,3,6,2,21,6,1,5,1,5,3,2,9,5,1, - 24,2,5,1,255,0,255,0,188,3,0,5,27,6,26,7, - 25,8,1,2,6,4,1,1,9,13,1,13,5,30,2,170, - 2,30,3,29,5,27,7,25,1,2,4,25,1,3,3,18, - 3,3,1,2,4,19,4,1,2,1,4,14,3,4,11,8, - 9,5,27,1,177,4,10,1,14,9,8,2,6,3,2,14, - 5,29,3,6,1,23,2,6,1,62,2,217,3,0,23,9, - 6,2,15,9,6,6,6,14,6,9,2,15,5,10,1,16, - 5,27,2,30,3,29,3,2,1,26,7,25,8,1,2,4, - 2,15,28,4,29,3,255,0,255,0,63,3,17,1,5,1, - 1,7,13,19,9,23,8,24,7,25,6,26,8,14,4,6, - 9,4,3,6,8,2,9,2,5,6,10,6,164,26,226,34, - 227,42,228,50,196,58,104,66,105,74,105,82,135,90,104,98, - 105,106,105,114,105,122,104,130,135,138,165,145,68,146,104,153, - 38,154,74,161,38,162,12,169,143,177,174,185,163,186,73,194, - 73,202,72,208,4,210,72,216,6,218,72,224,9,226,41,232, - 25,240,25,248,25,6,147,114,8,121,203,128,243,131,102,136, - 250,144,250,153,24,161,24,169,55,177,56,185,84,193,114,201, - 114,209,115,217,115,225,114,233,145,241,114,249,114,3,189,2, - 29,2,30,1,30,2,29,3,19,14,16,18,12,20,12,20, - 13,19,14,18,15,17,16,16,17,15,19,13,19,13,17,15, - 16,16,15,17,14,18,13,19,12,20,12,20,14,18,16,16, - 26,3,30,2,31,1,31,2,31,2,161,6,147,146,69,154, - 9,161,115,169,54,177,24,184,250,192,220,200,190,208,190,216, - 159,220,97,224,159,228,97,232,102,233,121,240,102,241,122,248, - 101,249,122,3,255,0,97,3,29,6,17,18,13,23,8,75, - 1,31,9,23,18,14,18,14,18,14,18,14,18,14,12,20, - 10,22,8,11,1,12,7,7,8,10,7,5,11,9,6,5, - 14,7,6,5,26,6,26,5,27,5,26,6,26,6,26,5, - 27,4,29,3,56,3,255,0,247,5,25,7,24,4,27,13, - 12,21,10,22,7,25,6,2,1,21,8,1,1,24,7,2, - 2,7,7,7,6,2,6,4,9,1,1,3,6,1,8,2, - 21,1,255,0,154,6,28,60,193,68,132,76,194,84,194,92, - 194,100,194,107,193,108,194,112,212,115,195,116,194,123,233,132, - 39,140,194,148,194,156,194,164,194,172,194,180,194,188,163,196, - 163,204,163,212,163,220,162,228,162,236,130,244,130,252,129,2, - 14,1,39,1,39,1,40,1,39,1,39,1,39,2,39,1, - 39,1,39,1,39,2,7,3,29,1,1,10,28,13,27,12, - 11,40,7,4,7,7,33,6,34,6,32,8,31,9,30,10, - 30,10,30,11,30,11,29,11,29,11,30,9,32,9,33,3, - 2,1,35,2,3,1,34,3,2,1,36,1,3,1,13,2, - 10,18,5,7,12,15,7,6,12,14,9,5,11,13,13,3, - 11,10,31,8,33,7,33,8,32,8,30,11,29,12,28,12, - 16,3,9,14,4,1,8,4,4,2,3,15,3,2,6,6, - 2,4,2,21,1,91,1,38,3,23,3,3,1,7,3,22, - 9,6,4,9,2,10,10,5,4,4,7,4,18,3,5,1, - 8,5,19,2,14,5,34,7,32,9,30,11,28,11,16,2, - 9,12,17,1,11,10,31,9,18,3,11,10,12,3,1,3, - 0,13,15,19,12,20,7,1,3,26,2,30,2,255,0,89, - 1,34,3,29,4,26,13,19,15,17,17,22,1,2,7,31, - 1,255,0,125,2,30,2,30,2,29,2,30,2,13,4,12, - 2,4,7,14,182,224,0,255,0,2,1,24,2,25,4,20, - 5,16,2,1,16,4,20,4,21,4,20,2,5,5,6,12, - 4,13,3,15,1,192,7,15,115,140,0,62,1,28,5,23, - 9,16,1,1,7,3,4,12,8,8,4,5,13,3,5,2, - 4,5,3,7,4,1,12,18,14,9,2,8,13,8,8,2, - 14,7,25,6,26,6,26,6,26,6,26,7,25,7,49,2, - 10,7,5,144,7,11,120,204,0,49,1,23,2,29,3,20, - 5,3,3,14,4,1,9,11,15,19,13,20,12,20,12,16, - 15,9,21,11,1,12,7,25,11,8,7,4,13,7,9,6, - 10,6,10,6,10,6,10,6,10,6,10,7,41,96,3,0, - 248,2,28,6,25,8,22,10,10,1,10,11,6,2,1,1, - 2,1,6,13,6,7,4,15,4,29,2,61,1,30,5,11, - 2,17,8,25,6,26,6,26,6,26,6,26,6,26,6,26, - 6,26,7,25,8,24,11,21,255,0,65,3,0,255,0,255, - 0,108,2,1,10,19,13,23,1,4,2,25,1,31,1,70, - 2,24,1,4,3,10,3,3,10,3,2,4,15,4,8,2, - 18,5,6,1,60,1,14,2,30,3,29,6,26,8,24,9, - 4,4,15,10,2,9,1,21,2,31,2,18,7,15,123,216, - 0,114,2,16,9,1,1,2,1,3,2,1,13,1,26,1, - 23,2,1,3,4,1,10,1,2,19,1,255,0,255,0,126, - 7,3,24,194,0,55,9,7,1,5,2,3,14,6,4,1, - 21,6,26,6,26,7,4,4,3,2,12,9,1,14,8,23, - 1,168,7,5,41,66,0,31,1,22,10,13,2,2,15,6, - 4,2,20,6,26,6,26,7,4,2,1,2,1,3,12,8, - 2,14,8,8,2,19,1,1,2,4,3,4,2,6,6,1, - 2,1,3,2,3,6,9,2,9,5,19,6,18,6,2,4, - 11,7,1,6,3,8,7,15,121,64,0,20,4,12,12,1, - 1,3,3,1,90,11,10,1,2,16,5,119,2,15,2,4, - 3,14,3,3,3,14,8,4,5,6,19,5,19,6,18,7, - 3,3,3,2,5,9,1,5,2,6,1,7,3,14,2,103, - 7,15,249,66,0,61,3,22,10,14,2,2,14,7,4,2, - 19,6,26,6,26,7,25,8,4,4,3,6,7,197,2,15, - 1,5,12,6,18,6,18,5,19,4,6,3,3,5,2,6, - 3,1,1,142,7,7,249,198,0,115,3,6,4,4,9,5, - 14,3,10,4,15,3,29,3,29,3,29,3,29,3,22,2, - 5,4,20,1,7,4,27,7,23,11,4,1,19,13,19,10, - 20,1,1,8,108,6,6,1,10,15,1,4,4,21,3,21, - 3,14,2,61,6,129,128,107,6,146,97,227,98,195,105,164, - 106,229,113,101,115,7,121,8,123,10,128,140,131,12,136,233, - 139,9,145,71,147,6,153,164,154,229,162,2,162,195,3,0, - 6,26,5,27,4,28,4,28,3,29,2,30,1,31,1,50, - 2,28,5,26,7,25,8,22,1,1,8,20,12,18,12,20, - 11,20,12,20,14,17,15,17,15,18,14,18,14,18,14,19, - 12,9,1,11,10,10,1,11,10,9,2,13,6,10,3,28, - 4,28,4,27,5,26,6,25,7,24,8,22,10,21,11,19, - 13,18,14,15,17,11,53,3,255,0,243,2,14,4,11,3, - 12,7,9,4,6,5,1,9,5,8,1,8,1,10,3,29, - 4,26,6,17,2,6,8,4,4,3,2,3,16,4,29,2, - 30,2,255,0,207,7,2,57,132,77,3,16,3,9,4,16, - 5,7,5,6,4,5,6,4,19,3,6,3,18,5,4,5, - 20,3,2,8,5,3,1,2,6,16,4,8,3,9,4,12, - 3,14,1,91,7,3,17,196,117,3,1,2,17,4,7,5, - 15,5,3,9,13,19,12,22,11,19,1,1,11,11,4,4, - 1,1,12,5,27,4,21,3,5,3,50,3,255,0,113,2, - 30,3,13,1,14,5,12,2,13,6,11,3,12,7,5,3, - 2,3,6,1,5,14,3,3,6,4,2,13,4,5,3,5, - 2,255,0,62,3,30,9,24,13,20,16,17,16,16,16,17, - 15,17,15,19,13,20,12,21,11,7,1,13,11,2,132,1, - 38,3,37,4,35,6,34,7,32,8,32,9,30,11,29,12, - 28,12,28,13,27,14,2,16,8,32,7,33,7,33,7,21, - 9,1,10,18,22,14,1,2,23,13,27,12,28,12,29,10, - 30,9,31,9,32,7,33,6,23,1,11,5,22,2,11,4, - 22,3,12,2,23,3,7,11,127,198,255,0,84,3,1,1, - 16,1,3,10,18,14,18,15,1,1,18,4,1,6,28,3, - 255,0,140,7,6,49,132,27,1,29,5,15,5,3,1,1, - 9,11,21,9,22,8,24,7,24,9,4,1,22,2,6,1, - 13,6,2,6,8,20,3,123,2,216,1,38,5,35,6,34, - 5,36,5,35,6,32,6,2,2,29,8,31,10,30,7,2, - 2,32,4,3,6,27,6,33,7,33,7,33,8,31,9,30, - 10,29,13,25,17,21,21,19,21,18,22,20,19,23,16,28, - 10,30,2,3,1,34,2,3,2,19,3,255,0,202,1,12, - 1,15,1,1,2,9,13,4,6,9,13,5,27,5,27,5, - 27,5,27,5,27,5,27,5,27,5,27,5,27,4,5,10, - 13,7,2,12,11,7,2,18,5,7,1,255,0,89,2,183, - 1,30,1,2,7,30,10,31,12,26,13,27,12,28,11,30, - 10,16,2,13,9,16,1,15,9,15,3,13,9,15,4,13, - 8,15,4,13,8,16,3,13,8,17,3,8,13,16,3,6, - 15,16,4,4,16,17,4,2,18,16,4,1,19,17,9,3, - 12,17,5,6,12,17,3,8,12,28,12,28,11,29,11,29, - 11,29,12,24,16,12,3,255,0,89,2,27,7,25,10,20, - 6,3,4,9,1,1,2,6,5,6,2,7,6,5,14,5, - 27,4,28,4,28,4,28,4,28,4,28,4,28,5,27,6, - 26,7,2,2,1,6,14,21,7,2,2,255,0,161,3,250, - 4,26,8,22,10,7,1,2,2,9,6,3,2,4,8,9, - 5,11,7,8,12,6,10,3,13,6,26,6,26,6,26,6, - 26,6,26,6,26,6,26,6,26,5,27,4,7,10,11,7, - 4,11,10,8,1,16,1,14,1,255,0,184,3,0,183,2, - 30,3,6,1,21,5,5,2,18,8,4,3,11,2,3,11, - 2,5,7,19,1,5,5,28,2,255,0,158,4,26,7,23, - 10,21,12,20,13,18,16,3,3,9,24,5,29,1,231,3, - 0,7,1,2,25,5,29,3,31,1,76,1,28,3,2,1, - 25,2,3,3,3,5,16,2,1,6,1,6,16,16,8,1, - 7,24,9,22,11,21,16,17,17,15,20,13,18,14,20,13, - 21,11,22,10,22,10,22,10,22,10,22,11,21,11,21,12, - 20,14,9,7,2,15,8,25,8,25,7,27,5,28,4,29, - 4,29,2,168,3,0,255,0,112,1,31,3,29,7,27,6, - 25,7,25,8,24,9,25,8,12,5,10,6,3,1,6,6, - 11,10,2,11,5,14,1,13,3,15,2,13,1,16,2,30, - 3,29,4,28,4,28,6,9,1,7,1,1,2,5,9,5, - 2,7,7,2,11,1,3,8,23,8,22,10,1,1,20,16, - 17,16,17,18,15,17,16,16,17,15,17,15,3,0,255,0, - 113,1,31,3,30,6,28,5,27,5,26,7,25,8,24,9, - 27,6,10,4,13,9,5,6,9,12,2,11,4,15,1,13, - 2,16,1,13,1,17,1,31,3,29,3,29,4,22,1,5, - 5,10,1,7,7,2,8,6,2,7,8,1,15,8,22,9, - 22,12,20,16,18,15,18,17,15,17,16,16,17,15,3,0, - 255,0,22,1,31,2,30,3,30,4,29,5,28,4,29,3, - 18,2,9,4,17,3,9,3,17,12,1,2,18,11,1,3, - 23,4,2,3,22,5,2,5,19,13,5,4,1,1,6,15, - 4,9,3,16,3,10,2,17,3,29,2,30,1,31,1,31, - 1,23,5,3,2,22,7,1,5,18,22,10,21,15,17,17, - 16,18,16,17,15,17,16,16,17,15,6,138,194,162,202,163, - 210,195,219,2,227,3,227,162,235,4,235,162,242,201,250,201, - 6,148,97,162,105,196,114,4,122,36,130,68,138,101,146,133, - 154,165,162,198,171,6,179,38,187,70,195,103,203,136,211,200, - 219,233,228,8,236,39,244,70,252,132,3,0,219,4,27,6, - 25,7,22,10,21,11,21,11,21,11,20,11,21,9,14,2, - 10,6,2,1,5,3,1,5,8,6,2,2,6,10,3,13, - 7,25,6,26,1,63,6,26,6,26,7,15,2,8,9,2, - 16,4,255,0,194,3,0,201,3,27,7,24,8,23,10,22, - 10,1,1,20,14,19,17,15,17,4,1,1,2,9,8,4, - 3,18,7,4,2,19,7,4,7,3,2,9,6,4,13,10, - 5,4,13,10,22,8,24,8,24,8,24,7,18,6,1,8, - 17,6,1,8,19,3,2,7,25,6,3,1,6,4,12,5, - 3,1,6,9,8,4,3,2,5,14,4,3,4,27,2,1, - 1,28,1,253,3,0,233,1,28,6,25,8,23,9,23,9, - 2,2,19,19,14,18,6,1,7,10,5,3,16,8,5,3, - 17,8,4,12,9,6,5,12,9,6,5,12,11,5,1,15, - 10,22,9,23,9,18,4,1,9,17,15,23,9,23,9,23, - 8,11,6,7,8,9,9,5,8,3,1,6,10,3,8,3, - 2,4,23,3,3,1,24,3,28,2,1,1,27,1,188,3, - 0,255,0,39,6,25,7,24,9,2,2,19,9,1,7,15, - 20,1,4,1,2,4,12,1,7,13,11,5,2,16,9,5, - 11,9,7,5,11,9,7,5,11,10,5,5,12,13,4,1, - 14,12,20,10,17,15,17,15,19,13,22,10,22,10,22,10, - 10,8,4,10,2,1,6,10,3,9,3,1,5,23,2,2, - 4,23,2,3,3,23,4,27,4,28,1,30,1,122,3,0, - 255,0,96,1,30,5,4,2,20,8,1,16,4,4,2,5, - 1,11,8,5,2,9,3,6,6,17,6,3,5,6,3,10, - 6,3,2,8,3,10,7,25,5,1,2,14,4,7,2,19, - 5,4,3,20,11,21,10,22,10,22,10,22,11,21,11,12, - 4,5,10,12,19,3,1,8,19,3,2,6,21,1,4,2, - 24,2,4,2,30,2,209,3,0,255,0,69,1,25,1,4, - 7,7,1,1,3,1,3,1,4,4,15,1,1,15,14,15, - 2,1,4,1,10,13,9,7,4,10,13,6,5,6,15,7, - 5,3,18,7,5,1,20,4,28,3,27,4,28,4,20,3, - 3,3,21,11,21,10,22,10,22,11,21,11,21,12,15,17, - 15,17,14,18,14,18,13,18,2,1,3,1,7,18,1,2, - 3,1,6,22,2,4,2,23,3,29,3,29,4,15,3,0, - 27,5,28,4,29,3,29,3,30,2,255,0,127,2,29,7, - 25,8,7,1,16,9,5,2,16,9,23,9,22,9,22,10, - 21,11,20,7,21,11,19,13,18,14,18,14,18,14,18,14, - 17,15,17,15,16,16,13,19,9,23,7,25,6,26,6,26, - 6,135,154,129,162,99,170,68,178,38,186,38,194,68,202,129, - 7,2,16,128,0,39,3,16,1,2,6,12,14,10,14,14, - 9,23,1,28,7,6,49,140,0,14,5,1,4,20,12,21, - 1,1,9,24,8,7,1,5,3,9,2,8,5,4,5,5, - 6,2,10,4,6,2,20,3,29,3,29,4,28,6,5,1, - 3,6,11,23,9,26,6,28,4,30,2,32,7,7,57,204, - 0,107,6,4,2,8,17,7,17,7,17,20,12,20,4,1, - 7,21,3,5,2,22,4,25,8,3,3,4,2,9,17,3, - 8,3,18,2,9,2,19,1,31,1,31,1,20,3,8,2, - 16,9,5,2,12,14,4,3,10,17,2,6,2,56,3,0, - 255,0,123,6,21,11,20,9,23,12,20,12,26,6,27,5, - 27,5,26,5,26,5,27,5,26,5,18,3,5,6,1,2, - 11,21,2,1,7,28,3,30,1,138,5,24,11,21,13,15, - 19,13,21,3,125,7,15,123,156,0,165,5,26,7,25,8, - 25,8,27,6,26,8,24,9,23,10,22,11,25,8,24,9, - 23,10,22,10,22,9,23,9,23,7,25,5,15,1,12,1, - 2,1,2,2,11,1,13,8,10,1,11,10,10,1,10,11, - 18,14,16,16,10,6,149,105,226,113,196,121,196,129,200,137, - 229,146,4,154,6,162,8,170,43,178,75,186,105,194,136,202, - 138,210,134,211,100,218,132,219,130,226,161,227,66,235,34,243, - 33,7,6,56,196,0,113,2,10,3,9,2,8,5,13,1, - 3,2,7,6,11,10,3,8,1,2,8,23,2,1,6,19, - 1,2,2,1,8,18,5,1,13,4,1,10,2,1,2,1, - 15,3,1,10,2,1,4,5,4,1,1,1,5,3,106,6, - 160,42,101,50,102,58,41,66,42,74,43,82,76,90,75,98, - 73,106,105,113,163,114,137,121,164,122,169,129,226,130,139,137, - 227,138,108,146,16,154,17,162,3,162,142,170,142,178,143,186, - 174,194,174,202,173,210,203,218,202,226,203,234,172,242,172,250, - 172,6,156,4,194,9,194,12,225,17,195,20,225,25,196,33, - 197,41,230,49,231,58,71,66,104,74,138,82,171,84,162,90, - 210,99,16,107,109,115,171,123,233,131,230,132,225,139,201,147, - 202,155,202,163,202,172,8,180,101,188,132,6,152,3,228,11, - 168,19,138,20,225,27,109,35,109,43,109,51,109,59,140,67, - 109,75,109,83,171,91,202,100,8,107,231,115,230,123,167,131, - 135,139,72,147,8,154,200,162,105,170,67,178,97,7,0,115, - 222,0,104,2,6,4,4,5,3,18,6,17,1,2,4,12, - 2,2,8,8,16,5,19,3,255,0,198,6,7,0,9,3, - 101,4,101,8,1,8,164,11,162,12,225,6,5,50,130,99, - 97,121,129,137,193,232,97,7,3,205,103,13,4,8,5,13, - 8,6,5,11,11,4,6,10,12,4,6,10,12,3,7,9, - 23,9,25,7,23,9,25,7,13,1,5,3,2,8,12,21, - 8,11,2,12,6,202,1,158,1,7,7,3,220,231,107,3, - 15,2,9,8,10,5,7,10,10,4,7,11,10,5,5,10, - 11,6,4,11,10,7,4,11,10,8,2,10,10,10,2,10, - 5,2,2,11,1,31,1,31,1,31,1,9,3,19,1,6, - 1,1,6,17,1,4,11,3,15,2,13,1,31,1,206,3, - 219,2,13,7,9,4,10,9,8,5,8,11,8,6,6,11, - 8,7,5,11,9,8,3,10,10,9,3,10,10,9,2,11, - 9,10,2,18,1,11,2,30,2,30,2,4,1,4,2,19, - 2,2,4,1,5,18,17,2,11,2,16,3,30,1,136,1, - 100,1,255,0,65,6,30,50,129,58,100,66,69,74,38,82, - 37,90,36,98,68,106,68,114,69,122,69,130,69,138,70,146, - 68,146,226,147,65,154,106,162,78,170,80,178,38,179,41,186, - 7,187,34,193,201,201,170,209,139,217,109,225,78,233,109,241, - 109,249,140,7,7,113,140,52,2,5,4,27,5,26,7,24, - 8,16,3,4,9,7,5,3,6,1,10,6,12,2,12,4, - 63,4,3,3,19,14,2,3,13,25,7,29,3,192,6,33, - 52,34,59,229,67,199,75,199,83,200,91,200,99,231,108,6, - 116,37,122,46,124,5,128,72,129,216,136,20,139,46,144,82, - 147,232,154,97,156,8,162,97,164,8,170,34,172,39,180,39, - 188,39,196,39,204,38,212,70,220,70,228,39,236,8,244,8, - 252,8,3,22,4,28,4,28,4,28,4,28,4,28,4,28, - 4,28,5,27,5,3,1,23,9,18,2,1,8,20,15,15, - 16,15,17,13,17,13,19,4,1,5,20,6,2,2,22,6, - 20,1,5,6,15,6,5,6,13,8,5,6,10,11,5,6, - 8,14,4,6,6,16,4,6,2,20,5,23,2,2,5,21, - 3,3,5,20,2,5,5,18,4,5,5,15,17,13,19,12, - 21,9,23,8,24,6,20,1,5,4,16,8,4,4,16,8, - 4,4,15,9,5,3,12,13,4,3,9,16,4,3,3,18, - 14,18,14,18,14,18,2,5,7,18,2,11,1,17,2,30, - 2,29,2,30,2,30,2,30,1,31,1,31,1,31,2,30, - 2,30,2,30,2,30,2,31,1,31,2,30,2,30,2,31, - 2,30,2,30,4,8,2,1,1,6,1,1,3,2,8,3, - 6,1,1,4,255,0,9,4,29,3,15,2,2,2,14,2, - 10,9,10,5,8,14,4,8,6,28,3,3,42,3,30,13, - 19,17,15,19,13,21,11,21,11,2,16,3,11,2,30,1, - 30,2,30,1,31,1,31,1,31,1,31,1,31,1,20,1, - 7,2,1,2,15,5,4,9,12,7,4,9,1,1,8,9, - 3,29,3,29,3,29,3,29,4,6,2,10,2,8,4,1, - 8,8,24,8,25,7,25,2,2,3,26,6,27,5,27,3, - 30,3,31,2,31,2,31,3,31,3,31,2,31,3,29,3, - 3,2,138,3,35,8,31,8,32,8,32,9,31,9,30,9, - 32,8,31,9,25,3,3,8,22,18,18,6,6,9,19,4, - 12,6,18,2,15,8,32,9,31,10,30,12,28,9,1,4, - 26,9,3,3,25,9,1,5,26,15,25,12,2,2,24,5, - 4,3,3,2,23,5,11,2,21,6,12,1,21,6,12,2, - 19,7,13,2,17,8,13,2,17,8,14,2,1,2,54,3, - 35,10,29,10,29,11,29,11,29,12,28,12,28,11,28,12, - 27,13,29,11,19,20,20,20,27,13,29,10,31,10,31,11, - 31,12,28,14,26,14,27,15,25,16,24,12,1,5,22,13, - 2,4,22,11,3,5,21,19,21,20,20,17,1,3,19,16, - 3,3,18,7,6,3,4,2,18,7,14,2,2,2,22,3, - 34,7,32,9,30,14,26,13,27,12,26,13,26,14,28,13, - 27,12,14,9,4,12,13,27,13,4,3,19,14,1,11,14, - 29,11,31,8,33,7,33,8,32,11,28,13,28,14,26,8, - 1,5,26,15,25,16,24,13,1,3,23,13,2,4,21,13, - 2,5,20,13,1,6,20,21,19,21,19,17,2,3,18,8, - 5,4,3,2,3,0,177,15,12,20,7,25,3,255,0,255, - 0,255,0,32,2,29,5,25,7,24,9,1,4,16,28,2, - 72,3,255,0,65,1,31,4,28,6,26,8,24,9,23,11, - 22,11,27,6,30,3,31,2,255,0,255,0,147,6,1,98, - 98,6,10,122,38,130,8,138,8,146,8,154,8,161,234,169, - 204,177,204,185,234,194,68,6,17,194,98,201,234,209,138,210, - 229,217,99,218,68,219,36,225,67,226,68,227,68,233,67,234, - 67,235,99,241,36,243,99,249,68,251,68,7,7,16,128,85, - 3,8,1,6,9,8,16,7,17,7,17,8,16,14,10,21, - 3,64,7,7,16,128,62,2,14,3,2,5,3,2,6,13, - 3,21,3,21,3,21,3,21,3,2,6,13,14,3,2,5, - 6,2,56,7,7,56,192,89,2,21,3,20,5,18,5,5, - 4,4,2,1,7,2,28,1,100,3,16,10,14,13,11,6, - 3,6,1,7,2,15,1,87,6,26,57,129,58,6,65,138, - 73,139,81,170,89,169,97,200,105,200,113,199,121,200,129,232, - 137,233,145,234,153,234,161,235,169,235,177,203,185,204,193,205, - 201,174,209,173,217,142,225,111,233,112,241,80,249,81,7,5, - 57,206,128,75,1,31,1,31,1,13,4,6,1,1,1,10, - 7,4,3,10,16,8,16,8,7,3,5,10,4,6,1,1, - 1,11,3,7,1,23,1,31,1,84,128,3,0,255,0,55, - 1,31,2,27,4,26,5,24,7,24,5,26,4,27,4,17, - 3,7,4,18,13,5,4,10,12,5,4,11,12,2,1,1, - 4,12,20,12,20,12,20,12,21,11,21,11,8,2,11,11, - 6,3,4,2,6,11,4,5,3,4,5,26,5,27,1,255, - 0,49,3,0,104,3,29,6,18,2,6,2,1,4,17,9, - 2,4,17,15,17,16,16,16,16,17,17,15,20,1,3,3, - 2,2,26,2,255,0,245,254,2,23,9,23,9,23,9,3, - 0,72,1,3,1,19,10,1,2,19,14,18,14,18,4,2, - 6,20,3,30,1,255,0,127,255,0,152,3,28,5,25,7, - 1,4,19,13,19,2,1,10,24,3,2,3,24,2,38,7, - 12,64,99,0,32,4,2,1,4,2,3,10,1,2,3,15, - 1,14,2,5,4,1,1,2,4,3,5,1,2,1,4,2, - 7,1,117,56,1,13,3,13,5,8,8,8,13,2,14,6, - 10,6,2,24,7,14,80,231,0,3,4,13,4,12,4,13, - 4,12,4,13,4,12,4,13,3,13,3,14,2,14,2,15, - 1,186,12,12,167,1,6,3,9,1,2,4,9,1,2,5, - 8,9,7,9,7,9,8,8,9,7,9,6,2,3,0,52, - 12,18,14,16,16,14,18,13,3,6,10,12,1,13,6,11, - 1,17,3,10,1,19,2,31,9,24,8,24,7,8,4,13, - 7,8,4,13,7,9,3,13,7,9,2,14,8,24,8,24, - 9,23,11,21,13,3,6,10,24,8,25,7,15,2,9,6, - 15,3,8,6,14,5,8,5,15,4,8,6,26,6,26,7, - 24,9,23,10,26,7,16,1,10,7,12,3,10,13,1,6, - 12,19,13,17,15,15,17,12,52,3,0,11,10,19,17,12, - 22,9,24,6,28,3,30,1,120,5,25,10,20,12,19,13, - 18,14,17,15,17,15,16,16,16,8,4,4,16,8,5,3, - 4,4,8,8,5,3,3,5,8,8,5,3,3,5,8,9, - 3,4,4,4,8,16,16,16,15,17,15,17,14,18,14,18, - 13,19,11,23,7,119,1,30,3,28,6,24,9,22,12,18, - 17,12,10,2,0,2,38,2,38,1,187,2,37,4,35,5, - 35,5,35,5,18,4,14,3,16,10,29,12,26,16,20,1, - 2,17,20,1,2,18,18,2,1,20,16,3,1,21,14,15, - 1,12,11,14,4,13,7,16,5,34,6,34,6,35,5,36, - 3,186,1,38,2,38,2,2,187,3,36,5,35,6,34,6, - 34,6,14,6,15,4,13,10,28,14,25,16,23,18,22,19, - 21,20,20,20,20,21,19,21,19,22,18,23,16,10,4,12, - 12,11,6,13,8,13,6,34,7,33,6,34,6,35,4,187, - 3,0,13,6,26,5,255,0,47,81,2,30,2,31,1,31, - 1,31,1,31,1,25,1,5,1,24,4,3,1,24,5,2, - 1,24,5,1,2,23,10,22,11,22,10,22,10,22,11,23, - 9,27,4,28,4,28,3,29,3,28,5,27,5,27,5,27, - 5,28,3,76,3,0,14,4,255,0,47,241,1,31,2,31, - 1,31,2,31,1,31,1,31,1,63,2,22,3,4,4,22, - 10,22,12,21,1,1,9,22,1,3,5,29,3,29,4,29, - 3,29,4,28,4,28,4,29,3,71,3,105,2,31,2,58, - 11,19,15,16,17,12,21,11,21,11,21,11,21,11,21,11, - 21,11,21,11,21,11,21,11,21,11,21,11,22,10,22,3, - 2,5,20,5,25,8,24,8,24,8,24,7,26,5,29,1, - 255,0,107,3,0,255,0,170,2,2,2,23,10,21,12,7, - 8,4,28,5,27,5,27,5,27,5,9,2,16,5,27,5, - 7,7,13,5,3,10,14,17,5,1,9,17,4,4,7,29, - 2,255,0,162,0,0, -}; diff --git a/ch32_decoder/funconfig.h b/ch32_decoder/funconfig.h deleted file mode 100644 index 998cf76..0000000 --- a/ch32_decoder/funconfig.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _FUNCONFIG_H -#define _FUNCONFIG_H - -#define CH32V003 1 - -#endif - diff --git a/ch32_decoder/gdbinit b/ch32_decoder/gdbinit deleted file mode 100644 index a0bb3de..0000000 --- a/ch32_decoder/gdbinit +++ /dev/null @@ -1,2 +0,0 @@ -#set debug remote 1 -target extended-remote /dev/ttyACM1 diff --git a/ch32_decoder/ssd1306.h b/ch32_decoder/ssd1306.h deleted file mode 100644 index 4e43133..0000000 --- a/ch32_decoder/ssd1306.h +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Single-File-Header for using SPI OLED - * 05-05-2023 E. Brombaugh - */ - -#ifndef _SSD1306_H -#define _SSD1306_H - -#include -#include - -// comfortable packet size for this OLED -#define SSD1306_PSZ 32 - -// characteristics of each type -#if !defined(SSD1306_64X32) && !defined(SSD1306_128X32) && !defined(SSD1306_128X64) -#error "Please define the SSD1306_WXH resolution used in your application" -#endif - -#ifdef SSD1306_64X32 -#define SSD1306_W 64 -#define SSD1306_H 32 -#define SSD1306_FULLUSE -#define SSD1306_OFFSET 32 -#endif - -#ifdef SSD1306_128X32 -#define SSD1306_W 128 -#define SSD1306_H 32 -#define SSD1306_OFFSET 0 -#endif - -#ifdef SSD1306_128X64 -#define SSD1306_W 128 -#define SSD1306_H 64 -#define SSD1306_FULLUSE -#define SSD1306_OFFSET 0 -#endif - -/* - * send OLED command byte - */ -uint8_t ssd1306_cmd(uint8_t cmd) -{ - ssd1306_pkt_send(&cmd, 1, 1); - return 0; -} - -/* - * send OLED data packet (up to 32 bytes) - */ -uint8_t ssd1306_data(uint8_t *data, uint8_t sz) -{ - ssd1306_pkt_send(data, sz, 0); - return 0; -} - -#define SSD1306_SETCONTRAST 0x81 -#define SSD1306_SEGREMAP 0xA0 -#define SSD1306_DISPLAYALLON_RESUME 0xA4 -#define SSD1306_DISPLAYALLON 0xA5 -#define SSD1306_NORMALDISPLAY 0xA6 -#define SSD1306_INVERTDISPLAY 0xA7 -#define SSD1306_DISPLAYOFF 0xAE -#define SSD1306_DISPLAYON 0xAF -#define SSD1306_SETDISPLAYOFFSET 0xD3 -#define SSD1306_SETCOMPINS 0xDA -#define SSD1306_SETVCOMDETECT 0xDB -#define SSD1306_SETDISPLAYCLOCKDIV 0xD5 -#define SSD1306_SETPRECHARGE 0xD9 -#define SSD1306_SETMULTIPLEX 0xA8 -#define SSD1306_SETLOWCOLUMN 0x00 -#define SSD1306_SETHIGHCOLUMN 0x10 -#define SSD1306_SETSTARTLINE 0x40 -#define SSD1306_MEMORYMODE 0x20 -#define SSD1306_COLUMNADDR 0x21 -#define SSD1306_PAGEADDR 0x22 -#define SSD1306_COMSCANINC 0xC0 -#define SSD1306_COMSCANDEC 0xC8 -#define SSD1306_CHARGEPUMP 0x8D -#define SSD1306_EXTERNALVCC 0x1 -#define SSD1306_SWITCHCAPVCC 0x2 -#define SSD1306_TERMINATE_CMDS 0xFF - -/* choose VCC mode */ -#define SSD1306_EXTERNALVCC 0x1 -#define SSD1306_SWITCHCAPVCC 0x2 -// #define vccstate SSD1306_EXTERNALVCC -#define vccstate SSD1306_SWITCHCAPVCC - -// OLED initialization commands for 128x32 -const uint8_t ssd1306_init_array[] = - { - SSD1306_DISPLAYOFF, // 0xAE - SSD1306_SETDISPLAYCLOCKDIV, // 0xD5 - 0x80, // the suggested ratio 0x80 - SSD1306_SETMULTIPLEX, // 0xA8 -#ifdef SSD1306_64X32 - 0x1F, // for 64-wide displays -#else - 0x3F, // for 128-wide displays -#endif - SSD1306_SETDISPLAYOFFSET, // 0xD3 - 0x00, // no offset - SSD1306_SETSTARTLINE | 0x0, // 0x40 | line - SSD1306_CHARGEPUMP, // 0x8D - 0x14, // enable? - SSD1306_MEMORYMODE, // 0x20 - 0x00, // 0x0 act like ks0108 - SSD1306_SEGREMAP | 0x1, // 0xA0 | bit - SSD1306_COMSCANDEC, - SSD1306_SETCOMPINS, // 0xDA - 0x12, // - SSD1306_SETCONTRAST, // 0x81 - 0x8F, - SSD1306_SETPRECHARGE, // 0xd9 - 0xF1, - SSD1306_SETVCOMDETECT, // 0xDB - 0x40, - SSD1306_DISPLAYALLON_RESUME, // 0xA4 - SSD1306_NORMALDISPLAY, // 0xA6 - SSD1306_DISPLAYON, // 0xAF --turn on oled panel - SSD1306_TERMINATE_CMDS // 0xFF --fake command to mark end -}; - -// the display buffer -uint8_t ssd1306_buffer[SSD1306_W * SSD1306_H / 8]; - -/* - * set the buffer to a color - */ -void ssd1306_setbuf(uint8_t color) -{ - memset(ssd1306_buffer, color ? 0xFF : 0x00, sizeof(ssd1306_buffer)); -} - -#ifndef SSD1306_FULLUSE -/* - * expansion array for OLED with every other row unused - */ -const uint8_t expand[16] = - { - 0x00, // 0000 0000 - 0x02, // 0000 0010 - 0x08, // 0000 1000 - 0x0a, // 0000 1010 - 0x20, // 0010 0000 - 0x22, // 0010 0010 - 0x28, // 0010 1000 - 0x2a, // 0010 1010 - 0x80, // 1000 0000 - 0x82, // 1000 0010 - 0x88, // 1000 1000 - 0x8a, // 1000 1010 - 0xa0, // 1010 0000 - 0xa2, // 1010 0010 - 0xa8, // 1010 1000 - 0xaa, // 1010 1010 -}; -#endif - -/* - * Send the frame buffer - */ -void ssd1306_refresh(void) -{ - uint16_t i; - - ssd1306_cmd(SSD1306_COLUMNADDR); - ssd1306_cmd(SSD1306_OFFSET); // Column start address (0 = reset) - ssd1306_cmd(SSD1306_OFFSET + SSD1306_W - 1); // Column end address (127 = reset) - - ssd1306_cmd(SSD1306_PAGEADDR); - ssd1306_cmd(0); // Page start address (0 = reset) - ssd1306_cmd(7); // Page end address - -#ifdef SSD1306_FULLUSE - /* for fully used rows just plow thru everything */ - for (i = 0; i < sizeof(ssd1306_buffer); i += SSD1306_PSZ) - { - /* send PSZ block of data */ - ssd1306_data(&ssd1306_buffer[i], SSD1306_PSZ); - } -#else - /* for displays with odd rows unused expand bytes */ - uint8_t tbuf[SSD1306_PSZ], j, k; - for (i = 0; i < sizeof(ssd1306_buffer); i += 128) // for each page - { - /* low nybble */ - for (j = 0; j < 128; j += SSD1306_PSZ) - { - for (k = 0; k < SSD1306_PSZ; k++) - tbuf[k] = expand[ssd1306_buffer[i + j + k] & 0xf]; - - /* send PSZ block of data */ - ssd1306_data(tbuf, SSD1306_PSZ); - } - - /* high nybble */ - for (j = 0; j < 128; j += SSD1306_PSZ) - { - for (k = 0; k < SSD1306_PSZ; k++) - tbuf[k] = expand[(ssd1306_buffer[i + j + k] >> 4) & 0xf]; - - /* send PSZ block of data */ - ssd1306_data(tbuf, SSD1306_PSZ); - } - } -#endif -} - -/* - * plot a pixel in the buffer - */ -void ssd1306_drawPixel(uint8_t x, uint8_t y, uint8_t color) -{ - uint16_t addr; - - /* clip */ - if (x >= SSD1306_W) - return; - if (y >= SSD1306_H) - return; - - /* compute buffer address */ - addr = x + SSD1306_W * (y / 8); - - /* set/clear bit in buffer */ - if (color) - ssd1306_buffer[addr] |= (1 << (y & 7)); - else - ssd1306_buffer[addr] &= ~(1 << (y & 7)); -} - -/* - * plot a pixel in the buffer - */ -void ssd1306_xorPixel(uint8_t x, uint8_t y) -{ - uint16_t addr; - - /* clip */ - if (x >= SSD1306_W) - return; - if (y >= SSD1306_H) - return; - - /* compute buffer address */ - addr = x + SSD1306_W * (y / 8); - - ssd1306_buffer[addr] ^= (1 << (y & 7)); -} - -/* - * draw a an image from an array, directly into to the display buffer - * the color modes allow for overwriting and even layering (sprites!) - */ -void ssd1306_drawImage(uint8_t x, uint8_t y, const unsigned char *input, uint8_t width, uint8_t height, uint8_t color_mode) -{ - uint8_t x_absolute; - uint8_t y_absolute; - uint8_t pixel; - uint8_t bytes_to_draw = width / 8; - uint16_t buffer_addr; - - for (uint8_t line = 0; line < height; line++) - { - y_absolute = y + line; - if (y_absolute >= SSD1306_H) - { - break; - } - - // SSD1306 is in vertical mode, yet we want to draw horizontally, which necessitates assembling the output bytes from the input data - // bitmask for current pixel in vertical (output) byte - uint8_t v_mask = 1 << (y_absolute & 7); - - for (uint8_t byte = 0; byte < bytes_to_draw; byte++) - { - uint8_t input_byte = input[byte + line * bytes_to_draw]; - - for (pixel = 0; pixel < 8; pixel++) - { - x_absolute = x + 8 * (bytes_to_draw - byte) + pixel; - if (x_absolute >= SSD1306_W) - { - break; - } - // looking at the horizontal display, we're drawing bytes bottom to top, not left to right, hence y / 8 - buffer_addr = x_absolute + SSD1306_W * (y_absolute / 8); - // state of current pixel - uint8_t input_pixel = input_byte & (1 << pixel); - - switch (color_mode) - { - case 0: - // write pixels as they are - ssd1306_buffer[buffer_addr] = (ssd1306_buffer[buffer_addr] & ~v_mask) | (input_pixel ? v_mask : 0); - break; - case 1: - // write pixels after inversion - ssd1306_buffer[buffer_addr] = (ssd1306_buffer[buffer_addr] & ~v_mask) | (!input_pixel ? v_mask : 0); - break; - case 2: - // 0 clears pixel - ssd1306_buffer[buffer_addr] &= input_pixel ? 0xFF : ~v_mask; - break; - case 3: - // 1 sets pixel - ssd1306_buffer[buffer_addr] |= input_pixel ? v_mask : 0; - break; - case 4: - // 0 sets pixel - ssd1306_buffer[buffer_addr] |= !input_pixel ? v_mask : 0; - break; - case 5: - // 1 clears pixel - ssd1306_buffer[buffer_addr] &= input_pixel ? ~v_mask : 0xFF; - break; - } - } -#if SSD1306_LOG_IMAGE == 1 - printf("%02x ", input_byte); -#endif - } -#if SSD1306_LOG_IMAGE == 1 - printf("\n\r"); -#endif - } -} - -/* - * fast vert line - */ -void ssd1306_drawFastVLine(uint8_t x, uint8_t y, uint8_t h, uint8_t color) -{ - // clipping - if ((x >= SSD1306_W) || (y >= SSD1306_H)) - return; - if ((y + h - 1) >= SSD1306_H) - h = SSD1306_H - y; - while (h--) - { - ssd1306_drawPixel(x, y++, color); - } -} - -/* - * fast horiz line - */ -void ssd1306_drawFastHLine(uint8_t x, uint8_t y, uint8_t w, uint8_t color) -{ - // clipping - if ((x >= SSD1306_W) || (y >= SSD1306_H)) - return; - if ((x + w - 1) >= SSD1306_W) - w = SSD1306_W - x; - - while (w--) - { - ssd1306_drawPixel(x++, y, color); - } -} - -/* - * abs() helper function for line drawing - */ -int16_t gfx_abs(int16_t x) -{ - return (x < 0) ? -x : x; -} - -/* - * swap() helper function for line drawing - */ -void gfx_swap(uint16_t *z0, uint16_t *z1) -{ - uint16_t temp = *z0; - *z0 = *z1; - *z1 = temp; -} - -/* - * Bresenham line draw routine swiped from Wikipedia - */ -void ssd1306_drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t color) -{ - int16_t steep; - int16_t deltax, deltay, error, ystep, x, y; - - /* flip sense 45deg to keep error calc in range */ - steep = (gfx_abs(y1 - y0) > gfx_abs(x1 - x0)); - - if (steep) - { - gfx_swap(&x0, &y0); - gfx_swap(&x1, &y1); - } - - /* run low->high */ - if (x0 > x1) - { - gfx_swap(&x0, &x1); - gfx_swap(&y0, &y1); - } - - /* set up loop initial conditions */ - deltax = x1 - x0; - deltay = gfx_abs(y1 - y0); - error = deltax / 2; - y = y0; - if (y0 < y1) - ystep = 1; - else - ystep = -1; - - /* loop x */ - for (x = x0; x <= x1; x++) - { - /* plot point */ - if (steep) - /* flip point & plot */ - ssd1306_drawPixel(y, x, color); - else - /* just plot */ - ssd1306_drawPixel(x, y, color); - - /* update error */ - error = error - deltay; - - /* update y */ - if (error < 0) - { - y = y + ystep; - error = error + deltax; - } - } -} - -/* - * draws a circle - */ -void ssd1306_drawCircle(int16_t x, int16_t y, int16_t radius, int8_t color) -{ - /* Bresenham algorithm */ - int16_t x_pos = -radius; - int16_t y_pos = 0; - int16_t err = 2 - 2 * radius; - int16_t e2; - - do - { - ssd1306_drawPixel(x - x_pos, y + y_pos, color); - ssd1306_drawPixel(x + x_pos, y + y_pos, color); - ssd1306_drawPixel(x + x_pos, y - y_pos, color); - ssd1306_drawPixel(x - x_pos, y - y_pos, color); - e2 = err; - if (e2 <= y_pos) - { - err += ++y_pos * 2 + 1; - if (-x_pos == y_pos && e2 <= x_pos) - { - e2 = 0; - } - } - if (e2 > x_pos) - { - err += ++x_pos * 2 + 1; - } - } while (x_pos <= 0); -} - -/* - * draws a filled circle - */ -void ssd1306_fillCircle(int16_t x, int16_t y, int16_t radius, int8_t color) -{ - /* Bresenham algorithm */ - int16_t x_pos = -radius; - int16_t y_pos = 0; - int16_t err = 2 - 2 * radius; - int16_t e2; - - do - { - ssd1306_drawPixel(x - x_pos, y + y_pos, color); - ssd1306_drawPixel(x + x_pos, y + y_pos, color); - ssd1306_drawPixel(x + x_pos, y - y_pos, color); - ssd1306_drawPixel(x - x_pos, y - y_pos, color); - ssd1306_drawFastHLine(x + x_pos, y + y_pos, 2 * (-x_pos) + 1, color); - ssd1306_drawFastHLine(x + x_pos, y - y_pos, 2 * (-x_pos) + 1, color); - e2 = err; - if (e2 <= y_pos) - { - err += ++y_pos * 2 + 1; - if (-x_pos == y_pos && e2 <= x_pos) - { - e2 = 0; - } - } - if (e2 > x_pos) - { - err += ++x_pos * 2 + 1; - } - } while (x_pos <= 0); -} - -/* - * draw a rectangle - */ -void ssd1306_drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) -{ - ssd1306_drawFastVLine(x, y, h, color); - ssd1306_drawFastVLine(x + w - 1, y, h, color); - ssd1306_drawFastHLine(x, y, w, color); - ssd1306_drawFastHLine(x, y + h - 1, w, color); -} - -/* - * fill a rectangle - */ -void ssd1306_fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) -{ - uint8_t m, n = y, iw = w; - - /* scan vertical */ - while (h--) - { - m = x; - w = iw; - /* scan horizontal */ - while (w--) - { - /* invert pixels */ - ssd1306_drawPixel(m++, n, color); - } - n++; - } -} - -/* - * invert a rectangle in the buffer - */ -void ssd1306_xorrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h) -{ - uint8_t m, n = y, iw = w; - - /* scan vertical */ - while (h--) - { - m = x; - w = iw; - /* scan horizontal */ - while (w--) - { - /* invert pixels */ - ssd1306_xorPixel(m++, n); - } - n++; - } -} - -/* - * initialize I2C and OLED - */ -uint8_t ssd1306_init(void) -{ - // pulse reset - ssd1306_rst(); - - // initialize OLED - uint8_t *cmd_list = (uint8_t *)ssd1306_init_array; - while (*cmd_list != SSD1306_TERMINATE_CMDS) - { - if (ssd1306_cmd(*cmd_list++)) - return 1; - } - - // clear display - ssd1306_setbuf(0); - ssd1306_refresh(); - - return 0; -} - -#endif diff --git a/ch32_decoder/ssd1306_i2c.h b/ch32_decoder/ssd1306_i2c.h deleted file mode 100644 index 023157f..0000000 --- a/ch32_decoder/ssd1306_i2c.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Single-File-Header for SSD1306 I2C interface - * 05-07-2023 E. Brombaugh - */ - -#ifndef _SSD1306_I2C_H -#define _SSD1306_I2C_H - -#include - -// SSD1306 I2C address -#define SSD1306_I2C_ADDR 0x3c - -// I2C Bus clock rate - must be lower the Logic clock rate -#define SSD1306_I2C_CLKRATE 1000000 - -// I2C Logic clock rate - must be higher than Bus clock rate -#define SSD1306_I2C_PRERATE 2000000 - -// uncomment this for high-speed 36% duty cycle, otherwise 33% -#define SSD1306_I2C_DUTY - -// I2C Timeout count -#define TIMEOUT_MAX 100000 - -// uncomment this to enable IRQ-driven operation -//#define SSD1306_I2C_IRQ - -#ifdef SSD1306_I2C_IRQ -// some stuff that IRQ mode needs -volatile uint8_t ssd1306_i2c_send_buffer[64], *ssd1306_i2c_send_ptr, ssd1306_i2c_send_sz, ssd1306_i2c_irq_state; - -// uncomment this to enable time diags in IRQ -//#define IRQ_DIAG -#endif - -/* - * init just I2C - */ -void ssd1306_i2c_setup(void) -{ - uint16_t tempreg; - - // Reset I2C1 to init all regs - RCC->APB1PRSTR |= RCC_APB1Periph_I2C1; - RCC->APB1PRSTR &= ~RCC_APB1Periph_I2C1; - - // set freq - tempreg = I2C1->CTLR2; - tempreg &= ~I2C_CTLR2_FREQ; - tempreg |= (FUNCONF_SYSTEM_CORE_CLOCK/SSD1306_I2C_PRERATE)&I2C_CTLR2_FREQ; - I2C1->CTLR2 = tempreg; - - // Set clock config - tempreg = 0; -#if (SSD1306_I2C_CLKRATE <= 100000) - // standard mode good to 100kHz - tempreg = (FUNCONF_SYSTEM_CORE_CLOCK/(2*SSD1306_I2C_CLKRATE))&SSD1306_I2C_CKCFGR_CCR; -#else - // fast mode over 100kHz -#ifndef SSD1306_I2C_DUTY - // 33% duty cycle - tempreg = (FUNCONF_SYSTEM_CORE_CLOCK/(3*SSD1306_I2C_CLKRATE))&SSD1306_I2C_CKCFGR_CCR; -#else - // 36% duty cycle - tempreg = (FUNCONF_SYSTEM_CORE_CLOCK/(25*SSD1306_I2C_CLKRATE))&I2C_CKCFGR_CCR; - tempreg |= I2C_CKCFGR_DUTY; -#endif - tempreg |= I2C_CKCFGR_FS; -#endif - I2C1->CKCFGR = tempreg; - -#ifdef SSD1306_I2C_IRQ - // enable IRQ driven operation - NVIC_EnableIRQ(I2C1_EV_IRQn); - - // initialize the state - ssd1306_i2c_irq_state = 0; -#endif - - // Enable I2C - I2C1->CTLR1 |= I2C_CTLR1_PE; - - // set ACK mode - I2C1->CTLR1 |= I2C_CTLR1_ACK; -} - -/* - * error descriptions - */ -char *errstr[] = -{ - "not busy", - "master mode", - "transmit mode", - "tx empty", - "transmit complete", -}; - -/* - * error handler - */ -uint8_t ssd1306_i2c_error(uint8_t err) -{ - // report error - printf("ssd1306_i2c_error - timeout waiting for %s\n\r", errstr[err]); - - // reset & initialize I2C - ssd1306_i2c_setup(); - - return 1; -} - -// event codes we use -#define SSD1306_I2C_EVENT_MASTER_MODE_SELECT ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */ -#define SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */ -#define SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084) /* TRA, BUSY, MSL, TXE and BTF flags */ - -/* - * check for 32-bit event codes - */ -uint8_t ssd1306_i2c_chk_evt(uint32_t event_mask) -{ - /* read order matters here! STAR1 before STAR2!! */ - uint32_t status = I2C1->STAR1 | (I2C1->STAR2<<16); - return (status & event_mask) == event_mask; -} - -#ifdef SSD1306_I2C_IRQ -/* - * packet send for IRQ-driven operation - */ -uint8_t ssd1306_i2c_send(uint8_t addr, uint8_t *data, uint8_t sz) -{ - int32_t timeout; - -#ifdef IRQ_DIAG - GPIOC->BSHR = (1<<(3)); -#endif - - // error out if buffer under/overflow - if((sz > sizeof(ssd1306_i2c_send_buffer)) || !sz) - return 2; - - // wait for previous packet to finish - while(ssd1306_i2c_irq_state); - -#ifdef IRQ_DIAG - GPIOC->BSHR = (1<<(16+3)); - GPIOC->BSHR = (1<<(4)); -#endif - - // init buffer for sending - ssd1306_i2c_send_sz = sz; - ssd1306_i2c_send_ptr = ssd1306_i2c_send_buffer; - memcpy((uint8_t *)ssd1306_i2c_send_buffer, data, sz); - - // wait for not busy - timeout = TIMEOUT_MAX; - while((I2C1->STAR2 & I2C_STAR2_BUSY) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(0); - - // Set START condition - I2C1->CTLR1 |= I2C_CTLR1_START; - - // wait for master mode select - timeout = TIMEOUT_MAX; - while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_MODE_SELECT)) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(1); - - // send 7-bit address + write flag - I2C1->DATAR = addr<<1; - - // wait for transmit condition - timeout = TIMEOUT_MAX; - while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(2); - - // Enable TXE interrupt - I2C1->CTLR2 |= I2C_CTLR2_ITBUFEN | I2C_CTLR2_ITEVTEN; - ssd1306_i2c_irq_state = 1; - -#ifdef IRQ_DIAG - GPIOC->BSHR = (1<<(16+4)); -#endif - - // exit - return 0; -} - -/* - * IRQ handler for I2C events - */ -void I2C1_EV_IRQHandler(void) __attribute__((interrupt)); -void I2C1_EV_IRQHandler(void) -{ - uint16_t STAR1, STAR2 __attribute__((unused)); - -#ifdef IRQ_DIAG - GPIOC->BSHR = (1<<(4)); -#endif - - // read status, clear any events - STAR1 = I2C1->STAR1; - STAR2 = I2C1->STAR2; - - /* check for TXE */ - if(STAR1 & I2C_STAR1_TXE) - { - /* check for remaining data */ - if(ssd1306_i2c_send_sz--) - I2C1->DATAR = *ssd1306_i2c_send_ptr++; - - /* was that the last byte? */ - if(!ssd1306_i2c_send_sz) - { - // disable TXE interrupt - I2C1->CTLR2 &= ~(I2C_CTLR2_ITBUFEN | I2C_CTLR2_ITEVTEN); - - // reset IRQ state - ssd1306_i2c_irq_state = 0; - - // wait for tx complete - while(!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED)); - - // set STOP condition - I2C1->CTLR1 |= I2C_CTLR1_STOP; - } - } - -#ifdef IRQ_DIAG - GPIOC->BSHR = (1<<(16+4)); -#endif -} -#else -/* - * low-level packet send for blocking polled operation via i2c - */ -uint8_t ssd1306_i2c_send(uint8_t addr, uint8_t *data, uint8_t sz) -{ - int32_t timeout; - - // wait for not busy - timeout = TIMEOUT_MAX; - while((I2C1->STAR2 & I2C_STAR2_BUSY) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(0); - - // Set START condition - I2C1->CTLR1 |= I2C_CTLR1_START; - - // wait for master mode select - timeout = TIMEOUT_MAX; - while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_MODE_SELECT)) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(1); - - // send 7-bit address + write flag - I2C1->DATAR = addr<<1; - - // wait for transmit condition - timeout = TIMEOUT_MAX; - while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(2); - - // send data one byte at a time - while(sz--) - { - // wait for TX Empty - timeout = TIMEOUT_MAX; - while(!(I2C1->STAR1 & I2C_STAR1_TXE) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(3); - - // send command - I2C1->DATAR = *data++; - } - - // wait for tx complete - timeout = TIMEOUT_MAX; - while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && (timeout--)); - if(timeout==-1) - return ssd1306_i2c_error(4); - - // set STOP condition - I2C1->CTLR1 |= I2C_CTLR1_STOP; - - // we're happy - return 0; -} -#endif - -/* - * high-level packet send for I2C - */ -uint8_t ssd1306_pkt_send(uint8_t *data, uint8_t sz, uint8_t cmd) -{ - uint8_t pkt[33]; - - /* build command or data packets */ - if(cmd) - { - pkt[0] = 0; - pkt[1] = *data; - } - else - { - pkt[0] = 0x40; - memcpy(&pkt[1], data, sz); - } - return ssd1306_i2c_send(SSD1306_I2C_ADDR, pkt, sz+1); -} - -/* - * init I2C and GPIO - */ -uint8_t ssd1306_i2c_init(void) -{ - // Enable GPIOC and I2C - RCC->APB2PCENR |= RCC_APB2Periph_GPIOC; - RCC->APB1PCENR |= RCC_APB1Periph_I2C1; - - // PC1 is SDA, 10MHz Output, alt func, open-drain - GPIOC->CFGLR &= ~(0xf<<(4*1)); - GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF)<<(4*1); - - // PC2 is SCL, 10MHz Output, alt func, open-drain - GPIOC->CFGLR &= ~(0xf<<(4*2)); - GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF)<<(4*2); - -#ifdef IRQ_DIAG - // GPIO diags on PC3/PC4 - GPIOC->CFGLR &= ~(0xf<<(4*3)); - GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*3); - GPIOC->BSHR = (1<<(16+3)); - GPIOC->CFGLR &= ~(0xf<<(4*4)); - GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4); - GPIOC->BSHR = (1<<(16+4)); -#endif - - // load I2C regs - ssd1306_i2c_setup(); - -#if 0 - // test if SSD1306 is on the bus by sending display off command - uint8_t command = 0xAF; - return ssd1306_pkt_send(&command, 1, 1); -#else - return 0; -#endif -} - -/* - * reset is not used for SSD1306 I2C interface - */ -void ssd1306_rst(void) -{ -} -#endif diff --git a/encoder/src/main.rs b/encoder/src/main.rs index 7a381bf..c07803c 100644 --- a/encoder/src/main.rs +++ b/encoder/src/main.rs @@ -10,7 +10,7 @@ pub use util::*; const INSPECT_ENC: bool = false; const INSPECT_DEC: bool = false; -const MAX_ERROR: usize = 0; // max wrong pixels +const MAX_ERROR: usize = 4; // max wrong pixels const MAX_LOSS: usize = 16; // highest "loss" value tried for all lossy encodings const LOSSLESS_ENCODINGS: &[FrameEncoder] = &[ @@ -43,7 +43,7 @@ fn main() { last_frame = decoder(&last_frame, &encoded[reader..], &mut reader); if INSPECT_DEC { println!( - "\n{frame_type:?}, error: {}, index: {frame_index}", + "\n{frame_type:?}, error: {}", frame_error(&frames[frame_index], &last_frame) ); render_images(&frames[frame_index], &last_frame); @@ -63,12 +63,7 @@ fn main() { ); let mut export_string = String::from("// Generated by the `encoder` rust app\n"); - for (encoding, count) in stats { - if count > 0 { - export_string += &format!("#define USE_{encoding:?}\n"); - } - } - export_string += "\n\ntypedef enum Encoding {\n"; + export_string += "typedef enum {\n"; for (encoding, count) in stats { if count > 0 { export_string += &format!("\tEncoding_{encoding:?} = {},\n", encoding as u8); @@ -86,7 +81,7 @@ fn main() { export_string += &format!("{byte},"); } export_string += "\n};\n"; - let mut file = File::create("../ch32_decoder/data.h").unwrap(); + let mut file = File::create("../data.h").unwrap(); file.write_all(export_string.as_bytes()).unwrap(); } @@ -122,7 +117,7 @@ fn encode(frames: &[Frame]) -> Vec { // render_images(&frame, &decoded); // panic!("error in 'loss 0' compression"); // } - if error <= MAX_ERROR { + if error < MAX_ERROR { options.push(encoded); } else { // higher loss value will mean more error so can be skipped