From bb222a7b1cfe875a7d168d0b8c72406c928237f7 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 30 Jan 2026 18:52:55 +0100 Subject: [PATCH 01/38] RM690B0 driver for Waveshare ESP32-S3 AMOLED 2.41" --- lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h | 72 + lib/esp_jpeg/src/esp_jpeg.c | 243 ++ locale/circuitpython.pot | 248 ++ ports/espressif/Makefile | 20 + ports/espressif/bindings/espsdcard/SDCard.c | 336 ++ ports/espressif/bindings/espsdcard/SDCard.h | 12 + ports/espressif/bindings/espsdcard/__init__.c | 103 + ports/espressif/bindings/espsdcard/__init__.h | 7 + .../waveshare_esp32_s3_amoled_241/board.c | 8 + .../mpconfigboard.h | 47 + .../mpconfigboard.mk | 93 + .../waveshare_esp32_s3_amoled_241/pins.c | 106 + .../waveshare_esp32_s3_amoled_241/sdkconfig | 33 + ports/espressif/common-hal/espsdcard/SDCard.c | 287 ++ ports/espressif/common-hal/espsdcard/SDCard.h | 55 + ports/espressif/common-hal/rm690b0/RM690B0.c | 3659 +++++++++++++++++ ports/espressif/common-hal/rm690b0/RM690B0.h | 26 + .../common-hal/rm690b0/esp_lcd_rm690b0.c | 341 ++ .../common-hal/rm690b0/esp_lcd_rm690b0.h | 109 + .../rm690b0/fonts/rm690b0_font_16x16.h | 494 +++ .../rm690b0/fonts/rm690b0_font_16x24.h | 589 +++ .../rm690b0/fonts/rm690b0_font_24x24.h | 779 ++++ .../rm690b0/fonts/rm690b0_font_24x32.h | 874 ++++ .../rm690b0/fonts/rm690b0_font_32x32.h | 1064 +++++ .../rm690b0/fonts/rm690b0_font_32x48.h | 1444 +++++++ .../rm690b0/fonts/rm690b0_font_8x8.h | 205 + py/circuitpy_defns.mk | 11 + py/circuitpy_mpconfig.h | 5 + py/circuitpy_mpconfig.mk | 6 + shared-bindings/rm690b0/RM690B0.c | 481 +++ shared-bindings/rm690b0/RM690B0.h | 49 + shared-bindings/rm690b0/__init__.c | 231 ++ shared-bindings/rm690b0/image_converter.c | 529 +++ shared-bindings/rm690b0/image_converter.h | 164 + 34 files changed, 12730 insertions(+) create mode 100644 lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h create mode 100644 lib/esp_jpeg/src/esp_jpeg.c create mode 100644 ports/espressif/bindings/espsdcard/SDCard.c create mode 100644 ports/espressif/bindings/espsdcard/SDCard.h create mode 100644 ports/espressif/bindings/espsdcard/__init__.c create mode 100644 ports/espressif/bindings/espsdcard/__init__.h create mode 100644 ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c create mode 100644 ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h create mode 100644 ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk create mode 100644 ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c create mode 100644 ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig create mode 100644 ports/espressif/common-hal/espsdcard/SDCard.c create mode 100644 ports/espressif/common-hal/espsdcard/SDCard.h create mode 100644 ports/espressif/common-hal/rm690b0/RM690B0.c create mode 100644 ports/espressif/common-hal/rm690b0/RM690B0.h create mode 100644 ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c create mode 100644 ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x16.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h create mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h create mode 100644 shared-bindings/rm690b0/RM690B0.c create mode 100644 shared-bindings/rm690b0/RM690B0.h create mode 100644 shared-bindings/rm690b0/__init__.c create mode 100644 shared-bindings/rm690b0/image_converter.c create mode 100644 shared-bindings/rm690b0/image_converter.h diff --git a/lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h b/lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h new file mode 100644 index 0000000000000..98ba5195f1079 --- /dev/null +++ b/lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT +// +// Minimal esp_jpeg interface used by the RM690B0 driver. +// Provides a drop-in replacement for the ESP-IDF component by wrapping TJpgDec. + +#pragma once + +#include +#include +#include + +#if defined(ESP_PLATFORM) +#include "esp_err.h" +#else +typedef int32_t esp_err_t; +#define ESP_OK 0 +#define ESP_FAIL -1 +#define ESP_ERR_INVALID_ARG 0x102 +#define ESP_ERR_NO_MEM 0x103 +#define ESP_ERR_NOT_SUPPORTED 0x105 +#define ESP_ERR_INVALID_SIZE 0x10B +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + JPEG_IMAGE_FORMAT_RGB565 = 0, + JPEG_IMAGE_FORMAT_RGB888 = 1, + JPEG_IMAGE_FORMAT_GRAYSCALE = 2, +} esp_jpeg_image_format_t; + +typedef enum { + JPEG_IMAGE_SCALE_0 = 0, +} esp_jpeg_image_scale_t; + +typedef struct { + bool swap_color_bytes : 1; + bool use_scaler : 1; +} esp_jpeg_flags_t; + +typedef struct { + const uint8_t *indata; + size_t indata_size; + uint8_t *outbuf; + size_t outbuf_size; + esp_jpeg_image_format_t out_format; + esp_jpeg_image_scale_t out_scale; + esp_jpeg_flags_t flags; + intptr_t user_data; + esp_err_t (*on_block)(intptr_t ctx, + uint32_t top, uint32_t left, + uint32_t bottom, uint32_t right, + const uint16_t *pixels); +} esp_jpeg_image_cfg_t; + +typedef struct { + uint32_t width; + uint32_t height; + uint8_t *outbuf; + size_t outbuf_size; +} esp_jpeg_image_output_t; + +esp_err_t esp_jpeg_get_image_info(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out); +esp_err_t esp_jpeg_decode(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out); + +#ifdef __cplusplus +} +#endif diff --git a/lib/esp_jpeg/src/esp_jpeg.c b/lib/esp_jpeg/src/esp_jpeg.c new file mode 100644 index 0000000000000..07ff497ed97c6 --- /dev/null +++ b/lib/esp_jpeg/src/esp_jpeg.c @@ -0,0 +1,243 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT +// +// Minimal esp_jpeg implementation backed by TJpgDec. + +#include "esp_jpeg/esp_jpeg.h" + +#include +#include + +#include "tjpgd.h" + +#if defined(ESP_PLATFORM) +#include "esp_heap_caps.h" +#endif + +#define ESP_JPEG_TJPGD_WORK_BUFFER_SIZE 4096 +#define ESP_JPEG_MAX_BLOCK_PIXELS 256 + +typedef struct { + uint8_t *rgb565_buffer; + uint32_t width; + const uint8_t *jpg_data; + size_t jpg_size; + size_t jpg_offset; + bool swap_bytes; + intptr_t user_data; + esp_err_t (*on_block)(intptr_t, + uint32_t, uint32_t, + uint32_t, uint32_t, + const uint16_t *); + esp_err_t last_error; +} esp_jpeg_tjpgd_ctx_t; + +static void *esp_jpeg_alloc(size_t size) { +#if defined(ESP_PLATFORM) + void *ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!ptr) { + ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + } + return ptr; +#else + return malloc(size); +#endif +} + +static void esp_jpeg_free(void *ptr) { +#if defined(ESP_PLATFORM) + heap_caps_free(ptr); +#else + free(ptr); +#endif +} + +static size_t esp_jpeg_input(JDEC *jd, uint8_t *buff, size_t ndata) { + esp_jpeg_tjpgd_ctx_t *ctx = (esp_jpeg_tjpgd_ctx_t *)jd->device; + + if (!buff) { + size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; + size_t bytes_to_skip = ndata; + if (bytes_to_skip > bytes_available) { + bytes_to_skip = bytes_available; + } + ctx->jpg_offset += bytes_to_skip; + return bytes_to_skip; + } + + size_t bytes_to_read = ndata; + size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; + if (bytes_to_read > bytes_available) { + bytes_to_read = bytes_available; + } + + if (bytes_to_read > 0) { + memcpy(buff, ctx->jpg_data + ctx->jpg_offset, bytes_to_read); + ctx->jpg_offset += bytes_to_read; + } + + return bytes_to_read; +} + +static int esp_jpeg_output(JDEC *jd, void *bitmap, JRECT *rect) { + esp_jpeg_tjpgd_ctx_t *ctx = (esp_jpeg_tjpgd_ctx_t *)jd->device; + + if (ctx->rgb565_buffer != NULL) { + uint8_t *src = (uint8_t *)bitmap; + for (int y = rect->top; y <= rect->bottom; y++) { + uint32_t row_base = (uint32_t)y * ctx->width; + for (int x = rect->left; x <= rect->right; x++) { + uint16_t rgb565 = ((uint16_t)src[0] << 8) | src[1]; + src += 2; + uint32_t offset = (row_base + x) * 2; + if (ctx->swap_bytes) { + ctx->rgb565_buffer[offset] = (rgb565 >> 8) & 0xFF; + ctx->rgb565_buffer[offset + 1] = rgb565 & 0xFF; + } else { + ctx->rgb565_buffer[offset] = rgb565 & 0xFF; + ctx->rgb565_buffer[offset + 1] = (rgb565 >> 8) & 0xFF; + } + } + } + } else if (ctx->on_block != NULL) { + uint32_t width = (uint32_t)rect->right - (uint32_t)rect->left + 1; + uint32_t height = (uint32_t)rect->bottom - (uint32_t)rect->top + 1; + uint32_t total = width * height; + if (total == 0 || total > ESP_JPEG_MAX_BLOCK_PIXELS) { + ctx->last_error = ESP_ERR_INVALID_SIZE; + return 0; + } + + uint16_t block_pixels[ESP_JPEG_MAX_BLOCK_PIXELS]; + const uint8_t *block_src = (const uint8_t *)bitmap; + for (uint32_t i = 0; i < total; i++) { + uint16_t rgb565 = ((uint16_t)block_src[0] << 8) | block_src[1]; + block_src += 2; + if (ctx->swap_bytes) { + rgb565 = (uint16_t)((rgb565 << 8) | (rgb565 >> 8)); + } + block_pixels[i] = rgb565; + } + + esp_err_t cb = ctx->on_block(ctx->user_data, + (uint32_t)rect->top, + (uint32_t)rect->left, + (uint32_t)rect->bottom, + (uint32_t)rect->right, + block_pixels); + if (cb != ESP_OK) { + ctx->last_error = cb; + return 0; + } + } else { + return 0; + } + + return 1; +} + +static esp_err_t esp_jpeg_prepare_decoder(const esp_jpeg_image_cfg_t *cfg, JDEC *out_dec, esp_jpeg_tjpgd_ctx_t *ctx, void **work_buffer) { + if (cfg == NULL || cfg->indata == NULL || cfg->indata_size == 0) { + return ESP_ERR_INVALID_ARG; + } + + if (cfg->out_scale != JPEG_IMAGE_SCALE_0) { + return ESP_ERR_NOT_SUPPORTED; + } + + void *work = esp_jpeg_alloc(ESP_JPEG_TJPGD_WORK_BUFFER_SIZE); + if (!work) { + return ESP_ERR_NO_MEM; + } + + ctx->rgb565_buffer = NULL; + ctx->width = 0; + ctx->jpg_data = cfg->indata; + ctx->jpg_size = cfg->indata_size; + ctx->jpg_offset = 0; + ctx->swap_bytes = cfg->flags.swap_color_bytes; + ctx->user_data = cfg->user_data; + ctx->on_block = cfg->on_block; + ctx->last_error = ESP_OK; + + JRESULT res = jd_prepare(out_dec, esp_jpeg_input, work, ESP_JPEG_TJPGD_WORK_BUFFER_SIZE, ctx); + if (res != JDR_OK) { + esp_jpeg_free(work); + return ESP_ERR_INVALID_ARG; + } + + if (out_dec->width == 0 || out_dec->height == 0) { + esp_jpeg_free(work); + return ESP_ERR_INVALID_ARG; + } + + *work_buffer = work; + return ESP_OK; +} + +esp_err_t esp_jpeg_get_image_info(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out) { + if (out == NULL) { + return ESP_ERR_INVALID_ARG; + } + + JDEC jdec; + esp_jpeg_tjpgd_ctx_t ctx; + void *work = NULL; + + esp_err_t err = esp_jpeg_prepare_decoder(cfg, &jdec, &ctx, &work); + if (err != ESP_OK) { + return err; + } + + out->width = jdec.width; + out->height = jdec.height; + out->outbuf = NULL; + out->outbuf_size = (size_t)jdec.width * jdec.height * 2; + + esp_jpeg_free(work); + return ESP_OK; +} + +esp_err_t esp_jpeg_decode(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out) { + if (cfg == NULL || (cfg->outbuf == NULL && cfg->on_block == NULL)) { + return ESP_ERR_INVALID_ARG; + } + if (cfg->out_format != JPEG_IMAGE_FORMAT_RGB565) { + return ESP_ERR_NOT_SUPPORTED; + } + + JDEC jdec; + esp_jpeg_tjpgd_ctx_t ctx; + void *work = NULL; + + esp_err_t err = esp_jpeg_prepare_decoder(cfg, &jdec, &ctx, &work); + if (err != ESP_OK) { + return err; + } + + size_t required_size = (size_t)jdec.width * jdec.height * 2; + if (cfg->outbuf != NULL && cfg->outbuf_size < required_size) { + esp_jpeg_free(work); + return ESP_ERR_NO_MEM; + } + + ctx.rgb565_buffer = cfg->outbuf; + ctx.width = jdec.width; + + JRESULT res = jd_decomp(&jdec, esp_jpeg_output, 0); + esp_jpeg_free(work); + + if (res != JDR_OK) { + return (ctx.last_error != ESP_OK) ? ctx.last_error : ESP_FAIL; + } + + if (out) { + out->width = jdec.width; + out->height = jdec.height; + out->outbuf = cfg->outbuf; + out->outbuf_size = (cfg->outbuf != NULL) ? required_size : 0; + } + + return ESP_OK; +} diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 1e167c30353dd..26f89e5bf8c6c 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -635,6 +635,15 @@ msgid "" "disable.\n" msgstr "" +#: shared-bindings/rm690b0/__init__.c +#, c-format +msgid "BMP conversion failed (%s)" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "BMP data too small" +msgstr "" + #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" msgstr "" @@ -648,6 +657,14 @@ msgstr "" msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Bitmap data too small for width * height" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Bitmap dimensions too large (max ~32767x32767 on 32-bit systems)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Bitmap size and bits per value must match" msgstr "" @@ -661,6 +678,10 @@ msgstr "" msgid "Both RX and TX required for flow control" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Brightness must be between 0.0 and 1.0" +msgstr "" + #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" @@ -693,6 +714,10 @@ msgstr "" msgid "Buffer must be a multiple of %d bytes" msgstr "" +#: ports/espressif/common-hal/espsdcard/SDCard.c +msgid "Buffer must be multiple of 512 bytes" +msgstr "" + #: shared-bindings/_bleio/PacketBuffer.c #, c-format msgid "Buffer too short by %d bytes" @@ -838,6 +863,10 @@ msgstr "" msgid "Clock unit in use" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Compressed BMP not supported" +msgstr "" + #: shared-bindings/_bleio/Connection.c msgid "" "Connection has been disconnected and can no longer be used. Create a new " @@ -889,6 +918,10 @@ msgstr "" msgid "DAC already in use" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "DMA transfer timed out - hardware requires reset" +msgstr "" + #: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c #: ports/nordic/common-hal/paralleldisplaybus/ParallelBus.c msgid "Data 0 pin must be byte aligned" @@ -924,11 +957,24 @@ msgstr "" msgid "Device in use" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Display initialization failed: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Display initialization failed: Out of memory" +msgstr "" + #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Display must have a 16 bit colorspace." msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Display not initialized. Call init_display() first" +msgstr "" + #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -1007,6 +1053,10 @@ msgstr "" msgid "Failed to allocate Wifi memory" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Failed to allocate memory for circle" +msgstr "" + #: ports/espressif/common-hal/wifi/ScannedNetworks.c msgid "Failed to allocate wifi scan memory" msgstr "" @@ -1015,6 +1065,11 @@ msgstr "" msgid "Failed to buffer the sample" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to clear display: %s" +msgstr "" + #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" @@ -1024,6 +1079,14 @@ msgstr "" msgid "Failed to connect: timeout" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Failed to create DMA semaphore" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Failed to create RM690B0 panel" +msgstr "" + #: ports/espressif/common-hal/audioio/AudioOut.c msgid "Failed to create continuous channels: invalid arg" msgstr "" @@ -1040,14 +1103,68 @@ msgstr "" msgid "Failed to create continuous channels: not found" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Failed to create panel I/O" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw BMP: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw JPEG: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw bitmap: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw circle: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw fill_circle: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw fill_rect: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to draw pixel: %s" +msgstr "" + #: ports/espressif/common-hal/audioio/AudioOut.c msgid "Failed to enable continuous" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to initialize SPI bus: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to latch brightness: %s" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to refresh display: %s (0x%x)" +msgstr "" + #: ports/espressif/common-hal/audioio/AudioOut.c msgid "Failed to register continuous events callback" msgstr "" @@ -1057,6 +1174,11 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to select brightness page: %s" +msgstr "" + #: ports/analog/common-hal/busio/SPI.c msgid "Failed to set SPI Clock Mode" msgstr "" @@ -1069,6 +1191,11 @@ msgstr "" msgid "Failed to start async audio" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "Failed to write brightness: %s" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "" @@ -1304,10 +1431,32 @@ msgstr "" msgid "Invalid BLE parameter" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Invalid BMP data offset" +msgstr "" + +#: shared-bindings/rm690b0/__init__.c +#, c-format +msgid "Invalid BMP format (%s)" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Invalid BMP header" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "Invalid BSSID" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Invalid JPEG data" +msgstr "" + +#: shared-bindings/rm690b0/__init__.c +#, c-format +msgid "Invalid JPEG format (%s)" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "Invalid MAC address" msgstr "" @@ -1334,6 +1483,10 @@ msgstr "" msgid "Invalid data_pins[%d]" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Invalid display handle" +msgstr "" + #: shared-module/msgpack/__init__.c msgid "Invalid format" msgstr "" @@ -1369,6 +1522,19 @@ msgstr "" msgid "Invalid unicode escape" msgstr "" +#: shared-bindings/rm690b0/__init__.c +#, c-format +msgid "JPEG conversion failed (%s)" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "JPEG decode failed" +msgstr "" + +#: shared-bindings/rm690b0/__init__.c +msgid "JPEG support not compiled in" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" msgstr "" @@ -1582,6 +1748,10 @@ msgstr "" msgid "No long integer support" msgstr "" +#: ports/espressif/common-hal/espsdcard/SDCard.c +msgid "No memory for SD card structure" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "No network with that ssid" msgstr "" @@ -1671,6 +1841,10 @@ msgstr "" msgid "Ok" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Only 16-bit and 24-bit BMP supported" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c #, c-format @@ -1938,6 +2112,11 @@ msgstr "" msgid "Random number generation error" msgstr "" +#: ports/espressif/common-hal/espsdcard/SDCard.c +#, c-format +msgid "Read failed: %d" +msgstr "" + #: shared-bindings/_bleio/__init__.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c shared-module/bitmaptools/__init__.c @@ -1981,6 +2160,10 @@ msgstr "" msgid "Right format but not supported" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Rotation must be 0, 90, 180, or 270" +msgstr "" + #: main.c msgid "Running in safe mode! Not running saved code.\n" msgstr "" @@ -1989,6 +2172,28 @@ msgstr "" msgid "SD card CSD format not supported" msgstr "" +#: ports/espressif/common-hal/espsdcard/SDCard.c +#, c-format +msgid "SD card init failed: %d" +msgstr "" + +#: ports/espressif/common-hal/espsdcard/SDCard.c +msgid "SD card not found" +msgstr "" + +#: ports/espressif/common-hal/espsdcard/SDCard.c +msgid "SD card not mounted" +msgstr "" + +#: ports/espressif/common-hal/espsdcard/SDCard.c +msgid "SD card not responding" +msgstr "" + +#: ports/espressif/common-hal/espsdcard/SDCard.c +#, c-format +msgid "SD host init failed: %d" +msgstr "" + #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "SDCard init" msgstr "" @@ -2004,6 +2209,11 @@ msgstr "" msgid "SDIO Init Error %x" msgstr "" +#: ports/espressif/common-hal/espsdcard/SDCard.c +#, c-format +msgid "SPI bus init failed: %d" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" msgstr "" @@ -2383,6 +2593,10 @@ msgstr "" msgid "Unsupported hash algorithm" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "Unsupported rotation" +msgstr "" + #: ports/espressif/common-hal/socketpool/Socket.c #: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" @@ -2445,6 +2659,11 @@ msgstr "" msgid "Woken up by alarm.\n" msgstr "" +#: ports/espressif/common-hal/espsdcard/SDCard.c +#, c-format +msgid "Write failed: %d" +msgstr "" + #: ports/espressif/common-hal/_bleio/PacketBuffer.c #: ports/nordic/common-hal/_bleio/PacketBuffer.c msgid "Writes not supported on Characteristic" @@ -3017,6 +3236,18 @@ msgstr "" msgid "cross is defined for 1D arrays of length 3" msgstr "" +#: ports/espressif/bindings/espsdcard/SDCard.c +msgid "cs pin required" +msgstr "" + +#: ports/espressif/bindings/espsdcard/SDCard.c +msgid "cs pin required when using busio.SPI" +msgstr "" + +#: ports/espressif/bindings/espsdcard/SDCard.c +msgid "cs, miso, mosi, and clk pins required" +msgstr "" + #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be iterable" msgstr "" @@ -3174,6 +3405,15 @@ msgstr "" msgid "file write is not available" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +#, c-format +msgid "fill_color failed: %s" +msgstr "" + +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "fill_color: unable to allocate DMA buffer" +msgstr "" + #: shared-bindings/storage/__init__.c msgid "filesystem must provide mount method" msgstr "" @@ -3653,6 +3893,10 @@ msgstr "" msgid "memoryview: length is not a multiple of itemsize" msgstr "" +#: ports/espressif/bindings/espsdcard/SDCard.c +msgid "miso, mosi, and clk pins required" +msgstr "" + #: extmod/modtime.c msgid "mktime needs a tuple of length 8 or 9" msgstr "" @@ -4081,6 +4325,10 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" +#: ports/espressif/common-hal/rm690b0/RM690B0.c +msgid "radius must be non-negative" +msgstr "" + #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index a063101991fdb..42703e95cc924 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -503,6 +503,17 @@ SRC_ESPNOW := \ SRC_C += $(SRC_ESPNOW) endif +ifneq ($(CIRCUITPY_ESPSDCARD),0) +SRC_ESPSDCARD := \ + $(wildcard common-hal/espsdcard/*.c) \ + $(wildcard bindings/espsdcard/*.c) +SRC_C += $(SRC_ESPSDCARD) +INC += -isystem esp-idf/components/sdmmc/include +INC += -isystem esp-idf/components/esp_driver_sdmmc/include +INC += -isystem esp-idf/components/esp_driver_sdspi/include +INC += -isystem esp-idf/components/driver/spi/include +endif + ifneq ($(CIRCUITPY_ESPULP),0) SRC_ULP := \ $(wildcard common-hal/espulp/*.c) \ @@ -510,6 +521,12 @@ SRC_ULP := \ SRC_C += $(SRC_ULP) endif +ifneq ($(CIRCUITPY_RM690B0),0) +SRC_RM690B0 := \ + $(wildcard common-hal/rm690b0/*.c) +SRC_C += $(SRC_RM690B0) +endif + ifneq ($(CIRCUITPY_NEOPIXEL_WRITE),0) CHIP_COMPONENTS += esp_driver_rmt endif @@ -729,6 +746,9 @@ ifneq ($(CIRCUITPY_SDIOIO),0) ESP_IDF_COMPONENTS_LINK += sdmmc esp_driver_sdmmc endif +# Add any board-specific extra components +ESP_IDF_COMPONENTS_LINK += $(ESP_IDF_EXTRA_COMPONENTS) + ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a) MBEDTLS_COMPONENTS_LINK = crypto tls x509 diff --git a/ports/espressif/bindings/espsdcard/SDCard.c b/ports/espressif/bindings/espsdcard/SDCard.c new file mode 100644 index 0000000000000..df7a53503fe2d --- /dev/null +++ b/ports/espressif/bindings/espsdcard/SDCard.c @@ -0,0 +1,336 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/objproperty.h" + +#include "bindings/espsdcard/SDCard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "shared-bindings/busio/SPI.h" +#include "common-hal/busio/SPI.h" + +//| class SDCard: +//| """ESP32-native SD card interface using ESP-IDF drivers +//| +//| This module is API-compatible with sdcardio for easy migration! +//| +//| You can use either pattern: +//| +//| Pattern 1 (sdcardio-compatible):: +//| +//| import busio +//| import espsdcard as sdcardio +//| spi = busio.SPI(board.SD_CLK, MOSI=board.SD_MOSI, MISO=board.SD_MISO) +//| sd = sdcardio.SDCard(spi, board.SD_CS) +//| +//| Pattern 2 (espsdcard native):: +//| +//| import espsdcard +//| sd = espsdcard.SDCard(cs=board.SD_CS, miso=board.SD_MISO, +//| mosi=board.SD_MOSI, clk=board.SD_CLK) +//| """ +//| +//| def __init__( +//| self, +//| spi_or_cs: Union[busio.SPI, microcontroller.Pin], +//| cs: Optional[microcontroller.Pin] = None, +//| *, +//| miso: Optional[microcontroller.Pin] = None, +//| mosi: Optional[microcontroller.Pin] = None, +//| clk: Optional[microcontroller.Pin] = None, +//| baudrate: int = 4000000, +//| spi_host: int = 2, +//| max_transfer_size: int = 4000, +//| allocation_unit_size: int = 16384, +//| max_files: int = 5, +//| format_if_mount_failed: bool = False, +//| dma_channel: int = -1 +//| ) -> None: +//| """Initialize SD card with ESP-IDF drivers +//| +//| :param spi_or_cs: Either a busio.SPI object (Pattern 1) or CS pin (Pattern 2) +//| :param cs: CS pin (required for Pattern 1 with busio.SPI) +//| :param miso: MISO pin (required for Pattern 2) +//| :param mosi: MOSI pin (required for Pattern 2) +//| :param clk: Clock pin (required for Pattern 2) +//| :param baudrate: SPI frequency in Hz (currently unused, ESP-IDF manages speed) +//| :param spi_host: SPI host (1=SPI2_HOST, 2=SPI3_HOST) +//| :param max_transfer_size: Maximum DMA transfer size in bytes (default 4000) +//| :param allocation_unit_size: FAT allocation unit size (default 16384) +//| :param max_files: Maximum number of open files (default 5) +//| :param format_if_mount_failed: Auto-format card if mount fails (default False) +//| :param dma_channel: DMA channel (-1 for automatic) +//| """ +//| ... +//| + +static mp_obj_t espsdcard_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { + ARG_spi_or_cs, ARG_cs, + ARG_miso, ARG_mosi, ARG_clk, + ARG_baudrate, ARG_spi_host, ARG_max_transfer_size, ARG_allocation_unit_size, + ARG_max_files, ARG_format_if_mount_failed, ARG_dma_channel + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_spi_or_cs, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4000000} }, + { MP_QSTR_spi_host, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_max_transfer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4000} }, + { MP_QSTR_allocation_unit_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16384} }, + { MP_QSTR_max_files, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_format_if_mount_failed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_dma_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + 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); + + // Detect API pattern and extract pins + const mcu_pin_obj_t *cs_pin; + const mcu_pin_obj_t *miso_pin; + const mcu_pin_obj_t *mosi_pin; + const mcu_pin_obj_t *clk_pin; + + // Check if first argument is a busio.SPI object (sdcardio compatibility) + if (args[ARG_spi_or_cs].u_obj != mp_const_none && + mp_obj_is_type(args[ARG_spi_or_cs].u_obj, &busio_spi_type)) { + // Pattern 1: sdcardio-compatible (spi, cs) + busio_spi_obj_t *spi = MP_OBJ_TO_PTR(args[ARG_spi_or_cs].u_obj); + + // CS must be provided as second argument + if (args[ARG_cs].u_obj == mp_const_none) { + mp_raise_TypeError(MP_ERROR_TEXT("cs pin required when using busio.SPI")); + } + cs_pin = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + + // Extract pins from SPI object + clk_pin = spi->clock; + mosi_pin = spi->MOSI; + miso_pin = spi->MISO; + + // Deinit the user's SPI (we're taking over the bus) + common_hal_busio_spi_deinit(spi); + + } else if (args[ARG_spi_or_cs].u_obj != mp_const_none) { + // Pattern 2a: espsdcard native with positional cs (cs_pin, miso=, mosi=, clk=) + cs_pin = validate_obj_is_free_pin(args[ARG_spi_or_cs].u_obj, MP_QSTR_spi_or_cs); + + // miso, mosi, clk must be provided + if (args[ARG_miso].u_obj == mp_const_none || + args[ARG_mosi].u_obj == mp_const_none || + args[ARG_clk].u_obj == mp_const_none) { + mp_raise_TypeError(MP_ERROR_TEXT("miso, mosi, and clk pins required")); + } + + miso_pin = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso); + mosi_pin = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); + clk_pin = validate_obj_is_free_pin(args[ARG_clk].u_obj, MP_QSTR_clk); + + } else { + // Pattern 2b: espsdcard native with keyword-only (cs=, miso=, mosi=, clk=) + if (args[ARG_cs].u_obj == mp_const_none) { + mp_raise_TypeError(MP_ERROR_TEXT("cs pin required")); + } + if (args[ARG_miso].u_obj == mp_const_none || + args[ARG_mosi].u_obj == mp_const_none || + args[ARG_clk].u_obj == mp_const_none) { + mp_raise_TypeError(MP_ERROR_TEXT("cs, miso, mosi, and clk pins required")); + } + + cs_pin = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + miso_pin = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso); + mosi_pin = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); + clk_pin = validate_obj_is_free_pin(args[ARG_clk].u_obj, MP_QSTR_clk); + } + + // Create object + espsdcard_sdcard_obj_t *self = mp_obj_malloc(espsdcard_sdcard_obj_t, &espsdcard_sdcard_type); + + // Initialize with ESP-IDF (same for both patterns) + common_hal_espsdcard_sdcard_construct( + self, + cs_pin, miso_pin, mosi_pin, clk_pin, + args[ARG_spi_host].u_int, + args[ARG_max_transfer_size].u_int, + args[ARG_allocation_unit_size].u_int, + args[ARG_max_files].u_int, + args[ARG_format_if_mount_failed].u_bool, + args[ARG_dma_channel].u_int + ); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialize the SD card and free resources""" +//| ... +//| +static mp_obj_t espsdcard_sdcard_deinit(mp_obj_t self_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_espsdcard_sdcard_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_deinit_obj, espsdcard_sdcard_deinit); + +//| def __enter__(self) -> SDCard: +//| """Context manager entry""" +//| ... +//| +static mp_obj_t espsdcard_sdcard___enter__(mp_obj_t self_in) { + return self_in; +} +static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard___enter___obj, espsdcard_sdcard___enter__); + +//| def __exit__(self) -> None: +//| """Context manager exit""" +//| ... +//| +static mp_obj_t espsdcard_sdcard___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_espsdcard_sdcard_deinit(args[0]); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espsdcard_sdcard___exit___obj, 4, 4, espsdcard_sdcard___exit__); + +//| def is_present(self) -> bool: +//| """Check if card is present and responding""" +//| ... +//| +static mp_obj_t espsdcard_sdcard_is_present(mp_obj_t self_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_espsdcard_sdcard_is_present(self)); +} +static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_is_present_obj, espsdcard_sdcard_is_present); + +//| def get_status(self) -> int: +//| """Get card status (0=OK, 1=ERROR, 2=NOT_PRESENT)""" +//| ... +//| +static mp_obj_t espsdcard_sdcard_get_status(mp_obj_t self_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(common_hal_espsdcard_sdcard_get_status(self)); +} +static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_status_obj, espsdcard_sdcard_get_status); + +//| capacity_mb: float +//| """Card capacity in megabytes""" +static mp_obj_t espsdcard_sdcard_get_capacity_mb(mp_obj_t self_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_float(common_hal_espsdcard_sdcard_get_capacity_mb(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_capacity_mb_obj, espsdcard_sdcard_get_capacity_mb); + +MP_PROPERTY_GETTER(espsdcard_sdcard_capacity_mb_obj, + (mp_obj_t)&espsdcard_sdcard_get_capacity_mb_obj); + +//| card_type: str +//| """Card type ('SD', 'SDHC/SDXC', or 'Unknown')""" +static mp_obj_t espsdcard_sdcard_get_card_type(mp_obj_t self_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_espsdcard_sdcard_get_card_type(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_card_type_obj, espsdcard_sdcard_get_card_type); + +MP_PROPERTY_GETTER(espsdcard_sdcard_card_type_obj, + (mp_obj_t)&espsdcard_sdcard_get_card_type_obj); + +//| count: int +//| """Number of 512-byte blocks (required by storage.VfsFat)""" +static mp_obj_t espsdcard_sdcard_get_count(mp_obj_t self_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(common_hal_espsdcard_sdcard_get_count(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_count_obj, espsdcard_sdcard_get_count); + +MP_PROPERTY_GETTER(espsdcard_sdcard_count_obj, + (mp_obj_t)&espsdcard_sdcard_get_count_obj); + +//| def readblocks(self, block_num: int, buf: WriteableBuffer) -> None: +//| """Read blocks from SD card (required by storage.VfsFat)""" +//| ... +//| +static mp_obj_t espsdcard_sdcard_readblocks(mp_obj_t self_in, mp_obj_t block_num_in, mp_obj_t buf_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint32_t block_num = mp_obj_get_int(block_num_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + common_hal_espsdcard_sdcard_readblocks(self, block_num, &bufinfo); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_3(espsdcard_sdcard_readblocks_obj, espsdcard_sdcard_readblocks); + +//| def writeblocks(self, block_num: int, buf: ReadableBuffer) -> None: +//| """Write blocks to SD card (required by storage.VfsFat)""" +//| ... +//| +static mp_obj_t espsdcard_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t block_num_in, mp_obj_t buf_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint32_t block_num = mp_obj_get_int(block_num_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + common_hal_espsdcard_sdcard_writeblocks(self, block_num, &bufinfo); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_3(espsdcard_sdcard_writeblocks_obj, espsdcard_sdcard_writeblocks); + +//| def ioctl(self, op: int, arg: int) -> Optional[int]: +//| """Control operations (required by storage.VfsFat)""" +//| ... +//| +static mp_obj_t espsdcard_sdcard_ioctl(mp_obj_t self_in, mp_obj_t op_in, mp_obj_t arg_in) { + espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t op = mp_obj_get_int(op_in); + + switch (op) { + case 1: // BP_IOCTL_INIT + return mp_const_none; + case 2: // BP_IOCTL_DEINIT + common_hal_espsdcard_sdcard_deinit(self); + return mp_const_none; + case 3: // BP_IOCTL_SYNC + return mp_obj_new_int(common_hal_espsdcard_sdcard_writeblocks_sync(self)); + case 4: // BP_IOCTL_SEC_COUNT + return mp_obj_new_int_from_uint(common_hal_espsdcard_sdcard_get_count(self)); + case 5: // BP_IOCTL_SEC_SIZE + return mp_obj_new_int(512); + default: + return mp_const_none; + } +} +static MP_DEFINE_CONST_FUN_OBJ_3(espsdcard_sdcard_ioctl_obj, espsdcard_sdcard_ioctl); + +static const mp_rom_map_elem_t espsdcard_sdcard_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espsdcard_sdcard_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&espsdcard_sdcard___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espsdcard_sdcard___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_is_present), MP_ROM_PTR(&espsdcard_sdcard_is_present_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_status), MP_ROM_PTR(&espsdcard_sdcard_get_status_obj) }, + + { MP_ROM_QSTR(MP_QSTR_capacity_mb), MP_ROM_PTR(&espsdcard_sdcard_capacity_mb_obj) }, + { MP_ROM_QSTR(MP_QSTR_card_type), MP_ROM_PTR(&espsdcard_sdcard_card_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&espsdcard_sdcard_count_obj) }, + + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&espsdcard_sdcard_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&espsdcard_sdcard_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&espsdcard_sdcard_ioctl_obj) }, +}; +static MP_DEFINE_CONST_DICT(espsdcard_sdcard_locals_dict, espsdcard_sdcard_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + espsdcard_sdcard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, espsdcard_sdcard_make_new, + locals_dict, &espsdcard_sdcard_locals_dict + ); diff --git a/ports/espressif/bindings/espsdcard/SDCard.h b/ports/espressif/bindings/espsdcard/SDCard.h new file mode 100644 index 0000000000000..3f559e1a73689 --- /dev/null +++ b/ports/espressif/bindings/espsdcard/SDCard.h @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/espsdcard/SDCard.h" + +extern const mp_obj_type_t espsdcard_sdcard_type; + +// Module-level deinit for convenience (static method support) +void espsdcard_sdcard_deinit_all(void); diff --git a/ports/espressif/bindings/espsdcard/__init__.c b/ports/espressif/bindings/espsdcard/__init__.c new file mode 100644 index 0000000000000..9cc3477603112 --- /dev/null +++ b/ports/espressif/bindings/espsdcard/__init__.c @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" +#include "bindings/espsdcard/SDCard.h" + +//| """ESP32-native SD card interface using ESP-IDF drivers +//| +//| This module provides reliable SD card access on ESP32 boards using +//| native ESP-IDF drivers. It is a drop-in replacement for the generic +//| sdcardio module with better reliability and performance. +//| +//| API Compatibility: +//| This module is fully compatible with sdcardio. Existing code using +//| sdcardio can simply import espsdcard instead: +//| +//| import espsdcard as sdcardio +//| +//| All sdcardio code will work without modifications. +//| +//| Native API: +//| For new code, the native API is cleaner and exposes ESP-IDF features: +//| +//| sd = espsdcard.SDCard( +//| cs=board.SD_CS, +//| miso=board.SD_MISO, +//| mosi=board.SD_MOSI, +//| clk=board.SD_CLK +//| ) +//| +//| Example (sdcardio-compatible):: +//| +//| import board +//| import busio +//| import espsdcard as sdcardio +//| import storage +//| +//| spi = busio.SPI(board.SD_CLK, MOSI=board.SD_MOSI, MISO=board.SD_MISO) +//| sd = sdcardio.SDCard(spi, board.SD_CS) +//| vfs = storage.VfsFat(sd) +//| storage.mount(vfs, "/sd") +//| +//| Example (espsdcard native):: +//| +//| import board +//| import espsdcard +//| import storage +//| +//| sd = espsdcard.SDCard( +//| cs=board.SD_CS, +//| miso=board.SD_MISO, +//| mosi=board.SD_MOSI, +//| clk=board.SD_CLK +//| ) +//| vfs = storage.VfsFat(sd) +//| storage.mount(vfs, "/sd") +//| """ + +//| SPI2_HOST: int +//| """SPI2 host constant""" +//| +//| SPI3_HOST: int +//| """SPI3 host constant""" +//| +//| DMA_AUTO: int +//| """Automatic DMA channel selection""" +//| +//| STATUS_OK: int +//| """Card status: OK""" +//| +//| STATUS_ERROR: int +//| """Card status: Error""" +//| +//| STATUS_NOT_PRESENT: int +//| """Card status: Not present""" +//| + +static const mp_rom_map_elem_t espsdcard_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espsdcard) }, + { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&espsdcard_sdcard_type) }, + + // SPI host constants + { MP_ROM_QSTR(MP_QSTR_SPI2_HOST), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_SPI3_HOST), MP_ROM_INT(2) }, + + // DMA constants + { MP_ROM_QSTR(MP_QSTR_DMA_AUTO), MP_ROM_INT(-1) }, + + // Status constants + { MP_ROM_QSTR(MP_QSTR_STATUS_OK), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_STATUS_ERROR), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_STATUS_NOT_PRESENT), MP_ROM_INT(2) }, +}; +static MP_DEFINE_CONST_DICT(espsdcard_module_globals, espsdcard_module_globals_table); + +const mp_obj_module_t espsdcard_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&espsdcard_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_espsdcard, espsdcard_module); diff --git a/ports/espressif/bindings/espsdcard/__init__.h b/ports/espressif/bindings/espsdcard/__init__.h new file mode 100644 index 0000000000000..0966ff424fd63 --- /dev/null +++ b/ports/espressif/bindings/espsdcard/__init__.h @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Module registration is handled in __init__.c via MP_REGISTER_MODULE diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c new file mode 100644 index 0000000000000..e1b896210d8a3 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +void board_init(void) { +} diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h new file mode 100644 index 0000000000000..883262bfe03d2 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Touch-AMOLED-2.41" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// USB identifiers +#define USB_VID 0x303A +#define USB_PID 0x82CE +#define USB_MANUFACTURER "Waveshare" +#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-2.41" + +// I2C bus - Disabled on boot to avoid conflicts. User must manually initialize I2C. +#define CIRCUITPY_BOARD_I2C (0) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}} + +// AMOLED Display +#define CIRCUITPY_BOARD_DISPLAY 1 +#define CIRCUITPY_DISPLAY_INIT_SEQUENCE rm690b0_rm690b0_init_sequence +#define CIRCUITPY_RM690B0_QSPI_CS (&pin_GPIO9) +#define CIRCUITPY_RM690B0_QSPI_CLK (&pin_GPIO10) +#define CIRCUITPY_RM690B0_QSPI_D0 (&pin_GPIO11) +#define CIRCUITPY_RM690B0_QSPI_D1 (&pin_GPIO12) +#define CIRCUITPY_RM690B0_QSPI_D2 (&pin_GPIO13) +#define CIRCUITPY_RM690B0_QSPI_D3 (&pin_GPIO14) +#define CIRCUITPY_RM690B0_RESET (&pin_GPIO21) +#define CIRCUITPY_RM690B0_POWER (&pin_GPIO16) +#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (true) +#define CIRCUITPY_RM690B0_WIDTH (600) +#define CIRCUITPY_RM690B0_HEIGHT (450) +#define CIRCUITPY_RM690B0_BITS_PER_PIXEL (16) +#define CIRCUITPY_RM690B0_USE_QSPI (1) +#define CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ (80 * 1000 * 1000) + +// SPI bus for SD Card +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO4, .mosi = &pin_GPIO5, .miso = &pin_GPIO6}} + +// Default UART bus +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +// Disable unnecessary modules to save space +#define CIRCUITPY_ESP32_CAMERA (0) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk new file mode 100644 index 0000000000000..1503ef6d6e94b --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -0,0 +1,93 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +# +# SPDX-License-Identifier: MIT + +CIRCUITPY_CREATOR_ID = 0x57415645 # 'WAVE' (Waveshare) +CIRCUITPY_CREATION_ID = 0x41323431 # 'A241' (AMOLED 2.41) + +# USB identifiers - from Arduino pins_arduino.h +USB_VID = 0x303A +USB_PID = 0x82CE +USB_MANUFACTURER = "Waveshare" +USB_PRODUCT = "ESP32-S3-Touch-AMOLED-2.41" + +# ESP32-S3 chip configuration +IDF_TARGET = esp32s3 +CHIP_VARIANT = ESP32S3 + +# Flash configuration - 16MB QSPI Flash +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +# PSRAM configuration - 8MB Octal PSRAM +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Add extra ESP-IDF components needed for board_init.c and rm690b0 module +ESP_IDF_EXTRA_COMPONENTS += driver freertos esp_lcd sdmmc esp_driver_sdmmc esp_driver_sdspi + +# Build optimization +OPTIMIZATION_FLAGS = -Os + +# Enable features for this board +CIRCUITPY_DISPLAYIO = 1 +CIRCUITPY_PARALLELDISPLAY = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_BITMAPTOOLS = 1 +CIRCUITPY_JPEGIO = 1 +CIRCUITPY_FRAMEBUFFERIO = 1 +CIRCUITPY_RM690B0 = 1 + +# Enable SD card support with native ESP-IDF drivers +CIRCUITPY_ESPSDCARD = 1 + +# Enable ESP-NOW for peer-to-peer wireless communication +CIRCUITPY_ESPNOW = 1 + +# Disable camera support (not present on this board) +CIRCUITPY_ESPCAMERA = 0 + +# Enable I2C for touch, RTC, and IMU +CIRCUITPY_BITBANGIO = 1 +CIRCUITPY_I2C = 1 + +# Enable SPI support +CIRCUITPY_SPI = 1 + +# Enable ADC for battery monitoring +CIRCUITPY_ANALOGIO = 1 + +# Enable WiFi and networking +CIRCUITPY_WIFI = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 + +# Enable USB features +CIRCUITPY_USB = 1 +CIRCUITPY_USB_CDC = 1 +CIRCUITPY_USB_HID = 1 +CIRCUITPY_USB_MIDI = 1 + +# Storage configuration +CIRCUITPY_STORAGE = 1 +CIRCUITPY_NVM = 1 + +# Enable touch support +CIRCUITPY_TOUCHIO = 0 +CIRCUITPY_TOUCHSCREEN = 1 + +# Enable RTC support +CIRCUITPY_RTC = 1 + +# Enable JSON support for configuration +CIRCUITPY_JSON = 1 + +# Enable other useful modules +CIRCUITPY_RANDOM = 1 +CIRCUITPY_STRUCT = 1 +CIRCUITPY_ULAB = 1 +CIRCUITPY_ZLIB = 1 diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c new file mode 100644 index 0000000000000..0098ecfc64fa0 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/rm690b0/RM690B0.h" +#include "shared-bindings/microcontroller/Pin.h" + +const rm690b0_rm690b0_obj_t rm690b0_rm690b0_init_sequence = { + .base = {&rm690b0_rm690b0_type}, +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // ================================================================= + // ONBOARD PERIPHERALS - Functional Names + // ================================================================= + + // Boot/Control/Battery + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO17) }, + + // I2C Bus (shared by Touch, RTC, IMU, IO Expander) + // NOTE: board.I2C auto-initialization is disabled (CIRCUITPY_BOARD_I2C=0) + // to avoid boot conflicts. Users must manually create I2C bus: + // i2c = busio.I2C(board.SCL, board.SDA) + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // Touch Panel (FT6336U on I2C) + { MP_ROM_QSTR(MP_QSTR_TP_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_TP_SCL), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_TP_RESET), MP_ROM_PTR(&pin_GPIO3) }, + + // RTC (PCF85063 on I2C) + { MP_ROM_QSTR(MP_QSTR_RTC_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_RTC_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // IMU (QMI8658 on I2C) + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // I/O Expander (TCA9554 on I2C) + { MP_ROM_QSTR(MP_QSTR_EXIO_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_EXIO_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // USB + { MP_ROM_QSTR(MP_QSTR_USB_D_N), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_USB_D_P), MP_ROM_PTR(&pin_GPIO20) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // QSPI Display (RM690B0) + { MP_ROM_QSTR(MP_QSTR_QSPI_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_QSPI_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_QSPI_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_QSPI_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_QSPI_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_QSPI_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_AMOLED_RESET), MP_ROM_PTR(&pin_GPIO21) }, + + // Display Aliases + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_RST), MP_ROM_PTR(&pin_GPIO21) }, + + // SD Card (SPI) + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // ================================================================= + // GENERAL PURPOSE I/O (IOxx - Espressif Convention) + // ================================================================= + // Only pins NOT dedicated to onboard peripherals are exposed here. + // Use functional names above for dedicated pins (e.g., SDA, SD_CS). + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, // BOOT button (available when not holding BOOT) + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, // TP_RESET (available if touch not used) + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // Available +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig new file mode 100644 index 0000000000000..d41ee3bcebd58 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig @@ -0,0 +1,33 @@ +# +# Configuration file for the Waveshare ESP32-S3 Touch AMOLED 2.41 +# + +# PSRAM Configuration +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_CLK_IO=39 +CONFIG_SPIRAM_CS_IO=38 + +# Performance and Cache +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y + +# Default flash settings for this board +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-16MB.csv" +CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-16MB.csv" + +# Networking +CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-amoled" + +# Disable USB-Serial/JTAG to free up I2C pins +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=n + +# Enable .app_desc structure +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 diff --git a/ports/espressif/common-hal/espsdcard/SDCard.c b/ports/espressif/common-hal/espsdcard/SDCard.c new file mode 100644 index 0000000000000..65b291f0d967b --- /dev/null +++ b/ports/espressif/common-hal/espsdcard/SDCard.c @@ -0,0 +1,287 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "common-hal/espsdcard/SDCard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "py/runtime.h" +#include "py/mperrno.h" + +#include "sdmmc_cmd.h" +#include "sd_protocol_defs.h" +#include "driver/sdmmc_host.h" +#include "driver/sdspi_host.h" +#include "esp_log.h" +#include +#include + +static const char *TAG = "espsdcard"; + +// Singleton tracker for cleanup +static espsdcard_sdcard_obj_t *espsdcard_singleton = NULL; + +void common_hal_espsdcard_sdcard_construct( + espsdcard_sdcard_obj_t *self, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *clk, + int spi_host, + int max_transfer_size, + int allocation_unit_size, + int max_files, + bool format_if_mount_failed, + int dma_channel + ) { + // Store pin assignments + self->cs_pin = cs->number; + self->miso_pin = miso->number; + self->mosi_pin = mosi->number; + self->clk_pin = clk->number; + self->spi_host = spi_host; + self->slot = -1; + self->mounted = false; + self->spi_bus_initialized = false; + self->card = NULL; + + // Configure SPI bus + spi_bus_config_t bus_cfg = { + .mosi_io_num = mosi->number, + .miso_io_num = miso->number, + .sclk_io_num = clk->number, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = max_transfer_size, + }; + + // Initialize SPI bus with DMA + spi_dma_chan_t dma = (dma_channel < 0) ? SPI_DMA_CH_AUTO : (spi_dma_chan_t)dma_channel; + esp_err_t ret = spi_bus_initialize((spi_host_device_t)spi_host, &bus_cfg, dma); + if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SPI bus init failed: %d"), ret); + return; + } + // Track if we initialized the bus (not if it was already initialized) + self->spi_bus_initialized = (ret == ESP_OK); + + // Configure SD card slot + sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); + slot_config.gpio_cs = (gpio_num_t)cs->number; + slot_config.host_id = (spi_host_device_t)spi_host; + + // Configure host + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + host.slot = spi_host; + + // Allocate card structure + self->card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); + if (self->card == NULL) { + spi_bus_free((spi_host_device_t)spi_host); + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory for SD card structure")); + return; + } + + // Initialize the card + ret = sdspi_host_init_device(&slot_config, &self->slot); + if (ret != ESP_OK) { + free(self->card); + self->card = NULL; + if (self->spi_bus_initialized) { + spi_bus_free((spi_host_device_t)spi_host); + self->spi_bus_initialized = false; + } + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD host init failed: %d"), ret); + return; + } + + // Probe and initialize the card + ret = sdmmc_card_init(&host, self->card); + + if (ret != ESP_OK) { + if (self->slot >= 0) { + sdspi_host_remove_device(self->slot); + self->slot = -1; + } + free(self->card); + self->card = NULL; + if (self->spi_bus_initialized) { + spi_bus_free((spi_host_device_t)spi_host); + self->spi_bus_initialized = false; + } + if (ret == ESP_ERR_TIMEOUT) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not responding")); + } else if (ret == ESP_ERR_NOT_FOUND) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not found")); + } else { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD card init failed: %d"), ret); + } + return; + } + + // Mark as mounted + self->mounted = true; + + // Claim pins + claim_pin(cs); + claim_pin(miso); + claim_pin(mosi); + claim_pin(clk); + + // Set singleton for cleanup + espsdcard_singleton = self; + + ESP_LOGI(TAG, "SD card mounted successfully"); + if (self->card != NULL) { + sdmmc_card_print_info(stdout, self->card); + } +} + +void common_hal_espsdcard_sdcard_deinit(espsdcard_sdcard_obj_t *self) { + if (!self->mounted) { + return; + } + + // Remove device from SPI slot + if (self->slot >= 0) { + sdspi_host_remove_device(self->slot); + self->slot = -1; + } + + // Free card structure + if (self->card != NULL) { + free(self->card); + self->card = NULL; + } + + // Free SPI bus only if we initialized it + if (self->spi_bus_initialized) { + esp_err_t ret = spi_bus_free((spi_host_device_t)self->spi_host); + if (ret == ESP_OK) { + self->spi_bus_initialized = false; + } + // If it fails, it might be in use - just mark as not initialized + // to prevent double-free attempts + else { + self->spi_bus_initialized = false; + } + } + + // Release pins + reset_pin_number(self->cs_pin); + reset_pin_number(self->miso_pin); + reset_pin_number(self->mosi_pin); + reset_pin_number(self->clk_pin); + + self->mounted = false; + + // Clear singleton if this was it + if (espsdcard_singleton == self) { + espsdcard_singleton = NULL; + } + + ESP_LOGI(TAG, "SD card deinitialized"); +} + +bool common_hal_espsdcard_sdcard_deinited(espsdcard_sdcard_obj_t *self) { + return !self->mounted; +} + +bool common_hal_espsdcard_sdcard_is_present(espsdcard_sdcard_obj_t *self) { + if (!self->mounted || self->card == NULL) { + return false; + } + + esp_err_t err = sdmmc_get_status(self->card); + return err == ESP_OK; +} + +int common_hal_espsdcard_sdcard_get_status(espsdcard_sdcard_obj_t *self) { + if (!self->mounted || self->card == NULL) { + return 2; // STATUS_NOT_PRESENT + } + + esp_err_t err = sdmmc_get_status(self->card); + return (err == ESP_OK) ? 0 : 1; // STATUS_OK or STATUS_ERROR +} + +uint32_t common_hal_espsdcard_sdcard_get_count(espsdcard_sdcard_obj_t *self) { + if (!self->mounted || self->card == NULL) { + return 0; + } + + // Return number of 512-byte blocks + return (uint32_t)self->card->csd.capacity; +} + +void common_hal_espsdcard_sdcard_readblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { + if (!self->mounted || self->card == NULL) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not mounted")); + return; + } + + if (buf->len % 512 != 0) { + mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Buffer must be multiple of 512 bytes")); + return; + } + + uint32_t block_count = buf->len / 512; + + esp_err_t err = sdmmc_read_sectors(self->card, buf->buf, start_block, block_count); + if (err != ESP_OK) { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("Read failed: %d"), err); + } +} + +void common_hal_espsdcard_sdcard_writeblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { + if (!self->mounted || self->card == NULL) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not mounted")); + return; + } + + if (buf->len % 512 != 0) { + mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Buffer must be multiple of 512 bytes")); + return; + } + + uint32_t block_count = buf->len / 512; + + esp_err_t err = sdmmc_write_sectors(self->card, buf->buf, start_block, block_count); + if (err != ESP_OK) { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("Write failed: %d"), err); + } +} + +int common_hal_espsdcard_sdcard_writeblocks_sync(espsdcard_sdcard_obj_t *self) { + // ESP-IDF handles synchronization internally + // Return 0 for success + return 0; +} + +float common_hal_espsdcard_sdcard_get_capacity_mb(espsdcard_sdcard_obj_t *self) { + if (!self->mounted || self->card == NULL) { + return 0.0f; + } + + // Capacity is in 512-byte sectors + uint64_t capacity_bytes = (uint64_t)self->card->csd.capacity * 512; + return (float)capacity_bytes / (1024.0f * 1024.0f); +} + +mp_obj_t common_hal_espsdcard_sdcard_get_card_type(espsdcard_sdcard_obj_t *self) { + if (!self->mounted || self->card == NULL) { + return mp_obj_new_str("Unknown", 7); + } + + if (self->card->ocr & SD_OCR_SDHC_CAP) { + return mp_obj_new_str("SDHC/SDXC", 9); + } else { + return mp_obj_new_str("SD", 2); + } +} + +// Module-level deinit for convenience +void espsdcard_sdcard_deinit_all(void) { + if (espsdcard_singleton != NULL) { + common_hal_espsdcard_sdcard_deinit(espsdcard_singleton); + } +} diff --git a/ports/espressif/common-hal/espsdcard/SDCard.h b/ports/espressif/common-hal/espsdcard/SDCard.h new file mode 100644 index 0000000000000..5ea1c13b742e1 --- /dev/null +++ b/ports/espressif/common-hal/espsdcard/SDCard.h @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "sdmmc_cmd.h" +#include "driver/gpio.h" +#include "common-hal/microcontroller/Pin.h" + +typedef struct { + mp_obj_base_t base; + sdmmc_card_t *card; + int spi_host; + int slot; + gpio_num_t cs_pin; + gpio_num_t miso_pin; + gpio_num_t mosi_pin; + gpio_num_t clk_pin; + bool mounted; + bool spi_bus_initialized; + const char *mount_point; +} espsdcard_sdcard_obj_t; + +extern const mp_obj_type_t espsdcard_sdcard_type; + +// Function declarations +void common_hal_espsdcard_sdcard_construct( + espsdcard_sdcard_obj_t *self, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *clk, + int spi_host, + int max_transfer_size, + int allocation_unit_size, + int max_files, + bool format_if_mount_failed, + int dma_channel + ); + +void common_hal_espsdcard_sdcard_deinit(espsdcard_sdcard_obj_t *self); +bool common_hal_espsdcard_sdcard_deinited(espsdcard_sdcard_obj_t *self); +bool common_hal_espsdcard_sdcard_is_present(espsdcard_sdcard_obj_t *self); +int common_hal_espsdcard_sdcard_get_status(espsdcard_sdcard_obj_t *self); +uint32_t common_hal_espsdcard_sdcard_get_count(espsdcard_sdcard_obj_t *self); +void common_hal_espsdcard_sdcard_readblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); +void common_hal_espsdcard_sdcard_writeblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); +int common_hal_espsdcard_sdcard_writeblocks_sync(espsdcard_sdcard_obj_t *self); +float common_hal_espsdcard_sdcard_get_capacity_mb(espsdcard_sdcard_obj_t *self); +mp_obj_t common_hal_espsdcard_sdcard_get_card_type(espsdcard_sdcard_obj_t *self); + +// Reset function +void espsdcard_sdcard_deinit_all(void); diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.c b/ports/espressif/common-hal/rm690b0/RM690B0.c new file mode 100644 index 0000000000000..8623505d5aa6a --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/RM690B0.c @@ -0,0 +1,3659 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/rm690b0/RM690B0.h" +#include "common-hal/rm690b0/RM690B0.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "py/runtime.h" +#include "py/mperrno.h" + +#include "esp_log.h" +#include "driver/gpio.h" +#include "driver/spi_master.h" +#include "esp_heap_caps.h" +#include "esp_rom_sys.h" + +static const char *TAG = "rm690b0"; + +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_vendor.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_ops.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_commands.h" +#include "esp_lcd_rm690b0.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include +#include +#include +#include +#include "esp_attr.h" +#include "esp_jpeg/esp_jpeg.h" +#include "fonts/rm690b0_font_8x8.h" +#include "fonts/rm690b0_font_16x16.h" +#include "fonts/rm690b0_font_16x24.h" +#include "fonts/rm690b0_font_24x24.h" +#include "fonts/rm690b0_font_24x32.h" +#include "fonts/rm690b0_font_32x32.h" +#include "fonts/rm690b0_font_32x48.h" + +#if !defined(CIRCUITPY_RM690B0_QSPI_CS) || !defined(CIRCUITPY_RM690B0_QSPI_CLK) || \ + !defined(CIRCUITPY_RM690B0_QSPI_D0) || !defined(CIRCUITPY_RM690B0_QSPI_D1) || \ + !defined(CIRCUITPY_RM690B0_QSPI_D2) || !defined(CIRCUITPY_RM690B0_QSPI_D3) || \ + !defined(CIRCUITPY_RM690B0_RESET) || !defined(CIRCUITPY_RM690B0_WIDTH) || \ + !defined(CIRCUITPY_RM690B0_HEIGHT) || !defined(CIRCUITPY_RM690B0_BITS_PER_PIXEL) +#error "Board must define CIRCUITPY_RM690B0_* macros to describe the RM690B0 hardware" +#endif + +#ifndef CIRCUITPY_RM690B0_POWER +#define CIRCUITPY_RM690B0_POWER (NULL) +#endif + +#ifndef CIRCUITPY_RM690B0_POWER_ON_LEVEL +#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (true) +#endif + +#ifndef CIRCUITPY_RM690B0_USE_QSPI +#define CIRCUITPY_RM690B0_USE_QSPI (0) +#endif + +#ifndef CIRCUITPY_RM690B0_X_GAP +#define CIRCUITPY_RM690B0_X_GAP (0) +#endif + +#ifndef CIRCUITPY_RM690B0_Y_GAP +#define CIRCUITPY_RM690B0_Y_GAP (16) +#endif + +#ifndef CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ +#define CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ (80 * 1000 * 1000) +#endif + +#define PIN_GPIO(pin_obj) ((pin_obj) == NULL ? (gpio_num_t)GPIO_NUM_NC : (gpio_num_t)(pin_obj)->number) + +#define LCD_CS_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_CS) +#define LCD_SCK_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_CLK) +#define LCD_D0_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D0) +#define LCD_D1_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D1) +#define LCD_D2_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D2) +#define LCD_D3_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D3) +#define LCD_RST_PIN PIN_GPIO(CIRCUITPY_RM690B0_RESET) +#define LCD_PWR_PIN PIN_GPIO(CIRCUITPY_RM690B0_POWER) +#define LCD_PWR_ON_LEVEL ((CIRCUITPY_RM690B0_POWER_ON_LEVEL) ? 1 : 0) + +#define LCD_H_RES (CIRCUITPY_RM690B0_WIDTH) +#define LCD_V_RES (CIRCUITPY_RM690B0_HEIGHT) +#define LCD_BIT_PER_PIXEL (CIRCUITPY_RM690B0_BITS_PER_PIXEL) +#define LCD_USE_QSPI (CIRCUITPY_RM690B0_USE_QSPI) +#define LCD_PIXEL_CLOCK_HZ (CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ) + +#define RGB565_SWAP_GB(c) (__builtin_bswap16(c)) + +#define RM690B0_OPCODE_WRITE_CMD (0x02U) + +#define RM690B0_PANEL_WIDTH LCD_H_RES +#define RM690B0_PANEL_HEIGHT LCD_V_RES +#define RM690B0_X_GAP (CIRCUITPY_RM690B0_X_GAP) +#define RM690B0_Y_GAP (CIRCUITPY_RM690B0_Y_GAP) +#define RM690B0_MAX_CHUNK_ROWS (24) +#define RM690B0_MAX_CHUNK_PIXELS (LCD_H_RES * RM690B0_MAX_CHUNK_ROWS) +#define RM690B0_MAX_DIAMETER ((RM690B0_PANEL_WIDTH * 2) + 1) +#define RM690B0_PANEL_IO_QUEUE_DEPTH (10) + +#define RM690B0_PENDING_BUFFER_FRAMEBUFFER (0xFF) +#define RM690B0_PENDING_BUFFER_ALLOC (0xFE) +#define RM690B0_PENDING_BUFFER_TEMP (0xFD) + +// Built-in font identifiers (must match shared-bindings docs) +#define RM690B0_FONT_8x8_MONO (0) +#define RM690B0_FONT_16x16_MONO (1) +#define RM690B0_FONT_16x24_MONO (2) +#define RM690B0_FONT_24x24_MONO (3) +#define RM690B0_FONT_24x32_MONO (4) +#define RM690B0_FONT_32x32_MONO (5) +#define RM690B0_FONT_32x48_MONO (6) + +// Macro to check if display is initialized +#define CHECK_INITIALIZED() \ + do { \ + if (!self->initialized) { \ + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Display not initialized. Call init_display() first")); \ + return; \ + } \ + } while (0) + +// Internal implementation structure +typedef struct { + mp_int_t top; + mp_int_t row_count; + int16_t *left; + int16_t *right; +} rm690b0_span_accumulator_t; + +typedef struct { + size_t head; + size_t tail; + size_t count; + uint8_t ids[RM690B0_PANEL_IO_QUEUE_DEPTH]; +} rm690b0_dma_pending_list_t; + +typedef struct rm690b0_impl { + esp_lcd_panel_io_handle_t io_handle; + esp_lcd_panel_handle_t panel_handle; + bool bus_initialized; + uint16_t *chunk_buffers[2]; + size_t chunk_buffer_pixels; + uint16_t *framebuffer; + size_t framebuffer_pixels; + uint16_t *framebuffer_front; + bool double_buffered; + bool dirty_region_valid; + mp_int_t dirty_x; + mp_int_t dirty_y; + mp_int_t dirty_w; + mp_int_t dirty_h; + SemaphoreHandle_t transfer_done_sem; + bool dma_buffer_in_use[2]; + bool dma_alloc_buffer_in_use; + size_t dma_inflight; + rm690b0_dma_pending_list_t dma_pending; + int16_t *circle_span_cache; + size_t circle_span_capacity; +} rm690b0_impl_t; +typedef struct { + rm690b0_rm690b0_obj_t *self; + rm690b0_impl_t *impl; + mp_int_t origin_x; + mp_int_t origin_y; + mp_int_t clip_x; + mp_int_t clip_y; + mp_int_t clip_w; + mp_int_t clip_h; + bool rotation_zero; +} rm690b0_jpeg_draw_ctx_t; + + +static portMUX_TYPE rm690b0_spinlock = portMUX_INITIALIZER_UNLOCKED; + +static inline void rm690b0_dma_pending_init(rm690b0_dma_pending_list_t *list) { + list->head = 0; + list->tail = 0; + list->count = 0; +} + +static inline void rm690b0_dma_pending_push(rm690b0_dma_pending_list_t *list, uint8_t id) { + portENTER_CRITICAL(&rm690b0_spinlock); + list->ids[list->tail] = id; + list->tail = (list->tail + 1) % RM690B0_PANEL_IO_QUEUE_DEPTH; + list->count++; + portEXIT_CRITICAL(&rm690b0_spinlock); +} + +static inline uint8_t rm690b0_dma_pending_pop(rm690b0_dma_pending_list_t *list) { + portENTER_CRITICAL(&rm690b0_spinlock); + uint8_t id = list->ids[list->head]; + list->head = (list->head + 1) % RM690B0_PANEL_IO_QUEUE_DEPTH; + list->count--; + portEXIT_CRITICAL(&rm690b0_spinlock); + return id; +} + +static inline void rm690b0_wait_for_dma_completion(rm690b0_impl_t *impl) { + if (impl->dma_inflight == 0) { + return; + } + + if (impl->transfer_done_sem) { + if (xSemaphoreTake(impl->transfer_done_sem, pdMS_TO_TICKS(1000)) != pdTRUE) { + ESP_LOGE("RM690B0", "DMA wait timeout! Halting to prevent memory corruption."); + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("DMA transfer timed out - hardware requires reset")); + return; + } + } else { + // Fallback - should not happen because semaphore allocation is mandatory + esp_rom_delay_us(50); + } + + if (impl->dma_inflight > 0) { + impl->dma_inflight--; + } + + if (impl->dma_pending.count > 0) { + uint8_t id = rm690b0_dma_pending_pop(&impl->dma_pending); + if (id < 2) { + impl->dma_buffer_in_use[id] = false; + } else if (id == RM690B0_PENDING_BUFFER_ALLOC) { + impl->dma_alloc_buffer_in_use = false; + } + // RM690B0_PENDING_BUFFER_TEMP is explicitly ignored - it's locally managed + } + +} + +static inline void rm690b0_wait_for_dma_slot(rm690b0_impl_t *impl) { + while (impl->dma_inflight >= RM690B0_PANEL_IO_QUEUE_DEPTH) { + rm690b0_wait_for_dma_completion(impl); + } +} + +static inline void rm690b0_wait_for_all_dma(rm690b0_impl_t *impl) { + while (impl->dma_inflight > 0) { + rm690b0_wait_for_dma_completion(impl); + } +} + +// (rm690b0_text_state_t typedefs removed – not used yet) + +// Forward declarations for functions used by font rendering +static void mark_dirty_region(rm690b0_impl_t *impl, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h); +static esp_err_t rm690b0_flush_region(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, bool skip_final_delay); +static void rm690b0_fill_rect_framebuffer(rm690b0_impl_t *impl, + mp_int_t bx, mp_int_t by, mp_int_t bw, mp_int_t bh, uint16_t swapped_color); + +// Callback for LCD IO transfer completion +static bool IRAM_ATTR rm690b0_on_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) { + rm690b0_impl_t *impl = (rm690b0_impl_t *)user_ctx; + BaseType_t high_task_awoken = pdFALSE; + xSemaphoreGiveFromISR(impl->transfer_done_sem, &high_task_awoken); + return high_task_awoken == pdTRUE; +} + + + +static inline void rm690b0_span_update(rm690b0_span_accumulator_t *acc, mp_int_t row_y, mp_int_t x_val) { + mp_int_t idx = row_y - acc->top; + if (idx < 0 || idx >= acc->row_count) { + return; + } + if (x_val < acc->left[idx]) { + acc->left[idx] = (int16_t)x_val; + } + if (x_val > acc->right[idx]) { + acc->right[idx] = (int16_t)x_val; + } +} + +static inline int16_t *rm690b0_acquire_span_cache(rm690b0_impl_t *impl, size_t needed_rows) { + if (impl == NULL || needed_rows == 0) { + return NULL; + } + + if (impl->circle_span_capacity < needed_rows) { + size_t new_capacity = needed_rows; + size_t total_entries = new_capacity * 2; + int16_t *new_cache = (int16_t *)heap_caps_realloc( + impl->circle_span_cache, + total_entries * sizeof(int16_t), + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (new_cache == NULL) { + return NULL; + } + impl->circle_span_cache = new_cache; + impl->circle_span_capacity = new_capacity; + } + return impl->circle_span_cache; +} + +static inline void rm690b0_fill_span_fast(uint16_t *dest, size_t span_width, uint16_t color) { + if (span_width == 0) { + return; + } + + if (((uintptr_t)dest & 0x2) != 0) { + *dest++ = color; + span_width--; + if (span_width == 0) { + return; + } + } + + while (span_width >= 2) { + dest[0] = color; + dest[1] = color; + dest += 2; + span_width -= 2; + } + + if (span_width & 1) { + *dest = color; + } +} + +static bool map_rect_for_rotation(const rm690b0_rm690b0_obj_t *self, + mp_int_t *x, mp_int_t *y, + mp_int_t *width, mp_int_t *height) { + mp_int_t rx = *x; + mp_int_t ry = *y; + mp_int_t rw = *width; + mp_int_t rh = *height; + + switch (self->rotation) { + case 0: + break; + case 90: + *x = RM690B0_PANEL_WIDTH - (ry + rh); + *y = rx; + *width = rh; + *height = rw; + break; + case 180: + *x = RM690B0_PANEL_WIDTH - (rx + rw); + *y = RM690B0_PANEL_HEIGHT - (ry + rh); + break; + case 270: + *x = ry; + *y = RM690B0_PANEL_HEIGHT - (rx + rw); + *width = rh; + *height = rw; + break; + default: + return false; + } + + if (*width <= 0 || *height <= 0) { + return false; + } + return true; +} + +// Helper function to safely check bitmap size and detect overflow +// Uses 64-bit arithmetic to accurately detect overflow on both 32-bit and 64-bit systems +static inline bool check_bitmap_size(size_t width, size_t height, size_t *out_bytes) { + // Use 64-bit arithmetic for accurate overflow detection + uint64_t pixels = (uint64_t)width * (uint64_t)height; + uint64_t bytes = pixels * sizeof(uint16_t); + + // Check if result fits in size_t + if (bytes > SIZE_MAX) { + return false; + } + + *out_bytes = (size_t)bytes; + return true; +} + +static bool clip_logical_rect(const rm690b0_rm690b0_obj_t *self, + mp_int_t *x, mp_int_t *y, + mp_int_t *width, mp_int_t *height) { + if (*width <= 0 || *height <= 0) { + return false; + } + + mp_int_t x0 = *x; + mp_int_t y0 = *y; + mp_int_t x1 = x0 + *width; + mp_int_t y1 = y0 + *height; + + if (x1 <= 0 || y1 <= 0 || x0 >= self->width || y0 >= self->height) { + return false; + } + + if (x0 < 0) { + x0 = 0; + } + if (y0 < 0) { + y0 = 0; + } + if (x1 > self->width) { + x1 = self->width; + } + if (y1 > self->height) { + y1 = self->height; + } + + mp_int_t new_width = x1 - x0; + mp_int_t new_height = y1 - y0; + if (new_width <= 0 || new_height <= 0) { + return false; + } + + *x = x0; + *y = y0; + *width = new_width; + *height = new_height; + return true; +} + +static inline mp_int_t clamp_int(mp_int_t v, mp_int_t lo, mp_int_t hi) { + return v < lo ? lo : (v > hi ? hi : v); +} + +// Compile-time assertions to ensure fallback character '?' exists in all fonts +_Static_assert('?' >= 32 && '?' <= 127, "Fallback character '?' must be in font range"); +_Static_assert(sizeof(rm690b0_font_8x8_data) / sizeof(rm690b0_font_8x8_data[0]) == 96, + "Font 8x8 must have exactly 96 glyphs (0x20-0x7F)"); +_Static_assert(sizeof(rm690b0_font_16x16_data) / sizeof(rm690b0_font_16x16_data[0]) == 95, + "Font 16x16 must have exactly 95 glyphs (0x20-0x7E)"); + +static inline const uint8_t *rm690b0_get_8x8_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7F (127) = 96 characters + if (codepoint < 32 || codepoint > 127) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 127] + } + // Safe array access: index range [0, 95] + return rm690b0_font_8x8_data[codepoint - 32]; +} + +static inline const uint8_t *rm690b0_get_16x16_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7E (126) = 95 characters + if (codepoint < 32 || codepoint > 126) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] + } + // Safe array access: index range [0, 94] + return rm690b0_font_16x16_data[codepoint - 32]; +} + +static inline const uint8_t *rm690b0_get_16x24_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7E (126) = 95 characters + if (codepoint < 32 || codepoint > 126) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] + } + // Safe array access: index range [0, 94] + return rm690b0_font_16x24_data[codepoint - 32]; +} + +static inline const uint8_t *rm690b0_get_24x24_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7E (126) = 95 characters + if (codepoint < 32 || codepoint > 126) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] + } + // Safe array access: index range [0, 94] + return rm690b0_font_24x24_data[codepoint - 32]; +} + +static inline const uint8_t *rm690b0_get_24x32_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7E (126) = 95 characters + if (codepoint < 32 || codepoint > 126) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] + } + // Safe array access: index range [0, 94] + return rm690b0_font_24x32_data[codepoint - 32]; +} + +static inline const uint8_t *rm690b0_get_32x32_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7E (126) = 95 characters + if (codepoint < 32 || codepoint > 126) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] + } + // Safe array access: index range [0, 94] + return rm690b0_font_32x32_data[codepoint - 32]; +} + +static inline const uint8_t *rm690b0_get_32x48_glyph(uint32_t codepoint) { + // Validate codepoint range and use fallback for invalid characters + // Font range: 0x20 (32) to 0x7E (126) = 95 characters + if (codepoint < 32 || codepoint > 126) { + codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] + } + // Safe array access: index range [0, 94] + return rm690b0_font_32x48_data[codepoint - 32]; +} + +// ============================================================================ +// OPTIMIZED FONT RENDERING - Universal rotation-aware batch write +// ============================================================================ + +/** + * Write a pixel to framebuffer with rotation support. + * This inline helper handles all 4 rotations in one place. + * Compiler will optimize this heavily for rotation=0 case. + */ +static inline void rm690b0_write_pixel_rotated( + rm690b0_rm690b0_obj_t *self, + rm690b0_impl_t *impl, + mp_int_t logical_x, mp_int_t logical_y, + uint16_t color) { + + uint16_t *framebuffer = impl->framebuffer; + size_t fb_stride = RM690B0_PANEL_WIDTH; + + mp_int_t phys_x, phys_y; + + // Transform logical coordinates to physical based on rotation + switch (self->rotation) { + case 0: + phys_x = logical_x; + phys_y = logical_y; + break; + case 90: + phys_x = RM690B0_PANEL_WIDTH - logical_y - 1; + phys_y = logical_x; + break; + case 180: + phys_x = RM690B0_PANEL_WIDTH - logical_x - 1; + phys_y = RM690B0_PANEL_HEIGHT - logical_y - 1; + break; + case 270: + phys_x = logical_y; + phys_y = RM690B0_PANEL_HEIGHT - logical_x - 1; + break; + default: + return; // Invalid rotation + } + + // Bounds check + if (phys_x < 0 || phys_x >= RM690B0_PANEL_WIDTH || + phys_y < 0 || phys_y >= RM690B0_PANEL_HEIGHT) { + return; + } + + // Direct write to framebuffer + framebuffer[phys_y * fb_stride + phys_x] = color; +} + +static void rm690b0_draw_glyph_8x8(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 8 <= 0 || y + 8 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 8 > self->width) ? (self->width - x) : 8; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 8 > self->height) ? (self->height - y) : 8; + + // Pre-swap colors once (not per-pixel) + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + // Batch write to framebuffer with rotation support (only visible pixels) + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint8_t bits = glyph[row]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + + // 90deg: phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1 + // phys_y = x + col + // index = (x + col) * stride + (PANEL_WIDTH - y - row - 1) + + for (int row = row_start; row < row_end; row++) { + uint8_t bits = glyph[row]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + // Base index for col=0. As col increases, phys_y increases, so index increases by stride. + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; // phys_y increments + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + + // 180deg: phys_x = RM690B0_PANEL_WIDTH - (x + col) - 1 + // phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1 + + for (int row = row_start; row < row_end; row++) { + uint8_t bits = glyph[row]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + + // As col increases, phys_x decreases, index decreases by 1 + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; // phys_x decrements + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + + // 270deg: phys_x = y + row + // phys_y = RM690B0_PANEL_HEIGHT - (x + col) - 1 + + for (int row = row_start; row < row_end; row++) { + uint8_t bits = glyph[row]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + + // As col increases, phys_y decreases, index decreases by stride + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; // phys_y decrements + } + } + } + + // Mark dirty region and flush once (not per-pixel) + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 8, dirty_h = 8; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +static void rm690b0_draw_glyph_16x16(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 16 <= 0 || y + 16 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 16 > self->width) ? (self->width - x) : 16; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 16 > self->height) ? (self->height - y) : 16; + + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; + } + } + } + + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 16, dirty_h = 16; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph 16x16 flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +static void rm690b0_draw_glyph_16x24(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 16 <= 0 || y + 24 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 16 > self->width) ? (self->width - x) : 16; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 24 > self->height) ? (self->height - y) : 24; + + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x8000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; + } + } + } + + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 16, dirty_h = 24; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph 16x24 flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +static void rm690b0_draw_glyph_24x24(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 24 <= 0 || y + 24 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 24 > self->width) ? (self->width - x) : 24; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 24 > self->height) ? (self->height - y) : 24; + + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; + } + } + } + + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 24, dirty_h = 24; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph 24x24 flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +static void rm690b0_draw_glyph_24x32(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 24 <= 0 || y + 32 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 24 > self->width) ? (self->width - x) : 24; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 32 > self->height) ? (self->height - y) : 32; + + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | + ((uint32_t)glyph[row * 3 + 1] << 8) | + glyph[row * 3 + 2]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x800000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; + } + } + } + + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 24, dirty_h = 32; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph 24x32 flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +static void rm690b0_draw_glyph_32x32(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 32 <= 0 || y + 32 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 32 > self->width) ? (self->width - x) : 32; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 32 > self->height) ? (self->height - y) : 32; + + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; + } + } + } + + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 32, dirty_h = 32; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph 32x32 flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +static void rm690b0_draw_glyph_32x48(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, + const uint8_t *glyph, + uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + // Early exit: check if glyph is completely off-screen + if (x >= self->width || y >= self->height || x + 32 <= 0 || y + 48 <= 0) { + return; + } + + // Calculate clipping bounds + mp_int_t col_start = (x < 0) ? -x : 0; + mp_int_t col_end = (x + 32 > self->width) ? (self->width - x) : 32; + mp_int_t row_start = (y < 0) ? -y : 0; + mp_int_t row_end = (y + 48 > self->height) ? (self->height - y) : 48; + + uint16_t fg_swapped = RGB565_SWAP_GB(fg); + uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; + + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[row_offset + (col - col_start)] = fg_swapped; + } else if (has_bg) { + fb_ptr[row_offset + (col - col_start)] = bg_swapped; + } + } + } + } else if (self->rotation == 90) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; + size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index += fb_stride; + } + } + } else if (self->rotation == 180) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; + mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; + size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index--; + } + } + } else if (self->rotation == 270) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb_ptr = impl->framebuffer; + for (int row = row_start; row < row_end; row++) { + uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | + ((uint32_t)glyph[row * 4 + 1] << 16) | + ((uint32_t)glyph[row * 4 + 2] << 8) | + glyph[row * 4 + 3]; + mp_int_t phys_x = y + row; + mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; + size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; + for (int col = col_start; col < col_end; col++) { + bool on = (bits & (0x80000000 >> col)) != 0; + if (on) { + fb_ptr[start_index] = fg_swapped; + } else if (has_bg) { + fb_ptr[start_index] = bg_swapped; + } + start_index -= fb_stride; + } + } + } + + mp_int_t dirty_x = x, dirty_y = y, dirty_w = 32, dirty_h = 48; + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); + + if (auto_flush && !impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Glyph 32x48 flush failed: %s", esp_err_to_name(ret)); + } + } + } +} + +// NOTE: Text state is currently stateless per-instance in C; we use a static variable +// for font id to avoid changing struct layout. 0 = 8x8 monospace. +void common_hal_rm690b0_rm690b0_set_font(rm690b0_rm690b0_obj_t *self, mp_int_t font_id) { + // Clamp to known range + if (font_id < RM690B0_FONT_8x8_MONO || font_id > RM690B0_FONT_32x48_MONO) { + font_id = RM690B0_FONT_8x8_MONO; + } + // Store in object instance + self->font_id = font_id; +} + +static inline mp_int_t rm690b0_get_current_font(const rm690b0_rm690b0_obj_t *self) { + return self->font_id; +} + +void common_hal_rm690b0_rm690b0_text(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, + const char *text, size_t text_len, uint16_t fg, bool has_bg, uint16_t bg) { + + CHECK_INITIALIZED(); + + if (text_len == 0) { + return; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + mp_int_t font_id = rm690b0_get_current_font(self); + mp_int_t cursor_x = x; + mp_int_t cursor_y = y; + + // Determine font dimensions based on ID + mp_int_t font_width, font_height; + switch (font_id) { + case RM690B0_FONT_16x16_MONO: + font_width = 16; + font_height = 16; + break; + case RM690B0_FONT_16x24_MONO: + font_width = 16; + font_height = 24; + break; + case RM690B0_FONT_24x24_MONO: + font_width = 24; + font_height = 24; + break; + case RM690B0_FONT_24x32_MONO: + font_width = 24; + font_height = 32; + break; + case RM690B0_FONT_32x32_MONO: + font_width = 32; + font_height = 32; + break; + case RM690B0_FONT_32x48_MONO: + font_width = 32; + font_height = 48; + break; + default: // RM690B0_FONT_8x8_MONO + font_width = 8; + font_height = 8; + break; + } + + // Initialize bounding box for batch flushing + // min_x is always x because newlines reset cursor_x to x. + mp_int_t min_x = x; + mp_int_t max_x = x; + mp_int_t min_y = y; + mp_int_t max_y = y + font_height; + + for (size_t i = 0; i < text_len; i++) { + uint8_t ch = (uint8_t)text[i]; + + if (ch == '\n') { + cursor_x = x; + cursor_y += font_height; + // Extend bounding box height to cover the new line + if (cursor_y + font_height > max_y) { + max_y = cursor_y + font_height; + } + continue; + } else if (ch == '\r') { + // Ignore carriage return + continue; + } + + // Draw character based on font ID (no flush) + switch (font_id) { + case RM690B0_FONT_16x16_MONO: { + const uint8_t *glyph = rm690b0_get_16x16_glyph(ch); + rm690b0_draw_glyph_16x16(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + case RM690B0_FONT_16x24_MONO: { + const uint8_t *glyph = rm690b0_get_16x24_glyph(ch); + rm690b0_draw_glyph_16x24(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + case RM690B0_FONT_24x24_MONO: { + const uint8_t *glyph = rm690b0_get_24x24_glyph(ch); + rm690b0_draw_glyph_24x24(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + case RM690B0_FONT_24x32_MONO: { + const uint8_t *glyph = rm690b0_get_24x32_glyph(ch); + rm690b0_draw_glyph_24x32(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + case RM690B0_FONT_32x32_MONO: { + const uint8_t *glyph = rm690b0_get_32x32_glyph(ch); + rm690b0_draw_glyph_32x32(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + case RM690B0_FONT_32x48_MONO: { + const uint8_t *glyph = rm690b0_get_32x48_glyph(ch); + rm690b0_draw_glyph_32x48(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + default: { // RM690B0_FONT_8x8_MONO + const uint8_t *glyph = rm690b0_get_8x8_glyph(ch); + rm690b0_draw_glyph_8x8(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); + break; + } + } + cursor_x += font_width; + + // Update bounding box width + if (cursor_x > max_x) { + max_x = cursor_x; + } + + if (cursor_x >= RM690B0_PANEL_WIDTH) { + cursor_x = x; + cursor_y += font_height; + if (cursor_y + font_height > max_y) { + max_y = cursor_y + font_height; + } + } + if (cursor_y >= RM690B0_PANEL_HEIGHT) { + break; + } + } + + // Final flush of the entire text bounding box + if (!impl->double_buffered) { + mp_int_t dirty_x = min_x; + mp_int_t dirty_y = min_y; + mp_int_t dirty_w = max_x - min_x; + mp_int_t dirty_h = max_y - min_y; + + if (dirty_w > 0 && dirty_h > 0) { + if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { + esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Batch text flush failed: %s", esp_err_to_name(ret)); + } + } + } + } +} + +static bool expand_even_region(mp_int_t *x, mp_int_t *y, mp_int_t *width, mp_int_t *height) { + mp_int_t start_x = *x; + mp_int_t start_y = *y; + mp_int_t end_x = start_x + *width; + mp_int_t end_y = start_y + *height; + + if (start_x < 0) { + start_x = 0; + } + if (start_y < 0) { + start_y = 0; + } + if (end_x > RM690B0_PANEL_WIDTH) { + end_x = RM690B0_PANEL_WIDTH; + } + if (end_y > RM690B0_PANEL_HEIGHT) { + end_y = RM690B0_PANEL_HEIGHT; + } + + if (start_x >= end_x || start_y >= end_y) { + return false; + } + + if (start_x & 1) { + if (start_x > 0) { + start_x -= 1; + } else if (end_x < RM690B0_PANEL_WIDTH) { + end_x += 1; + } + } + if (end_x & 1) { + if (end_x < RM690B0_PANEL_WIDTH) { + end_x += 1; + } else if (start_x > 0) { + start_x -= 1; + } + } + if (((end_x - start_x) & 1) != 0) { + if (end_x < RM690B0_PANEL_WIDTH) { + end_x += 1; + } else if (start_x > 0) { + start_x -= 1; + } + } + + if (start_y & 1) { + if (start_y > 0) { + start_y -= 1; + } else if (end_y < RM690B0_PANEL_HEIGHT) { + end_y += 1; + } + } + if (end_y & 1) { + if (end_y < RM690B0_PANEL_HEIGHT) { + end_y += 1; + } else if (start_y > 0) { + start_y -= 1; + } + } + if (((end_y - start_y) & 1) != 0) { + if (end_y < RM690B0_PANEL_HEIGHT) { + end_y += 1; + } else if (start_y > 0) { + start_y -= 1; + } + } + + if ((end_y - start_y) < 2) { + if (end_y < RM690B0_PANEL_HEIGHT) { + end_y = start_y + 2; + } else if (start_y >= 1) { + start_y = end_y - 2; + } + } + + if (start_x >= end_x || start_y >= end_y) { + return false; + } + + *x = start_x; + *y = start_y; + *width = end_x - start_x; + *height = end_y - start_y; + return true; +} + + + +static const rm690b0_lcd_init_cmd_t lcd_init_cmds[] = { + {0xFE, (uint8_t []) {0x20}, 1, 0}, + {0x26, (uint8_t []) {0x0A}, 1, 0}, + {0x24, (uint8_t []) {0x80}, 1, 0}, + {0xFE, (uint8_t []) {0x13}, 1, 0}, + {0xEB, (uint8_t []) {0x0E}, 1, 0}, + {0xFE, (uint8_t []) {0x00}, 1, 0}, + {0x3A, (uint8_t []) {0x55}, 1, 0}, + {0xC2, (uint8_t []) {0x00}, 1, 10}, + {0x35, (uint8_t []) {0x00}, 0, 0}, + {0x51, (uint8_t []) {0x00}, 1, 10}, + {0x11, (uint8_t []) {0x00}, 0, 80}, + {0x2A, (uint8_t []) {0x00, 0x10, 0x01, 0xD1}, 4, 0}, + {0x2B, (uint8_t []) {0x00, 0x00, 0x02, 0x57}, 4, 0}, + {0x29, (uint8_t []) {0x00}, 0, 10}, + {0x36, (uint8_t []) {0x30}, 1, 10}, // MADCTL for Landscape with RGB color order + {0x51, (uint8_t []) {0xFF}, 1, 0}, +}; + +// rm690b0_impl_t structure is defined earlier in the file (before font rendering functions) + +// Singleton instance tracker for static deinit support +static rm690b0_rm690b0_obj_t *rm690b0_singleton = NULL; + +static esp_err_t rm690b0_tx_param(const rm690b0_impl_t *impl, uint8_t cmd, const void *param, size_t param_size) { + if (impl == NULL || impl->io_handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + uint32_t packed_cmd = ((uint32_t)RM690B0_OPCODE_WRITE_CMD << 24) | ((uint32_t)cmd << 8); + return esp_lcd_panel_io_tx_param(impl->io_handle, packed_cmd, param, param_size); +} + +// Mark a region as dirty for next swap_buffers() +static void mark_dirty_region(rm690b0_impl_t *impl, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h) { + if (!impl->double_buffered) { + // Single-buffer mode: no dirty tracking needed (flush happens immediately) + return; + } + + if (w <= 0 || h <= 0) { + return; + } + + if (!impl->dirty_region_valid) { + // First dirty region + impl->dirty_x = x; + impl->dirty_y = y; + impl->dirty_w = w; + impl->dirty_h = h; + impl->dirty_region_valid = true; + } else { + // Expand to include new region + mp_int_t x1 = impl->dirty_x; + mp_int_t y1 = impl->dirty_y; + mp_int_t x2 = impl->dirty_x + impl->dirty_w; + mp_int_t y2 = impl->dirty_y + impl->dirty_h; + + mp_int_t new_x1 = (x < x1) ? x : x1; + mp_int_t new_y1 = (y < y1) ? y : y1; + mp_int_t new_x2 = (x + w > x2) ? x + w : x2; + mp_int_t new_y2 = (y + h > y2) ? y + h : y2; + + impl->dirty_x = new_x1; + impl->dirty_y = new_y1; + impl->dirty_w = new_x2 - new_x1; + impl->dirty_h = new_y2 - new_y1; + } +} + +static esp_err_t rm690b0_flush_region(rm690b0_rm690b0_obj_t *self, + mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, bool skip_final_delay) { + (void)skip_final_delay; + + if (width <= 0 || height <= 0) { + return ESP_OK; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->panel_handle == NULL || impl->framebuffer == NULL) { + return ESP_ERR_INVALID_STATE; + } + + mp_int_t fx = x; + mp_int_t fy = y; + mp_int_t fw = width; + mp_int_t fh = height; + + if (!expand_even_region(&fx, &fy, &fw, &fh)) { + return ESP_OK; + } + + size_t fb_stride = RM690B0_PANEL_WIDTH; + size_t fw_sz = (size_t)fw; + size_t fh_sz = (size_t)fh; + + size_t available_pixels = RM690B0_MAX_CHUNK_PIXELS; + if (impl->chunk_buffers[0] != NULL) { + available_pixels = impl->chunk_buffer_pixels; + } + + size_t max_chunk_height = available_pixels / fw_sz; + if (max_chunk_height == 0) { + max_chunk_height = 1; + } + + size_t chunk_height = fh_sz; + if (chunk_height > max_chunk_height) { + chunk_height = max_chunk_height; + } + if (chunk_height == 0) { + chunk_height = 1; + } + if (chunk_height & 1) { + if (chunk_height < fh_sz) { + chunk_height += 1; + } else if (chunk_height > 1) { + chunk_height -= 1; + } + } + + size_t max_chunk_pixels = fw_sz * chunk_height; + + bool use_static_buffers = (impl->chunk_buffers[0] != NULL && + impl->chunk_buffers[1] != NULL && + impl->chunk_buffer_pixels >= max_chunk_pixels); + + uint16_t *alloc_buffer = NULL; + if (!use_static_buffers) { + alloc_buffer = heap_caps_malloc(max_chunk_pixels * sizeof(uint16_t), MALLOC_CAP_DMA); + if (alloc_buffer == NULL) { + return ESP_ERR_NO_MEM; + } + } + + esp_err_t ret = ESP_OK; + uint16_t *framebuffer = impl->framebuffer; + int buf_idx = 0; + bool direct_dma = (fx == 0 && fw == RM690B0_PANEL_WIDTH && x == 0 && width == RM690B0_PANEL_WIDTH); + + for (mp_int_t start_y = fy; start_y < fy + fh && ret == ESP_OK; start_y += (mp_int_t)chunk_height) { + size_t rows_this_chunk = (size_t)((fy + fh) - start_y); + if (rows_this_chunk > chunk_height) { + rows_this_chunk = chunk_height; + } + + rm690b0_wait_for_dma_slot(impl); + + const void *dma_buffer = NULL; + uint8_t pending_id = RM690B0_PENDING_BUFFER_FRAMEBUFFER; + + if (direct_dma) { + dma_buffer = framebuffer + (size_t)start_y * fb_stride; + } else { + uint16_t *current_buffer = NULL; + if (use_static_buffers) { + uint8_t current_idx = (uint8_t)buf_idx; + while (impl->dma_buffer_in_use[current_idx]) { + rm690b0_wait_for_dma_completion(impl); + } + current_buffer = impl->chunk_buffers[current_idx]; + impl->dma_buffer_in_use[current_idx] = true; + pending_id = current_idx; + buf_idx = (buf_idx + 1) % 2; + } else { + while (impl->dma_alloc_buffer_in_use) { + rm690b0_wait_for_dma_completion(impl); + } + current_buffer = alloc_buffer; + impl->dma_alloc_buffer_in_use = true; + pending_id = RM690B0_PENDING_BUFFER_ALLOC; + } + + dma_buffer = current_buffer; + + if (x == 0 && width == RM690B0_PANEL_WIDTH) { + size_t bytes_per_row = fb_stride * sizeof(uint16_t); + size_t chunk_bytes = rows_this_chunk * bytes_per_row; + const uint16_t *src = framebuffer + (size_t)start_y * fb_stride; + memcpy(current_buffer, src, chunk_bytes); + } else { + size_t dest_index = 0; + for (size_t row = 0; row < rows_this_chunk; row++) { + mp_int_t phys_row = start_y + (mp_int_t)row; + mp_int_t src_row = phys_row; + if (src_row < 0) { + src_row = 0; + } else if (src_row >= RM690B0_PANEL_HEIGHT) { + src_row = RM690B0_PANEL_HEIGHT - 1; + } + + const uint16_t *row_base = framebuffer + (size_t)src_row * fb_stride; + mp_int_t dest_col = 0; + mp_int_t flush_end_x = fx + fw; + + mp_int_t src_left = x; + if (src_left < 0) { + src_left = 0; + } + mp_int_t src_right = x + width - 1; + if (src_right >= RM690B0_PANEL_WIDTH) { + src_right = RM690B0_PANEL_WIDTH - 1; + } + + for (mp_int_t phys_col = fx; phys_col < src_left; phys_col++) { + mp_int_t safe_col = (phys_col < 0) ? 0 : ((phys_col >= RM690B0_PANEL_WIDTH) ? RM690B0_PANEL_WIDTH - 1 : phys_col); + current_buffer[dest_index + dest_col++] = row_base[safe_col]; + } + + if (src_left <= src_right) { + size_t middle_len = (size_t)(src_right - src_left + 1); + memcpy(¤t_buffer[dest_index + dest_col], &row_base[src_left], middle_len * sizeof(uint16_t)); + dest_col += (mp_int_t)middle_len; + } + + for (mp_int_t phys_col = src_right + 1; phys_col < flush_end_x; phys_col++) { + mp_int_t safe_col = (phys_col < 0) ? 0 : ((phys_col >= RM690B0_PANEL_WIDTH) ? RM690B0_PANEL_WIDTH - 1 : phys_col); + current_buffer[dest_index + dest_col++] = row_base[safe_col]; + } + dest_index += fw_sz; + } + } + } + + ret = esp_lcd_panel_draw_bitmap( + impl->panel_handle, + fx, + start_y, + fx + fw, + start_y + (mp_int_t)rows_this_chunk, + dma_buffer); + + if (ret != ESP_OK) { + if (!direct_dma) { + if (pending_id < 2) { + impl->dma_buffer_in_use[pending_id] = false; + } else if (pending_id == RM690B0_PENDING_BUFFER_ALLOC) { + impl->dma_alloc_buffer_in_use = false; + } + } + break; + } + + rm690b0_dma_pending_push(&impl->dma_pending, pending_id); + impl->dma_inflight++; + if (!use_static_buffers && !direct_dma) { + rm690b0_wait_for_dma_completion(impl); + } + } + + if (!use_static_buffers && alloc_buffer != NULL) { + // Ensure the last dynamic transfer is complete before freeing. + while (impl->dma_alloc_buffer_in_use) { + rm690b0_wait_for_dma_completion(impl); + } + } + + if (alloc_buffer != NULL) { + heap_caps_free(alloc_buffer); + } + + return ret; +} + +void common_hal_rm690b0_rm690b0_construct(rm690b0_rm690b0_obj_t *self) { + self->initialized = false; + // Start in landscape mode (rotation 0) - display is 600x450 + self->width = RM690B0_PANEL_WIDTH; + self->height = RM690B0_PANEL_HEIGHT; + self->rotation = 0; + self->brightness_raw = 0xFF; + self->font_id = RM690B0_FONT_8x8_MONO; // Initialize with default font + self->impl = m_malloc(sizeof(rm690b0_impl_t)); + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + impl->io_handle = NULL; + impl->panel_handle = NULL; + impl->bus_initialized = false; + impl->chunk_buffers[0] = NULL; + impl->chunk_buffers[1] = NULL; + impl->chunk_buffer_pixels = 0; + impl->framebuffer = NULL; + impl->framebuffer_pixels = 0; + impl->framebuffer_front = NULL; + impl->double_buffered = false; + impl->circle_span_cache = NULL; + impl->circle_span_capacity = 0; + + // Initialize dirty region tracking + impl->dirty_region_valid = false; + impl->dirty_x = 0; + impl->dirty_y = 0; + impl->dirty_w = 0; + impl->dirty_h = 0; + + // Create synchronization semaphore (counting, one slot per queued transfer) + impl->transfer_done_sem = xSemaphoreCreateCounting(RM690B0_PANEL_IO_QUEUE_DEPTH, 0); + if (impl->transfer_done_sem == NULL) { + m_free(impl); + self->impl = NULL; + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to create DMA semaphore")); + } + impl->dma_buffer_in_use[0] = false; + impl->dma_buffer_in_use[1] = false; + impl->dma_alloc_buffer_in_use = false; + impl->dma_inflight = 0; + rm690b0_dma_pending_init(&impl->dma_pending); + + // Track this instance as the singleton + rm690b0_singleton = self; + + ESP_LOGI(TAG, "RM690B0 module constructed"); +} + +void common_hal_rm690b0_rm690b0_deinit(rm690b0_rm690b0_obj_t *self) { + // Early safety checks + if (!self) { + ESP_LOGW(TAG, "deinit called with NULL self pointer"); + return; + } + + if (!self->initialized) { + ESP_LOGI(TAG, "deinit called on already deinitialized instance"); + return; + } + + ESP_LOGI(TAG, "Starting RM690B0 deinit"); + + // Check if impl is valid + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (!impl) { + ESP_LOGW(TAG, "deinit: impl pointer is NULL, nothing to free"); + self->initialized = false; + if (rm690b0_singleton == self) { + rm690b0_singleton = NULL; + } + return; + } + + // Clear singleton reference + if (rm690b0_singleton == self) { + rm690b0_singleton = NULL; + } + + // Mark as uninitialized early to prevent re-entry + self->initialized = false; + + // Clear screen to black before freeing resources + if (impl->panel_handle != NULL && impl->framebuffer != NULL) { + ESP_LOGI(TAG, "Clearing display to black before deinit"); + + // Fill framebuffer with black + size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; + memset(impl->framebuffer, 0, framebuffer_pixels * sizeof(uint16_t)); + + // Flush to display + esp_err_t ret = rm690b0_flush_region(self, 0, 0, RM690B0_PANEL_WIDTH, RM690B0_PANEL_HEIGHT, false); + if (ret == ESP_OK) { + // Brief delay to ensure screen update completes + rm690b0_wait_for_all_dma(impl); + vTaskDelay(pdMS_TO_TICKS(10)); + ESP_LOGI(TAG, "Screen cleared successfully"); + } else { + ESP_LOGW(TAG, "Failed to clear screen before deinit (non-critical)"); + } + } + + // Free memory buffers + rm690b0_wait_for_all_dma(impl); + + if (impl->framebuffer_front) { + ESP_LOGI(TAG, "Freeing front framebuffer"); + heap_caps_free(impl->framebuffer_front); + impl->framebuffer_front = NULL; + impl->double_buffered = false; + } + + if (impl->framebuffer) { + ESP_LOGI(TAG, "Freeing back framebuffer"); + heap_caps_free(impl->framebuffer); + impl->framebuffer = NULL; + impl->framebuffer_pixels = 0; + } + + if (impl->chunk_buffers[0]) { + ESP_LOGI(TAG, "Freeing chunk buffer A"); + heap_caps_free(impl->chunk_buffers[0]); + impl->chunk_buffers[0] = NULL; + } + if (impl->chunk_buffers[1]) { + ESP_LOGI(TAG, "Freeing chunk buffer B"); + heap_caps_free(impl->chunk_buffers[1]); + impl->chunk_buffers[1] = NULL; + } + impl->chunk_buffer_pixels = 0; + + if (impl->circle_span_cache) { + ESP_LOGI(TAG, "Freeing cached circle spans"); + heap_caps_free(impl->circle_span_cache); + impl->circle_span_cache = NULL; + impl->circle_span_capacity = 0; + } + + if (impl->transfer_done_sem) { + vSemaphoreDelete(impl->transfer_done_sem); + impl->transfer_done_sem = NULL; + } + + // Turn off display power before freeing hardware resources + if (LCD_PWR_PIN != GPIO_NUM_NC) { + ESP_LOGI(TAG, "Turning off display power"); + int off_level = LCD_PWR_ON_LEVEL ? 0 : 1; + gpio_set_level(LCD_PWR_PIN, off_level); + vTaskDelay(pdMS_TO_TICKS(5)); + } + + // Delete LCD panel (must be before IO handle) + if (impl->panel_handle != NULL) { + ESP_LOGI(TAG, "Deleting LCD panel handle"); + esp_err_t ret = esp_lcd_panel_del(impl->panel_handle); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to delete LCD panel: %s", esp_err_to_name(ret)); + } + impl->panel_handle = NULL; + } + + // Delete LCD IO handle (must be before SPI bus) + if (impl->io_handle != NULL) { + ESP_LOGI(TAG, "Deleting LCD IO handle"); + esp_err_t ret = esp_lcd_panel_io_del(impl->io_handle); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to delete LCD IO: %s", esp_err_to_name(ret)); + } + impl->io_handle = NULL; + } + + // Free SPI bus (must be LAST, after all users are deleted) + if (impl->bus_initialized) { + ESP_LOGI(TAG, "Freeing SPI bus"); + esp_err_t ret = spi_bus_free(SPI2_HOST); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to free SPI bus: %s (may be in use)", esp_err_to_name(ret)); + } + impl->bus_initialized = false; + } + + // Prevent use-after-free + self->impl = NULL; + + ESP_LOGI(TAG, "RM690B0 deinit complete - all resources freed"); +} + +void common_hal_rm690b0_rm690b0_deinit_all(void) { + // Static deinit for REPL convenience - cleans up any active instance + if (rm690b0_singleton != NULL) { + ESP_LOGI(TAG, "Static deinit: cleaning up singleton instance"); + common_hal_rm690b0_rm690b0_deinit(rm690b0_singleton); + rm690b0_singleton = NULL; + ESP_LOGI(TAG, "Static deinit: singleton cleaned up"); + } else { + ESP_LOGI(TAG, "Static deinit: no active instance to clean up"); + } +} + +// Helper function to expose panel handle for LVGL integration +esp_lcd_panel_handle_t rm690b0_get_panel_handle(void) { + if (rm690b0_singleton == NULL) { + ESP_LOGW(TAG, "rm690b0_get_panel_handle: no active display instance"); + return NULL; + } + + if (!rm690b0_singleton->initialized) { + ESP_LOGW(TAG, "rm690b0_get_panel_handle: display not initialized"); + return NULL; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)rm690b0_singleton->impl; + if (impl == NULL) { + ESP_LOGE(TAG, "rm690b0_get_panel_handle: impl is NULL"); + return NULL; + } + + return impl->panel_handle; +} + +void common_hal_rm690b0_rm690b0_init_display(rm690b0_rm690b0_obj_t *self) { + if (self->initialized) { + ESP_LOGW(TAG, "Display already initialized"); + return; + } + + ESP_LOGI(TAG, "Initializing RM690B0 display (%s mode)", LCD_USE_QSPI ? "QSPI" : "SPI"); + + // Enable display power if a dedicated control pin is provided + if (LCD_PWR_PIN != GPIO_NUM_NC) { + gpio_config_t io_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = (1ULL << LCD_PWR_PIN), + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .pull_up_en = GPIO_PULLUP_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&io_conf); + gpio_set_level(LCD_PWR_PIN, LCD_PWR_ON_LEVEL); + ESP_LOGI(TAG, "Display power enabled on GPIO%d", LCD_PWR_PIN); + } else { + ESP_LOGI(TAG, "No display power control pin configured; assuming panel is already powered"); + } + + // Wait for power to stabilize (longer wait for display power-up) + vTaskDelay(pdMS_TO_TICKS(200)); + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + esp_err_t ret = ESP_OK; + + if (!impl->bus_initialized) { + // Initialize SPI bus using configuration macros from esp_lcd_rm690b0.h + // These macros correctly configure either QSPI (4 data lines) or standard SPI (1 data line) + // QSPI: Uses data0-data3 for 4-bit parallel data transfer (faster) + // SPI: Uses mosi (data0) for single-bit serial data transfer (compatible) + size_t max_transfer_bytes = RM690B0_MAX_CHUNK_PIXELS * sizeof(uint16_t); + const spi_bus_config_t buscfg = LCD_USE_QSPI ? + RM690B0_PANEL_BUS_QSPI_CONFIG(LCD_SCK_PIN, LCD_D0_PIN, LCD_D1_PIN, LCD_D2_PIN, LCD_D3_PIN, max_transfer_bytes) : + RM690B0_PANEL_BUS_SPI_CONFIG(LCD_SCK_PIN, LCD_D0_PIN, max_transfer_bytes); + ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to initialize SPI bus: %s"), esp_err_to_name(ret)); + return; + } + impl->bus_initialized = true; + ESP_LOGI(TAG, "%s bus initialized", LCD_USE_QSPI ? "QSPI" : "SPI"); + } + + // Configure panel I/O layer using macros from esp_lcd_rm690b0.h + // These macros set up the correct communication protocol: + // - QSPI mode: 32-bit commands, no DC pin, quad_mode flag enabled + // - SPI mode: 8-bit commands, DC pin required, standard SPI + // Both use 8-bit parameters and 10-depth transaction queue + // We provide a callback to release the semaphore when transfer completes + if (LCD_USE_QSPI) { + const esp_lcd_panel_io_spi_config_t io_config = RM690B0_PANEL_IO_QSPI_CONFIG(LCD_CS_PIN, rm690b0_on_color_trans_done, impl, LCD_PIXEL_CLOCK_HZ); + ret = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &impl->io_handle); + } else { + const esp_lcd_panel_io_spi_config_t io_config = RM690B0_PANEL_IO_SPI_CONFIG(LCD_CS_PIN, -1, rm690b0_on_color_trans_done, impl, LCD_PIXEL_CLOCK_HZ); + ret = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &impl->io_handle); + } + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create panel I/O: %s", esp_err_to_name(ret)); + spi_bus_free(SPI2_HOST); + impl->bus_initialized = false; + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to create panel I/O")); + return; + } + ESP_LOGI(TAG, "Panel I/O created"); + + // Configure vendor-specific settings for RM690B0 + rm690b0_vendor_config_t vendor_config = { + .init_cmds = lcd_init_cmds, + .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(rm690b0_lcd_init_cmd_t), + .flags = { + .use_qspi_interface = LCD_USE_QSPI, + }, + }; + + // Configure panel device - exact configuration from board.c.old + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = LCD_RST_PIN, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = LCD_BIT_PER_PIXEL, + .flags = { + .reset_active_high = false, + }, + .vendor_config = &vendor_config, + }; + + ret = esp_lcd_new_panel_rm690b0(impl->io_handle, &panel_config, &impl->panel_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create RM690B0 panel: %s", esp_err_to_name(ret)); + esp_lcd_panel_io_del(impl->io_handle); + impl->io_handle = NULL; + spi_bus_free(SPI2_HOST); + impl->bus_initialized = false; + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to create RM690B0 panel")); + return; + } + ESP_LOGI(TAG, "RM690B0 panel created"); + + // Initialize the display - exact sequence from board.c.old + ret = esp_lcd_panel_reset(impl->panel_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to reset panel: %s", esp_err_to_name(ret)); + goto cleanup; + } + ESP_LOGI(TAG, "Panel reset complete"); + + ret = esp_lcd_panel_init(impl->panel_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize panel: %s", esp_err_to_name(ret)); + goto cleanup; + } + ESP_LOGI(TAG, "Panel initialization complete"); + + // Set the gap after init - exact values from board.c.old + esp_lcd_panel_set_gap(impl->panel_handle, RM690B0_X_GAP, RM690B0_Y_GAP); + ESP_LOGI(TAG, "Display gap set to (0, 16)"); + + // Turn on the display + ret = esp_lcd_panel_disp_on_off(impl->panel_handle, true); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to turn on display: %s", esp_err_to_name(ret)); + goto cleanup; + } + ESP_LOGI(TAG, "Display turned on"); + + // Attempt to allocate static chunk buffers with a downgrade strategy + // Priority 1: Full size in Internal RAM (fastest) - unlikely for 450px wide high colors + // Priority 2: Full size in PSRAM (standard) + // Priority 3: Reduced size in Internal RAM or PSRAM + if (impl->chunk_buffers[0] == NULL) { + size_t current_chunk_rows = RM690B0_MAX_CHUNK_ROWS; + + while (current_chunk_rows >= 2) { + size_t buf_pixels = (size_t)RM690B0_PANEL_WIDTH * current_chunk_rows; + size_t buf_size = buf_pixels * sizeof(uint16_t); + + // Try explicit internal first for smaller sizes or just best effort caps? + // We use MALLOC_CAP_DMA which allows both internal and PSRAM, but + // heap_caps_malloc usually prefers internal if available and small enough. + // For large buffers, we might want to let it go to PSRAM to save internal for stack/heap. + // Let's rely on MALLOC_CAP_DMA. + + impl->chunk_buffers[0] = heap_caps_malloc(buf_size, MALLOC_CAP_DMA); + impl->chunk_buffers[1] = heap_caps_malloc(buf_size, MALLOC_CAP_DMA); + + if (impl->chunk_buffers[0] != NULL && impl->chunk_buffers[1] != NULL) { + // Success + impl->chunk_buffer_pixels = buf_pixels; + ESP_LOGI(TAG, "Allocated dual DMA chunk buffers (%zu pixels each, %zu rows)", + impl->chunk_buffer_pixels, current_chunk_rows); + break; + } + + // Allocation failed, cleanup partial and try smaller + if (impl->chunk_buffers[0]) { + heap_caps_free(impl->chunk_buffers[0]); + } + if (impl->chunk_buffers[1]) { + heap_caps_free(impl->chunk_buffers[1]); + } + impl->chunk_buffers[0] = NULL; + impl->chunk_buffers[1] = NULL; + + // Reduce size + current_chunk_rows /= 2; + } + + if (impl->chunk_buffers[0] == NULL) { + impl->chunk_buffer_pixels = 0; + ESP_LOGW(TAG, "Unable to allocate dual DMA chunk buffers; operations will use slower allocation per draw"); + } + } + + size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; + if (impl->framebuffer == NULL) { + impl->framebuffer = heap_caps_malloc(framebuffer_pixels * sizeof(uint16_t), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (impl->framebuffer == NULL) { + ESP_LOGE(TAG, "Unable to allocate PSRAM framebuffer"); + goto cleanup; + } + impl->framebuffer_pixels = framebuffer_pixels; + ESP_LOGI(TAG, "Allocated back framebuffer (%zu pixels, %zu KB)", + framebuffer_pixels, (framebuffer_pixels * sizeof(uint16_t)) / 1024); + } + + // Front buffer will be allocated lazily on first swap_buffers() call + // This avoids 540KB memory overhead unless tear-free rendering is actually used + + // Initialize back buffer with black + for (size_t i = 0; i < framebuffer_pixels; i++) { + impl->framebuffer[i] = 0x0000; + } + esp_err_t clear_ret = rm690b0_flush_region(self, 0, 0, RM690B0_PANEL_WIDTH, RM690B0_PANEL_HEIGHT, false); + if (clear_ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to clear display: %s"), esp_err_to_name(clear_ret)); + return; + } + ESP_LOGI(TAG, "Display filled with black"); + + self->rotation = 0; + self->width = RM690B0_PANEL_WIDTH; + self->height = RM690B0_PANEL_HEIGHT; + self->brightness_raw = 0xFF; + self->initialized = true; + ESP_LOGI(TAG, "RM690B0 display initialization complete"); + return; + +cleanup: + // Free resources in reverse order + if (impl->chunk_buffers[0]) { + heap_caps_free(impl->chunk_buffers[0]); + impl->chunk_buffers[0] = NULL; + } + if (impl->chunk_buffers[1]) { + heap_caps_free(impl->chunk_buffers[1]); + impl->chunk_buffers[1] = NULL; + } + impl->chunk_buffer_pixels = 0; + + // Panel handle must be valid if we got here (checked before reset/init) + if (impl->panel_handle) { + esp_lcd_panel_del(impl->panel_handle); + impl->panel_handle = NULL; + } + + if (impl->io_handle) { + esp_lcd_panel_io_del(impl->io_handle); + impl->io_handle = NULL; + } + + if (impl->bus_initialized) { + spi_bus_free(SPI2_HOST); + impl->bus_initialized = false; + } + + if (ret == ESP_OK) { + // Must be memory error if ret is OK but we jumped to cleanup + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Display initialization failed: Out of memory")); + } else { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Display initialization failed: %s"), esp_err_to_name(ret)); + } +} + +static void rm690b0_fill_color_direct(rm690b0_rm690b0_obj_t *self, uint16_t color) { + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->panel_handle == NULL || impl->transfer_done_sem == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + uint16_t swapped = RGB565_SWAP_GB(color); + size_t dma_lines = RM690B0_MAX_CHUNK_ROWS; + if (dma_lines > RM690B0_PANEL_HEIGHT) { + dma_lines = RM690B0_PANEL_HEIGHT; + } + const size_t line_pixels = RM690B0_PANEL_WIDTH; + const size_t dma_pixels = line_pixels * dma_lines; + const size_t dma_bytes = dma_pixels * sizeof(uint16_t); + + uint16_t *dma_buffer = heap_caps_malloc(dma_bytes, MALLOC_CAP_DMA); + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("fill_color: unable to allocate DMA buffer")); + return; + } + + for (size_t i = 0; i < dma_pixels; i++) { + dma_buffer[i] = swapped; + } + + size_t rows_remaining = RM690B0_PANEL_HEIGHT; + mp_int_t current_y = 0; + esp_err_t ret = ESP_OK; + + while (rows_remaining > 0 && ret == ESP_OK) { + size_t rows_this_pass = rows_remaining > dma_lines ? dma_lines : rows_remaining; + + // Wait for queue slot before submitting + rm690b0_wait_for_dma_slot(impl); + + ret = esp_lcd_panel_draw_bitmap( + impl->panel_handle, + 0, + current_y, + RM690B0_PANEL_WIDTH, + current_y + (mp_int_t)rows_this_pass, + dma_buffer); + + if (ret != ESP_OK) { + break; + } + + rm690b0_dma_pending_push(&impl->dma_pending, RM690B0_PENDING_BUFFER_TEMP); + impl->dma_inflight++; + current_y += (mp_int_t)rows_this_pass; + rows_remaining -= rows_this_pass; + } + + rm690b0_wait_for_all_dma(impl); + if (ret == ESP_OK && impl->framebuffer != NULL) { + rm690b0_fill_rect_framebuffer(impl, 0, 0, + RM690B0_PANEL_WIDTH, RM690B0_PANEL_HEIGHT, swapped); + impl->dirty_region_valid = false; + } + + heap_caps_free(dma_buffer); + + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("fill_color failed: %s"), esp_err_to_name(ret)); + } +} + +static esp_err_t rm690b0_fill_rect_direct_fullwidth(rm690b0_rm690b0_obj_t *self, + mp_int_t start_y, mp_int_t rows, uint16_t swapped_color) { + + if (rows <= 0) { + return ESP_OK; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->panel_handle == NULL || impl->transfer_done_sem == NULL) { + return ESP_ERR_INVALID_STATE; + } + + size_t dma_lines = RM690B0_MAX_CHUNK_ROWS; + if (dma_lines > (size_t)rows) { + dma_lines = rows; + } + const size_t line_pixels = RM690B0_PANEL_WIDTH; + const size_t dma_pixels = line_pixels * dma_lines; + const size_t dma_bytes = dma_pixels * sizeof(uint16_t); + + uint16_t *dma_buffer = heap_caps_malloc(dma_bytes, MALLOC_CAP_DMA); + if (dma_buffer == NULL) { + return ESP_ERR_NO_MEM; + } + + for (size_t i = 0; i < dma_pixels; i++) { + dma_buffer[i] = swapped_color; + } + + size_t rows_remaining = (size_t)rows; + mp_int_t current_y = start_y; + esp_err_t ret = ESP_OK; + + while (rows_remaining > 0 && ret == ESP_OK) { + size_t rows_this_pass = rows_remaining > dma_lines ? dma_lines : rows_remaining; + + rm690b0_wait_for_dma_slot(impl); + + ret = esp_lcd_panel_draw_bitmap( + impl->panel_handle, + 0, + current_y, + RM690B0_PANEL_WIDTH, + current_y + (mp_int_t)rows_this_pass, + dma_buffer); + + if (ret != ESP_OK) { + break; + } + + rm690b0_dma_pending_push(&impl->dma_pending, RM690B0_PENDING_BUFFER_TEMP); + impl->dma_inflight++; + current_y += (mp_int_t)rows_this_pass; + rows_remaining -= rows_this_pass; + } + + rm690b0_wait_for_all_dma(impl); + heap_caps_free(dma_buffer); + + if (ret == ESP_OK && impl->framebuffer != NULL) { + rm690b0_fill_rect_framebuffer(impl, 0, start_y, RM690B0_PANEL_WIDTH, rows, swapped_color); + } + + return ret; +} + +void common_hal_rm690b0_rm690b0_fill_color(rm690b0_rm690b0_obj_t *self, uint16_t color) { + CHECK_INITIALIZED(); + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl != NULL && !impl->double_buffered) { + rm690b0_fill_color_direct(self, color); + return; + } + + common_hal_rm690b0_rm690b0_fill_rect(self, 0, 0, self->width, self->height, color); +} + +void common_hal_rm690b0_rm690b0_pixel(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t color) { + CHECK_INITIALIZED(); + + mp_int_t bx = x; + mp_int_t by = y; + mp_int_t bw = 1; + mp_int_t bh = 1; + + if (!clip_logical_rect(self, &bx, &by, &bw, &bh)) { + return; + } + if (!map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { + return; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + uint16_t swapped_color = RGB565_SWAP_GB(color); + size_t fb_stride = RM690B0_PANEL_WIDTH; + impl->framebuffer[(size_t)by * fb_stride + bx] = swapped_color; + + // Mark region as dirty for next swap + mark_dirty_region(impl, bx, by, bw, bh); + + // Only flush immediately if not double-buffered + // When double-buffered, swap_buffers() will handle the flush + if (!impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, bx, by, bw, bh, false); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw pixel: %s"), esp_err_to_name(ret)); + } + } +} + +static void rm690b0_fill_rect_framebuffer(rm690b0_impl_t *impl, + mp_int_t bx, mp_int_t by, mp_int_t bw, mp_int_t bh, uint16_t swapped_color) { + + uint16_t *base_ptr = impl->framebuffer + (size_t)by * RM690B0_PANEL_WIDTH + bx; + + for (mp_int_t col = 0; col < bw; col++) { + base_ptr[col] = swapped_color; + } + + mp_int_t filled_rows = 1; + size_t row_bytes = (size_t)bw * sizeof(uint16_t); + size_t fb_stride = RM690B0_PANEL_WIDTH; + + while (filled_rows < bh) { + mp_int_t rows_to_copy = filled_rows; + if (filled_rows + rows_to_copy > bh) { + rows_to_copy = bh - filled_rows; + } + + for (mp_int_t i = 0; i < rows_to_copy; i++) { + uint16_t *src_row = base_ptr + (size_t)i * fb_stride; + uint16_t *dest_row = base_ptr + (size_t)(filled_rows + i) * fb_stride; + memcpy(dest_row, src_row, row_bytes); + } + + filled_rows += rows_to_copy; + } +} + +void common_hal_rm690b0_rm690b0_fill_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color) { + CHECK_INITIALIZED(); + + mp_int_t bx = x; + mp_int_t by = y; + mp_int_t bw = width; + mp_int_t bh = height; + + if (!clip_logical_rect(self, &bx, &by, &bw, &bh)) { + return; + } + if (!map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { + return; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + uint16_t swapped_color = RGB565_SWAP_GB(color); + + if (!impl->double_buffered && bx == 0 && bw == RM690B0_PANEL_WIDTH) { + esp_err_t direct_ret = rm690b0_fill_rect_direct_fullwidth(self, by, bh, swapped_color); + if (direct_ret == ESP_OK) { + mark_dirty_region(impl, bx, by, bw, bh); + return; + } + ESP_LOGW(TAG, "Full-width fast fill_rect path failed (%s) – falling back", + esp_err_to_name(direct_ret)); + } + + rm690b0_fill_rect_framebuffer(impl, bx, by, bw, bh, swapped_color); + + // Mark region as dirty for next swap + mark_dirty_region(impl, bx, by, bw, bh); + + // Only flush immediately if not double-buffered + // When double-buffered, swap_buffers() will handle the flush + if (!impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, bx, by, bw, bh, false); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw fill_rect: %s"), esp_err_to_name(ret)); + } + } +} + +// ============================================================================ +// IMAGE SUPPORT +// ============================================================================ + +#pragma pack(push, 1) +typedef struct { + uint16_t type; // Magic identifier: 0x4d42 + uint32_t size; // File size in bytes + uint16_t reserved1; + uint16_t reserved2; + uint32_t offset; // Offset to image data in bytes from beginning of file + uint32_t header_size; // Header size in bytes + int32_t width; // Width of the image + int32_t height; // Height of the image + uint16_t planes; // Number of color planes + uint16_t bpp; // Bits per pixel + uint32_t compression; // Compression type + uint32_t image_size; // Image size in bytes + int32_t x_res; // Pixels per meter + int32_t y_res; // Pixels per meter + uint32_t n_colors; // Number of colors + uint32_t important_colors; // Important colors +} bmp_header_t; +#pragma pack(pop) + +void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data) { + CHECK_INITIALIZED(); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(bmp_data, &bufinfo, MP_BUFFER_READ); + + if (bufinfo.len < sizeof(bmp_header_t)) { + mp_raise_ValueError(MP_ERROR_TEXT("BMP data too small")); + return; + } + + const bmp_header_t *header = (const bmp_header_t *)bufinfo.buf; + + if (header->type != 0x4D42) { // 'BM' + mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP header")); + return; + } + + if (header->bpp != 24 && header->bpp != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("Only 16-bit and 24-bit BMP supported")); + return; + } + + if (header->compression != 0 && header->compression != 3) { + mp_raise_ValueError(MP_ERROR_TEXT("Compressed BMP not supported")); + return; + } + + mp_int_t width = header->width; + mp_int_t height = abs(header->height); + bool top_down = (header->height < 0); + size_t data_offset = header->offset; + + if (data_offset >= bufinfo.len) { + mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP data offset")); + return; + } + + // Clip to screen (logical coordinates) + mp_int_t clip_x = x; + mp_int_t clip_y = y; + mp_int_t clip_w = width; + mp_int_t clip_h = height; + + if (!clip_logical_rect(self, &clip_x, &clip_y, &clip_w, &clip_h)) { + return; + } + + // Calculate source offset based on clipping + mp_int_t x_offset = clip_x - x; + mp_int_t y_offset = clip_y - y; + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + const uint8_t *src_data = (const uint8_t *)bufinfo.buf + data_offset; + + // BMP rows are padded to 4 bytes + int row_padding = (4 - ((width * (header->bpp / 8)) % 4)) % 4; + int src_stride = width * (header->bpp / 8) + row_padding; + + // Optimized path for rotation 0 + if (self->rotation == 0) { + size_t fb_stride = RM690B0_PANEL_WIDTH; + uint16_t *fb = impl->framebuffer; + + for (int row = 0; row < clip_h; row++) { + // Source row calculation + int src_y = y_offset + row; + int src_row_idx = top_down ? src_y : (height - 1 - src_y); + const uint8_t *row_ptr = src_data + (size_t)src_row_idx * src_stride + (size_t)x_offset * (header->bpp / 8); + + // Destination row + uint16_t *dst_ptr = fb + (size_t)(clip_y + row) * fb_stride + clip_x; + + if (header->bpp == 24) { + for (int col = 0; col < clip_w; col++) { + uint8_t b = row_ptr[col * 3]; + uint8_t g = row_ptr[col * 3 + 1]; + uint8_t r = row_ptr[col * 3 + 2]; + // Convert RGB888 to RGB565 (swapped for display) + uint16_t rgb = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); + dst_ptr[col] = RGB565_SWAP_GB(rgb); + } + } else { // 16-bit + for (int col = 0; col < clip_w; col++) { + uint16_t val = row_ptr[col * 2] | (row_ptr[col * 2 + 1] << 8); + dst_ptr[col] = RGB565_SWAP_GB(val); + } + } + } + } else { + // Rotated path (pixel by pixel, but clipped) + for (int row = 0; row < clip_h; row++) { + int src_y = y_offset + row; + int src_row_idx = top_down ? src_y : (height - 1 - src_y); + const uint8_t *row_ptr = src_data + (size_t)src_row_idx * src_stride + (size_t)x_offset * (header->bpp / 8); + + for (int col = 0; col < clip_w; col++) { + uint16_t color565; + if (header->bpp == 24) { + uint8_t b = row_ptr[col * 3]; + uint8_t g = row_ptr[col * 3 + 1]; + uint8_t r = row_ptr[col * 3 + 2]; + uint16_t rgb = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); + color565 = RGB565_SWAP_GB(rgb); + } else { + uint16_t val = row_ptr[col * 2] | (row_ptr[col * 2 + 1] << 8); + color565 = RGB565_SWAP_GB(val); + } + rm690b0_write_pixel_rotated(self, impl, clip_x + col, clip_y + row, color565); + } + } + } + + // Mark dirty region + mp_int_t bx = clip_x, by = clip_y, bw = clip_w, bh = clip_h; + if (map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { + mark_dirty_region(impl, bx, by, bw, bh); + if (!impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, bx, by, bw, bh, false); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw BMP: %s"), esp_err_to_name(ret)); + } + } + } +} + +static esp_err_t rm690b0_jpeg_on_block(intptr_t ctx_ptr, + uint32_t block_top, uint32_t block_left, + uint32_t block_bottom, uint32_t block_right, + const uint16_t *pixels) { + + rm690b0_jpeg_draw_ctx_t *ctx = (rm690b0_jpeg_draw_ctx_t *)ctx_ptr; + rm690b0_impl_t *impl = ctx->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return ESP_ERR_INVALID_ARG; + } + + mp_int_t dest_left = ctx->origin_x + (mp_int_t)block_left; + mp_int_t dest_top = ctx->origin_y + (mp_int_t)block_top; + mp_int_t dest_right = ctx->origin_x + (mp_int_t)block_right; + mp_int_t dest_bottom = ctx->origin_y + (mp_int_t)block_bottom; + + mp_int_t clip_right = ctx->clip_x + ctx->clip_w - 1; + mp_int_t clip_bottom = ctx->clip_y + ctx->clip_h - 1; + + mp_int_t draw_left = dest_left > ctx->clip_x ? dest_left : ctx->clip_x; + mp_int_t draw_top = dest_top > ctx->clip_y ? dest_top : ctx->clip_y; + mp_int_t draw_right = dest_right < clip_right ? dest_right : clip_right; + mp_int_t draw_bottom = dest_bottom < clip_bottom ? dest_bottom : clip_bottom; + + if (draw_left > draw_right || draw_top > draw_bottom) { + return ESP_OK; + } + + mp_int_t block_w = (mp_int_t)(block_right - block_left + 1); + if (block_w <= 0) { + return ESP_OK; + } + + size_t fb_stride = RM690B0_PANEL_WIDTH; + + for (mp_int_t row = draw_top; row <= draw_bottom; row++) { + mp_int_t src_row = row - dest_top; + const uint16_t *row_src = pixels + (size_t)src_row * block_w + (draw_left - dest_left); + + if (ctx->rotation_zero) { + uint16_t *dst = impl->framebuffer + (size_t)row * fb_stride + draw_left; + for (mp_int_t col = draw_left; col <= draw_right; col++) { + dst[col - draw_left] = RGB565_SWAP_GB(*row_src++); + } + } else { + for (mp_int_t col = draw_left; col <= draw_right; col++) { + uint16_t color = RGB565_SWAP_GB(*row_src++); + rm690b0_write_pixel_rotated(ctx->self, impl, col, row, color); + } + } + } + + return ESP_OK; +} + + +void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data) { + CHECK_INITIALIZED(); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(jpeg_data, &bufinfo, MP_BUFFER_READ); + + esp_jpeg_image_cfg_t jpeg_cfg = { + .indata = (uint8_t *)bufinfo.buf, + .indata_size = bufinfo.len, + .out_format = JPEG_IMAGE_FORMAT_RGB565, + .out_scale = JPEG_IMAGE_SCALE_0, + .flags = { .swap_color_bytes = 0 }, // Do not swap in decoder, we handle it manually + .outbuf = NULL, + .outbuf_size = 0, + .user_data = 0, + .on_block = NULL, + }; + + esp_jpeg_image_output_t jpeg_out; + esp_err_t ret = esp_jpeg_get_image_info(&jpeg_cfg, &jpeg_out); + if (ret != ESP_OK) { + mp_raise_ValueError(MP_ERROR_TEXT("Invalid JPEG data")); + return; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + int width = jpeg_out.width; + int height = jpeg_out.height; + + // Clip to screen (logical coordinates) + mp_int_t clip_x = x; + mp_int_t clip_y = y; + mp_int_t clip_w = width; + mp_int_t clip_h = height; + + if (clip_logical_rect(self, &clip_x, &clip_y, &clip_w, &clip_h)) { + rm690b0_jpeg_draw_ctx_t draw_ctx = { + .self = self, + .impl = impl, + .origin_x = x, + .origin_y = y, + .clip_x = clip_x, + .clip_y = clip_y, + .clip_w = clip_w, + .clip_h = clip_h, + .rotation_zero = (self->rotation == 0), + }; + + jpeg_cfg.user_data = (intptr_t)&draw_ctx; + jpeg_cfg.on_block = rm690b0_jpeg_on_block; + + ret = esp_jpeg_decode(&jpeg_cfg, NULL); + if (ret != ESP_OK) { + mp_raise_ValueError(MP_ERROR_TEXT("JPEG decode failed")); + return; + } + + // Mark dirty + mp_int_t bx = clip_x, by = clip_y, bw = clip_w, bh = clip_h; + if (map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { + mark_dirty_region(impl, bx, by, bw, bh); + if (!impl->double_buffered) { + esp_err_t flush_ret = rm690b0_flush_region(self, bx, by, bw, bh, false); + if (flush_ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw JPEG: %s"), esp_err_to_name(flush_ret)); + } + } + } + } +} + +void common_hal_rm690b0_rm690b0_hline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t color) { + common_hal_rm690b0_rm690b0_fill_rect(self, x, y, width, 1, color); +} + +void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t height, mp_int_t color) { + common_hal_rm690b0_rm690b0_fill_rect(self, x, y, 1, height, color); +} + +void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color) { + common_hal_rm690b0_rm690b0_hline(self, x, y, width, color); + common_hal_rm690b0_rm690b0_hline(self, x, y + height - 1, width, color); + common_hal_rm690b0_rm690b0_vline(self, x, y, height, color); + common_hal_rm690b0_rm690b0_vline(self, x + width - 1, y, height, color); +} + +static void rm690b0_draw_line_segment(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color) { + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + return; + } + + uint16_t swapped_color = RGB565_SWAP_GB(color); + size_t fb_stride = RM690B0_PANEL_WIDTH; + + mp_int_t px0, py0, px1, py1; + switch (self->rotation) { + case 90: + px0 = RM690B0_PANEL_WIDTH - y0 - 1; + py0 = x0; + px1 = RM690B0_PANEL_WIDTH - y1 - 1; + py1 = x1; + break; + case 180: + px0 = RM690B0_PANEL_WIDTH - x0 - 1; + py0 = RM690B0_PANEL_HEIGHT - y0 - 1; + px1 = RM690B0_PANEL_WIDTH - x1 - 1; + py1 = RM690B0_PANEL_HEIGHT - y1 - 1; + break; + case 270: + px0 = y0; + py0 = RM690B0_PANEL_HEIGHT - x0 - 1; + px1 = y1; + py1 = RM690B0_PANEL_HEIGHT - x1 - 1; + break; + default: + px0 = x0; + py0 = y0; + px1 = x1; + py1 = y1; + break; + } + + mp_int_t pdx = labs(px1 - px0); + mp_int_t pdy = labs(py1 - py0); + mp_int_t sx = (px0 < px1) ? 1 : -1; + mp_int_t sy = (py0 < py1) ? 1 : -1; + mp_int_t err = pdx - pdy; + + mp_int_t x = px0; + mp_int_t y = py0; + mp_int_t dirty_min_x = x, dirty_min_y = y; + mp_int_t dirty_max_x = x, dirty_max_y = y; + + while (1) { + if (x < dirty_min_x) { + dirty_min_x = x; + } + if (x > dirty_max_x) { + dirty_max_x = x; + } + if (y < dirty_min_y) { + dirty_min_y = y; + } + if (y > dirty_max_y) { + dirty_max_y = y; + } + + if (x >= 0 && x < RM690B0_PANEL_WIDTH && y >= 0 && y < RM690B0_PANEL_HEIGHT) { + impl->framebuffer[(size_t)y * fb_stride + x] = swapped_color; + } + + if (x == px1 && y == py1) { + break; + } + mp_int_t e2 = 2 * err; + if (e2 > -pdy) { + err -= pdy; + x += sx; + } + if (e2 < pdx) { + err += pdx; + y += sy; + } + } + + mp_int_t bx = dirty_min_x; + mp_int_t by = dirty_min_y; + mp_int_t bw = dirty_max_x - dirty_min_x + 1; + mp_int_t bh = dirty_max_y - dirty_min_y + 1; + + if (bx < 0) { + bw += bx; + bx = 0; + } + if (by < 0) { + bh += by; + by = 0; + } + if (bx + bw > RM690B0_PANEL_WIDTH) { + bw = RM690B0_PANEL_WIDTH - bx; + } + if (by + bh > RM690B0_PANEL_HEIGHT) { + bh = RM690B0_PANEL_HEIGHT - by; + } + + if (bw > 0 && bh > 0) { + mark_dirty_region(impl, bx, by, bw, bh); + if (!impl->double_buffered) { + rm690b0_flush_region(self, bx, by, bw, bh, false); + } + } +} + +void common_hal_rm690b0_rm690b0_line(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color) { + CHECK_INITIALIZED(); + + if (x0 == x1) { + if (y1 < y0) { + mp_int_t tmp = y0; + y0 = y1; + y1 = tmp; + } + common_hal_rm690b0_rm690b0_vline(self, x0, y0, y1 - y0 + 1, color); + return; + } + if (y0 == y1) { + if (x1 < x0) { + mp_int_t tmp = x0; + x0 = x1; + x1 = tmp; + } + common_hal_rm690b0_rm690b0_hline(self, x0, y0, x1 - x0 + 1, color); + return; + } + + mp_int_t dx = labs(x1 - x0); + mp_int_t dy = labs(y1 - y0); + mp_int_t line_length = (dx > dy) ? dx : dy; + + const mp_int_t SPLIT_THRESHOLD = 100; + const mp_int_t TARGET_SEGMENT = 50; + + if (line_length > SPLIT_THRESHOLD) { + mp_int_t num_segments = (line_length + TARGET_SEGMENT - 1) / TARGET_SEGMENT; + for (mp_int_t i = 0; i < num_segments; i++) { + mp_int_t seg_x0 = x0 + (x1 - x0) * i / num_segments; + mp_int_t seg_y0 = y0 + (y1 - y0) * i / num_segments; + mp_int_t seg_x1 = x0 + (x1 - x0) * (i + 1) / num_segments; + mp_int_t seg_y1 = y0 + (y1 - y0) * (i + 1) / num_segments; + rm690b0_draw_line_segment(self, seg_x0, seg_y0, seg_x1, seg_y1, color); + } + return; + } + + rm690b0_draw_line_segment(self, x0, y0, x1, y1, color); +} + +void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color) { + CHECK_INITIALIZED(); + if (radius < 0) { + mp_raise_ValueError(MP_ERROR_TEXT("radius must be non-negative")); + return; + } + if (radius == 0) { + common_hal_rm690b0_rm690b0_pixel(self, x, y, color); + return; + } + + + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + uint16_t swapped_color = RGB565_SWAP_GB(color); + size_t fb_stride = RM690B0_PANEL_WIDTH; + + mp_int_t bx = x - radius; + mp_int_t by = y - radius; + mp_int_t bw = radius * 2 + 1; + mp_int_t bh = radius * 2 + 1; + bool circle_fully_inside = (bx >= 0 && by >= 0 && + bx + bw <= self->width && by + bh <= self->height); + + #define RM690B0_DRAW_CIRCLE_LOOP() \ + do { \ + mp_int_t x0 = 0; \ + mp_int_t y0 = radius; \ + mp_int_t d = 1 - radius; \ + while (x0 <= y0) { \ + WRITE_CIRCLE_PIXEL(x + x0, y + y0); \ + WRITE_CIRCLE_PIXEL(x - x0, y + y0); \ + WRITE_CIRCLE_PIXEL(x + x0, y - y0); \ + WRITE_CIRCLE_PIXEL(x - x0, y - y0); \ + WRITE_CIRCLE_PIXEL(x + y0, y + x0); \ + WRITE_CIRCLE_PIXEL(x - y0, y + x0); \ + WRITE_CIRCLE_PIXEL(x + y0, y - x0); \ + WRITE_CIRCLE_PIXEL(x - y0, y - x0); \ + x0 += 1; \ + if (d < 0) { \ + d += (x0 << 1) + 1; \ + } else { \ + y0 -= 1; \ + d += ((x0 - y0) << 1) + 1; \ + } \ + } \ + } while (0) + + if (circle_fully_inside) { + #define WRITE_CIRCLE_PIXEL(px, py) \ + impl->framebuffer[(size_t)(py) * fb_stride + (px)] = swapped_color + RM690B0_DRAW_CIRCLE_LOOP(); +#undef WRITE_CIRCLE_PIXEL + } else { + #define WRITE_CIRCLE_PIXEL(px, py) do { \ + mp_int_t px_val = (px); \ + mp_int_t py_val = (py); \ + if (px_val >= 0 && px_val < self->width && \ + py_val >= 0 && py_val < self->height) { \ + impl->framebuffer[(size_t)py_val * fb_stride + px_val] = swapped_color; \ + } \ +} while (0) + RM690B0_DRAW_CIRCLE_LOOP(); +#undef WRITE_CIRCLE_PIXEL + } + +#undef RM690B0_DRAW_CIRCLE_LOOP + + mp_int_t clip_bx = bx; + mp_int_t clip_by = by; + mp_int_t clip_bw = bw; + mp_int_t clip_bh = bh; + + if (!circle_fully_inside) { + if (clip_bx < 0) { + clip_bw += clip_bx; + clip_bx = 0; + } + if (clip_by < 0) { + clip_bh += clip_by; + clip_by = 0; + } + if (clip_bx + clip_bw > self->width) { + clip_bw = self->width - clip_bx; + } + if (clip_by + clip_bh > self->height) { + clip_bh = self->height - clip_by; + } + } + + if (clip_bw > 0 && clip_bh > 0) { + // Mark region as dirty for next swap + mark_dirty_region(impl, clip_bx, clip_by, clip_bw, clip_bh); + + // Only flush immediately if not double-buffered + // When double-buffered, swap_buffers() will handle the flush + if (!impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, clip_bx, clip_by, clip_bw, clip_bh, false); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw circle: %s"), esp_err_to_name(ret)); + } + } + } +} + +void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color) { + CHECK_INITIALIZED(); + if (radius < 0) { + mp_raise_ValueError(MP_ERROR_TEXT("radius must be non-negative")); + return; + } + if (radius == 0) { + common_hal_rm690b0_rm690b0_pixel(self, x, y, color); + return; + } + + + mp_int_t max_radius = (RM690B0_MAX_DIAMETER - 1) / 2; + if (radius > max_radius) { + radius = max_radius; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + mp_int_t top = y - radius; + mp_int_t row_count = radius * 2 + 1; + if (row_count <= 0) { + return; + } + + mp_int_t bx = x - radius; + mp_int_t by = y - radius; + mp_int_t bw = row_count; + mp_int_t bh = row_count; + bool circle_fully_inside = (bx >= 0 && by >= 0 && + bx + bw <= self->width && by + bh <= self->height); + + #define STACK_ALLOC_THRESHOLD 128 + int16_t left_stack[STACK_ALLOC_THRESHOLD]; + int16_t right_stack[STACK_ALLOC_THRESHOLD]; + int16_t *left = left_stack; + int16_t *right = right_stack; + int16_t *heap_span = NULL; + + if (row_count > STACK_ALLOC_THRESHOLD) { + int16_t *cache = rm690b0_acquire_span_cache(impl, (size_t)row_count); + if (cache != NULL) { + left = cache; + right = cache + (mp_int_t)impl->circle_span_capacity; + } else { + size_t span_entries = (size_t)row_count * 2; + heap_span = (int16_t *)heap_caps_malloc(span_entries * sizeof(int16_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (heap_span == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to allocate memory for circle")); + return; + } + left = heap_span; + right = heap_span + row_count; + } + } + + for (mp_int_t i = 0; i < row_count; i++) { + left[i] = INT16_MAX; + right[i] = INT16_MIN; + } + + rm690b0_span_accumulator_t acc = { + .top = top, + .row_count = row_count, + .left = left, + .right = right, + }; + + mp_int_t xi = 0; + mp_int_t yi = radius; + mp_int_t d = 1 - radius; + + while (xi <= yi) { + rm690b0_span_update(&acc, y + yi, x + xi); + rm690b0_span_update(&acc, y + yi, x - xi); + rm690b0_span_update(&acc, y - yi, x + xi); + rm690b0_span_update(&acc, y - yi, x - xi); + + if (yi != xi) { + rm690b0_span_update(&acc, y + xi, x + yi); + rm690b0_span_update(&acc, y + xi, x - yi); + rm690b0_span_update(&acc, y - xi, x + yi); + rm690b0_span_update(&acc, y - xi, x - yi); + } + + xi += 1; + if (d < 0) { + d += (xi << 1) + 1; + } else { + yi -= 1; + d += ((xi - yi) << 1) + 1; + } + } + + uint16_t swapped_color = RGB565_SWAP_GB(color); + size_t fb_stride = RM690B0_PANEL_WIDTH; + + if (circle_fully_inside) { + for (mp_int_t row = 0; row < row_count; row++) { + int16_t span_left = left[row]; + int16_t span_right = right[row]; + if (span_left > span_right) { + continue; + } + mp_int_t yy = top + row; + size_t span_width = (size_t)(span_right - span_left + 1); + uint16_t *dest = impl->framebuffer + (size_t)yy * fb_stride + span_left; + rm690b0_fill_span_fast(dest, span_width, swapped_color); + } + } else { + for (mp_int_t row = 0; row < row_count; row++) { + int16_t span_left = left[row]; + int16_t span_right = right[row]; + if (span_left > span_right) { + continue; + } + mp_int_t yy = top + row; + if (yy < 0 || yy >= self->height) { + continue; + } + mp_int_t span_left_i = (mp_int_t)span_left; + mp_int_t span_right_i = (mp_int_t)span_right; + + if (span_left_i < 0) { + span_left_i = 0; + } + if (span_right_i >= self->width) { + span_right_i = self->width - 1; + } + + mp_int_t span_width = span_right_i - span_left_i + 1; + if (span_width <= 0) { + continue; + } + + uint16_t *dest = impl->framebuffer + (size_t)yy * fb_stride + span_left_i; + rm690b0_fill_span_fast(dest, (size_t)span_width, swapped_color); + } + } + + mp_int_t clip_bx = bx; + mp_int_t clip_by = by; + mp_int_t clip_bw = bw; + mp_int_t clip_bh = bh; + + if (!circle_fully_inside) { + if (clip_bx < 0) { + clip_bw += clip_bx; + clip_bx = 0; + } + if (clip_by < 0) { + clip_bh += clip_by; + clip_by = 0; + } + if (clip_bx + clip_bw > self->width) { + clip_bw = self->width - clip_bx; + } + if (clip_by + clip_bh > self->height) { + clip_bh = self->height - clip_by; + } + } + + if (clip_bw > 0 && clip_bh > 0) { + // Mark region as dirty for next swap + mark_dirty_region(impl, clip_bx, clip_by, clip_bw, clip_bh); + + // Only flush immediately if not double-buffered + // When double-buffered, swap_buffers() will handle the flush + if (!impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, clip_bx, clip_by, clip_bw, clip_bh, false); + if (ret != ESP_OK) { + if (heap_span != NULL) { + heap_caps_free(heap_span); + } + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw fill_circle: %s"), esp_err_to_name(ret)); + } + } + } + + if (heap_span != NULL) { + heap_caps_free(heap_span); + } +} + +void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees) { + CHECK_INITIALIZED(); + + mp_int_t normalized = ((degrees % 360) + 360) % 360; + switch (normalized) { + case 0: + case 180: + self->width = RM690B0_PANEL_WIDTH; + self->height = RM690B0_PANEL_HEIGHT; + break; + case 90: + case 270: + self->width = RM690B0_PANEL_HEIGHT; + self->height = RM690B0_PANEL_WIDTH; + break; + default: + mp_raise_ValueError(MP_ERROR_TEXT("Rotation must be 0, 90, 180, or 270")); + return; + } + + self->rotation = normalized; + ESP_LOGI(TAG, "Display rotation set to %d (logical size %dx%d)", (int)normalized, (int)self->width, (int)self->height); +} + +mp_int_t common_hal_rm690b0_rm690b0_get_rotation(const rm690b0_rm690b0_obj_t *self) { + return self->rotation; +} + +void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t value) { + CHECK_INITIALIZED(); + if (value < 0.0f || value > 1.0f) { + mp_raise_ValueError(MP_ERROR_TEXT("Brightness must be between 0.0 and 1.0")); + return; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->io_handle == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + uint8_t brightness; + if (value <= 0.0f) { + brightness = 0; + } else if (value >= 1.0f) { + brightness = 0xFF; + } else { + brightness = (uint8_t)(value * 255.0f + 0.5f); + } + + if (brightness == self->brightness_raw) { + return; + } + + uint8_t page_cmd = 0x00; + esp_err_t err = rm690b0_tx_param(impl, 0xFE, &page_cmd, 1); + if (err != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to select brightness page: %s"), esp_err_to_name(err)); + return; + } + + err = rm690b0_tx_param(impl, 0x51, &brightness, 1); + if (err != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to write brightness: %s"), esp_err_to_name(err)); + return; + } + + uint8_t ctrl_display = (brightness == 0) ? 0x20 : 0x2C; + err = rm690b0_tx_param(impl, 0x53, &ctrl_display, 1); + if (err != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to latch brightness: %s"), esp_err_to_name(err)); + return; + } + + self->brightness_raw = brightness; + ESP_LOGI(TAG, "Set brightness to %u/255 (%.3f)", brightness, (double)value); +} + +mp_float_t common_hal_rm690b0_rm690b0_get_brightness(const rm690b0_rm690b0_obj_t *self) { + uint8_t raw = self->brightness_raw; + return (mp_float_t)raw / 255.0f; +} + +void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data) { + CHECK_INITIALIZED(); + + if (width <= 0 || height <= 0) { + return; + } + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(bitmap_data, &bufinfo, MP_BUFFER_READ); + + size_t src_width = (size_t)width; + size_t src_height = (size_t)height; + + // Check for overflow in bitmap size calculation + size_t expected_bytes; + if (!check_bitmap_size(src_width, src_height, &expected_bytes)) { + mp_raise_ValueError(MP_ERROR_TEXT("Bitmap dimensions too large (max ~32767x32767 on 32-bit systems)")); + return; + } + + if (bufinfo.len < expected_bytes) { + mp_raise_ValueError(MP_ERROR_TEXT("Bitmap data too small for width * height")); + return; + } + + mp_int_t logical_x = x; + mp_int_t logical_y = y; + mp_int_t logical_w = width; + mp_int_t logical_h = height; + + if (!clip_logical_rect(self, &logical_x, &logical_y, &logical_w, &logical_h)) { + return; + } + + mp_int_t crop_left = logical_x - x; + mp_int_t crop_top = logical_y - y; + if (crop_left < 0) { + crop_left = 0; + } + if (crop_top < 0) { + crop_top = 0; + } + + mp_int_t phys_x = logical_x; + mp_int_t phys_y = logical_y; + mp_int_t phys_w = logical_w; + mp_int_t phys_h = logical_h; + + if (!map_rect_for_rotation(self, &phys_x, &phys_y, &phys_w, &phys_h)) { + return; + } + + if (phys_w <= 0 || phys_h <= 0) { + return; + } + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + if (impl == NULL || impl->framebuffer == NULL) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); + return; + } + + const uint16_t *src_base = (const uint16_t *)bufinfo.buf; + size_t src_stride = src_width; + const uint16_t *src_pixels = src_base + (size_t)crop_top * src_stride + (size_t)crop_left; + + uint16_t *framebuffer = impl->framebuffer; + size_t fb_stride = RM690B0_PANEL_WIDTH; + + switch (self->rotation) { + case 0: + for (mp_int_t row = 0; row < logical_h; row++) { + const uint16_t *src_row = src_pixels + (size_t)row * src_stride; + uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; + for (mp_int_t col = 0; col < logical_w; col++) { + dst_row[col] = RGB565_SWAP_GB(src_row[col]); + } + } + break; + case 180: + for (mp_int_t row = 0; row < logical_h; row++) { + const uint16_t *src_row = src_pixels + (size_t)(logical_h - 1 - row) * src_stride; + uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; + for (mp_int_t col = 0; col < logical_w; col++) { + dst_row[col] = RGB565_SWAP_GB(src_row[logical_w - 1 - col]); + } + } + break; + case 90: { + mp_int_t phys_h_rows = phys_h; + mp_int_t phys_w_cols = phys_w; + for (mp_int_t row = 0; row < phys_h_rows; row++) { + uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; + for (mp_int_t col = 0; col < phys_w_cols; col++) { + mp_int_t src_row_idx = logical_h - 1 - col; + mp_int_t src_col_idx = row; + const uint16_t *src_row = src_pixels + (size_t)src_row_idx * src_stride; + dst_row[col] = RGB565_SWAP_GB(src_row[src_col_idx]); + } + } + break; + } + case 270: { + mp_int_t phys_h_rows = phys_h; + mp_int_t phys_w_cols = phys_w; + for (mp_int_t row = 0; row < phys_h_rows; row++) { + uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; + for (mp_int_t col = 0; col < phys_w_cols; col++) { + mp_int_t src_row_idx = col; + mp_int_t src_col_idx = logical_w - 1 - row; + const uint16_t *src_row = src_pixels + (size_t)src_row_idx * src_stride; + dst_row[col] = RGB565_SWAP_GB(src_row[src_col_idx]); + } + } + break; + } + default: + mp_raise_ValueError(MP_ERROR_TEXT("Unsupported rotation")); + return; + } + + // Mark region as dirty for next swap + mark_dirty_region(impl, phys_x, phys_y, phys_w, phys_h); + + // Only flush immediately if not double-buffered + // When double-buffered, swap_buffers() will handle the flush + if (!impl->double_buffered) { + esp_err_t ret = rm690b0_flush_region(self, phys_x, phys_y, phys_w, phys_h, false); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw bitmap: %s"), esp_err_to_name(ret)); + } + } +} + +void common_hal_rm690b0_rm690b0_swap_buffers(rm690b0_rm690b0_obj_t *self, bool copy) { + CHECK_INITIALIZED(); + + rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; + + // Lazy allocation: allocate front buffer on first call + if (!impl->double_buffered && impl->framebuffer_front == NULL) { + size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; + impl->framebuffer_front = heap_caps_malloc(framebuffer_pixels * sizeof(uint16_t), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + + if (impl->framebuffer_front == NULL) { + ESP_LOGW(TAG, "Unable to allocate front framebuffer - falling back to single-buffered refresh"); + // Fall through to single-buffer mode below + } else { + impl->double_buffered = true; + ESP_LOGI(TAG, "Allocated front framebuffer (%zu KB) - double-buffering enabled", + (framebuffer_pixels * sizeof(uint16_t)) / 1024); + + // Copy current back buffer to front buffer so swap has valid data + memcpy(impl->framebuffer_front, impl->framebuffer, + framebuffer_pixels * sizeof(uint16_t)); + } + } + + if (!impl->double_buffered || impl->framebuffer_front == NULL) { + // Single-buffered mode - just flush current framebuffer + esp_err_t ret = rm690b0_flush_region(self, 0, 0, self->width, self->height, false); + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, + MP_ERROR_TEXT("Failed to refresh display: %s (0x%x)"), + esp_err_to_name(ret), ret); + } + return; + } + + // Double-buffered mode: flush dirty region + // If no dirty region, flush everything + mp_int_t flush_x = 0; + mp_int_t flush_y = 0; + mp_int_t flush_w = self->width; + mp_int_t flush_h = self->height; + + if (impl->dirty_region_valid) { + // Only flush the dirty region for better performance + flush_x = impl->dirty_x; + flush_y = impl->dirty_y; + flush_w = impl->dirty_w; + flush_h = impl->dirty_h; + ESP_LOGI(TAG, "Flushing dirty region: %d,%d %dx%d", flush_x, flush_y, flush_w, flush_h); + } else { + ESP_LOGI(TAG, "Flushing full screen (no dirty region)"); + } + + // Skip final delay if we're doing a copy - the memcpy will protect the SPI transfer + esp_err_t ret = rm690b0_flush_region(self, flush_x, flush_y, flush_w, flush_h, copy); + + + // Now swap the buffer pointers + // After swap: framebuffer becomes the old front buffer (ready for new drawing) + // framebuffer_front becomes the old back buffer (now being displayed) + uint16_t *temp = impl->framebuffer_front; + impl->framebuffer_front = impl->framebuffer; + impl->framebuffer = temp; + + // Reset dirty region after flush + impl->dirty_region_valid = false; + impl->dirty_x = 0; + impl->dirty_y = 0; + impl->dirty_w = 0; + impl->dirty_h = 0; + + // Optionally copy front buffer to back buffer for incremental drawing + // Standard double-buffering: back buffer inherits current display content + // Skip copy for better performance when doing full redraws (animations) + if (copy) { + size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; + memcpy(impl->framebuffer, impl->framebuffer_front, + framebuffer_pixels * sizeof(uint16_t)); + ESP_LOGI(TAG, "Buffers swapped and back buffer updated"); + } else { + ESP_LOGI(TAG, "Buffers swapped (no copy)"); + } + if (ret != ESP_OK) { + mp_raise_msg_varg(&mp_type_RuntimeError, + MP_ERROR_TEXT("Failed to refresh display: %s (0x%x)"), + esp_err_to_name(ret), ret); + } +} diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.h b/ports/espressif/common-hal/rm690b0/RM690B0.h new file mode 100644 index 0000000000000..f0b14305f6eac --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/RM690B0.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-bindings/rm690b0/RM690B0.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_types.h" + +void common_hal_rm690b0_rm690b0_pixel(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t color); +void common_hal_rm690b0_rm690b0_fill_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); +void common_hal_rm690b0_rm690b0_hline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t color); +void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t height, mp_int_t color); +void common_hal_rm690b0_rm690b0_line(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color); +void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); +void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); +void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); +void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees); +void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t value); +void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data); +void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data); +void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data); +void common_hal_rm690b0_rm690b0_deinit_all(void); + +// Helper function to expose panel handle for LVGL integration +esp_lcd_panel_handle_t rm690b0_get_panel_handle(void); diff --git a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c new file mode 100644 index 0000000000000..e22d6a6a2855b --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_check.h" +#include "esp-idf/components/esp_lcd/interface/esp_lcd_panel_interface.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_vendor.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_ops.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_commands.h" +#include "esp_log.h" + +#include "esp_lcd_rm690b0.h" + +#define LCD_OPCODE_WRITE_CMD (0x02ULL) +#define LCD_OPCODE_READ_CMD (0x03ULL) +#define LCD_OPCODE_WRITE_COLOR (0x32ULL) + +static const char *TAG = "rm690b0"; + +static esp_err_t panel_rm690b0_del(esp_lcd_panel_t *panel); +static esp_err_t panel_rm690b0_reset(esp_lcd_panel_t *panel); +static esp_err_t panel_rm690b0_init(esp_lcd_panel_t *panel); +static esp_err_t panel_rm690b0_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); +static esp_err_t panel_rm690b0_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); +static esp_err_t panel_rm690b0_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); +static esp_err_t panel_rm690b0_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); +static esp_err_t panel_rm690b0_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); +static esp_err_t panel_rm690b0_disp_on_off(esp_lcd_panel_t *panel, bool off); + +typedef struct { + esp_lcd_panel_t base; + esp_lcd_panel_io_handle_t io; + int reset_gpio_num; + int x_gap; + int y_gap; + uint8_t fb_bits_per_pixel; + uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register + uint8_t colmod_val; // save surrent value of LCD_CMD_COLMOD register + const rm690b0_lcd_init_cmd_t *init_cmds; + uint16_t init_cmds_size; + struct { + unsigned int use_qspi_interface : 1; + unsigned int reset_level : 1; + } flags; +} rm690b0_panel_t; + +esp_err_t esp_lcd_new_panel_rm690b0(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel) { + ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + esp_err_t ret = ESP_OK; + rm690b0_panel_t *rm690b0 = NULL; + rm690b0 = calloc(1, sizeof(rm690b0_panel_t)); + ESP_GOTO_ON_FALSE(rm690b0, ESP_ERR_NO_MEM, err, TAG, "no mem for rm690b0 panel"); + + if (panel_dev_config->reset_gpio_num >= 0) { + gpio_config_t io_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, + }; + ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); + } + + switch (panel_dev_config->rgb_ele_order) { + case LCD_RGB_ELEMENT_ORDER_RGB: + rm690b0->madctl_val = 0; + break; + case LCD_RGB_ELEMENT_ORDER_BGR: + rm690b0->madctl_val |= LCD_CMD_BGR_BIT; + break; + default: + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order"); + break; + } + + uint8_t fb_bits_per_pixel = 0; + switch (panel_dev_config->bits_per_pixel) { + case 16: // RGB565 + rm690b0->colmod_val = 0x55; + fb_bits_per_pixel = 16; + break; + case 18: // RGB666 + rm690b0->colmod_val = 0x66; + // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel + fb_bits_per_pixel = 24; + break; + case 24: // RGB888 + rm690b0->colmod_val = 0x77; + fb_bits_per_pixel = 24; + break; + default: + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); + break; + } + + rm690b0->io = io; + rm690b0->reset_gpio_num = panel_dev_config->reset_gpio_num; + rm690b0->fb_bits_per_pixel = fb_bits_per_pixel; + rm690b0_vendor_config_t *vendor_config = (rm690b0_vendor_config_t *)panel_dev_config->vendor_config; + if (vendor_config) { + rm690b0->init_cmds = vendor_config->init_cmds; + rm690b0->init_cmds_size = vendor_config->init_cmds_size; + rm690b0->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface; + } + rm690b0->flags.reset_level = panel_dev_config->flags.reset_active_high; + rm690b0->base.del = panel_rm690b0_del; + rm690b0->base.reset = panel_rm690b0_reset; + rm690b0->base.init = panel_rm690b0_init; + rm690b0->base.draw_bitmap = panel_rm690b0_draw_bitmap; + rm690b0->base.invert_color = panel_rm690b0_invert_color; + rm690b0->base.set_gap = panel_rm690b0_set_gap; + rm690b0->base.mirror = panel_rm690b0_mirror; + rm690b0->base.swap_xy = panel_rm690b0_swap_xy; + rm690b0->base.disp_on_off = panel_rm690b0_disp_on_off; + *ret_panel = &(rm690b0->base); + ESP_LOGD(TAG, "new rm690b0 panel @%p", rm690b0); + + return ESP_OK; + +err: + if (rm690b0) { + if (panel_dev_config->reset_gpio_num >= 0) { + gpio_reset_pin(panel_dev_config->reset_gpio_num); + } + free(rm690b0); + } + return ret; +} + +static esp_err_t tx_param(rm690b0_panel_t *rm690b0, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size) { + if (rm690b0->flags.use_qspi_interface) { + lcd_cmd &= 0xff; + lcd_cmd <<= 8; + lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; + } + return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size); +} + +static esp_err_t tx_color(rm690b0_panel_t *rm690b0, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size) { + if (rm690b0->flags.use_qspi_interface) { + lcd_cmd &= 0xff; + lcd_cmd <<= 8; + lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24; + } + return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size); +} + +static esp_err_t panel_rm690b0_del(esp_lcd_panel_t *panel) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + + if (rm690b0->reset_gpio_num >= 0) { + gpio_reset_pin(rm690b0->reset_gpio_num); + } + ESP_LOGD(TAG, "del rm690b0 panel @%p", rm690b0); + free(rm690b0); + return ESP_OK; +} + +static esp_err_t panel_rm690b0_reset(esp_lcd_panel_t *panel) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + esp_lcd_panel_io_handle_t io = rm690b0->io; + + // Perform hardware reset + if (rm690b0->reset_gpio_num >= 0) { + gpio_set_level(rm690b0->reset_gpio_num, rm690b0->flags.reset_level); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(rm690b0->reset_gpio_num, !rm690b0->flags.reset_level); + vTaskDelay(pdMS_TO_TICKS(150)); + } else { // Perform software reset + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); + vTaskDelay(pdMS_TO_TICKS(80)); + } + + return ESP_OK; +} + +static const rm690b0_lcd_init_cmd_t vendor_specific_init_default[] = { +// {cmd, { data }, data_size, delay_ms} + {0xFE, (uint8_t []) {0x20}, 1, 0}, + {0x26, (uint8_t []) {0x0A}, 1, 0}, + {0x24, (uint8_t []) {0x80}, 1, 0}, + {0xFE, (uint8_t []) {0x00}, 1, 0}, + {0x3A, (uint8_t []) {0x55}, 1, 0}, + {0xC2, (uint8_t []) {0x00}, 1, 10}, + {0x35, (uint8_t []) {0x00}, 0, 0}, + {0x51, (uint8_t []) {0x00}, 1, 10}, + {0x11, (uint8_t []) {0x00}, 0, 80}, + {0x2A, (uint8_t []) {0x00, 0x10, 0x01, 0xD1}, 4, 0}, + {0x2B, (uint8_t []) {0x00, 0x00, 0x02, 0x57}, 4, 0}, + {0x29, (uint8_t []) {0x00}, 0, 10}, + {0x51, (uint8_t []) {0xFF}, 1, 0}, + {0x51, (uint8_t []) {0xFF}, 1, 0}, +}; + +static esp_err_t panel_rm690b0_init(esp_lcd_panel_t *panel) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + esp_lcd_panel_io_handle_t io = rm690b0->io; + const rm690b0_lcd_init_cmd_t *init_cmds = NULL; + uint16_t init_cmds_size = 0; + bool is_cmd_overwritten = false; + + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_MADCTL, (uint8_t[]) { + rm690b0->madctl_val, + }, 1), TAG, "send command failed"); + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_COLMOD, (uint8_t[]) { + rm690b0->colmod_val, + }, 1), TAG, "send command failed"); + + // vendor specific initialization, it can be different between manufacturers + // should consult the LCD supplier for initialization sequence code + if (rm690b0->init_cmds) { + init_cmds = rm690b0->init_cmds; + init_cmds_size = rm690b0->init_cmds_size; + } else { + init_cmds = vendor_specific_init_default; + init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(rm690b0_lcd_init_cmd_t); + } + + for (int i = 0; i < init_cmds_size; i++) { + // Check if the command has been used or conflicts with the internal + switch (init_cmds[i].cmd) { + case LCD_CMD_MADCTL: + is_cmd_overwritten = true; + rm690b0->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; + break; + case LCD_CMD_COLMOD: + is_cmd_overwritten = true; + rm690b0->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; + break; + default: + is_cmd_overwritten = false; + break; + } + + if (is_cmd_overwritten) { + ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd); + } + + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, + "send command failed"); + vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); + } + ESP_LOGD(TAG, "send init commands success"); + + return ESP_OK; +} + +static esp_err_t panel_rm690b0_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); + esp_lcd_panel_io_handle_t io = rm690b0->io; + + x_start += rm690b0->x_gap; + x_end += rm690b0->x_gap; + y_start += rm690b0->y_gap; + y_end += rm690b0->y_gap; + + // define an area of frame memory where MCU can access + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_CASET, (uint8_t[]) { + (x_start >> 8) & 0xFF, + x_start & 0xFF, + ((x_end - 1) >> 8) & 0xFF, + (x_end - 1) & 0xFF, + }, 4), TAG, "send command failed"); + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_RASET, (uint8_t[]) { + (y_start >> 8) & 0xFF, + y_start & 0xFF, + ((y_end - 1) >> 8) & 0xFF, + (y_end - 1) & 0xFF, + }, 4), TAG, "send command failed"); + // transfer frame buffer + size_t len = (x_end - x_start) * (y_end - y_start) * rm690b0->fb_bits_per_pixel / 8; + tx_color(rm690b0, io, LCD_CMD_RAMWR, color_data, len); + + return ESP_OK; +} + +static esp_err_t panel_rm690b0_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + esp_lcd_panel_io_handle_t io = rm690b0->io; + int command = 0; + if (invert_color_data) { + command = LCD_CMD_INVON; + } else { + command = LCD_CMD_INVOFF; + } + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, command, NULL, 0), TAG, "send command failed"); + return ESP_OK; +} + +static esp_err_t panel_rm690b0_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + esp_lcd_panel_io_handle_t io = rm690b0->io; + esp_err_t ret = ESP_OK; + + if (mirror_x) { + rm690b0->madctl_val |= BIT(6); + } else { + rm690b0->madctl_val &= ~BIT(6); + } + if (mirror_y) { + ESP_LOGE(TAG, "mirror_y is not supported by this panel"); + ret = ESP_ERR_NOT_SUPPORTED; + } + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_MADCTL, (uint8_t[]) { + rm690b0->madctl_val + }, 1), TAG, "send command failed"); + return ret; +} + +static esp_err_t panel_rm690b0_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) { + ESP_LOGE(TAG, "swap_xy is not supported by this panel"); + return ESP_ERR_NOT_SUPPORTED; +} + +static esp_err_t panel_rm690b0_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + rm690b0->x_gap = x_gap; + rm690b0->y_gap = y_gap; + return ESP_OK; +} + +static esp_err_t panel_rm690b0_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { + rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); + esp_lcd_panel_io_handle_t io = rm690b0->io; + int command = 0; + + if (on_off) { + command = LCD_CMD_DISPON; + } else { + command = LCD_CMD_DISPOFF; + } + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, command, NULL, 0), TAG, "send command failed"); + return ESP_OK; +} diff --git a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h new file mode 100644 index 0000000000000..f331f19970ce1 --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "driver/spi_master.h" +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_vendor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LCD panel initialization commands. + * + */ +typedef struct { + int cmd; /* + +// Font: LiberationMono-Bold.ttf +// Size: 16x16 pixels +// Characters: 0x20..0x7E (' '..'~') +// Each character: 32 bytes (16 rows × 2 bytes per row) +// Each row: 2 byte(s) for 16 pixels, MSB = leftmost pixel +// Indexing: glyph = rm690b0_font_16x16_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E +// +// Generated by ttf_to_rm690b0.py + +static const uint8_t rm690b0_font_16x16_data[95][32] = { + // 0x20 ' ' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x21 '!' + { + 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x22 '\"' + { + 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x23 '#' + { + 0x00, 0x00, 0x03, 0x20, 0x02, 0x20, 0x02, 0x20, 0x0F, 0xF0, 0x02, 0x40, 0x06, 0x40, 0x04, 0x40, + 0x1F, 0xF0, 0x04, 0xC0, 0x04, 0x80, 0x0C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x24 '$' + { + 0x01, 0x00, 0x07, 0xC0, 0x0F, 0xE0, 0x0D, 0x60, 0x0D, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x01, 0x70, + 0x01, 0x30, 0x0D, 0x30, 0x0F, 0xE0, 0x07, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x25 '%' + { + 0x00, 0x00, 0x0E, 0x30, 0x1A, 0x20, 0x12, 0x40, 0x12, 0xC0, 0x1A, 0x80, 0x0F, 0xF0, 0x03, 0xD0, + 0x02, 0xD8, 0x04, 0xD8, 0x0C, 0xD0, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x26 '&' + { + 0x00, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x06, 0x40, 0x06, 0xC0, 0x07, 0x80, 0x0F, 0x20, 0x0D, 0x20, + 0x19, 0xE0, 0x1C, 0xE0, 0x0F, 0xF8, 0x07, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x27 '\'' + { + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x28 '(' + { + 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x00, 0x00 + }, + // 0x29 ')' + { + 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00 + }, + // 0x2A '*' + { + 0x01, 0x80, 0x05, 0x80, 0x07, 0xE0, 0x03, 0xC0, 0x03, 0x80, 0x06, 0xC0, 0x02, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2B '+' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2C ',' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00 + }, + // 0x2D '-' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x03, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2E '.' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2F '/' + { + 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x30 '0' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x70, 0x0D, 0xF0, 0x0D, 0xF0, 0x0C, 0x70, + 0x0C, 0x60, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x31 '1' + { + 0x00, 0x00, 0x01, 0x80, 0x03, 0x80, 0x0F, 0x80, 0x0D, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x32 '2' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x00, 0x60, 0x00, 0x60, 0x01, 0xC0, 0x03, 0x80, + 0x07, 0x00, 0x0E, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x33 '3' + { + 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xE0, 0x0C, 0x60, 0x00, 0x60, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0x60, + 0x00, 0x30, 0x0C, 0x70, 0x0F, 0xE0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x34 '4' + { + 0x00, 0x00, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x03, 0x60, 0x06, 0x60, 0x04, 0x60, 0x0C, 0x60, + 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x35 '5' + { + 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0C, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x00, 0x70, + 0x00, 0x70, 0x0C, 0x60, 0x0F, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x36 '6' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x00, 0x0D, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, + 0x0C, 0x70, 0x06, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x37 '7' + { + 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x60, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, + 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x38 '8' + { + 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xE0, 0x0E, 0x60, 0x0E, 0x60, 0x07, 0xC0, 0x07, 0xE0, 0x0E, 0x60, + 0x0C, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x39 '9' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0E, 0x70, 0x0F, 0xF0, 0x07, 0xF0, + 0x00, 0x60, 0x0C, 0x60, 0x07, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3A ':' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3B ';' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00 + }, + // 0x3C '<' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xF0, 0x07, 0xE0, 0x0F, 0x00, 0x0C, 0x00, 0x0F, 0x00, + 0x07, 0xE0, 0x00, 0xF0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3D '=' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3E '>' + { + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0F, 0x00, 0x07, 0xE0, 0x00, 0xF0, 0x00, 0x30, 0x00, 0xF0, + 0x07, 0xC0, 0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3F '?' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x00, 0x60, 0x00, 0xE0, 0x01, 0x80, + 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x40 '@' + { + 0x03, 0xC0, 0x06, 0x20, 0x04, 0x30, 0x09, 0xB0, 0x0A, 0x50, 0x0A, 0x50, 0x1E, 0x50, 0x14, 0x50, + 0x14, 0x50, 0x1C, 0xD0, 0x0E, 0xD0, 0x0B, 0x60, 0x08, 0x00, 0x04, 0x20, 0x03, 0xC0, 0x00, 0x00 + }, + // 0x41 'A' + { + 0x00, 0x00, 0x03, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x06, 0xC0, 0x06, 0x60, 0x06, 0x60, 0x0F, 0xE0, + 0x0F, 0xF0, 0x0C, 0x30, 0x1C, 0x30, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x42 'B' + { + 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x0C, 0x70, 0x0C, 0x60, 0x0F, 0xE0, 0x0F, 0xE0, 0x0C, 0x30, + 0x0C, 0x30, 0x0C, 0x30, 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x43 'C' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x20, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0C, 0x30, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x44 'D' + { + 0x00, 0x00, 0x0F, 0x80, 0x0F, 0xE0, 0x0C, 0x60, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, + 0x0C, 0x70, 0x0C, 0x60, 0x0F, 0xE0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x45 'E' + { + 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0C, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x46 'F' + { + 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x00, 0x0E, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0E, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x47 'G' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0C, 0x00, 0x0C, 0xF0, 0x0C, 0xF0, + 0x0C, 0x30, 0x0E, 0x70, 0x07, 0xF0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x48 'H' + { + 0x00, 0x00, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0F, 0xF0, 0x0F, 0xF0, 0x0C, 0x70, + 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x49 'I' + { + 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4A 'J' + { + 0x00, 0x00, 0x03, 0xE0, 0x03, 0xE0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x0C, 0x60, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4B 'K' + { + 0x00, 0x00, 0x0C, 0x70, 0x0C, 0x60, 0x0C, 0xE0, 0x0D, 0xC0, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0xC0, + 0x0E, 0xE0, 0x0C, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4C 'L' + { + 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4D 'M' + { + 0x00, 0x00, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0xF0, 0x0F, 0xF0, 0x0B, 0xB0, 0x09, 0xB0, + 0x09, 0xB0, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4E 'N' + { + 0x00, 0x00, 0x0E, 0x30, 0x0E, 0x30, 0x0F, 0x30, 0x0F, 0x30, 0x0F, 0x30, 0x0D, 0xB0, 0x0D, 0xB0, + 0x0C, 0xF0, 0x0C, 0xF0, 0x0C, 0xF0, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4F 'O' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, + 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x50 'P' + { + 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x70, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x51 'Q' + { + 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, + 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x00 + }, + // 0x52 'R' + { + 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xF0, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x70, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0C, 0xC0, 0x0C, 0x60, 0x0C, 0x70, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x53 'S' + { + 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xE0, 0x0C, 0x70, 0x0C, 0x00, 0x0F, 0x80, 0x07, 0xE0, 0x00, 0xF0, + 0x00, 0x30, 0x0C, 0x30, 0x0F, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x54 'T' + { + 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x55 'U' + { + 0x00, 0x00, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, + 0x0C, 0x70, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x56 'V' + { + 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0C, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x57 'W' + { + 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x18, 0x30, 0x09, 0xB0, 0x0D, 0xB0, 0x0F, 0xB0, 0x0F, 0xF0, + 0x0E, 0xE0, 0x0E, 0xE0, 0x0E, 0x60, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x58 'X' + { + 0x00, 0x00, 0x0C, 0x30, 0x0E, 0x60, 0x06, 0xE0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0xC0, + 0x07, 0xC0, 0x06, 0x60, 0x0C, 0x70, 0x1C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x59 'Y' + { + 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x06, 0xC0, 0x03, 0xC0, 0x03, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5A 'Z' + { + 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x60, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x00, + 0x06, 0x00, 0x0E, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5B '[' + { + 0x03, 0xE0, 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, 0xE0, 0x00, 0x00 + }, + // 0x5C '\\' + { + 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, + 0x00, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5D ']' + { + 0x07, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x07, 0xC0, 0x00, 0x00 + }, + // 0x5E '^' + { + 0x00, 0x00, 0x03, 0x80, 0x03, 0xC0, 0x06, 0xC0, 0x06, 0x40, 0x0C, 0x60, 0x0C, 0x20, 0x08, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5F '_' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00 + }, + // 0x60 '`' + { + 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x61 'a' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x07, 0xE0, 0x0F, 0xE0, + 0x0C, 0x60, 0x0C, 0xE0, 0x0F, 0xF0, 0x07, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x62 'b' + { + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0D, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, + 0x0C, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x0D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x63 'c' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x64 'd' + { + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x07, 0x60, 0x0F, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0C, 0x60, + 0x0C, 0x60, 0x0E, 0x60, 0x0F, 0xE0, 0x07, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x65 'e' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0C, 0x60, 0x0F, 0xF0, 0x0F, 0xF0, + 0x0C, 0x00, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x66 'f' + { + 0x01, 0xF0, 0x03, 0xF0, 0x03, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x67 'g' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xB0, 0x07, 0xF0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x70, + 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x60, 0x07, 0xE0, 0x07, 0xC0, 0x00, 0x00 + }, + // 0x68 'h' + { + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0xE0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x70, + 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x69 'i' + { + 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x07, 0x80, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6A 'j' + { + 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x07, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x0F, 0x80, 0x0F, 0x00, 0x00, 0x00 + }, + // 0x6B 'k' + { + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x60, 0x0E, 0xE0, 0x0E, 0xC0, 0x0F, 0x80, 0x0F, 0xC0, + 0x0E, 0xC0, 0x0E, 0xE0, 0x0E, 0x60, 0x0E, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6C 'l' + { + 0x07, 0x80, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6D 'm' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x60, 0x0F, 0xF0, 0x0D, 0xB0, 0x09, 0xB0, 0x09, 0xB0, + 0x09, 0xB0, 0x09, 0xB0, 0x09, 0xB0, 0x09, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6E 'n' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x70, + 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6F 'o' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, + 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x70 'p' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, + 0x0C, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x0D, 0xC0, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00 + }, + // 0x71 'q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x60, 0x0F, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0C, 0x60, + 0x0C, 0x60, 0x0E, 0x60, 0x0F, 0xE0, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00 + }, + // 0x72 'r' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE0, 0x07, 0xE0, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x73 's' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0C, 0x60, 0x0F, 0x00, 0x07, 0xE0, + 0x00, 0xE0, 0x0C, 0x70, 0x0F, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x74 't' + { + 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0xE0, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x75 'u' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, + 0x0C, 0x60, 0x0E, 0x60, 0x0F, 0xE0, 0x07, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x76 'v' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x0E, 0x60, 0x06, 0x60, + 0x06, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x77 'w' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x18, 0x10, 0x19, 0xB0, 0x09, 0xB0, 0x0B, 0xB0, + 0x0F, 0xF0, 0x0E, 0xE0, 0x0E, 0x60, 0x0E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x78 'x' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x06, 0x60, 0x06, 0xC0, 0x03, 0xC0, 0x03, 0x80, + 0x03, 0xC0, 0x06, 0xC0, 0x0E, 0x60, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x79 'y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x06, 0x60, 0x06, 0x60, + 0x06, 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00 + }, + // 0x7A 'z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, + 0x07, 0x00, 0x06, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x7B '{' + { + 0x01, 0xE0, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0x00 + }, + // 0x7C '|' + { + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80 + }, + // 0x7D '}' + { + 0x0F, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x00, 0xE0, + 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0F, 0x00, 0x00, 0x00 + }, + // 0x7E '~' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0F, 0x90, 0x09, 0xF0, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h new file mode 100644 index 0000000000000..b50d12521ffbf --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h @@ -0,0 +1,589 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Font: LiberationMono-Bold.ttf +// Size: 16x24 pixels +// Characters: 0x20..0x7E (' '..'~') +// Each character: 48 bytes (24 rows × 2 bytes per row) +// Each row: 2 byte(s) for 16 pixels, MSB = leftmost pixel +// Indexing: glyph = rm690b0_font_16x24_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E +// +// Generated by ttf_to_rm690b0.py + +static const uint8_t rm690b0_font_16x24_data[95][48] = { + // 0x20 ' ' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x21 '!' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x22 '\"' + { + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x30, 0x0E, 0x30, + 0x0E, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x23 '#' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x03, 0x18, 0x06, 0x18, 0x3F, 0xFE, 0x3F, 0xFE, + 0x06, 0x30, 0x04, 0x30, 0x0C, 0x30, 0x0C, 0x20, 0x3F, 0xFC, 0x3F, 0xFC, 0x08, 0x60, 0x18, 0x60, + 0x18, 0x40, 0x18, 0xC0, 0x18, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x24 '$' + { + 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x07, 0xF0, 0x1F, 0xF8, 0x1C, 0xBC, 0x3C, 0x9C, 0x3C, 0x80, + 0x1C, 0x80, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x9C, 0x38, 0x9C, 0x38, 0x9C, 0x38, 0x9C, + 0x1C, 0xBC, 0x0F, 0xF8, 0x07, 0xF0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x25 '%' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, 0x7C, 0x18, 0xCE, 0x30, 0xC6, 0x60, 0xC6, 0x60, + 0xCE, 0xC0, 0x7D, 0x80, 0x79, 0x80, 0x03, 0x78, 0x06, 0xFC, 0x0E, 0xCC, 0x0C, 0xCC, 0x18, 0xCC, + 0x30, 0xCC, 0x30, 0xFC, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x26 '&' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0F, 0xE0, 0x1C, 0xE0, 0x18, 0x60, 0x1C, 0xE0, + 0x1F, 0xC0, 0x0F, 0x00, 0x3E, 0x18, 0x7F, 0x38, 0x77, 0x30, 0xE3, 0xF0, 0xE1, 0xF0, 0xE0, 0xE0, + 0x71, 0xF0, 0x7F, 0xFC, 0x1F, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x27 '\'' + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x80, + 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x28 '(' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x80, + 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0xE0 + }, + // 0x29 ')' + { + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xE0, + 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, + 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x07, 0x00 + }, + // 0x2A '*' + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x09, 0x90, 0x0F, 0xF8, 0x0F, 0xF0, 0x03, 0xC0, + 0x07, 0xE0, 0x06, 0x70, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2B '+' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x3F, 0xFC, 0x3F, 0xFC, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2C ',' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x80, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x0C, 0x00 + }, + // 0x2D '-' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2E '.' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2F '/' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x38, 0x00, 0x30, 0x00, 0x70, 0x00, 0x60, + 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0E, 0x00, + 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x30 '0' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x38, 0x1C, 0x3C, + 0x1C, 0x1C, 0x3D, 0x9C, 0x3D, 0x9C, 0x3D, 0x9C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1C, 0x38, + 0x0E, 0x78, 0x0F, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x31 '1' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x03, 0xE0, 0x07, 0xE0, 0x1F, 0xE0, 0x19, 0xE0, + 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, + 0x01, 0xE0, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x32 '2' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x00, 0x3C, + 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF8, 0x01, 0xF0, 0x03, 0xE0, 0x07, 0xC0, 0x0F, 0x00, 0x1E, 0x00, + 0x1E, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x33 '3' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1E, 0x78, 0x1C, 0x3C, 0x00, 0x3C, + 0x00, 0x38, 0x00, 0x78, 0x03, 0xF0, 0x03, 0xF0, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x3C, 0x1C, + 0x1C, 0x3C, 0x1F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x34 '4' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x01, 0xF0, 0x03, 0xF0, 0x03, 0xF0, + 0x07, 0x70, 0x0E, 0x70, 0x0C, 0x70, 0x1C, 0x70, 0x38, 0x70, 0x3F, 0xFE, 0x3F, 0xFE, 0x00, 0x70, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x35 '5' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, + 0x1D, 0xE0, 0x1F, 0xF8, 0x1E, 0x38, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x3C, 0x3C, + 0x1C, 0x38, 0x1F, 0xF0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x36 '6' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x07, 0xF8, 0x0E, 0x38, 0x1E, 0x38, 0x1C, 0x00, + 0x1C, 0x00, 0x1D, 0xF0, 0x3F, 0xF8, 0x3E, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, + 0x0E, 0x38, 0x07, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x37 '7' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, + 0x00, 0xF0, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x07, 0x80, + 0x07, 0x80, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x38 '8' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x38, 0x1E, 0x38, 0x07, 0xF0, 0x0F, 0xF0, 0x1E, 0x38, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, + 0x1E, 0x3C, 0x0F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x39 '9' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, 0x1E, 0x78, 0x1C, 0x38, 0x3C, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x1C, 0x3C, 0x1E, 0x7C, 0x0F, 0xFC, 0x07, 0x9C, 0x00, 0x38, 0x1C, 0x38, + 0x1E, 0x78, 0x0F, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3A ':' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3B ';' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00 + }, + // 0x3C '<' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x78, + 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0x38, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0x78, + 0x00, 0x1C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3D '=' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, + 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3E '>' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x1F, 0x00, + 0x07, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1F, 0x00, + 0x3C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3F '?' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1E, 0x3C, 0x3C, 0x1C, 0x38, 0x1C, + 0x00, 0x3C, 0x00, 0xF8, 0x01, 0xE0, 0x03, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x40 '@' + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x07, 0xF8, 0x0E, 0x18, 0x18, 0x0C, 0x19, 0xDC, 0x33, 0xF6, + 0x37, 0x76, 0x36, 0x36, 0x24, 0x36, 0x2C, 0x26, 0x2C, 0x66, 0x2C, 0x66, 0x2C, 0x64, 0x26, 0xEC, + 0x37, 0xBC, 0x33, 0x38, 0x18, 0x00, 0x1C, 0x18, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00 + }, + // 0x41 'A' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x07, 0xC0, 0x0F, 0xC0, 0x0E, 0xC0, 0x0E, 0xE0, + 0x1C, 0xE0, 0x1C, 0xE0, 0x1C, 0x70, 0x38, 0x70, 0x3F, 0xF0, 0x3F, 0xF8, 0x70, 0x38, 0x70, 0x38, + 0x70, 0x3C, 0xF0, 0x1C, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x42 'B' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF8, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x38, 0x1F, 0xF0, 0x1F, 0xF8, 0x1C, 0x3C, 0x1C, 0x1E, 0x1C, 0x1E, 0x1C, 0x1E, 0x1C, 0x1E, + 0x1C, 0x3C, 0x1F, 0xFC, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x43 'C' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF8, 0x1E, 0x3C, 0x1C, 0x1C, 0x3C, 0x18, + 0x3C, 0x00, 0x3C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x1C, 0x1C, 0x1C, + 0x1E, 0x3C, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x44 'D' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x1F, 0xF0, 0x1C, 0x78, 0x1C, 0x3C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x78, 0x1F, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x45 'E' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, + 0x1C, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, + 0x1C, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x46 'F' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, + 0x1C, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, + 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x47 'G' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x18, + 0x3C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0xFC, 0x3C, 0xFC, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, + 0x1E, 0x3C, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x48 'H' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x3C, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x49 'I' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4A 'J' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x03, 0xF8, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x1C, 0x78, 0x3C, 0x78, + 0x1E, 0x70, 0x0F, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4B 'K' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3C, 0x38, 0x78, 0x38, 0xF0, 0x38, 0xE0, 0x39, 0xE0, + 0x3B, 0xC0, 0x3F, 0x80, 0x3F, 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x3D, 0xE0, 0x38, 0xF0, 0x38, 0xF0, + 0x38, 0x78, 0x38, 0x78, 0x38, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4C 'L' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, + 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, + 0x1E, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4D 'M' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x3E, 0x3C, 0x3E, 0x3C, 0x3E, 0x7C, 0x3E, 0x7C, + 0x3F, 0x6C, 0x3B, 0x6C, 0x3B, 0xEC, 0x3B, 0xCC, 0x3B, 0xCC, 0x39, 0xCC, 0x39, 0xCC, 0x38, 0x0C, + 0x38, 0x0C, 0x38, 0x0C, 0x38, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4E 'N' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x1C, 0x1E, 0x1C, 0x1E, 0x1C, 0x1F, 0x1C, 0x1F, 0x1C, + 0x1F, 0x9C, 0x1F, 0x9C, 0x1D, 0x9C, 0x1D, 0xDC, 0x1D, 0xDC, 0x1C, 0xDC, 0x1C, 0xFC, 0x1C, 0xFC, + 0x1C, 0x7C, 0x1C, 0x7C, 0x1C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4F 'O' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x1C, + 0x3C, 0x1C, 0x38, 0x1C, 0x38, 0x1E, 0x38, 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x3C, + 0x1E, 0x38, 0x0F, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x50 'P' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x1F, 0xF8, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1F, 0xF8, 0x1F, 0xE0, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, + 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x51 'Q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x1C, + 0x3C, 0x1C, 0x38, 0x1C, 0x38, 0x1E, 0x38, 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x3C, + 0x1E, 0x38, 0x0F, 0xF8, 0x07, 0xE0, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0xFE, 0x00, 0x3E + }, + // 0x52 'R' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xF0, 0x38, 0x78, 0x38, 0x38, 0x38, 0x3C, + 0x38, 0x38, 0x38, 0x78, 0x3F, 0xF0, 0x3F, 0xE0, 0x39, 0xE0, 0x38, 0xE0, 0x38, 0xF0, 0x38, 0x70, + 0x38, 0x78, 0x38, 0x3C, 0x38, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x53 'S' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1C, 0x38, 0x3C, 0x3C, 0x3C, 0x1C, + 0x3C, 0x00, 0x1F, 0x80, 0x0F, 0xF0, 0x03, 0xFC, 0x00, 0x7C, 0x00, 0x1E, 0x38, 0x1E, 0x38, 0x1C, + 0x3C, 0x3C, 0x1F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x54 'T' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x3F, 0xFE, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x55 'U' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x38, + 0x1E, 0x78, 0x0F, 0xF0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x56 'V' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1C, 0x70, 0x3C, 0x70, 0x3C, 0x78, 0x38, 0x38, 0x78, + 0x38, 0x78, 0x3C, 0x70, 0x1C, 0x70, 0x1C, 0xF0, 0x1C, 0xE0, 0x0E, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, + 0x07, 0xC0, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x57 'W' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1C, 0xE0, 0x1C, 0xE0, 0x1C, 0x60, 0x1C, 0x73, 0x1C, + 0x73, 0x9C, 0x77, 0x98, 0x77, 0xB8, 0x77, 0xF8, 0x7E, 0xF8, 0x3E, 0xF8, 0x3C, 0xF8, 0x3C, 0xF0, + 0x3C, 0xF0, 0x3C, 0x70, 0x38, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x58 'X' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x3C, 0x78, 0x78, 0x3C, 0x70, 0x1C, 0xF0, 0x1E, 0xE0, + 0x0F, 0xC0, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0, 0x0F, 0xC0, 0x0F, 0xE0, 0x1C, 0xE0, 0x3C, 0x70, + 0x38, 0x78, 0x78, 0x38, 0xF0, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x59 'Y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3C, 0x70, 0x38, 0x38, 0x78, 0x3C, 0x70, 0x1C, 0xF0, + 0x1E, 0xE0, 0x0F, 0xC0, 0x07, 0xC0, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, + 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5A 'Z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x38, 0x00, 0x78, 0x00, 0xF0, + 0x00, 0xE0, 0x01, 0xE0, 0x03, 0xC0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x0F, 0x00, 0x1E, 0x00, + 0x3C, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5B '[' + { + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xF0, 0x07, 0xF0 + }, + // 0x5C '\\' + { + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x03, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x30, + 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5D ']' + { + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, + 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, + 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0 + }, + // 0x5E '^' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x07, 0xE0, 0x06, 0x60, 0x0E, 0x70, + 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x38, 0x1C, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5F '_' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x60 '`' + { + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x61 'a' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, + 0x1E, 0x78, 0x1C, 0x38, 0x00, 0x38, 0x07, 0xF8, 0x1F, 0xF8, 0x1C, 0x38, 0x3C, 0x38, 0x3C, 0x78, + 0x3C, 0xF8, 0x1F, 0xBE, 0x0F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x62 'b' + { + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0xF0, 0x1D, 0xF8, + 0x1E, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x3C, + 0x1E, 0x38, 0x1D, 0xF8, 0x1C, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x63 'c' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF8, + 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x1C, 0x1C, 0x1C, 0x3C, + 0x1E, 0x38, 0x0F, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x64 'd' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x07, 0xBC, 0x0F, 0xFC, + 0x1E, 0x7C, 0x1C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x1C, 0x3C, + 0x1E, 0x7C, 0x0F, 0xFC, 0x07, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x65 'e' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, + 0x1E, 0x38, 0x1C, 0x1C, 0x3C, 0x1C, 0x3F, 0xFC, 0x3F, 0xFC, 0x3C, 0x00, 0x3C, 0x00, 0x1C, 0x1C, + 0x1E, 0x38, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x66 'f' + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x03, 0xFC, 0x03, 0x80, 0x07, 0x80, 0x3F, 0xFC, 0x3F, 0xFC, + 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, + 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x67 'g' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x9C, 0x0F, 0xDC, + 0x1E, 0x7C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, + 0x1E, 0x3C, 0x0F, 0xDC, 0x07, 0x9C, 0x00, 0x1C, 0x1C, 0x3C, 0x1E, 0x38, 0x0F, 0xF8, 0x03, 0xE0 + }, + // 0x68 'h' + { + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0xF0, 0x1D, 0xF8, + 0x1E, 0x3C, 0x1E, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x69 'i' + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6A 'j' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, + 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, + 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x3F, 0xC0, 0x1F, 0x00 + }, + // 0x6B 'k' + { + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x3C, 0x1C, 0x38, + 0x1C, 0x70, 0x1C, 0xE0, 0x1D, 0xC0, 0x1F, 0xC0, 0x1F, 0xE0, 0x1E, 0xE0, 0x1C, 0x70, 0x1C, 0x78, + 0x1C, 0x38, 0x1C, 0x3C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6C 'l' + { + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6D 'm' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x38, 0x3F, 0xBC, + 0x3B, 0xDC, 0x39, 0xCC, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, + 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6E 'n' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xF0, 0x1D, 0xF8, + 0x1E, 0x3C, 0x1E, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6F 'o' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, + 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x3C, + 0x1E, 0x38, 0x0F, 0xF0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x70 'p' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xF0, 0x1F, 0xF8, + 0x1E, 0x38, 0x1E, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, + 0x1E, 0x38, 0x1F, 0xF8, 0x1C, 0xF0, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00 + }, + // 0x71 'q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x9C, 0x0F, 0xFC, + 0x1E, 0x7C, 0x1C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x1C, 0x3C, + 0x1E, 0x7C, 0x1F, 0xFC, 0x07, 0xBC, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C + }, + // 0x72 'r' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x7C, 0x0E, 0xFC, + 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x73 's' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, + 0x1C, 0x38, 0x1C, 0x18, 0x1E, 0x00, 0x1F, 0xE0, 0x0F, 0xF8, 0x01, 0xFC, 0x00, 0x3C, 0x18, 0x1C, + 0x1C, 0x3C, 0x0F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x74 't' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, + 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x80, 0x03, 0xF8, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x75 'u' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, + 0x1E, 0x7C, 0x1F, 0xFC, 0x07, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x76 'v' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1E, 0x38, 0x1C, + 0x3C, 0x1C, 0x1C, 0x3C, 0x1C, 0x38, 0x1E, 0x38, 0x0E, 0x78, 0x0E, 0x70, 0x0F, 0x70, 0x07, 0xE0, + 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x77 'w' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0C, 0xE0, 0x1C, + 0x60, 0x1C, 0x63, 0x1C, 0x63, 0x9C, 0x77, 0x98, 0x77, 0x98, 0x76, 0xD8, 0x3E, 0xF8, 0x3C, 0xF8, + 0x3C, 0xF0, 0x3C, 0x70, 0x38, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x78 'x' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x1C, 0x1C, 0x38, + 0x0E, 0x38, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x07, 0x70, 0x0E, 0x70, + 0x1E, 0x38, 0x1C, 0x3C, 0x38, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x79 'y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1E, 0x38, 0x1C, + 0x3C, 0x1C, 0x1C, 0x3C, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0xE0, + 0x03, 0xE0, 0x03, 0xE0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x07, 0x80, 0x1F, 0x00, 0x1E, 0x00 + }, + // 0x7A 'z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, + 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x01, 0xC0, 0x03, 0xC0, 0x07, 0x80, 0x07, 0x00, 0x0F, 0x00, + 0x1E, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x7B '{' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xF8, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, + 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0x80, 0x1F, 0x00, 0x1F, 0x00, 0x07, 0x80, 0x03, 0x80, + 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x01, 0xF8, 0x00, 0xF8 + }, + // 0x7C '|' + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0 + }, + // 0x7D '}' + { + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x1F, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0xE0, 0x00, 0x78, 0x00, 0x78, 0x00, 0xE0, 0x01, 0xE0, + 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x1F, 0xC0, 0x1F, 0x80 + }, + // 0x7E '~' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x3F, 0x00, 0x31, 0xC4, 0x20, 0xFC, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h new file mode 100644 index 0000000000000..f5289f8767894 --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h @@ -0,0 +1,779 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Font: LiberationMono-Bold.ttf +// Size: 24x24 pixels +// Characters: 0x20..0x7E (' '..'~') +// Each character: 72 bytes (24 rows × 3 bytes per row) +// Each row: 3 byte(s) for 24 pixels, MSB = leftmost pixel +// Indexing: glyph = rm690b0_font_24x24_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E +// +// Generated by ttf_to_rm690b0.py + +static const uint8_t rm690b0_font_24x24_data[95][72] = { + // 0x20 ' ' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x21 '!' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x22 '\"' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, + 0xE7, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x23 '#' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x00, 0x31, 0x80, 0x00, + 0x61, 0x80, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x63, 0x00, 0x00, 0x43, 0x00, 0x00, 0xC3, + 0x00, 0x00, 0xC2, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x86, 0x00, 0x01, 0x86, 0x00, + 0x01, 0x84, 0x00, 0x01, 0x8C, 0x00, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x24 '$' + { + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xFF, 0x80, 0x01, + 0xCB, 0xC0, 0x03, 0xC9, 0xC0, 0x03, 0xC8, 0x00, 0x01, 0xC8, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x3F, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x09, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, + 0x01, 0xCB, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x25 '%' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0x80, 0x07, 0xC1, 0x80, 0x0C, + 0xE3, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0xEC, 0x00, 0x07, 0xD8, 0x00, 0x07, 0x98, + 0x00, 0x00, 0x37, 0x80, 0x00, 0x6F, 0xC0, 0x00, 0xEC, 0xC0, 0x00, 0xCC, 0xC0, 0x01, 0x8C, 0xC0, + 0x03, 0x0C, 0xC0, 0x03, 0x0F, 0xC0, 0x06, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x26 '&' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFE, 0x00, 0x01, + 0xCE, 0x00, 0x01, 0x86, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xE1, + 0x80, 0x07, 0xF3, 0x80, 0x07, 0x73, 0x00, 0x0E, 0x3F, 0x00, 0x0E, 0x1F, 0x00, 0x0E, 0x0E, 0x00, + 0x07, 0x1F, 0x00, 0x07, 0xFF, 0xC0, 0x01, 0xF1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x27 '\'' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x28 '(' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00 + }, + // 0x29 ')' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00 + }, + // 0x2A '*' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x99, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x67, 0x00, 0x00, 0x22, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2B '+' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x03, 0xFF, + 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2C ',' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00 + }, + // 0x2D '-' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2E '.' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2F '/' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, + 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x30 '0' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xD9, + 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, + 0x00, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x31 '1' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x01, 0x9E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x32 '2' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x33 '3' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE7, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x3F, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC1, 0xC0, + 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x34 '4' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC7, + 0x00, 0x01, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x35 '5' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDE, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, + 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC3, 0xC0, + 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x36 '6' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0x80, 0x00, + 0xE3, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDF, 0x00, 0x03, 0xFF, + 0x80, 0x03, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x00, 0xE3, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x37 '7' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, + 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x38 '8' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xE3, 0x80, 0x00, 0x7F, + 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x39 '9' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x03, 0x80, 0x01, 0xC3, 0x80, + 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3A ':' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3B ';' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00 + }, + // 0x3C '<' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x01, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, + 0x00, 0x03, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0x80, + 0x00, 0x01, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3D '=' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3E '>' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x01, 0xF0, 0x00, + 0x03, 0xC0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3F '?' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x40 '@' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x7F, 0x80, 0x00, 0xE1, 0x80, 0x01, + 0x80, 0xC0, 0x01, 0x9D, 0xC0, 0x03, 0x3F, 0x60, 0x03, 0x77, 0x60, 0x03, 0x63, 0x60, 0x02, 0x43, + 0x60, 0x02, 0xC2, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x40, 0x02, 0x6E, 0xC0, + 0x03, 0x7B, 0xC0, 0x03, 0x33, 0x80, 0x01, 0x80, 0x00, 0x01, 0xC1, 0x80, 0x00, 0xFF, 0x80, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x41 'A' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0xEC, 0x00, 0x00, 0xEE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xC7, + 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0x03, 0x80, 0x07, 0x03, 0x80, + 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0F, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x42 'B' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x01, + 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFF, + 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, + 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x43 'C' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, + 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x44 'D' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFF, 0x00, 0x01, + 0xC7, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xC7, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x45 'E' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, + 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x46 'F' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, + 0xC0, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x47 'G' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, + 0x00, 0x03, 0x8F, 0xC0, 0x03, 0xCF, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x48 'H' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, + 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, + 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x49 'I' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4A 'J' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0x80, 0x00, + 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, + 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x01, 0xC7, 0x80, 0x03, 0xC7, 0x80, + 0x01, 0xE7, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4B 'K' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0xC0, 0x03, 0x87, 0x80, 0x03, + 0x8F, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x9E, 0x00, 0x03, 0xBC, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF8, + 0x00, 0x03, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xDE, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x8F, 0x00, + 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4C 'L' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, + 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4D 'M' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xC0, 0x03, 0xE3, 0xC0, 0x03, + 0xE3, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xF6, 0xC0, 0x03, 0xB6, 0xC0, 0x03, 0xBE, + 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x80, 0xC0, + 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4E 'N' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE1, 0xC0, 0x01, 0xE1, 0xC0, 0x01, + 0xE1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xD9, + 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xCD, 0xC0, 0x01, 0xCF, 0xC0, 0x01, 0xCF, 0xC0, + 0x01, 0xC7, 0xC0, 0x01, 0xC7, 0xC0, 0x01, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4F 'O' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, + 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x50 'P' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xFF, 0x80, 0x01, + 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xFF, 0x80, 0x01, 0xFE, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x51 'Q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, + 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xE0 + }, + // 0x52 'R' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x03, + 0x87, 0x80, 0x03, 0x83, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0xFF, + 0x00, 0x03, 0xFE, 0x00, 0x03, 0x9E, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x87, 0x00, + 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x53 'S' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC0, 0x00, 0x01, 0xF8, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, + 0x03, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x54 'T' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x55 'U' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, + 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, + 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x56 'V' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x01, 0xC0, 0x07, 0x03, 0xC0, 0x07, + 0x03, 0xC0, 0x07, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xC7, + 0x00, 0x01, 0xCF, 0x00, 0x01, 0xCE, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x57 'W' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, + 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x07, 0x31, 0xC0, 0x07, 0x39, 0xC0, 0x07, 0x79, 0x80, 0x07, 0x7B, + 0x80, 0x07, 0x7F, 0x80, 0x07, 0xEF, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, 0x03, 0xCF, 0x00, + 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x58 'X' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0xC0, 0x07, 0x87, 0x80, 0x03, + 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xCE, 0x00, 0x03, 0xC7, 0x00, + 0x03, 0x87, 0x80, 0x07, 0x83, 0x80, 0x0F, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x59 'Y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xC0, 0x07, 0x03, 0x80, 0x03, + 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5A 'Z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, + 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5B '[' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00 + }, + // 0x5C '\\' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5D ']' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00 + }, + // 0x5E '^' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x66, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC3, 0x00, 0x01, 0xC3, 0x80, 0x01, 0x81, + 0x80, 0x03, 0x81, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5F '_' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x60 '`' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x61 'a' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x00, 0x03, + 0x80, 0x00, 0x7F, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0x80, 0x03, 0xC7, 0x80, + 0x03, 0xCF, 0x80, 0x01, 0xFB, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x62 'b' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xE3, 0xC0, + 0x01, 0xE3, 0x80, 0x01, 0xDF, 0x80, 0x01, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x63 'c' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC0, + 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x64 'd' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, + 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x65 'e' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x01, 0xC1, 0xC0, 0x03, 0xC1, + 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x66 'f' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x38, 0x00, 0x00, + 0x78, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x67 'g' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFD, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFD, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x01, 0xC0, 0x01, 0xC3, 0xC0, 0x01, + 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00 + }, + // 0x68 'h' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x69 'i' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6A 'j' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x1E, 0x00, 0x03, 0xFC, 0x00, 0x01, 0xF0, 0x00 + }, + // 0x6B 'k' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xC7, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xDC, + 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xC7, 0x00, 0x01, 0xC7, 0x80, + 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6C 'l' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6D 'm' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x33, 0x80, 0x03, 0xFB, 0xC0, 0x03, 0xBD, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, + 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, + 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6E 'n' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6F 'o' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, + 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x70 'p' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xCF, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00 + }, + // 0x71 'q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, + 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0 + }, + // 0x72 'r' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0xEF, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x73 's' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xC3, 0x80, 0x01, 0xC1, 0x80, 0x01, 0xE0, + 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0x81, 0xC0, + 0x01, 0xC3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x74 't' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x70, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x75 'u' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x71, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x76 'v' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, + 0x80, 0x01, 0xE3, 0x80, 0x00, 0xE7, 0x80, 0x00, 0xE7, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x77 'w' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x06, 0x31, 0xC0, 0x06, 0x39, + 0xC0, 0x07, 0x79, 0x80, 0x07, 0x79, 0x80, 0x07, 0x6D, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, + 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x78 'x' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x7E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, + 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x79 'y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xE3, + 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x00 + }, + // 0x7A 'z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x7B '{' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x3C, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0x80 + }, + // 0x7C '|' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00 + }, + // 0x7D '}' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xF8, 0x00 + }, + // 0x7E '~' + { + 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, 0xE0, 0x00, 0x03, 0xF0, 0x00, 0x03, 0x1C, + 0x40, 0x02, 0x0F, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h new file mode 100644 index 0000000000000..8039ebe5edef8 --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h @@ -0,0 +1,874 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Font: LiberationMono-Bold.ttf +// Size: 24x32 pixels +// Characters: 0x20..0x7E (' '..'~') +// Each character: 96 bytes (32 rows × 3 bytes per row) +// Each row: 3 byte(s) for 24 pixels, MSB = leftmost pixel +// Indexing: glyph = rm690b0_font_24x32_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E +// +// Generated by ttf_to_rm690b0.py + +static const uint8_t rm690b0_font_24x32_data[95][96] = { + // 0x20 ' ' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x21 '!' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x22 '\"' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, + 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC3, + 0x80, 0x03, 0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x23 '#' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x00, + 0x60, 0xC0, 0x00, 0xE0, 0xC0, 0x00, 0xE1, 0xC0, 0x00, 0xC1, 0x80, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, + 0xF0, 0x01, 0xC3, 0x80, 0x01, 0x83, 0x80, 0x01, 0x83, 0x00, 0x03, 0x83, 0x00, 0x03, 0x87, 0x00, + 0x1F, 0xFF, 0xE0, 0x1F, 0xFF, 0xE0, 0x03, 0x06, 0x00, 0x07, 0x06, 0x00, 0x07, 0x0E, 0x00, 0x06, + 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x24 '$' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x9B, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x10, + 0x00, 0x0F, 0x90, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, + 0x00, 0x1F, 0xF0, 0x00, 0x11, 0xF0, 0x0E, 0x10, 0xF0, 0x1E, 0x10, 0xF0, 0x0F, 0x10, 0xF0, 0x0F, + 0x9B, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x25 '%' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x70, 0x1F, + 0xC0, 0xE0, 0x39, 0xC0, 0xE0, 0x38, 0xE1, 0xC0, 0x38, 0xE3, 0x80, 0x38, 0xE3, 0x00, 0x38, 0xE7, + 0x00, 0x38, 0xEE, 0x00, 0x1D, 0xCC, 0x00, 0x1F, 0xDC, 0x00, 0x0F, 0xBB, 0xE0, 0x00, 0x37, 0xF0, + 0x00, 0x77, 0x38, 0x00, 0xEE, 0x38, 0x01, 0xCE, 0x38, 0x01, 0xCE, 0x38, 0x03, 0x8E, 0x38, 0x07, + 0x0E, 0x38, 0x06, 0x07, 0x38, 0x0E, 0x07, 0xF0, 0x1C, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x26 '&' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01, + 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, + 0x00, 0x03, 0xDF, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xE0, 0xE0, 0x0F, 0xF0, 0xE0, + 0x1E, 0x78, 0xE0, 0x1E, 0x39, 0xE0, 0x3C, 0x3F, 0xC0, 0x3C, 0x1F, 0xC0, 0x1E, 0x0F, 0x80, 0x1F, + 0x0F, 0xE8, 0x1F, 0xFF, 0xF8, 0x0F, 0xFD, 0xF8, 0x03, 0xF0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x27 '\'' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x28 '(' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00 + }, + // 0x29 ')' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00 + }, + // 0x2A '*' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x03, + 0x39, 0x80, 0x03, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xEE, + 0x00, 0x01, 0xEF, 0x00, 0x01, 0xC7, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2B '+' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, + 0x0F, 0xFF, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2C ',' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2D '-' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0x00, + 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 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 + }, + // 0x2E '.' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2F '/' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, + 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x30 '0' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, + 0x0F, 0x39, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, + 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x31 '1' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xBE, 0x00, 0x0E, 0x3E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, + 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x3E, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x32 '2' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x03, + 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0xFC, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x33 '3' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x87, 0xE0, 0x0F, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, + 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0xC0, + 0x00, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, + 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x34 '4' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x1F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x80, 0x00, 0xF7, 0x80, 0x00, 0xF7, + 0x80, 0x01, 0xE7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x07, 0x87, 0x80, 0x0F, 0x07, 0x80, + 0x1E, 0x07, 0x80, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x07, 0x80, 0x00, + 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x35 '5' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, + 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, + 0x00, 0x07, 0xBE, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x87, 0xE0, + 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x36 '6' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 0xE7, 0xC0, 0x07, 0xC3, 0xE0, 0x07, 0x81, 0xC0, 0x0F, 0x80, + 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x1F, 0x00, 0x0F, 0x7F, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xC3, 0xE0, + 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xE0, 0x03, + 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x37 '7' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x38 '8' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, + 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC3, 0xC0, + 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC3, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x39 '9' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x03, + 0xFF, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, + 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, 0xFF, 0xE0, + 0x03, 0xFD, 0xE0, 0x00, 0xF9, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x07, 0x83, 0xC0, 0x07, + 0x87, 0xC0, 0x07, 0xFF, 0x80, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3A ':' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3B ';' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3C '<' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0xF0, 0x03, 0xFF, + 0xE0, 0x0F, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x0F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3D '=' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, + 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3E '>' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFF, + 0x80, 0x00, 0xFF, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xF0, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x0F, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3F '?' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x1F, 0x01, 0xE0, 0x1F, 0x01, + 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3E, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x40 '@' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xC1, 0xC0, 0x03, + 0x80, 0xE0, 0x07, 0x00, 0x60, 0x06, 0x00, 0x70, 0x0C, 0x39, 0xB0, 0x0C, 0x7D, 0xB0, 0x1C, 0xE7, + 0xB0, 0x18, 0xC3, 0xB0, 0x19, 0xC3, 0x38, 0x19, 0x83, 0x18, 0x19, 0x83, 0x38, 0x1B, 0x87, 0x30, + 0x1B, 0x87, 0x30, 0x1B, 0x86, 0x30, 0x1B, 0x86, 0x30, 0x19, 0x8E, 0x30, 0x19, 0x9E, 0x60, 0x19, + 0xFB, 0xE0, 0x0C, 0xE3, 0x80, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x03, 0x83, + 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x41 'A' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xE7, + 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, + 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x1F, 0x01, 0xF0, 0x1F, + 0x00, 0xF0, 0x1E, 0x00, 0xF0, 0x3E, 0x00, 0xF8, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x42 'B' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, + 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, + 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, + 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, + 0xFF, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x43 'C' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, + 0xC0, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x80, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0xC3, 0xF0, 0x07, + 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x44 'D' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x0F, + 0xFF, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0x8F, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, + 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, + 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xE0, 0x0F, + 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x45 'E' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x0F, 0x80, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, + 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x46 'F' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, + 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, + 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, + 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, + 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x47 'G' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0x80, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, + 0x1F, 0x1F, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0xC1, 0xF0, 0x07, + 0xFF, 0xF0, 0x03, 0xFF, 0xE0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x48 'H' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xE0, 0x0F, + 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, + 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, + 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x49 'I' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4A 'J' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, + 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x07, 0x07, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0xC0, 0x07, + 0xFF, 0x80, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4B 'K' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xF8, 0x0F, + 0x83, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x9F, + 0x00, 0x0F, 0xBE, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xFE, 0x00, + 0x0F, 0xFF, 0x00, 0x0F, 0xDF, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, + 0x83, 0xE0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4C 'L' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, + 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, + 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4D 'M' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xF0, 0x0F, + 0x83, 0xF0, 0x0F, 0xC3, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xE7, 0xF0, 0x0E, 0xE7, + 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xFE, 0xF0, 0x0E, 0x7E, 0xF0, 0x0E, 0x7C, 0xF0, + 0x0E, 0x7C, 0xF0, 0x0E, 0x3C, 0xF0, 0x0E, 0x38, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, + 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4E 'N' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC1, 0xE0, 0x0F, + 0xC1, 0xE0, 0x0F, 0xC1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xF1, + 0xE0, 0x0F, 0x71, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x3D, 0xE0, + 0x0F, 0x3D, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, + 0x0F, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4F 'O' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, + 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, + 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x50 'P' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x0F, + 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, + 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, + 0x0F, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x51 'Q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, + 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, + 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, + 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00 + }, + // 0x52 'R' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, + 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, + 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, + 0x0F, 0xFF, 0x00, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, + 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x53 'S' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x0F, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, + 0x00, 0x07, 0xF0, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x81, 0xF0, 0x0F, + 0xFF, 0xF0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x54 'T' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x1F, + 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x55 'U' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, + 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, + 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0xC7, 0xE0, 0x07, + 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x56 'V' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1E, + 0x00, 0xF8, 0x1F, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, + 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xC7, 0x80, + 0x03, 0xE7, 0x80, 0x01, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x57 'W' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, + 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, 0x78, 0x1E, 0x00, 0x70, 0x1E, 0x00, 0xF0, 0x1E, 0x38, + 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x7C, 0xF0, 0x1E, 0x7C, 0xF0, 0x0E, 0x7C, 0xF0, 0x0E, 0xFE, 0xE0, + 0x0F, 0xEE, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xE7, 0xE0, 0x07, 0xC7, 0xE0, 0x07, + 0xC7, 0xC0, 0x07, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x58 'X' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, + 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xEF, 0x80, 0x01, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, + 0x00, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xEF, 0x80, 0x03, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x0F, + 0x83, 0xE0, 0x0F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x59 'Y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1F, + 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, 0x03, 0xC7, + 0x80, 0x01, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5A 'Z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, + 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, + 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, + 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, + 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5B '[' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80 + }, + // 0x5C '\\' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, + 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, + 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5D ']' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00 + }, + // 0x5E '^' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, + 0x80, 0x03, 0x83, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0E, 0x01, 0xE0, + 0x1E, 0x00, 0xE0, 0x1C, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5F '_' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x60 '`' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x61 'a' + { + 0x00, 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, 0x00, 0x03, 0xFF, 0x00, 0x07, 0xFF, + 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x87, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0xFF, 0xC0, + 0x07, 0xFF, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, + 0x8F, 0xC0, 0x0F, 0xFF, 0xF0, 0x07, 0xF9, 0xF0, 0x03, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x62 'b' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, + 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, + 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, + 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x63 'c' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, + 0xC0, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x64 'd' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x01, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, + 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, + 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x65 'e' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xFF, + 0x80, 0x07, 0xC3, 0xC0, 0x0F, 0x81, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0xFF, 0xE0, + 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x07, + 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x66 'f' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, + 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, + 0xE0, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x67 'g' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x03, 0xFD, 0xE0, 0x07, 0xFF, + 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFD, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0xE0, 0x07, 0x83, 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00 + }, + // 0x68 'h' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x8F, 0x00, 0x0F, 0xBF, 0xC0, 0x0F, 0xFF, + 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, + 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x69 'i' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6A 'j' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xE0, 0x00 + }, + // 0x6B 'k' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, + 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0x87, + 0xC0, 0x07, 0x8F, 0x80, 0x07, 0x9F, 0x00, 0x07, 0xBE, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, + 0x07, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x07, 0x8F, 0x00, 0x07, 0x8F, 0x80, 0x07, 0x87, 0xC0, 0x07, + 0x87, 0xC0, 0x07, 0x83, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x81, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6C 'l' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6D 'm' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE1, 0xC0, 0x1D, 0xF3, 0xE0, 0x1F, 0xFF, + 0xF0, 0x1F, 0x7C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, + 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, + 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6E 'n' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x0F, 0x3F, 0xC0, 0x0F, 0x7F, + 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, + 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6F 'o' + { + 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, + 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, + 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x70 'p' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, + 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, + 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00 + }, + // 0x71 'q' + { + 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, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, + 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, + 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0 + }, + // 0x72 'r' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0xE0, 0x07, 0xCF, 0xE0, 0x03, 0xDF, + 0xE0, 0x03, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x73 's' + { + 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, + 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x81, 0xC0, 0x07, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFF, 0x00, + 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, + 0x83, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x74 't' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0x07, 0xFF, + 0x80, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, + 0xF0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x75 'u' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, + 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, + 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x07, 0xFD, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xE1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x76 'v' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x01, + 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, + 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x77 'w' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, + 0x78, 0x1C, 0x00, 0x70, 0x1C, 0x38, 0x70, 0x1C, 0x3C, 0x70, 0x1E, 0x7C, 0x70, 0x1E, 0x7C, 0xF0, + 0x0E, 0x7C, 0xF0, 0x0E, 0xEE, 0xE0, 0x0E, 0xEE, 0xE0, 0x0E, 0xE7, 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x78 'x' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, + 0xC0, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xEF, 0x00, 0x03, 0xC7, 0x80, 0x07, + 0xC7, 0xC0, 0x07, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x1F, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x79 'y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, + 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, + 0x03, 0xC7, 0x80, 0x01, 0xE7, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, + 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xC0, 0x00 + }, + // 0x7A 'z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0xFF, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x7B '{' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, + 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x07, 0xE0, 0x00, + 0x07, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0 + }, + // 0x7C '|' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00 + }, + // 0x7D '}' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF0, 0x00 + }, + // 0x7E '~' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x0F, 0xF8, 0x30, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, + 0x18, 0x3F, 0xF0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h new file mode 100644 index 0000000000000..91262bf63f2b2 --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h @@ -0,0 +1,1064 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Font: LiberationMono-Bold.ttf +// Size: 32x32 pixels +// Characters: 0x20..0x7E (' '..'~') +// Each character: 128 bytes (32 rows × 4 bytes per row) +// Each row: 4 byte(s) for 32 pixels, MSB = leftmost pixel +// Indexing: glyph = rm690b0_font_32x32_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E +// +// Generated by ttf_to_rm690b0.py + +static const uint8_t rm690b0_font_32x32_data[95][128] = { + // 0x20 ' ' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x21 '!' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x22 '\"' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x38, 0x00, 0x00, 0x3C, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x23 '#' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x0C, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x0E, 0x0C, 0x00, 0x00, 0x0E, 0x1C, 0x00, + 0x00, 0x0C, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x38, 0x00, + 0x00, 0x18, 0x38, 0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x38, 0x30, 0x00, 0x00, 0x38, 0x70, 0x00, + 0x01, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x70, 0x60, 0x00, + 0x00, 0x70, 0xE0, 0x00, 0x00, 0x60, 0xE0, 0x00, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x60, 0xC0, 0x00, + 0x00, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x24 '$' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xF9, 0xBE, 0x00, + 0x00, 0xF1, 0x1E, 0x00, 0x00, 0xF1, 0x1E, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, + 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0x1F, 0x00, 0x00, 0xE1, 0x0F, 0x00, 0x01, 0xE1, 0x0F, 0x00, + 0x00, 0xF1, 0x0F, 0x00, 0x00, 0xF9, 0xBE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x25 '%' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x07, 0x00, 0x01, 0xFC, 0x0E, 0x00, 0x03, 0x9C, 0x0E, 0x00, 0x03, 0x8E, 0x1C, 0x00, + 0x03, 0x8E, 0x38, 0x00, 0x03, 0x8E, 0x30, 0x00, 0x03, 0x8E, 0x70, 0x00, 0x03, 0x8E, 0xE0, 0x00, + 0x01, 0xDC, 0xC0, 0x00, 0x01, 0xFD, 0xC0, 0x00, 0x00, 0xFB, 0xBE, 0x00, 0x00, 0x03, 0x7F, 0x00, + 0x00, 0x07, 0x73, 0x80, 0x00, 0x0E, 0xE3, 0x80, 0x00, 0x1C, 0xE3, 0x80, 0x00, 0x1C, 0xE3, 0x80, + 0x00, 0x38, 0xE3, 0x80, 0x00, 0x70, 0xE3, 0x80, 0x00, 0x60, 0x73, 0x80, 0x00, 0xE0, 0x7F, 0x00, + 0x01, 0xC0, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x26 '&' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x38, 0x78, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x38, 0x70, 0x00, 0x00, 0x3D, 0xF0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7E, 0x0E, 0x00, 0x00, 0xFF, 0x0E, 0x00, + 0x01, 0xE7, 0x8E, 0x00, 0x01, 0xE3, 0x9E, 0x00, 0x03, 0xC3, 0xFC, 0x00, 0x03, 0xC1, 0xFC, 0x00, + 0x01, 0xE0, 0xF8, 0x00, 0x01, 0xF0, 0xFE, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xDF, 0x80, + 0x00, 0x3F, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x27 '\'' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x28 '(' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00 + }, + // 0x29 ')' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00 + }, + // 0x2A '*' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x33, 0x98, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x1E, 0xF0, 0x00, + 0x00, 0x1C, 0x70, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2B '+' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2C ',' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2D '-' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2E '.' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2F '/' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x30 '0' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0x7C, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF3, 0x9E, 0x00, + 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x31 '1' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, + 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xFB, 0xE0, 0x00, 0x00, 0xE3, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 + }, + // 0x32 '2' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7C, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x33 '3' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xF8, 0x7E, 0x00, + 0x00, 0xF0, 0x3E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x34 '4' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x78, 0x00, 0x00, 0x0F, 0x78, 0x00, 0x00, 0x1E, 0x78, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, 0xF0, 0x78, 0x00, + 0x01, 0xE0, 0x78, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x35 '5' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7B, 0xE0, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xF8, 0x7E, 0x00, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x36 '6' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3E, 0x7C, 0x00, + 0x00, 0x7C, 0x3E, 0x00, 0x00, 0x78, 0x1C, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0xF1, 0xF0, 0x00, 0x00, 0xF7, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFC, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x78, 0x1E, 0x00, + 0x00, 0x78, 0x3E, 0x00, 0x00, 0x3C, 0x3E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x37 '7' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xF8, 0x00, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x38 '8' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7C, 0x7E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7C, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0x3C, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x3E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x39 '9' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7C, 0x7C, 0x00, + 0x00, 0xF8, 0x3C, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0x3F, 0xDE, 0x00, 0x00, 0x0F, 0x9E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3A ':' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3B ';' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3C '<' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0xFF, 0xF0, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3D '=' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3E '>' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3F, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3F '?' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x40 '@' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00, 0x60, 0x07, 0x00, + 0x00, 0xC3, 0x9B, 0x00, 0x00, 0xC7, 0xDB, 0x00, 0x01, 0xCE, 0x7B, 0x00, 0x01, 0x8C, 0x3B, 0x00, + 0x01, 0x9C, 0x33, 0x80, 0x01, 0x98, 0x31, 0x80, 0x01, 0x98, 0x33, 0x80, 0x01, 0xB8, 0x73, 0x00, + 0x01, 0xB8, 0x73, 0x00, 0x01, 0xB8, 0x63, 0x00, 0x01, 0xB8, 0x63, 0x00, 0x01, 0x98, 0xE3, 0x00, + 0x01, 0x99, 0xE6, 0x00, 0x01, 0x9F, 0xBE, 0x00, 0x00, 0xCE, 0x38, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0x70, 0x0C, 0x00, 0x00, 0x38, 0x3C, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x41 'A' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1E, 0x70, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x78, 0x3C, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x0F, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x03, 0xE0, 0x0F, 0x80, + 0x03, 0xE0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x42 'B' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x43 'C' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1C, 0x00, 0x01, 0xF0, 0x00, 0x00, + 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, + 0x01, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x0E, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x44 'D' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, + 0x00, 0xF8, 0xFE, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xF8, 0x7E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xF0, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x45 'E' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 + }, + // 0x46 'F' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x47 'G' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x18, 0x00, 0x01, 0xF0, 0x00, 0x00, + 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF1, 0xFF, 0x00, 0x01, 0xF1, 0xFF, 0x00, 0x01, 0xF1, 0xFF, 0x00, + 0x01, 0xF1, 0xFF, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x48 'H' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x49 'I' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4A 'J' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x70, 0x7C, 0x00, 0x00, 0xF8, 0x7C, 0x00, + 0x00, 0xF8, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4B 'K' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x1F, 0x80, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x7C, 0x00, + 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xFB, 0xE0, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFD, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x7C, 0x00, + 0x00, 0xF8, 0x7C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4C 'L' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, + 0x00, 0x7F, 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 + }, + // 0x4D 'M' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x7F, 0x00, + 0x00, 0xFC, 0x7F, 0x00, 0x00, 0xFE, 0x7F, 0x00, 0x00, 0xEE, 0x7F, 0x00, 0x00, 0xEE, 0xEF, 0x00, + 0x00, 0xEE, 0xEF, 0x00, 0x00, 0xEF, 0xEF, 0x00, 0x00, 0xE7, 0xEF, 0x00, 0x00, 0xE7, 0xCF, 0x00, + 0x00, 0xE7, 0xCF, 0x00, 0x00, 0xE3, 0xCF, 0x00, 0x00, 0xE3, 0x8F, 0x00, 0x00, 0xE0, 0x0F, 0x00, + 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, + 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4E 'N' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0x1E, 0x00, 0x00, 0xFC, 0x1E, 0x00, 0x00, 0xFC, 0x1E, 0x00, 0x00, 0xFE, 0x1E, 0x00, + 0x00, 0xFE, 0x1E, 0x00, 0x00, 0xFE, 0x1E, 0x00, 0x00, 0xFF, 0x1E, 0x00, 0x00, 0xF7, 0x1E, 0x00, + 0x00, 0xF7, 0x9E, 0x00, 0x00, 0xF7, 0x9E, 0x00, 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF3, 0xDE, 0x00, + 0x00, 0xF3, 0xDE, 0x00, 0x00, 0xF1, 0xFE, 0x00, 0x00, 0xF1, 0xFE, 0x00, 0x00, 0xF0, 0xFE, 0x00, + 0x00, 0xF0, 0xFE, 0x00, 0x00, 0xF0, 0xFE, 0x00, 0x00, 0xF0, 0x7E, 0x00, 0x00, 0xF0, 0x7E, 0x00, + 0x00, 0xF0, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4F 'O' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x50 'P' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x51 'Q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x52 'R' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF0, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x7C, 0x00, + 0x00, 0xF8, 0x7C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x53 'S' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, + 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x01, 0xF0, 0x0F, 0x00, + 0x01, 0xF8, 0x1F, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x54 'T' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x55 'U' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x56 'V' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xE0, 0x0F, 0x80, 0x01, 0xE0, 0x0F, 0x80, 0x01, 0xF0, 0x0F, 0x00, 0x01, 0xF0, 0x1F, 0x00, + 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3E, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x3C, 0x00, 0x00, 0x3C, 0x7C, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3E, 0x78, 0x00, 0x00, 0x1E, 0xF8, 0x00, 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x57 'W' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xC0, 0x07, 0x80, 0x03, 0xC0, 0x07, 0x80, 0x03, 0xC0, 0x07, 0x80, 0x01, 0xC0, 0x07, 0x80, + 0x01, 0xE0, 0x07, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0xCF, 0x00, + 0x01, 0xE7, 0xCF, 0x00, 0x01, 0xE7, 0xCF, 0x00, 0x00, 0xE7, 0xCF, 0x00, 0x00, 0xEF, 0xEE, 0x00, + 0x00, 0xFE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0x7E, 0x00, + 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x7C, 0x3C, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x58 'X' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x3C, 0x00, + 0x00, 0x3C, 0x7C, 0x00, 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x3C, 0x7C, 0x00, + 0x00, 0x7C, 0x3C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, + 0x03, 0xE0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x59 'Y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xE0, 0x0F, 0x80, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x1E, 0xF8, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5A 'Z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, + 0x01, 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 + }, + // 0x5B '[' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00 + }, + // 0x5C '\\' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5D ']' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00 + }, + // 0x5E '^' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1E, 0xE0, 0x00, + 0x00, 0x1C, 0xF0, 0x00, 0x00, 0x3C, 0x70, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x38, 0x38, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x70, 0x3C, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0xE0, 0x1E, 0x00, + 0x01, 0xE0, 0x0E, 0x00, 0x01, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5F '_' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x60 '`' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x61 'a' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7C, 0x7C, 0x00, + 0x00, 0x78, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1F, 0xFC, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xF8, 0x3C, 0x00, 0x00, 0xF0, 0x3C, 0x00, 0x00, 0xF0, 0x7C, 0x00, + 0x00, 0xF0, 0x7C, 0x00, 0x00, 0xF8, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0x9F, 0x00, + 0x00, 0x3E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x62 'b' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xFB, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, + 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFB, 0xF8, 0x00, + 0x00, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x63 'c' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x7C, 0x7C, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x64 'd' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x3F, 0x9E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0xFC, 0x7E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0x9E, 0x00, + 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x65 'e' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0x3C, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x7C, 0x3E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x66 'f' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x67 'g' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x1E, 0x00, 0x00, 0x3F, 0xDE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7C, 0x7E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xDE, 0x00, + 0x00, 0x0F, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x78, 0x3E, 0x00, + 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xE0, 0x00 + }, + // 0x68 'h' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0xF0, 0x00, 0x00, 0xFB, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFE, 0x3E, 0x00, + 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x69 'i' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 + }, + // 0x6A 'j' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFE, 0x00, 0x00 + }, + // 0x6B 'k' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x1E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x78, 0xF8, 0x00, + 0x00, 0x79, 0xF0, 0x00, 0x00, 0x7B, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x78, 0xF0, 0x00, 0x00, 0x78, 0xF8, 0x00, + 0x00, 0x78, 0x7C, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x78, 0x3E, 0x00, 0x00, 0x78, 0x1E, 0x00, + 0x00, 0x78, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6C 'l' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 + }, + // 0x6D 'm' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xCE, 0x1C, 0x00, 0x01, 0xDF, 0x3E, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xF7, 0xCF, 0x00, + 0x01, 0xE3, 0xCF, 0x00, 0x01, 0xE3, 0xCF, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, + 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, + 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, + 0x01, 0xE3, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6E 'n' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xF3, 0xFC, 0x00, 0x00, 0xF7, 0xFC, 0x00, 0x00, 0xFE, 0x3E, 0x00, + 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6F 'o' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7C, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x70 'p' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xFB, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, + 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, + 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFB, 0xF8, 0x00, + 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00 + }, + // 0x71 'q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x3F, 0x9E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7C, 0x7E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0x9E, 0x00, + 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00 + }, + // 0x72 'r' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x7E, 0x00, 0x00, 0x7C, 0xFE, 0x00, 0x00, 0x3D, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x73 's' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x78, 0x3C, 0x00, + 0x00, 0x78, 0x1C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, + 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x74 't' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xFC, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x75 'u' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, + 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, + 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xDE, 0x00, 0x00, 0x3F, 0x9E, 0x00, + 0x00, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x76 'v' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE0, 0x0F, 0x00, 0x01, 0xF0, 0x0F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x7C, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x1E, 0xF0, 0x00, + 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x77 'w' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xC0, 0x07, 0x80, 0x03, 0xC0, 0x07, 0x80, 0x01, 0xC0, 0x07, 0x80, 0x01, 0xC0, 0x07, 0x00, + 0x01, 0xC3, 0x87, 0x00, 0x01, 0xC3, 0xC7, 0x00, 0x01, 0xE7, 0xC7, 0x00, 0x01, 0xE7, 0xCF, 0x00, + 0x00, 0xE7, 0xCF, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0x7E, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x78, 0x3C, 0x00, + 0x00, 0x78, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x78 'x' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x78, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, + 0x01, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x79 'y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE0, 0x0F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, + 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x3C, 0x00, 0x00, 0x3C, 0x7C, 0x00, + 0x00, 0x3C, 0x78, 0x00, 0x00, 0x1E, 0x78, 0x00, 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00 + }, + // 0x7A 'z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x7B '{' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00 + }, + // 0x7C '|' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, + 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00 + }, + // 0x7D '}' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xFC, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x00, 0x00 + }, + // 0x7E '~' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFF, 0x83, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, + 0x01, 0x83, 0xFF, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h new file mode 100644 index 0000000000000..7b1e2892e7177 --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h @@ -0,0 +1,1444 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Font: LiberationMono-Bold.ttf +// Size: 32x48 pixels +// Characters: 0x20..0x7E (' '..'~') +// Each character: 192 bytes (48 rows × 4 bytes per row) +// Each row: 4 byte(s) for 32 pixels, MSB = leftmost pixel +// Indexing: glyph = rm690b0_font_32x48_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E +// +// Generated by ttf_to_rm690b0.py + +static const uint8_t rm690b0_font_32x48_data[95][192] = { + // 0x20 ' ' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x21 '!' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x22 '\"' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x3F, 0x00, + 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, + 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, + 0x01, 0xF8, 0x3E, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, + 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x23 '#' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x03, 0xC0, 0x00, 0x1E, 0x03, 0xC0, + 0x00, 0x1E, 0x03, 0x80, 0x00, 0x1C, 0x03, 0x80, 0x00, 0x1C, 0x07, 0x80, 0x00, 0x3C, 0x07, 0x80, + 0x00, 0x3C, 0x07, 0x80, 0x00, 0x3C, 0x07, 0x00, 0x00, 0x38, 0x07, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, + 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x70, 0x0E, 0x00, 0x00, 0x70, 0x1E, 0x00, + 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0xE0, 0x1C, 0x00, + 0x00, 0xE0, 0x3C, 0x00, 0x01, 0xE0, 0x3C, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xE0, + 0x3F, 0xFF, 0xFF, 0xE0, 0x03, 0xC0, 0x78, 0x00, 0x03, 0xC0, 0x78, 0x00, 0x03, 0xC0, 0x70, 0x00, + 0x03, 0x80, 0x70, 0x00, 0x03, 0x80, 0xF0, 0x00, 0x07, 0x80, 0xF0, 0x00, 0x07, 0x80, 0xF0, 0x00, + 0x07, 0x80, 0xE0, 0x00, 0x07, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x24 '$' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xF3, 0xBF, 0xC0, + 0x0F, 0xC3, 0x8F, 0xE0, 0x0F, 0xC3, 0x87, 0xE0, 0x0F, 0xC3, 0x87, 0x80, 0x0F, 0xC3, 0x80, 0x00, + 0x0F, 0xE3, 0x80, 0x00, 0x07, 0xFB, 0x80, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xE0, + 0x00, 0x03, 0x9F, 0xE0, 0x00, 0x03, 0x87, 0xE0, 0x00, 0x03, 0x87, 0xF0, 0x03, 0x83, 0x83, 0xF0, + 0x1F, 0x83, 0x83, 0xF0, 0x1F, 0x83, 0x83, 0xF0, 0x1F, 0xC3, 0x83, 0xF0, 0x0F, 0xE3, 0x87, 0xF0, + 0x0F, 0xF3, 0x9F, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x25 '%' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0xF0, 0x1F, 0xF0, 0x01, 0xE0, + 0x3F, 0xF8, 0x01, 0xE0, 0x3C, 0x7C, 0x03, 0xC0, 0x7C, 0x3C, 0x07, 0x80, 0x78, 0x3C, 0x07, 0x80, + 0x78, 0x3C, 0x0F, 0x00, 0x78, 0x3C, 0x1E, 0x00, 0x78, 0x3C, 0x3E, 0x00, 0x78, 0x3C, 0x3C, 0x00, + 0x78, 0x3C, 0x78, 0x00, 0x7C, 0x3C, 0xF8, 0x00, 0x3C, 0x7C, 0xF0, 0x00, 0x3F, 0xF9, 0xE0, 0x00, + 0x1F, 0xF3, 0xC0, 0x00, 0x07, 0xE3, 0xC0, 0x00, 0x00, 0x07, 0x8F, 0xC0, 0x00, 0x0F, 0x1F, 0xF0, + 0x00, 0x0F, 0x3F, 0xF8, 0x00, 0x1E, 0x7C, 0x78, 0x00, 0x3C, 0x78, 0x78, 0x00, 0x3C, 0x78, 0x7C, + 0x00, 0x78, 0xF8, 0x3C, 0x00, 0xF0, 0xF8, 0x3C, 0x00, 0xF0, 0xF8, 0x3C, 0x01, 0xE0, 0xF8, 0x3C, + 0x03, 0xC0, 0x78, 0x7C, 0x03, 0xC0, 0x78, 0x78, 0x07, 0x80, 0x7C, 0xF8, 0x0F, 0x00, 0x3F, 0xF0, + 0x1F, 0x00, 0x1F, 0xF0, 0x1E, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x26 '&' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xF8, 0x7E, 0x00, 0x01, 0xF0, 0x3E, 0x00, + 0x01, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x7E, 0x00, + 0x01, 0xF8, 0xFC, 0x00, 0x00, 0xFB, 0xF8, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xE0, 0x00, + 0x01, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x03, 0xC0, 0x07, 0xFE, 0x03, 0xE0, 0x0F, 0xFF, 0x03, 0xE0, + 0x1F, 0xDF, 0x87, 0xC0, 0x3F, 0x8F, 0x87, 0xC0, 0x3F, 0x0F, 0xC7, 0xC0, 0x3F, 0x07, 0xEF, 0x80, + 0x3E, 0x03, 0xFF, 0x80, 0x3E, 0x01, 0xFF, 0x80, 0x3E, 0x01, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, + 0x3F, 0x00, 0xFF, 0x80, 0x1F, 0xC1, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xF7, 0xFC, + 0x07, 0xFF, 0xC3, 0xFC, 0x00, 0xFF, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x27 '\'' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x28 '(' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00 + }, + // 0x29 ')' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00 + }, + // 0x2A '*' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x87, 0xC2, 0x00, + 0x01, 0xE7, 0xCF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3E, 0xF8, 0x00, + 0x00, 0x7E, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x7E, 0x00, 0x00, 0x38, 0x38, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2B '+' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, + 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2C ',' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2D '-' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2E '.' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x2F '/' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, + 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0x80, + 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, + 0x03, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, + 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x30 '0' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xF8, 0x3F, 0x80, + 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, + 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, + 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, + 0x03, 0xF8, 0x7F, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x31 '1' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, + 0x0F, 0xFB, 0xF0, 0x00, 0x0F, 0xF3, 0xF0, 0x00, 0x0F, 0xC3, 0xF0, 0x00, 0x0F, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, + 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x32 '2' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, + 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, + 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x33 '3' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F, 0xFF, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0x80, + 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, + 0x0F, 0xC0, 0x07, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, + 0x0F, 0xF8, 0x3F, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x34 '4' + { + 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x1F, 0xBF, 0x00, 0x00, 0x1F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, + 0x00, 0x7E, 0x3F, 0x00, 0x00, 0x7C, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, + 0x03, 0xF0, 0x3F, 0x00, 0x03, 0xE0, 0x3F, 0x00, 0x07, 0xE0, 0x3F, 0x00, 0x0F, 0xC0, 0x3F, 0x00, + 0x0F, 0x80, 0x3F, 0x00, 0x1F, 0x80, 0x3F, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0x00, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x35 '5' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, + 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xE0, 0x00, 0x00, + 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, + 0x07, 0xE3, 0xF0, 0x00, 0x07, 0xEF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, + 0x0F, 0xF8, 0x3F, 0xC0, 0x07, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x36 '6' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFC, 0x3F, 0xC0, + 0x03, 0xF8, 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE1, 0xF8, 0x00, 0x0F, 0xCF, 0xFE, 0x00, 0x0F, 0xDF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x1F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, + 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x03, 0xF8, 0x1F, 0xC0, + 0x03, 0xFC, 0x3F, 0xC0, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0x00, + 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x37 '7' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x38 '8' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, + 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, + 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x80, + 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, + 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, + 0x0F, 0xF8, 0x3F, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x39 '9' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0xF8, 0x00, + 0x01, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xF8, 0x7F, 0x80, + 0x0F, 0xF0, 0x3F, 0x80, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, + 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, + 0x0F, 0xF0, 0x1F, 0xE0, 0x07, 0xF8, 0x7F, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, + 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xCF, 0xE0, 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x01, 0xE0, 0x1F, 0x80, 0x07, 0xE0, 0x3F, 0x80, + 0x07, 0xF0, 0x7F, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFC, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3A ':' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3B ';' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3C '<' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFC, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFC, 0x00, + 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3D '=' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, + 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, + 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3E '>' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x00, 0x7F, 0xE0, + 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x7F, 0xFE, 0x00, + 0x03, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x3F '?' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xF8, 0x3F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x40 '@' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFC, 0x1F, 0x80, 0x01, 0xF0, 0x07, 0x80, + 0x01, 0xE0, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0xE0, 0x07, 0x80, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xE0, + 0x0F, 0x03, 0xC0, 0x70, 0x0E, 0x0F, 0xE7, 0x70, 0x0E, 0x1F, 0xEF, 0x70, 0x1E, 0x3E, 0x3E, 0x70, + 0x1C, 0x3C, 0x3E, 0x38, 0x1C, 0x78, 0x1E, 0x38, 0x1C, 0x78, 0x1E, 0x38, 0x1C, 0x70, 0x1E, 0x38, + 0x3C, 0xF0, 0x1C, 0x38, 0x38, 0xF0, 0x1C, 0x38, 0x38, 0xE0, 0x3C, 0x38, 0x38, 0xE0, 0x3C, 0x38, + 0x38, 0xE0, 0x3C, 0x38, 0x38, 0xE0, 0x38, 0x70, 0x38, 0xE0, 0x38, 0x70, 0x38, 0xE0, 0x78, 0x70, + 0x38, 0xE0, 0x78, 0x70, 0x38, 0xE0, 0xF8, 0xE0, 0x3C, 0xF0, 0xF8, 0xE0, 0x1C, 0xF1, 0xF9, 0xE0, + 0x1C, 0x7F, 0x9F, 0xC0, 0x1C, 0x3F, 0x1F, 0x80, 0x1E, 0x1E, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x07, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x0F, 0x80, + 0x01, 0xF0, 0x3F, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x41 'A' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7C, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x01, 0xF8, 0x7E, 0x00, 0x01, 0xF8, 0x3F, 0x00, + 0x01, 0xF8, 0x3F, 0x00, 0x03, 0xF8, 0x3F, 0x00, 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0x80, + 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x1F, 0xC0, 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0x80, 0x07, 0xF0, 0x3F, 0x80, 0x03, 0xF0, 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, + 0x7F, 0x00, 0x01, 0xF8, 0x7F, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x42 'B' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, + 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x03, 0xF8, + 0x0F, 0xE0, 0x03, 0xF8, 0x0F, 0xE0, 0x03, 0xF8, 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x07, 0xF0, + 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x43 'C' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFC, 0x3F, 0xC0, + 0x07, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, + 0x1F, 0xC0, 0x06, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x03, 0x80, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x0F, 0xE0, + 0x07, 0xFC, 0x3F, 0xE0, 0x03, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x44 'D' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xF0, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xE0, 0xFF, 0x80, + 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, + 0x0F, 0xE0, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x45 'E' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x80, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, + 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x46 'F' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, + 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x47 'G' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFC, 0x3F, 0x80, + 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0E, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC1, 0xFF, 0xE0, + 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC0, 0x07, 0xE0, 0x1F, 0xE0, 0x07, 0xE0, + 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xF0, 0x07, 0xE0, 0x07, 0xF8, 0x07, 0xE0, + 0x03, 0xFC, 0x1F, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x48 'H' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x49 'I' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4A 'J' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x01, 0xC0, 0x3F, 0x80, + 0x1F, 0xE0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0x00, 0x0F, 0xF0, 0x7F, 0x00, + 0x07, 0xF8, 0xFF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFC, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4B 'K' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x0F, 0xF0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xE0, 0x7F, 0x80, + 0x0F, 0xE0, 0x7F, 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x0F, 0xE1, 0xFE, 0x00, 0x0F, 0xE3, 0xFC, 0x00, + 0x0F, 0xE3, 0xF8, 0x00, 0x0F, 0xE7, 0xF0, 0x00, 0x0F, 0xEF, 0xF0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, + 0x0F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF8, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFB, 0xFC, 0x00, 0x0F, 0xF9, 0xFE, 0x00, 0x0F, 0xF0, 0xFE, 0x00, + 0x0F, 0xE0, 0xFF, 0x00, 0x0F, 0xE0, 0x7F, 0x80, 0x0F, 0xE0, 0x7F, 0x80, 0x0F, 0xE0, 0x3F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, + 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4C 'L' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, + 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4D 'M' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x0F, 0xE0, 0x1F, 0xF0, 0x1F, 0xE0, + 0x1F, 0xF0, 0x1F, 0xE0, 0x1F, 0xF0, 0x1F, 0xE0, 0x1F, 0xF8, 0x3F, 0xE0, 0x1F, 0xF8, 0x3F, 0xE0, + 0x1F, 0xF8, 0x3F, 0xE0, 0x1F, 0xFC, 0x3F, 0xE0, 0x1F, 0x7C, 0x7F, 0xE0, 0x1F, 0x7C, 0x7F, 0xE0, + 0x1F, 0x3C, 0x7B, 0xE0, 0x1F, 0x3E, 0xFB, 0xE0, 0x1F, 0x3E, 0xFB, 0xE0, 0x1F, 0x3E, 0xFB, 0xE0, + 0x1F, 0x1E, 0xF3, 0xE0, 0x1F, 0x1F, 0xF3, 0xE0, 0x1F, 0x1F, 0xF3, 0xE0, 0x1F, 0x1F, 0xE3, 0xE0, + 0x1F, 0x0F, 0xE3, 0xE0, 0x1F, 0x0F, 0xE3, 0xE0, 0x1F, 0x0F, 0xE3, 0xE0, 0x1F, 0x0F, 0xC3, 0xE0, + 0x1F, 0x07, 0xC3, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, + 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, + 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4E 'N' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x07, 0xE0, 0x0F, 0xF8, 0x07, 0xE0, + 0x0F, 0xF8, 0x07, 0xE0, 0x0F, 0xF8, 0x07, 0xE0, 0x0F, 0xFC, 0x07, 0xE0, 0x0F, 0xFC, 0x07, 0xE0, + 0x0F, 0xFC, 0x07, 0xE0, 0x0F, 0xFE, 0x07, 0xE0, 0x0F, 0xFE, 0x07, 0xE0, 0x0F, 0xFF, 0x07, 0xE0, + 0x0F, 0xFF, 0x07, 0xE0, 0x0F, 0xDF, 0x07, 0xE0, 0x0F, 0xDF, 0x87, 0xE0, 0x0F, 0xCF, 0x87, 0xE0, + 0x0F, 0xCF, 0x87, 0xE0, 0x0F, 0xCF, 0xC7, 0xE0, 0x0F, 0xC7, 0xC7, 0xE0, 0x0F, 0xC7, 0xE7, 0xE0, + 0x0F, 0xC7, 0xE7, 0xE0, 0x0F, 0xC3, 0xE7, 0xE0, 0x0F, 0xC3, 0xF7, 0xE0, 0x0F, 0xC1, 0xF7, 0xE0, + 0x0F, 0xC1, 0xF7, 0xE0, 0x0F, 0xC1, 0xFF, 0xE0, 0x0F, 0xC0, 0xFF, 0xE0, 0x0F, 0xC0, 0xFF, 0xE0, + 0x0F, 0xC0, 0xFF, 0xE0, 0x0F, 0xC0, 0x7F, 0xE0, 0x0F, 0xC0, 0x7F, 0xE0, 0x0F, 0xC0, 0x3F, 0xE0, + 0x0F, 0xC0, 0x3F, 0xE0, 0x0F, 0xC0, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x4F 'O' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, + 0x0F, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, + 0x07, 0xF8, 0x7F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x50 'P' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xE0, 0x3F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x3F, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x51 'Q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, + 0x0F, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xF0, 0x1F, 0xC0, + 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xF0, + 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00 + }, + // 0x52 'R' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x3F, 0xE0, + 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xE1, 0xFE, 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x0F, 0xE0, 0xFF, 0x00, + 0x0F, 0xE0, 0x7F, 0x00, 0x0F, 0xE0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, + 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x53 'S' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0xFE, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xC0, 0x1F, 0xC0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, + 0x03, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xE0, + 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x07, 0xF0, + 0x07, 0x80, 0x03, 0xF0, 0x3F, 0x80, 0x03, 0xF0, 0x3F, 0xC0, 0x07, 0xF0, 0x1F, 0xE0, 0x07, 0xF0, + 0x1F, 0xF0, 0x1F, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x54 'T' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, + 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x55 'U' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, + 0x07, 0xF8, 0x7F, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x56 'V' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x03, 0xF8, + 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF0, 0x1F, 0x80, + 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x7F, 0x00, + 0x01, 0xFC, 0x7F, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFE, 0xFC, 0x00, + 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x57 'W' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, + 0x7E, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, + 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF0, 0x3F, 0x07, 0xC1, 0xF0, + 0x1F, 0x07, 0xC3, 0xF0, 0x1F, 0x8F, 0xC3, 0xF0, 0x1F, 0x8F, 0xE3, 0xF0, 0x1F, 0x8F, 0xE3, 0xF0, + 0x1F, 0x8F, 0xE3, 0xF0, 0x1F, 0x9F, 0xF3, 0xE0, 0x0F, 0x9F, 0xF3, 0xE0, 0x0F, 0x9F, 0xF3, 0xE0, + 0x0F, 0xBE, 0xF3, 0xE0, 0x0F, 0xBE, 0xFB, 0xE0, 0x0F, 0xBE, 0xFF, 0xE0, 0x0F, 0xFC, 0x7F, 0xC0, + 0x0F, 0xFC, 0x7F, 0xC0, 0x07, 0xFC, 0x7F, 0xC0, 0x07, 0xFC, 0x7F, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, + 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF8, 0x3F, 0x80, 0x03, 0xF0, 0x3F, 0x80, + 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x58 'X' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x1F, 0xC0, 0x07, 0xF0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x3F, 0x80, + 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xFC, 0x7F, 0x00, 0x01, 0xFC, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFE, 0xFE, 0x00, + 0x01, 0xFC, 0x7F, 0x00, 0x03, 0xF8, 0x7F, 0x00, 0x03, 0xF8, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, + 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x3F, 0x80, 0x03, 0xF8, 0x7F, 0x80, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x59 'Y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xF8, 0x3F, 0x00, + 0x01, 0xFC, 0x7F, 0x00, 0x00, 0xFC, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x7F, 0xFC, 0x00, + 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5A 'Z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, + 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, + 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5B '[' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x00, + 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00 + }, + // 0x5C '\\' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, + 0x0F, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, + 0x03, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x07, 0xC0, + 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5D ']' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, + 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00 + }, + // 0x5E '^' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, + 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7D, 0xF8, 0x00, 0x00, 0x7C, 0xF8, 0x00, + 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xF8, 0x7C, 0x00, 0x00, 0xF8, 0x7C, 0x00, 0x01, 0xF0, 0x3E, 0x00, + 0x01, 0xF0, 0x3E, 0x00, 0x03, 0xE0, 0x3F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x07, 0xE0, 0x1F, 0x80, + 0x07, 0xC0, 0x0F, 0x80, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0x80, 0x07, 0xC0, 0x0F, 0x80, 0x07, 0xC0, + 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x3F, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x5F '_' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x60 '`' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x07, 0xE0, 0x00, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x61 'a' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x03, 0xF8, 0x7F, 0x00, 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x3F, 0x80, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0x80, + 0x0F, 0xE0, 0x3F, 0x80, 0x0F, 0xC0, 0x3F, 0x80, 0x0F, 0xC0, 0x3F, 0x80, 0x0F, 0xE0, 0x7F, 0x80, + 0x0F, 0xF1, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xCF, 0xF8, 0x07, 0xFF, 0x8F, 0xF8, + 0x03, 0xFF, 0x07, 0xF8, 0x00, 0xFC, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x62 'b' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE1, 0xF8, 0x00, 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xEF, 0xFF, 0x00, 0x0F, 0xEF, 0xFF, 0x80, + 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, + 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF8, 0x1F, 0xC0, + 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xEF, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0x00, + 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xE1, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x63 'c' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, + 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, + 0x07, 0xFC, 0x3F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x64 'd' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0xFF, 0x8F, 0xC0, 0x01, 0xFF, 0xCF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x7F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, + 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, + 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, + 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, 0x01, 0xFF, 0xCF, 0xC0, + 0x00, 0xFF, 0x8F, 0xC0, 0x00, 0x3E, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x65 'e' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, + 0x03, 0xF8, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x07, 0xC0, + 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, + 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x07, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, + 0x07, 0xFC, 0x3F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x66 'f' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, + 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xE0, + 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x67 'g' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0x07, 0xE0, 0x00, 0xFF, 0xC7, 0xE0, 0x01, 0xFF, 0xE7, 0xE0, 0x03, 0xFF, 0xF7, 0xE0, + 0x03, 0xFF, 0xFF, 0xE0, 0x07, 0xFC, 0x7F, 0xE0, 0x07, 0xF0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xE0, + 0x07, 0xFC, 0x3F, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xEF, 0xE0, + 0x00, 0xFF, 0xCF, 0xE0, 0x00, 0x3F, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, + 0x00, 0x00, 0x0F, 0xE0, 0x01, 0xF0, 0x0F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xFC, 0x3F, 0x80, + 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00 + }, + // 0x68 'h' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0xFC, 0x00, 0x0F, 0xE3, 0xFF, 0x00, 0x0F, 0xE7, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, + 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x69 'i' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, + 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6A 'j' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, + 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x08, 0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, + 0x0F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00 + }, + // 0x6B 'k' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, + 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x3F, 0x80, + 0x07, 0xF0, 0x7F, 0x00, 0x07, 0xF0, 0xFE, 0x00, 0x07, 0xF1, 0xFC, 0x00, 0x07, 0xF3, 0xF8, 0x00, + 0x07, 0xF3, 0xF0, 0x00, 0x07, 0xF7, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xF9, 0xFC, 0x00, + 0x07, 0xF0, 0xFE, 0x00, 0x07, 0xF0, 0xFE, 0x00, 0x07, 0xF0, 0x7F, 0x00, 0x07, 0xF0, 0x3F, 0x80, + 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, + 0x07, 0xF0, 0x0F, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6C 'l' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, + 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6D 'm' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1E, 0x07, 0x80, 0x1F, 0x7F, 0x1F, 0xC0, 0x1F, 0x7F, 0xBF, 0xE0, 0x1F, 0xFF, 0xBF, 0xE0, + 0x1F, 0xCF, 0xF3, 0xF0, 0x1F, 0x8F, 0xE3, 0xF0, 0x1F, 0x87, 0xE1, 0xF0, 0x1F, 0x87, 0xC1, 0xF0, + 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, + 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, + 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, + 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, + 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6E 'n' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xC0, 0xFC, 0x00, 0x0F, 0xE3, 0xFF, 0x00, 0x0F, 0xE7, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, + 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x6F 'o' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, + 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, + 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x1F, 0xC0, + 0x07, 0xF8, 0x3F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x70 'p' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xE0, 0xF8, 0x00, 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xE7, 0xFF, 0x00, 0x0F, 0xEF, 0xFF, 0x80, + 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, + 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, + 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, + 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF8, 0x1F, 0xE0, + 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xEF, 0xFF, 0x80, 0x0F, 0xE7, 0xFF, 0x00, + 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xE1, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00 + }, + // 0x71 'q' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x0F, 0xC0, 0x00, 0xFF, 0x8F, 0xC0, 0x01, 0xFF, 0xCF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x7F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, + 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, + 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, + 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, 0x03, 0xFF, 0xCF, 0xC0, + 0x00, 0xFF, 0x8F, 0xC0, 0x00, 0x7E, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0 + }, + // 0x72 'r' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xF0, 0x3F, 0xC0, 0x03, 0xF0, 0xFF, 0xC0, 0x03, 0xF9, 0xFF, 0xC0, 0x03, 0xFB, 0xFF, 0xC0, + 0x03, 0xFB, 0xFF, 0xC0, 0x01, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, + 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, + 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, + 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, + 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x73 's' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0x80, 0x07, 0xE0, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xC0, + 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, + 0x0F, 0xF0, 0x1F, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x74 't' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, + 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x7F, 0x80, 0x80, 0x00, 0x7F, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x75 'u' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, + 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, + 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xEF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, 0x03, 0xFF, 0xCF, 0xC0, + 0x01, 0xFF, 0x8F, 0xC0, 0x00, 0x7E, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x76 'v' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xC0, + 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x3F, 0x80, + 0x03, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x7E, 0x00, 0x01, 0xFC, 0x7E, 0x00, + 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, + 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x77 'w' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, + 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x01, 0xF8, 0x3E, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, + 0x1F, 0x0F, 0xC1, 0xF0, 0x1F, 0x0F, 0xE1, 0xF0, 0x1F, 0x0F, 0xE1, 0xF0, 0x1F, 0x1F, 0xE1, 0xF0, + 0x1F, 0x1F, 0xF3, 0xE0, 0x1F, 0x1F, 0xF3, 0xE0, 0x0F, 0x9E, 0xF3, 0xE0, 0x0F, 0xBE, 0xF3, 0xE0, + 0x0F, 0xBC, 0x7B, 0xE0, 0x0F, 0xBC, 0x7B, 0xE0, 0x0F, 0xFC, 0x7F, 0xC0, 0x0F, 0xF8, 0x7F, 0xC0, + 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF0, 0x3F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, + 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xE0, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x78 'x' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, + 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xF8, 0x7F, 0x00, 0x01, 0xFC, 0x7E, 0x00, 0x00, 0xFE, 0xFE, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x01, 0xFC, 0x7E, 0x00, 0x01, 0xF8, 0x7F, 0x00, + 0x03, 0xF8, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, + 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x79 'y' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x80, 0x03, 0xF8, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, + 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, + 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF8, 0x1F, 0x80, 0x01, 0xF8, 0x3F, 0x00, + 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, + 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x3E, 0xF8, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F, 0xFF, 0x00, 0x00, + 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00 + }, + // 0x7A 'z' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, + 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + // 0x7B '{' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, + 0x00, 0x07, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x1F, 0xE0, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, + 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x80 + }, + // 0x7C '|' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00 + }, + // 0x7D '}' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, + 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x00, 0x00 + }, + // 0x7E '~' + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x30, + 0x1F, 0xFF, 0xE0, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1C, 0x0F, 0xFF, 0xF0, + 0x10, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h new file mode 100644 index 0000000000000..aadea05bd5282 --- /dev/null +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h @@ -0,0 +1,205 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// Simple 8x8 ASCII font for characters 0x20..0x7F. +// Each character: 8 bytes, MSB = left pixel, LSB = right pixel, 1 bit per pixel. +// Indexing: glyph = rm690b0_font_8x8_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7F. +static const uint8_t rm690b0_font_8x8_data[96][8] = { + // 0x20 ' ' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + // 0x21 '!' + {0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, + // 0x22 '"' + {0x6C, 0x6C, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00}, + // 0x23 '#' + {0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00}, + // 0x24 '$' + {0x18, 0x3E, 0x58, 0x3C, 0x1A, 0x7C, 0x18, 0x00}, + // 0x25 '%' + {0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00}, + // 0x26 '&' + {0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00}, + // 0x27 ''' + {0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, + // 0x28 '(' + {0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00}, + // 0x29 ')' + {0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00}, + // 0x2A '*' + {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, + // 0x2B '+' + {0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, + // 0x2C ',' + {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00}, + // 0x2D '-' + {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, + // 0x2E '.' + {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, + // 0x2F '/' + {0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00}, + // 0x30 '0' + {0x7C, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0x7C, 0x00}, + // 0x31 '1' + {0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, + // 0x32 '2' + {0x7C, 0xC6, 0x0E, 0x1C, 0x70, 0xC0, 0xFE, 0x00}, + // 0x33 '3' + {0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00}, + // 0x34 '4' + {0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00}, + // 0x35 '5' + {0xFE, 0xC0, 0xFC, 0x06, 0x06, 0xC6, 0x7C, 0x00}, + // 0x36 '6' + {0x3C, 0x60, 0xC0, 0xFC, 0xC6, 0xC6, 0x7C, 0x00}, + // 0x37 '7' + {0xFE, 0xC6, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00}, + // 0x38 '8' + {0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0x00}, + // 0x39 '9' + {0x7C, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00}, + // 0x3A ':' + {0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00}, + // 0x3B ';' + {0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x00}, + // 0x3C '<' + {0x0E, 0x1C, 0x38, 0x70, 0x38, 0x1C, 0x0E, 0x00}, + // 0x3D '=' + {0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, + // 0x3E '>' + {0x70, 0x38, 0x1C, 0x0E, 0x1C, 0x38, 0x70, 0x00}, + // 0x3F '?' + {0x7C, 0xC6, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00}, + // 0x40 '@' + {0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x7C, 0x00}, + // 0x41 'A' + {0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00}, + // 0x42 'B' + {0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00}, + // 0x43 'C' + {0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00}, + // 0x44 'D' + {0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00}, + // 0x45 'E' + {0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00}, + // 0x46 'F' + {0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00}, + // 0x47 'G' + {0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00}, + // 0x48 'H' + {0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00}, + // 0x49 'I' + {0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, + // 0x4A 'J' + {0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0x78, 0x00}, + // 0x4B 'K' + {0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00}, + // 0x4C 'L' + {0xF0, 0x60, 0x60, 0x60, 0x60, 0x62, 0xFE, 0x00}, + // 0x4D 'M' + {0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00}, + // 0x4E 'N' + {0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00}, + // 0x4F 'O' + {0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, + // 0x50 'P' + {0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00}, + // 0x51 'Q' + {0x7C, 0xC6, 0xC6, 0xC6, 0xDE, 0xCC, 0x7A, 0x00}, + // 0x52 'R' + {0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00}, + // 0x53 'S' + {0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00}, + // 0x54 'T' + {0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x3C, 0x00}, + // 0x55 'U' + {0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, + // 0x56 'V' + {0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, + // 0x57 'W' + {0xC6, 0xC6, 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x00}, + // 0x58 'X' + {0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00}, + // 0x59 'Y' + {0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x00}, + // 0x5A 'Z' + {0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00}, + // 0x5B '[' + {0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00}, + // 0x5C '\' + {0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00}, + // 0x5D ']' + {0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00}, + // 0x5E '^' + {0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, + // 0x5F '_' + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, + // 0x60 '`' + {0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, + // 0x61 'a' + {0x00, 0x00, 0x7C, 0x06, 0x7E, 0xC6, 0x7E, 0x00}, + // 0x62 'b' + {0xE0, 0x60, 0x7C, 0x66, 0x66, 0x66, 0xDC, 0x00}, + // 0x63 'c' + {0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00}, + // 0x64 'd' + {0x1C, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, + // 0x65 'e' + {0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0x7C, 0x00}, + // 0x66 'f' + {0x1C, 0x36, 0x30, 0x7C, 0x30, 0x30, 0x78, 0x00}, + // 0x67 'g' + {0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8}, + // 0x68 'h' + {0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00}, + // 0x69 'i' + {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, + // 0x6A 'j' + {0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78}, + // 0x6B 'k' + {0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00}, + // 0x6C 'l' + {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, + // 0x6D 'm' + {0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xC6, 0x00}, + // 0x6E 'n' + {0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x00}, + // 0x6F 'o' + {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, + // 0x70 'p' + {0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0}, + // 0x71 'q' + {0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E}, + // 0x72 'r' + {0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00}, + // 0x73 's' + {0x00, 0x00, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x00}, + // 0x74 't' + {0x30, 0x30, 0xFC, 0x30, 0x30, 0x36, 0x1C, 0x00}, + // 0x75 'u' + {0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, + // 0x76 'v' + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, + // 0x77 'w' + {0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00}, + // 0x78 'x' + {0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00}, + // 0x79 'y' + {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0xFC}, + // 0x7A 'z' + {0x00, 0x00, 0xFE, 0x8C, 0x18, 0x32, 0xFE, 0x00}, + // 0x7B '{' + {0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0x00}, + // 0x7C '|' + {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, + // 0x7D '}' + {0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0x00}, + // 0x7E '~' + {0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + // 0x7F (DEL / unused) + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index d6569bc39bd8e..029d5c385af71 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -372,6 +372,9 @@ endif ifeq ($(CIRCUITPY_SHARPDISPLAY),1) SRC_PATTERNS += sharpdisplay/% endif +ifeq ($(CIRCUITPY_RM690B0),1) +SRC_PATTERNS += rm690b0/% +endif ifeq ($(CIRCUITPY_SOCKETPOOL),1) SRC_PATTERNS += socketpool/% endif @@ -569,6 +572,7 @@ SRC_COMMON_HAL_ALL = \ wifi/Radio.c \ wifi/ScannedNetworks.c \ wifi/__init__.c \ + rm690b0/RM690B0.c \ SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) @@ -627,6 +631,8 @@ $(filter $(SRC_PATTERNS), \ wifi/AuthMode.c \ wifi/Packet.c \ wifi/PowerManagement.c \ + rm690b0/__init__.c \ + rm690b0/image_converter.c \ ) ifeq ($(CIRCUITPY_BLEIO_HCI),1) @@ -900,6 +906,11 @@ SRC_MOD += lib/tjpgd/src/tjpgd.c $(BUILD)/lib/tjpgd/src/tjpgd.o: CFLAGS += -Wno-shadow -Wno-cast-align endif +ifneq ($(filter 1,$(CIRCUITPY_JPEGIO) $(CIRCUITPY_RM690B0)),) +SRC_MOD += lib/esp_jpeg/src/esp_jpeg.c +CFLAGS_MOD += -I$(TOP)/lib/tjpgd/src -I$(TOP)/lib/esp_jpeg/include +endif + ifeq ($(CIRCUITPY_HASHLIB_MBEDTLS_ONLY),1) SRC_MOD += $(addprefix lib/mbedtls/library/, \ sha1.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 2754d57b01c9b..ad9e3c50a015e 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -393,6 +393,11 @@ typedef long mp_off_t; #define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (0) #endif +// RM690B0 AMOLED display driver +#ifndef CIRCUITPY_RM690B0 +#define CIRCUITPY_RM690B0 (0) +#endif + // This is not a top-level module; it's microcontroller.nvm. #if CIRCUITPY_NVM extern const struct _mp_obj_module_t nvm_module; diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 8c838a41218a3..4c4587dd23a0c 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -253,6 +253,9 @@ CFLAGS += -DCIRCUITPY_EPAPERDISPLAY=$(CIRCUITPY_EPAPERDISPLAY) CIRCUITPY_I2CDISPLAYBUS ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_I2CDISPLAYBUS=$(CIRCUITPY_I2CDISPLAYBUS) +CIRCUITPY_RM690B0 ?= 0 +CFLAGS += -DCIRCUITPY_RM690B0=$(CIRCUITPY_RM690B0) + ifeq ($(CIRCUITPY_DISPLAYIO),1) CIRCUITPY_PARALLELDISPLAYBUS ?= $(CIRCUITPY_FULL_BUILD) else @@ -303,6 +306,9 @@ CFLAGS += -DCIRCUITPY_ESP_USB_SERIAL_JTAG=$(CIRCUITPY_ESP_USB_SERIAL_JTAG) CIRCUITPY_ESPCAMERA ?= 0 CFLAGS += -DCIRCUITPY_ESPCAMERA=$(CIRCUITPY_ESPCAMERA) +CIRCUITPY_ESPSDCARD ?= 0 +CFLAGS += -DCIRCUITPY_ESPSDCARD=$(CIRCUITPY_ESPSDCARD) + CIRCUITPY__EVE ?= 0 CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE) diff --git a/shared-bindings/rm690b0/RM690B0.c b/shared-bindings/rm690b0/RM690B0.c new file mode 100644 index 0000000000000..ccd94b28da374 --- /dev/null +++ b/shared-bindings/rm690b0/RM690B0.c @@ -0,0 +1,481 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/rm690b0/RM690B0.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/time/__init__.h" +#include "py/objproperty.h" +#include "py/objstr.h" + +//| class RM690B0: +//| """RM690B0 driver for AMOLED displays +//| +//| This is a basic driver for the RM690B0 AMOLED display controller. +//| It provides low-level drawing primitives (pixels, lines, rectangles, circles, +//| blitting bitmaps) and a small built-in text API with several fixed fonts. +//| """ +//| +//| def __init__(self) -> None: +//| """Initialize the RM690B0 display driver +//| +//| Initializes the panel and internal framebuffers. Call `init_display()` +//| before performing any drawing operations. +//| """ +//| ... +//| + +static mp_obj_t rm690b0_rm690b0_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // For now, accept no arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + rm690b0_rm690b0_obj_t *self = mp_obj_malloc(rm690b0_rm690b0_obj_t, &rm690b0_rm690b0_type); + + common_hal_rm690b0_rm690b0_construct(self); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialize the display driver +//| +//| Can be called as instance method or static method: +//| +//| Instance method:: +//| +//| d = rm690b0.RM690B0() +//| d.deinit() # Cleans up this specific instance +//| +//| Static method (REPL convenience):: +//| +//| import rm690b0 +//| # If display is stuck/initialized without a reference +//| rm690b0.RM690B0.deinit() # Cleans up any active instance +//| # Now you can create a new instance +//| d = rm690b0.RM690B0() +//| """ +//| ... +//| +static mp_obj_t rm690b0_rm690b0_deinit(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + // Called as static method: RM690B0.deinit() + common_hal_rm690b0_rm690b0_deinit_all(); + } else { + // Called as instance method: d.deinit() + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + common_hal_rm690b0_rm690b0_deinit(self); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_deinit_obj, 0, 1, rm690b0_rm690b0_deinit); + +//| def init_display(self) -> None: +//| """Initialize the display with default settings""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_init_display(mp_obj_t self_in) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_rm690b0_rm690b0_init_display(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_init_display_obj, rm690b0_rm690b0_init_display); + +//| # --- Built-in font and text API --- +//| +//| def set_font(self, font: int) -> None: +//| """Select one of the built-in fonts for subsequent text drawing. +//| +//| :param int font: Font identifier. Available fonts: +//| 0 = 8x8 monospace (smallest) +//| 1 = 16x16 monospace (Liberation Sans) +//| 2 = 16x24 monospace (Liberation Mono Bold) +//| 3 = 24x24 monospace +//| 4 = 24x32 monospace +//| 5 = 32x32 monospace +//| 6 = 32x48 monospace (largest) +//| +//| This affects `text()` only and does not interact with LVGL or Tiny TTF. +//| """ +//| ... +//| +static mp_obj_t rm690b0_rm690b0_set_font(mp_obj_t self_in, mp_obj_t font_obj) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t font_id = mp_obj_get_int(font_obj); + common_hal_rm690b0_rm690b0_set_font(self, font_id); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_set_font_obj, rm690b0_rm690b0_set_font); + +//| def text(self, x: int, y: int, text: str, color: int = 0xFFFF, background: int | None = None) -> None: +//| """Draw a UTF-8 string using the currently selected built-in font. +//| +//| :param int x: Left coordinate (in pixels) +//| :param int y: Top coordinate (in pixels) +//| :param str text: Text to draw (UTF-8; unsupported glyphs may be replaced) +//| :param int color: Foreground RGB565 color (default: white) +//| :param int|None background: Optional background RGB565 color. If None, text is drawn transparent over existing pixels. +//| +//| This is a lightweight, non-LVGL text API intended for labels, debug info +//| and simple UIs. For full-featured text layout and TTF fonts, use `rm690b0_lvgl`. +//| """ +//| ... +//| +static mp_obj_t rm690b0_rm690b0_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_text, ARG_color, ARG_background }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_color, MP_ARG_INT, {.u_int = 0xFFFF} }, + { MP_QSTR_background, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + + // Accept any object that can be converted to str + mp_obj_t text_obj = args[ARG_text].u_obj; + GET_STR_DATA_LEN(text_obj, text_data, text_len); + + uint16_t fg = (uint16_t)(args[ARG_color].u_int & 0xFFFF); + bool has_bg = args[ARG_background].u_obj != mp_const_none; + uint16_t bg = 0; + if (has_bg) { + bg = (uint16_t)(mp_obj_get_int(args[ARG_background].u_obj) & 0xFFFF); + } + + common_hal_rm690b0_rm690b0_text(self, x, y, + (const char *)text_data, (size_t)text_len, + fg, has_bg, bg); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(rm690b0_rm690b0_text_obj, 1, rm690b0_rm690b0_text); + +static mp_obj_t rm690b0_rm690b0_fill_color(mp_obj_t self_in, mp_obj_t color_obj) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint16_t color = mp_obj_get_int(color_obj) & 0xFFFF; + common_hal_rm690b0_rm690b0_fill_color(self, color); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_fill_color_obj, rm690b0_rm690b0_fill_color); + +//| def pixel(self, x: int, y: int, color: int) -> None: +//| """Draw a single pixel""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_pixel(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t color = mp_obj_get_int(args[3]); + common_hal_rm690b0_rm690b0_pixel(self, x, y, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_pixel_obj, 4, 4, rm690b0_rm690b0_pixel); + +//| def fill_rect(self, x: int, y: int, width: int, height: int, color: int) -> None: +//| """Draw a filled rectangle""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_fill_rect(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t width = mp_obj_get_int(args[3]); + mp_int_t height = mp_obj_get_int(args[4]); + mp_int_t color = mp_obj_get_int(args[5]); + common_hal_rm690b0_rm690b0_fill_rect(self, x, y, width, height, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_fill_rect_obj, 6, 6, rm690b0_rm690b0_fill_rect); + +//| def hline(self, x: int, y: int, width: int, color: int) -> None: +//| """Draw a horizontal line""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_hline(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t width = mp_obj_get_int(args[3]); + mp_int_t color = mp_obj_get_int(args[4]); + common_hal_rm690b0_rm690b0_hline(self, x, y, width, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_hline_obj, 5, 5, rm690b0_rm690b0_hline); + +//| def vline(self, x: int, y: int, height: int, color: int) -> None: +//| """Draw a vertical line""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_vline(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t height = mp_obj_get_int(args[3]); + mp_int_t color = mp_obj_get_int(args[4]); + common_hal_rm690b0_rm690b0_vline(self, x, y, height, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_vline_obj, 5, 5, rm690b0_rm690b0_vline); + +//| def line(self, x0: int, y0: int, x1: int, y1: int, color: int) -> None: +//| """Draw a line""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_line(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x0 = mp_obj_get_int(args[1]); + mp_int_t y0 = mp_obj_get_int(args[2]); + mp_int_t x1 = mp_obj_get_int(args[3]); + mp_int_t y1 = mp_obj_get_int(args[4]); + mp_int_t color = mp_obj_get_int(args[5]); + common_hal_rm690b0_rm690b0_line(self, x0, y0, x1, y1, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_line_obj, 6, 6, rm690b0_rm690b0_line); + +//| def rect(self, x: int, y: int, width: int, height: int, color: int) -> None: +//| """Draw a rectangle outline""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_rect(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t width = mp_obj_get_int(args[3]); + mp_int_t height = mp_obj_get_int(args[4]); + mp_int_t color = mp_obj_get_int(args[5]); + common_hal_rm690b0_rm690b0_rect(self, x, y, width, height, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_rect_obj, 6, 6, rm690b0_rm690b0_rect); + +//| def circle(self, x: int, y: int, radius: int, color: int) -> None: +//| """Draw a circle outline""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_circle(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t radius = mp_obj_get_int(args[3]); + mp_int_t color = mp_obj_get_int(args[4]); + common_hal_rm690b0_rm690b0_circle(self, x, y, radius, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_circle_obj, 5, 5, rm690b0_rm690b0_circle); + +//| def fill_circle(self, x: int, y: int, radius: int, color: int) -> None: +//| """Draw a filled circle""" +//| ... +//| +static mp_obj_t rm690b0_rm690b0_fill_circle(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t radius = mp_obj_get_int(args[3]); + mp_int_t color = mp_obj_get_int(args[4]); + common_hal_rm690b0_rm690b0_fill_circle(self, x, y, radius, color); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_fill_circle_obj, 5, 5, rm690b0_rm690b0_fill_circle); + + + + +//| def blit_buffer(self, x: int, y: int, width: int, height: int, bitmap_data: bytearray) -> None: +//| """Draw a bitmap""" +//| ... +//| +//| def blit_bmp(self, x: int, y: int, bmp_data: readablebuffer) -> None: +//| """Draw a BMP image from memory. +//| +//| :param int x: X coordinate of the top-left corner +//| :param int y: Y coordinate of the top-left corner +//| :param readablebuffer bmp_data: BMP image data""" +//| ... +static mp_obj_t rm690b0_rm690b0_blit_bmp(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_obj_t bmp_data = args[3]; + common_hal_rm690b0_rm690b0_blit_bmp(self, x, y, bmp_data); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_bmp_obj, 4, 4, rm690b0_rm690b0_blit_bmp); + +//| def blit_jpeg(self, x: int, y: int, jpeg_data: readablebuffer) -> None: +//| """Draw a JPEG image from memory. +//| +//| :param int x: X coordinate of the top-left corner +//| :param int y: Y coordinate of the top-left corner +//| :param readablebuffer jpeg_data: JPEG image data""" +//| ... +static mp_obj_t rm690b0_rm690b0_blit_jpeg(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_obj_t jpeg_data = args[3]; + common_hal_rm690b0_rm690b0_blit_jpeg(self, x, y, jpeg_data); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_jpeg_obj, 4, 4, rm690b0_rm690b0_blit_jpeg); + +static mp_obj_t rm690b0_rm690b0_blit_buffer(size_t n_args, const mp_obj_t *args) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t width = mp_obj_get_int(args[3]); + mp_int_t height = mp_obj_get_int(args[4]); + mp_obj_t bitmap_data = args[5]; + common_hal_rm690b0_rm690b0_blit_buffer(self, x, y, width, height, bitmap_data); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_buffer_obj, 6, 6, rm690b0_rm690b0_blit_buffer); + +//| def swap_buffers(self, copy: bool = True) -> None: +//| """Swap the front and back framebuffers and display the result +//| +//| If double-buffering is enabled (two framebuffers allocated), this atomically +//| swaps the buffer pointers and then flushes the new front buffer to the display. +//| This provides tear-free rendering for animations and graphics. +//| +//| If double-buffering is not enabled (single framebuffer), this simply flushes +//| the current framebuffer to the display, equivalent to a refresh operation. +//| +//| :param bool copy: If True (default), copies front buffer to back buffer after swap. +//| This allows incremental drawing on top of existing content. +//| If False, back buffer is left unchanged (better performance for +//| full redraws like animations that clear the screen each frame). +//| """ +//| ... +//| +static mp_obj_t rm690b0_rm690b0_swap_buffers(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_copy }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_copy, MP_ARG_BOOL, {.u_bool = true} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + bool copy = args[ARG_copy].u_bool; + common_hal_rm690b0_rm690b0_swap_buffers(self, copy); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(rm690b0_rm690b0_swap_buffers_obj, 1, rm690b0_rm690b0_swap_buffers); + +//| rotation: int +//| """The rotation of the display as an int in degrees.""" +static mp_obj_t rm690b0_rm690b0_get_rotation_prop(mp_obj_t self_in) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(common_hal_rm690b0_rm690b0_get_rotation(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_rotation_prop_obj, rm690b0_rm690b0_get_rotation_prop); + +static mp_obj_t rm690b0_rm690b0_set_rotation_prop(mp_obj_t self_in, mp_obj_t rotation_obj) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t rotation = mp_obj_get_int(rotation_obj); + common_hal_rm690b0_rm690b0_set_rotation(self, rotation); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_set_rotation_prop_obj, rm690b0_rm690b0_set_rotation_prop); + +MP_PROPERTY_GETSET(rm690b0_rm690b0_rotation_obj, + (mp_obj_t)&rm690b0_rm690b0_get_rotation_prop_obj, + (mp_obj_t)&rm690b0_rm690b0_set_rotation_prop_obj); + + + + +//| brightness: float +//| """The brightness of the display, from 0.0 to 1.0""" +static mp_obj_t rm690b0_rm690b0_get_brightness_prop(mp_obj_t self_in) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_float(common_hal_rm690b0_rm690b0_get_brightness(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_brightness_prop_obj, rm690b0_rm690b0_get_brightness_prop); + +static mp_obj_t rm690b0_rm690b0_set_brightness_prop(mp_obj_t self_in, mp_obj_t brightness_obj) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_float_t brightness = mp_obj_get_float(brightness_obj); + common_hal_rm690b0_rm690b0_set_brightness(self, brightness); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_set_brightness_prop_obj, rm690b0_rm690b0_set_brightness_prop); + +MP_PROPERTY_GETSET(rm690b0_rm690b0_brightness_obj, + (mp_obj_t)&rm690b0_rm690b0_get_brightness_prop_obj, + (mp_obj_t)&rm690b0_rm690b0_set_brightness_prop_obj); + +//| width: int +//| """Gets the width of the display""" +static mp_obj_t rm690b0_rm690b0_get_width(mp_obj_t self_in) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(self->width); +} +MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_width_obj, rm690b0_rm690b0_get_width); + +MP_PROPERTY_GETTER(rm690b0_rm690b0_width_obj, + (mp_obj_t)&rm690b0_rm690b0_get_width_obj); + +//| height: int +//| """Gets the height of the display""" +static mp_obj_t rm690b0_rm690b0_get_height(mp_obj_t self_in) { + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(self->height); +} +MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_height_obj, rm690b0_rm690b0_get_height); + +MP_PROPERTY_GETTER(rm690b0_rm690b0_height_obj, + (mp_obj_t)&rm690b0_rm690b0_get_height_obj); + +static const mp_rom_map_elem_t rm690b0_rm690b0_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rm690b0_rm690b0_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_init_display), MP_ROM_PTR(&rm690b0_rm690b0_init_display_obj) }, + { MP_ROM_QSTR(MP_QSTR_fill_color), MP_ROM_PTR(&rm690b0_rm690b0_fill_color_obj) }, + + { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&rm690b0_rm690b0_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&rm690b0_rm690b0_pixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&rm690b0_rm690b0_fill_rect_obj) }, + { MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&rm690b0_rm690b0_hline_obj) }, + { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&rm690b0_rm690b0_vline_obj) }, + { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&rm690b0_rm690b0_line_obj) }, + { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&rm690b0_rm690b0_rect_obj) }, + { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&rm690b0_rm690b0_circle_obj) }, + { MP_ROM_QSTR(MP_QSTR_fill_circle), MP_ROM_PTR(&rm690b0_rm690b0_fill_circle_obj) }, + + // Built-in text and font API + { MP_ROM_QSTR(MP_QSTR_set_font), MP_ROM_PTR(&rm690b0_rm690b0_set_font_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&rm690b0_rm690b0_text_obj) }, + + { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&rm690b0_rm690b0_rotation_obj) }, + { MP_ROM_QSTR(MP_QSTR_blit_buffer), MP_ROM_PTR(&rm690b0_rm690b0_blit_buffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_blit_bmp), MP_ROM_PTR(&rm690b0_rm690b0_blit_bmp_obj) }, + { MP_ROM_QSTR(MP_QSTR_blit_jpeg), MP_ROM_PTR(&rm690b0_rm690b0_blit_jpeg_obj) }, + { MP_ROM_QSTR(MP_QSTR_swap_buffers), MP_ROM_PTR(&rm690b0_rm690b0_swap_buffers_obj) }, + + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&rm690b0_rm690b0_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&rm690b0_rm690b0_height_obj) }, +}; +static MP_DEFINE_CONST_DICT(rm690b0_rm690b0_locals_dict, rm690b0_rm690b0_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + rm690b0_rm690b0_type, + MP_QSTR_RM690B0, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, rm690b0_rm690b0_make_new, + locals_dict, &rm690b0_rm690b0_locals_dict + ); diff --git a/shared-bindings/rm690b0/RM690B0.h b/shared-bindings/rm690b0/RM690B0.h new file mode 100644 index 0000000000000..ec65b008a2d2b --- /dev/null +++ b/shared-bindings/rm690b0/RM690B0.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include "py/obj.h" + +// Forward declaration for the rm690b0 object type +typedef struct { + mp_obj_base_t base; + bool initialized; + mp_int_t width; + mp_int_t height; + mp_int_t rotation; + uint8_t brightness_raw; + mp_int_t font_id; // Current font ID for text rendering + // Port-specific implementation data will be added by common-hal + void *impl; +} rm690b0_rm690b0_obj_t; + +extern const mp_obj_type_t rm690b0_rm690b0_type; + +// Common HAL function declarations +void common_hal_rm690b0_rm690b0_construct(rm690b0_rm690b0_obj_t *self); +void common_hal_rm690b0_rm690b0_deinit(rm690b0_rm690b0_obj_t *self); +void common_hal_rm690b0_rm690b0_init_display(rm690b0_rm690b0_obj_t *self); +void common_hal_rm690b0_rm690b0_fill_color(rm690b0_rm690b0_obj_t *self, uint16_t color); +void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t brightness); +mp_float_t common_hal_rm690b0_rm690b0_get_brightness(const rm690b0_rm690b0_obj_t *self); +void common_hal_rm690b0_rm690b0_pixel(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t color); +void common_hal_rm690b0_rm690b0_fill_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); +void common_hal_rm690b0_rm690b0_hline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t color); +void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t height, mp_int_t color); +void common_hal_rm690b0_rm690b0_line(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color); +void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); +void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); +void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); +void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees); +mp_int_t common_hal_rm690b0_rm690b0_get_rotation(const rm690b0_rm690b0_obj_t *self); +void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data); +void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data); +void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data); +void common_hal_rm690b0_rm690b0_swap_buffers(rm690b0_rm690b0_obj_t *self, bool copy); +void common_hal_rm690b0_rm690b0_deinit_all(void); +void common_hal_rm690b0_rm690b0_set_font(rm690b0_rm690b0_obj_t *self, mp_int_t font_id); +void common_hal_rm690b0_rm690b0_text(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, + const char *text, size_t text_len, uint16_t fg, bool has_bg, uint16_t bg); diff --git a/shared-bindings/rm690b0/__init__.c b/shared-bindings/rm690b0/__init__.c new file mode 100644 index 0000000000000..57665e0bfc412 --- /dev/null +++ b/shared-bindings/rm690b0/__init__.c @@ -0,0 +1,231 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/rm690b0/RM690B0.h" +#include "image_converter.h" + +//| """RM690B0 AMOLED display driver with image conversion support +//| +//| This module provides direct control of the RM690B0 AMOLED display controller +//| along with hardware-accelerated image format conversion (RAW, BMP, JPEG). +//| +//| **Font Constants** +//| +//| Built-in font size constants for use with ``set_font()``:: +//| +//| rm690b0.FONT_8x8 # 8×8 monospace (smallest, debug/logs) +//| rm690b0.FONT_16x16 # 16×16 monospace (standard UI) +//| rm690b0.FONT_16x24 # 16×24 monospace (readable UI) +//| rm690b0.FONT_24x24 # 24×24 monospace (headers) +//| rm690b0.FONT_24x32 # 24×32 monospace (large headers) +//| rm690b0.FONT_32x32 # 32×32 monospace (big displays) +//| rm690b0.FONT_32x48 # 32×48 monospace (huge displays) +//| +//| Example:: +//| +//| import rm690b0 +//| display = rm690b0.RM690B0() +//| display.init_display() +//| +//| # Use font constants instead of magic numbers +//| display.set_font(rm690b0.FONT_8x8) +//| display.text(10, 10, "Debug info", rm690b0.WHITE) +//| +//| display.set_font(rm690b0.FONT_24x24) +//| display.text(10, 50, "Header", rm690b0.CYAN) +//| +//| **Color Constants** +//| +//| RGB565 color constants are also provided (WHITE, BLACK, RED, GREEN, BLUE, etc.) +//| """ +//| + +//| def jpg_to_rgb565(jpg_data: bytes) -> tuple[bytearray, dict]: +//| """Convert JPEG image data to RGB565 format +//| +//| :param bytes jpg_data: JPEG file data including headers +//| :return: Tuple of (rgb565_buffer, info_dict) +//| :rtype: tuple[bytearray, dict] +//| +//| The info_dict contains: width, height, data_size, bit_depth, channels, has_alpha +//| +//| Example:: +//| +//| import rm690b0 +//| with open("/image.jpg", "rb") as f: +//| jpg_data = f.read() +//| rgb565_buffer, info = rm690b0.jpg_to_rgb565(jpg_data) +//| print(f"Image: {info['width']}x{info['height']}") +//| """ +//| ... +//| +//| def bmp_to_rgb565(bmp_data: bytes) -> tuple[bytearray, dict]: +//| """Convert BMP image data to RGB565 format +//| +//| :param bytes bmp_data: BMP file data including headers +//| :return: Tuple of (rgb565_buffer, info_dict) +//| :rtype: tuple[bytearray, dict] +//| +//| The info_dict contains: width, height, data_size, bit_depth, channels, has_alpha +//| +//| Example:: +//| +//| import rm690b0 +//| with open("/image.bmp", "rb") as f: +//| bmp_data = f.read() +//| rgb565_buffer, info = rm690b0.bmp_to_rgb565(bmp_data) +//| print(f"Image: {info['width']}x{info['height']}") +//| """ +//| ... +//| +static mp_obj_t rm690b0_bmp_to_rgb565(mp_obj_t bmp_data_obj) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(bmp_data_obj, &bufinfo, MP_BUFFER_READ); + + // Parse header to get dimensions + img_info_t info; + img_error_t err = img_bmp_parse_header(bufinfo.buf, bufinfo.len, &info); + if (err != IMG_OK) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Invalid BMP format (%s)"), img_error_string(err)); + } + + // Allocate output buffer + size_t buffer_size = info.width * info.height * 2; + vstr_t vstr; + vstr_init_len(&vstr, buffer_size); + + // Convert + err = img_bmp_to_rgb565(bufinfo.buf, bufinfo.len, + (uint8_t *)vstr.buf, buffer_size, &info); + if (err != IMG_OK) { + vstr_clear(&vstr); + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("BMP conversion failed (%s)"), img_error_string(err)); + } + + // Create info dict + mp_obj_t info_dict = mp_obj_new_dict(6); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_width), MP_OBJ_NEW_SMALL_INT(info.width)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_height), MP_OBJ_NEW_SMALL_INT(info.height)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_data_size), MP_OBJ_NEW_SMALL_INT(info.data_size)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_bit_depth), MP_OBJ_NEW_SMALL_INT(info.bit_depth)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_channels), MP_OBJ_NEW_SMALL_INT(info.channels)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_has_alpha), mp_obj_new_bool(info.has_alpha)); + + // Return tuple of (buffer, info) + mp_obj_t buffer_obj = mp_obj_new_bytes_from_vstr(&vstr); + mp_obj_t tuple[2] = {buffer_obj, info_dict}; + return mp_obj_new_tuple(2, tuple); +} +static MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_bmp_to_rgb565_obj, rm690b0_bmp_to_rgb565); + +static mp_obj_t rm690b0_jpg_to_rgb565(mp_obj_t jpg_data_obj) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(jpg_data_obj, &bufinfo, MP_BUFFER_READ); + + // Parse header to get dimensions + img_info_t info; + img_error_t err = img_jpg_parse_header(bufinfo.buf, bufinfo.len, &info); + if (err != IMG_OK) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Invalid JPEG format (%s)"), img_error_string(err)); + } + + // Allocate output buffer + size_t buffer_size = info.width * info.height * 2; + vstr_t vstr; + vstr_init_len(&vstr, buffer_size); + + // Convert + err = img_jpg_to_rgb565(bufinfo.buf, bufinfo.len, + (uint8_t *)vstr.buf, buffer_size, &info); + + // If function returns unsupported, JPEG support was not compiled in + if (err == IMG_ERR_UNSUPPORTED) { + vstr_clear(&vstr); + mp_raise_NotImplementedError(MP_ERROR_TEXT("JPEG support not compiled in")); + } + + if (err != IMG_OK) { + const char *error_text = img_error_string(err); + vstr_clear(&vstr); + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("JPEG conversion failed (%s)"), error_text); + } + + // Create info dict + mp_obj_t info_dict = mp_obj_new_dict(6); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_width), MP_OBJ_NEW_SMALL_INT(info.width)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_height), MP_OBJ_NEW_SMALL_INT(info.height)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_data_size), MP_OBJ_NEW_SMALL_INT(info.data_size)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_bit_depth), MP_OBJ_NEW_SMALL_INT(info.bit_depth)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_channels), MP_OBJ_NEW_SMALL_INT(info.channels)); + mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_has_alpha), mp_obj_new_bool(info.has_alpha)); + + // Return tuple of (buffer, info) + mp_obj_t buffer_obj = mp_obj_new_bytes_from_vstr(&vstr); + mp_obj_t tuple[2] = {buffer_obj, info_dict}; + return mp_obj_new_tuple(2, tuple); +} +static MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_jpg_to_rgb565_obj, rm690b0_jpg_to_rgb565); + + + +static const mp_rom_map_elem_t rm690b0_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rm690b0) }, + { MP_ROM_QSTR(MP_QSTR_RM690B0), MP_ROM_PTR(&rm690b0_rm690b0_type) }, + + // Image conversion functions + { MP_ROM_QSTR(MP_QSTR_bmp_to_rgb565), MP_ROM_PTR(&rm690b0_bmp_to_rgb565_obj) }, + { MP_ROM_QSTR(MP_QSTR_jpg_to_rgb565), MP_ROM_PTR(&rm690b0_jpg_to_rgb565_obj) }, + + // RGB565 convenience constants + { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(0xFFFF) }, + { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(0x0000) }, + { MP_ROM_QSTR(MP_QSTR_DARK_GRAY), MP_ROM_INT(0x2104) }, + { MP_ROM_QSTR(MP_QSTR_GRAY), MP_ROM_INT(0x8410) }, + { MP_ROM_QSTR(MP_QSTR_LIGHT_GRAY), MP_ROM_INT(0xC618) }, + { MP_ROM_QSTR(MP_QSTR_BROWN), MP_ROM_INT(0x59E4) }, + { MP_ROM_QSTR(MP_QSTR_DARK_BROWN), MP_ROM_INT(0x30A0) }, + { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(0xFFE0) }, + { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(0x001F) }, + { MP_ROM_QSTR(MP_QSTR_ROYAL_BLUE), MP_ROM_INT(0x435C) }, + { MP_ROM_QSTR(MP_QSTR_SKY_BLUE), MP_ROM_INT(0x867D) }, + { MP_ROM_QSTR(MP_QSTR_DARK_BLUE), MP_ROM_INT(0x0010) }, + { MP_ROM_QSTR(MP_QSTR_LIGHT_BLUE), MP_ROM_INT(0x261F) }, + { MP_ROM_QSTR(MP_QSTR_LIGHT_VIOLET), MP_ROM_INT(0x8BFD) }, + { MP_ROM_QSTR(MP_QSTR_VIOLET), MP_ROM_INT(0x49F1) }, + { MP_ROM_QSTR(MP_QSTR_PURPLE), MP_ROM_INT(0x8010) }, + { MP_ROM_QSTR(MP_QSTR_PINK), MP_ROM_INT(0xF81F) }, + { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(0xBABA) }, + { MP_ROM_QSTR(MP_QSTR_OLIVE), MP_ROM_INT(0x8400) }, + { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(0x0400) }, + { MP_ROM_QSTR(MP_QSTR_DARK_GREEN), MP_ROM_INT(0x0200) }, + { MP_ROM_QSTR(MP_QSTR_LIME), MP_ROM_INT(0xAFE5) }, + { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(0x07FF) }, + { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(0xF800) }, + { MP_ROM_QSTR(MP_QSTR_ORANGE), MP_ROM_INT(0xFC60) }, + + // Font size constants + { MP_ROM_QSTR(MP_QSTR_FONT_8x8), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_FONT_16x16), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_FONT_16x24), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_FONT_24x24), MP_ROM_INT(3) }, + { MP_ROM_QSTR(MP_QSTR_FONT_24x32), MP_ROM_INT(4) }, + { MP_ROM_QSTR(MP_QSTR_FONT_32x32), MP_ROM_INT(5) }, + { MP_ROM_QSTR(MP_QSTR_FONT_32x48), MP_ROM_INT(6) }, +}; + +static MP_DEFINE_CONST_DICT(rm690b0_module_globals, rm690b0_module_globals_table); + +const mp_obj_module_t rm690b0_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&rm690b0_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_rm690b0, rm690b0_module); diff --git a/shared-bindings/rm690b0/image_converter.c b/shared-bindings/rm690b0/image_converter.c new file mode 100644 index 0000000000000..c5dff0e19f913 --- /dev/null +++ b/shared-bindings/rm690b0/image_converter.c @@ -0,0 +1,529 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "image_converter.h" +#include +#include + +#ifdef CIRCUITPY +#include "py/misc.h" +#include "py/runtime.h" +#endif + +#if defined(ESP_PLATFORM) +#include "esp_heap_caps.h" +#include "esp_err.h" +#if __has_include("esp_jpeg/esp_jpeg.h") +#include "esp_jpeg/esp_jpeg.h" +#define USE_ESP_JPEG 1 +#else +#define USE_ESP_JPEG 0 +#endif +#else +#define USE_ESP_JPEG 0 +#endif + +#if !USE_ESP_JPEG +#if defined(ESP_PLATFORM) +static void *image_malloc(size_t size) { + void *ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!ptr) { + ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + } + return ptr; +} +static void image_free(void *ptr) { + if (ptr) { + heap_caps_free(ptr); + } +} +#define IMAGE_MALLOC(size) image_malloc(size) +#define IMAGE_FREE(ptr) image_free(ptr) +#elif defined(CIRCUITPY) +#define IMAGE_MALLOC(size) m_malloc_maybe(size) +#define IMAGE_FREE(ptr) m_free(ptr) +#else +#define IMAGE_MALLOC(size) malloc(size) +#define IMAGE_FREE(ptr) free(ptr) +#endif +#endif + + +#if !USE_ESP_JPEG +#include "tjpgd.h" +#endif + +// ============================================================================= +// Utility Functions +// ============================================================================= + +const char *img_error_string(img_error_t error) { + switch (error) { + case IMG_OK: + return "Success"; + case IMG_ERR_NULL_POINTER: + return "NULL pointer"; + case IMG_ERR_INVALID_SIZE: + return "Invalid size"; + case IMG_ERR_BUFFER_TOO_SMALL: + return "Buffer too small"; + case IMG_ERR_INVALID_FORMAT: + return "Invalid format"; + case IMG_ERR_CORRUPTED_DATA: + return "Corrupted data"; + case IMG_ERR_UNSUPPORTED: + return "Unsupported feature"; + case IMG_ERR_OUT_OF_MEMORY: + return "Out of memory"; + case IMG_ERR_IO_ERROR: + return "I/O error"; + default: + return "Unknown error"; + } +} + +// Read 16-bit little-endian value +static inline uint16_t read_le16(const uint8_t *data) { + return (uint16_t)data[0] | ((uint16_t)data[1] << 8); +} + +// Read 32-bit little-endian value +static inline uint32_t read_le32(const uint8_t *data) { + return (uint32_t)data[0] | ((uint32_t)data[1] << 8) | + ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24); +} + +// Read 32-bit signed little-endian value +static inline int32_t read_le32_signed(const uint8_t *data) { + return (int32_t)read_le32(data); +} + + + +// ============================================================================= +// BMP Format Converter +// ============================================================================= + +img_error_t img_bmp_parse_header( + const uint8_t *bmp_data, + size_t bmp_size, + img_info_t *info + ) { + if (bmp_data == NULL || info == NULL) { + return IMG_ERR_NULL_POINTER; + } + + // Check minimum size for headers (14 byte file header + 40 byte info header) + if (bmp_size < 54) { + return IMG_ERR_INVALID_FORMAT; + } + + // Check BMP signature ('BM') + if (bmp_data[0] != 'B' || bmp_data[1] != 'M') { + return IMG_ERR_INVALID_FORMAT; + } + + // Parse info header size + uint32_t header_size = read_le32(bmp_data + 14); + if (header_size < 40) { + return IMG_ERR_INVALID_FORMAT; + } + + // Parse dimensions + int32_t width = read_le32_signed(bmp_data + 18); + int32_t height = read_le32_signed(bmp_data + 22); + + // Validate dimensions + if (width <= 0 || height == 0) { + return IMG_ERR_INVALID_SIZE; + } + + // Parse format information + uint16_t planes = read_le16(bmp_data + 26); + uint16_t bit_count = read_le16(bmp_data + 28); + uint32_t compression = read_le32(bmp_data + 30); + + // Validate format + if (planes != 1) { + return IMG_ERR_INVALID_FORMAT; + } + + // Check for supported bit depths + if (bit_count != 16 && bit_count != 24 && bit_count != 32) { + return IMG_ERR_UNSUPPORTED; + } + + // Check compression (0 = BI_RGB uncompressed, 3 = BI_BITFIELDS) + if (compression != 0 && compression != 3) { + return IMG_ERR_UNSUPPORTED; + } + + // Fill info structure + info->width = (uint32_t)width; + info->height = (uint32_t)(height > 0 ? height : -height); + info->data_size = img_rgb565_buffer_size(info->width, info->height); + info->bit_depth = bit_count; + info->channels = (bit_count == 32) ? 4 : 3; + info->has_alpha = (bit_count == 32); + + return IMG_OK; +} + +img_error_t img_bmp_to_rgb565( + const uint8_t *bmp_data, + size_t bmp_size, + uint8_t *rgb565_buffer, + size_t buffer_size, + img_info_t *info + ) { + if (bmp_data == NULL || rgb565_buffer == NULL) { + return IMG_ERR_NULL_POINTER; + } + + // Parse header + img_info_t local_info; + img_error_t err = img_bmp_parse_header(bmp_data, bmp_size, &local_info); + if (err != IMG_OK) { + return err; + } + + // Check buffer size + if (buffer_size < local_info.data_size) { + return IMG_ERR_BUFFER_TOO_SMALL; + } + + // Get parameters + uint32_t width = local_info.width; + uint32_t height = local_info.height; + uint32_t data_offset = read_le32(bmp_data + 10); + int32_t height_signed = read_le32_signed(bmp_data + 22); + uint16_t bit_count = read_le16(bmp_data + 28); + + // Check if we have enough data + if (data_offset >= bmp_size) { + return IMG_ERR_CORRUPTED_DATA; + } + + // Determine if image is bottom-up (positive height) or top-down (negative height) + bool bottom_up = (height_signed > 0); + + // Calculate bytes per pixel and row stride + uint32_t bytes_per_pixel = bit_count / 8; + uint32_t row_stride = ((width * bytes_per_pixel + 3) & ~3); // Rows padded to 4-byte boundary + + // Verify we have enough data + if (data_offset + (row_stride * height) > bmp_size) { + return IMG_ERR_CORRUPTED_DATA; + } + + // Convert pixel data + const uint8_t *src_base = bmp_data + data_offset; + uint8_t *dst = rgb565_buffer; + + for (uint32_t y = 0; y < height; y++) { + // Calculate source row based on orientation + uint32_t src_row = bottom_up ? (height - 1 - y) : y; + const uint8_t *src = src_base + src_row * row_stride; + + for (uint32_t x = 0; x < width; x++) { + uint8_t r, g, b; + + if (bit_count == 24) { + // 24-bit BGR format + b = src[0]; + g = src[1]; + r = src[2]; + src += 3; + } else if (bit_count == 32) { + // 32-bit BGRA format + b = src[0]; + g = src[1]; + r = src[2]; + // src[3] is alpha (ignored for now) + src += 4; + } else if (bit_count == 16) { + // 16-bit format (assume RGB565) + uint16_t pixel = read_le16(src); + r = RGB565_TO_R(pixel); + g = RGB565_TO_G(pixel); + b = RGB565_TO_B(pixel); + src += 2; + } else { + // Should not reach here due to earlier validation + return IMG_ERR_UNSUPPORTED; + } + + // Convert to RGB565 and store (byte-by-byte to avoid alignment issues) + uint16_t rgb565 = RGB888_TO_RGB565(r, g, b); + dst[0] = rgb565 & 0xFF; // Low byte + dst[1] = (rgb565 >> 8) & 0xFF; // High byte + dst += 2; + } + } + + // Copy info if requested + if (info != NULL) { + *info = local_info; + } + + return IMG_OK; +} + +// ============================================================================= +// JPEG Format Converter +// ============================================================================= + +#if USE_ESP_JPEG + +img_error_t img_jpg_parse_header( + const uint8_t *jpg_data, + size_t jpg_size, + img_info_t *info + ) { + if (jpg_data == NULL || info == NULL) { + return IMG_ERR_NULL_POINTER; + } + + esp_jpeg_image_cfg_t cfg = { + .indata = jpg_data, + .indata_size = jpg_size, + .outbuf = NULL, + .outbuf_size = 0, + .out_format = JPEG_IMAGE_FORMAT_RGB565, + .out_scale = JPEG_IMAGE_SCALE_0, + .flags = { + .swap_color_bytes = false, + .use_scaler = false, + }, + }; + + esp_jpeg_image_output_t out; + esp_err_t err = esp_jpeg_get_image_info(&cfg, &out); + if (err != ESP_OK) { + return IMG_ERR_INVALID_FORMAT; + } + + info->width = out.width; + info->height = out.height; + info->data_size = img_rgb565_buffer_size(out.width, out.height); + info->bit_depth = 8; + info->channels = 3; + info->has_alpha = false; + + return IMG_OK; +} + +img_error_t img_jpg_to_rgb565( + const uint8_t *jpg_data, + size_t jpg_size, + uint8_t *rgb565_buffer, + size_t buffer_size, + img_info_t *info + ) { + if (jpg_data == NULL || rgb565_buffer == NULL) { + return IMG_ERR_NULL_POINTER; + } + + esp_jpeg_image_cfg_t cfg = { + .indata = jpg_data, + .indata_size = jpg_size, + .outbuf = rgb565_buffer, + .outbuf_size = buffer_size, + .out_format = JPEG_IMAGE_FORMAT_RGB565, + .out_scale = JPEG_IMAGE_SCALE_0, + .flags = { + .swap_color_bytes = false, + .use_scaler = false, + }, + }; + + esp_jpeg_image_output_t out_info; + esp_err_t err = esp_jpeg_decode(&cfg, &out_info); + if (err == ESP_ERR_NO_MEM) { + return IMG_ERR_BUFFER_TOO_SMALL; + } + if (err != ESP_OK) { + return IMG_ERR_CORRUPTED_DATA; + } + + if (info != NULL) { + info->width = out_info.width; + info->height = out_info.height; + info->data_size = out_info.outbuf_size; + info->bit_depth = 8; + info->channels = 3; + info->has_alpha = false; + } + + return IMG_OK; +} + +#else // USE_ESP_JPEG + +#define TJPGD_WORK_BUFFER_SIZE 4096 + +typedef struct { + uint8_t *rgb565_buffer; + uint32_t width; + const uint8_t *jpg_data; + size_t jpg_size; + size_t jpg_offset; +} tjpgd_context_t; + +static size_t tjpgd_input_func(JDEC *jd, uint8_t *buff, size_t ndata) { + tjpgd_context_t *ctx = (tjpgd_context_t *)jd->device; + + if (!buff) { + size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; + size_t bytes_to_skip = ndata; + if (bytes_to_skip > bytes_available) { + bytes_to_skip = bytes_available; + } + ctx->jpg_offset += bytes_to_skip; + return bytes_to_skip; + } + + size_t bytes_to_read = ndata; + size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; + if (bytes_to_read > bytes_available) { + bytes_to_read = bytes_available; + } + + if (bytes_to_read > 0) { + memcpy(buff, ctx->jpg_data + ctx->jpg_offset, bytes_to_read); + ctx->jpg_offset += bytes_to_read; + } + + return bytes_to_read; +} + +static int tjpgd_output_func(JDEC *jd, void *bitmap, JRECT *rect) { + tjpgd_context_t *ctx = (tjpgd_context_t *)jd->device; + uint8_t *src = (uint8_t *)bitmap; + + for (int y = rect->top; y <= rect->bottom; y++) { + uint32_t row_base = (uint32_t)y * ctx->width; + for (int x = rect->left; x <= rect->right; x++) { + uint16_t rgb565 = ((uint16_t)src[0] << 8) | src[1]; + src += 2; + uint32_t offset = (row_base + x) * 2; + ctx->rgb565_buffer[offset] = rgb565 & 0xFF; + ctx->rgb565_buffer[offset + 1] = (rgb565 >> 8) & 0xFF; + } + } + + return 1; +} + +img_error_t img_jpg_to_rgb565( + const uint8_t *jpg_data, + size_t jpg_size, + uint8_t *rgb565_buffer, + size_t buffer_size, + img_info_t *info + ) { + if (jpg_data == NULL || rgb565_buffer == NULL) { + return IMG_ERR_NULL_POINTER; + } + + void *work_buffer = IMAGE_MALLOC(TJPGD_WORK_BUFFER_SIZE); + if (work_buffer == NULL) { + return IMG_ERR_OUT_OF_MEMORY; + } + + JDEC jdec; + tjpgd_context_t ctx = { + .rgb565_buffer = NULL, + .width = 0, + .jpg_data = jpg_data, + .jpg_size = jpg_size, + .jpg_offset = 0, + }; + + JRESULT res = jd_prepare(&jdec, tjpgd_input_func, work_buffer, TJPGD_WORK_BUFFER_SIZE, (void *)&ctx); + if (res != JDR_OK) { + IMAGE_FREE(work_buffer); + return IMG_ERR_INVALID_FORMAT; + } + + if (jdec.width == 0 || jdec.height == 0) { + IMAGE_FREE(work_buffer); + return IMG_ERR_INVALID_SIZE; + } + + size_t required_size = img_rgb565_buffer_size(jdec.width, jdec.height); + if (buffer_size < required_size) { + IMAGE_FREE(work_buffer); + return IMG_ERR_BUFFER_TOO_SMALL; + } + + ctx.rgb565_buffer = rgb565_buffer; + ctx.width = jdec.width; + + res = jd_decomp(&jdec, tjpgd_output_func, 0); + + IMAGE_FREE(work_buffer); + + if (res != JDR_OK) { + return IMG_ERR_CORRUPTED_DATA; + } + + if (info != NULL) { + info->width = jdec.width; + info->height = jdec.height; + info->data_size = required_size; + info->bit_depth = 8; + info->channels = 3; + info->has_alpha = false; + } + + return IMG_OK; +} + +img_error_t img_jpg_parse_header( + const uint8_t *jpg_data, + size_t jpg_size, + img_info_t *info + ) { + if (jpg_data == NULL || info == NULL) { + return IMG_ERR_NULL_POINTER; + } + + void *work_buffer = IMAGE_MALLOC(TJPGD_WORK_BUFFER_SIZE); + if (work_buffer == NULL) { + return IMG_ERR_OUT_OF_MEMORY; + } + + JDEC jdec; + tjpgd_context_t ctx = { + .rgb565_buffer = NULL, + .width = 0, + .jpg_data = jpg_data, + .jpg_size = jpg_size, + .jpg_offset = 0, + }; + + JRESULT res = jd_prepare(&jdec, tjpgd_input_func, work_buffer, TJPGD_WORK_BUFFER_SIZE, (void *)&ctx); + if (res != JDR_OK) { + IMAGE_FREE(work_buffer); + return IMG_ERR_INVALID_FORMAT; + } + + if (jdec.width == 0 || jdec.height == 0) { + IMAGE_FREE(work_buffer); + return IMG_ERR_INVALID_SIZE; + } + + info->width = jdec.width; + info->height = jdec.height; + info->data_size = img_rgb565_buffer_size(jdec.width, jdec.height); + info->bit_depth = 8; + info->channels = 3; + info->has_alpha = false; + + IMAGE_FREE(work_buffer); + return IMG_OK; +} + +#endif // USE_ESP_JPEG diff --git a/shared-bindings/rm690b0/image_converter.h b/shared-bindings/rm690b0/image_converter.h new file mode 100644 index 0000000000000..1d285ad825857 --- /dev/null +++ b/shared-bindings/rm690b0/image_converter.h @@ -0,0 +1,164 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_RM690B0_IMAGE_CONVERTER_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_RM690B0_IMAGE_CONVERTER_H + +#include +#include +#include + +// ============================================================================= +// Error Codes +// ============================================================================= + +typedef enum { + IMG_OK = 0, // Success + IMG_ERR_NULL_POINTER = -1, // NULL pointer passed + IMG_ERR_INVALID_SIZE = -2, // Invalid image dimensions + IMG_ERR_BUFFER_TOO_SMALL = -3, // Output buffer too small + IMG_ERR_INVALID_FORMAT = -4, // Invalid or unsupported format + IMG_ERR_CORRUPTED_DATA = -5, // Corrupted image data + IMG_ERR_UNSUPPORTED = -6, // Unsupported feature + IMG_ERR_OUT_OF_MEMORY = -7, // Memory allocation failed + IMG_ERR_IO_ERROR = -8 // File I/O error +} img_error_t; + +// ============================================================================= +// Image Information Structure +// ============================================================================= + +typedef struct { + uint32_t width; // Image width in pixels + uint32_t height; // Image height in pixels + uint32_t data_size; // Size of RGB565 data in bytes + uint8_t bit_depth; // Original bit depth + uint8_t channels; // Number of color channels + bool has_alpha; // Whether image has alpha channel +} img_info_t; + +// ============================================================================= +// RGB Conversion Macros +// ============================================================================= + +// Convert 24-bit RGB to 16-bit RGB565 +// Format: RRRR RGGG GGGB BBBB (5 bits R, 6 bits G, 5 bits B) +#define RGB888_TO_RGB565(r, g, b) \ + ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3)) + +// Extract components from RGB565 +#define RGB565_TO_R(rgb565) (((rgb565) >> 8) & 0xF8) +#define RGB565_TO_G(rgb565) (((rgb565) >> 3) & 0xFC) +#define RGB565_TO_B(rgb565) (((rgb565) << 3) & 0xF8) + +// Note: RGB565 data is stored in little-endian byte order: +// byte[0] = low byte (GGGBBBBB) +// byte[1] = high byte (RRRRRGGG) +// This matches the byte order expected by most display controllers. + + + +// ============================================================================= +// BMP Format Converter +// ============================================================================= + +/** + * @brief Convert BMP image to RGB565 buffer + * + * Supports uncompressed BMP files with 16, 24, or 32 bits per pixel. + * Handles bottom-up and top-down orientations. + * + * @param bmp_data Pointer to BMP file data (including headers) + * @param bmp_size Size of BMP data in bytes + * @param rgb565_buffer Output buffer for RGB565 data + * @param buffer_size Size of output buffer in bytes + * @param info Optional pointer to receive image info (can be NULL) + * @return IMG_OK on success, error code otherwise + */ +img_error_t img_bmp_to_rgb565( + const uint8_t *bmp_data, + size_t bmp_size, + uint8_t *rgb565_buffer, + size_t buffer_size, + img_info_t *info + ); + +/** + * @brief Parse BMP header and extract image information + * + * @param bmp_data Pointer to BMP file data + * @param bmp_size Size of BMP data in bytes + * @param info Pointer to receive image info + * @return IMG_OK on success, error code otherwise + */ +img_error_t img_bmp_parse_header( + const uint8_t *bmp_data, + size_t bmp_size, + img_info_t *info + ); + +// ============================================================================= +// JPEG Format Converter +// ============================================================================= + +/** + * @brief Convert JPEG image to RGB565 buffer + * + * Uses the ESP-IDF `esp_jpeg` decoder on supported ESP32-class ports. Builds without the esp_jpeg headers will + * return IMG_ERR_UNSUPPORTED for JPEG requests. + * + * @param jpg_data Pointer to JPEG file data + * @param jpg_size Size of JPEG data in bytes + * @param rgb565_buffer Output buffer for RGB565 data + * @param buffer_size Size of output buffer in bytes + * @param info Optional pointer to receive image info (can be NULL) + * @return IMG_OK on success, IMG_ERR_UNSUPPORTED if not compiled with JPEG support + */ + +img_error_t img_jpg_to_rgb565( + const uint8_t *jpg_data, + size_t jpg_size, + uint8_t *rgb565_buffer, + size_t buffer_size, + img_info_t *info + ); + +/** + * @brief Parse JPEG header and extract image information + * + * @param jpg_data Pointer to JPEG file data + * @param jpg_size Size of JPEG data in bytes + * @param info Pointer to receive image info + * @return IMG_OK on success, error code otherwise + */ +img_error_t img_jpg_parse_header( + const uint8_t *jpg_data, + size_t jpg_size, + img_info_t *info + ); + +// ============================================================================= +// Utility Functions +// ============================================================================= + +/** + * @brief Calculate required buffer size for RGB565 data + * + * @param width Image width in pixels + * @param height Image height in pixels + * @return Required buffer size in bytes + */ +static inline size_t img_rgb565_buffer_size(uint32_t width, uint32_t height) { + return (size_t)width * height * 2; +} + +/** + * @brief Get error message string + * + * @param error Error code + * @return Human-readable error message + */ +const char *img_error_string(img_error_t error); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_RM690B0_IMAGE_CONVERTER_H From 99915438e254e479979b275af5649aa6411df5c8 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 30 Jan 2026 19:06:10 +0100 Subject: [PATCH 02/38] Pre-commit hook fixes (1) --- .../rm690b0/fonts/rm690b0_font_24x24.h | 950 +++++++------- .../rm690b0/fonts/rm690b0_font_24x32.h | 1140 ++++++++--------- 2 files changed, 1045 insertions(+), 1045 deletions(-) diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h index f5289f8767894..da11bb19d099e 100644 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h @@ -18,762 +18,762 @@ static const uint8_t rm690b0_font_24x24_data[95][72] = { // 0x20 ' ' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x21 '!' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x22 '\"' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, - 0xE7, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, + 0xE7, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x23 '#' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x00, 0x31, 0x80, 0x00, - 0x61, 0x80, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x63, 0x00, 0x00, 0x43, 0x00, 0x00, 0xC3, - 0x00, 0x00, 0xC2, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x86, 0x00, 0x01, 0x86, 0x00, - 0x01, 0x84, 0x00, 0x01, 0x8C, 0x00, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x00, 0x31, 0x80, 0x00, + 0x61, 0x80, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x63, 0x00, 0x00, 0x43, 0x00, 0x00, 0xC3, + 0x00, 0x00, 0xC2, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x86, 0x00, 0x01, 0x86, 0x00, + 0x01, 0x84, 0x00, 0x01, 0x8C, 0x00, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x24 '$' { - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xFF, 0x80, 0x01, - 0xCB, 0xC0, 0x03, 0xC9, 0xC0, 0x03, 0xC8, 0x00, 0x01, 0xC8, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x09, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, - 0x01, 0xCB, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xFF, 0x80, 0x01, + 0xCB, 0xC0, 0x03, 0xC9, 0xC0, 0x03, 0xC8, 0x00, 0x01, 0xC8, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x3F, + 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x09, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, + 0x01, 0xCB, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x25 '%' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0x80, 0x07, 0xC1, 0x80, 0x0C, - 0xE3, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0xEC, 0x00, 0x07, 0xD8, 0x00, 0x07, 0x98, - 0x00, 0x00, 0x37, 0x80, 0x00, 0x6F, 0xC0, 0x00, 0xEC, 0xC0, 0x00, 0xCC, 0xC0, 0x01, 0x8C, 0xC0, - 0x03, 0x0C, 0xC0, 0x03, 0x0F, 0xC0, 0x06, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0x80, 0x07, 0xC1, 0x80, 0x0C, + 0xE3, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0xEC, 0x00, 0x07, 0xD8, 0x00, 0x07, 0x98, + 0x00, 0x00, 0x37, 0x80, 0x00, 0x6F, 0xC0, 0x00, 0xEC, 0xC0, 0x00, 0xCC, 0xC0, 0x01, 0x8C, 0xC0, + 0x03, 0x0C, 0xC0, 0x03, 0x0F, 0xC0, 0x06, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x26 '&' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFE, 0x00, 0x01, - 0xCE, 0x00, 0x01, 0x86, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xE1, - 0x80, 0x07, 0xF3, 0x80, 0x07, 0x73, 0x00, 0x0E, 0x3F, 0x00, 0x0E, 0x1F, 0x00, 0x0E, 0x0E, 0x00, - 0x07, 0x1F, 0x00, 0x07, 0xFF, 0xC0, 0x01, 0xF1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFE, 0x00, 0x01, + 0xCE, 0x00, 0x01, 0x86, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xE1, + 0x80, 0x07, 0xF3, 0x80, 0x07, 0x73, 0x00, 0x0E, 0x3F, 0x00, 0x0E, 0x1F, 0x00, 0x0E, 0x0E, 0x00, + 0x07, 0x1F, 0x00, 0x07, 0xFF, 0xC0, 0x01, 0xF1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x27 '\'' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x28 '(' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00 }, // 0x29 ')' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00 }, // 0x2A '*' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x99, 0x00, 0x00, - 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x67, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x99, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x67, 0x00, 0x00, 0x22, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2B '+' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x03, 0xFF, - 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x03, 0xFF, + 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2C ',' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00 }, // 0x2D '-' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2E '.' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2F '/' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, + 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x30 '0' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xD9, - 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, - 0x00, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xD9, + 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, + 0x00, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x31 '1' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x01, 0x9E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x01, 0x9E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x32 '2' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x33 '3' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE7, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x3F, - 0x00, 0x00, 0x3F, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC1, 0xC0, - 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE7, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x3F, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC1, 0xC0, + 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x34 '4' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC7, - 0x00, 0x01, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC7, + 0x00, 0x01, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x35 '5' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDE, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, - 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC3, 0xC0, - 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7E, 0x00, 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, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDE, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, + 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC3, 0xC0, + 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x36 '6' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0x80, 0x00, - 0xE3, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDF, 0x00, 0x03, 0xFF, - 0x80, 0x03, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x00, 0xE3, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0x80, 0x00, + 0xE3, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDF, 0x00, 0x03, 0xFF, + 0x80, 0x03, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x00, 0xE3, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x37 '7' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, - 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 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, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, + 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x38 '8' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xE3, 0x80, 0x00, 0x7F, - 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xE3, 0x80, 0x00, 0x7F, + 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x39 '9' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x03, 0x80, 0x01, 0xC3, 0x80, - 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x03, 0x80, 0x01, 0xC3, 0x80, + 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3A ':' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3B ';' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00 }, // 0x3C '<' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x01, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, - 0x00, 0x03, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0x80, - 0x00, 0x01, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x01, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, + 0x00, 0x03, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0x80, + 0x00, 0x01, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3D '=' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3E '>' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x01, 0xF0, 0x00, - 0x03, 0xC0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x01, 0xF0, 0x00, + 0x03, 0xC0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3F '?' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x40 '@' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x7F, 0x80, 0x00, 0xE1, 0x80, 0x01, - 0x80, 0xC0, 0x01, 0x9D, 0xC0, 0x03, 0x3F, 0x60, 0x03, 0x77, 0x60, 0x03, 0x63, 0x60, 0x02, 0x43, - 0x60, 0x02, 0xC2, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x40, 0x02, 0x6E, 0xC0, - 0x03, 0x7B, 0xC0, 0x03, 0x33, 0x80, 0x01, 0x80, 0x00, 0x01, 0xC1, 0x80, 0x00, 0xFF, 0x80, 0x00, - 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x7F, 0x80, 0x00, 0xE1, 0x80, 0x01, + 0x80, 0xC0, 0x01, 0x9D, 0xC0, 0x03, 0x3F, 0x60, 0x03, 0x77, 0x60, 0x03, 0x63, 0x60, 0x02, 0x43, + 0x60, 0x02, 0xC2, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x40, 0x02, 0x6E, 0xC0, + 0x03, 0x7B, 0xC0, 0x03, 0x33, 0x80, 0x01, 0x80, 0x00, 0x01, 0xC1, 0x80, 0x00, 0xFF, 0x80, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x41 'A' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0xEC, 0x00, 0x00, 0xEE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xC7, - 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0x03, 0x80, 0x07, 0x03, 0x80, - 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0F, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0xEC, 0x00, 0x00, 0xEE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xC7, + 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0x03, 0x80, 0x07, 0x03, 0x80, + 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0F, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x42 'B' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x01, - 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFF, - 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, - 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 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, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x01, + 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFF, + 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, + 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x43 'C' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, - 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xE3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, + 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x44 'D' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFF, 0x00, 0x01, - 0xC7, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xC7, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFC, 0x00, 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, 0xFC, 0x00, 0x01, 0xFF, 0x00, 0x01, + 0xC7, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xC7, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x45 'E' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, - 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 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, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, + 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x46 'F' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, - 0xC0, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 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, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, + 0xC0, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x47 'G' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, - 0x00, 0x03, 0x8F, 0xC0, 0x03, 0xCF, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, + 0x00, 0x03, 0x8F, 0xC0, 0x03, 0xCF, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 'H' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, - 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, - 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 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, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, + 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, + 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x49 'I' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 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, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4A 'J' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0x80, 0x00, - 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, - 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x01, 0xC7, 0x80, 0x03, 0xC7, 0x80, - 0x01, 0xE7, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0x80, 0x00, + 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, + 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x01, 0xC7, 0x80, 0x03, 0xC7, 0x80, + 0x01, 0xE7, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4B 'K' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0xC0, 0x03, 0x87, 0x80, 0x03, - 0x8F, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x9E, 0x00, 0x03, 0xBC, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF8, - 0x00, 0x03, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xDE, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x8F, 0x00, - 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0xC0, 0x03, 0x87, 0x80, 0x03, + 0x8F, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x9E, 0x00, 0x03, 0xBC, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF8, + 0x00, 0x03, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xDE, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x8F, 0x00, + 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4C 'L' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, - 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, - 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 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, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, + 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4D 'M' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xC0, 0x03, 0xE3, 0xC0, 0x03, - 0xE3, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xF6, 0xC0, 0x03, 0xB6, 0xC0, 0x03, 0xBE, - 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x80, 0xC0, - 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xC0, 0x03, 0xE3, 0xC0, 0x03, + 0xE3, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xF6, 0xC0, 0x03, 0xB6, 0xC0, 0x03, 0xBE, + 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x80, 0xC0, + 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4E 'N' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE1, 0xC0, 0x01, 0xE1, 0xC0, 0x01, - 0xE1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xD9, - 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xCD, 0xC0, 0x01, 0xCF, 0xC0, 0x01, 0xCF, 0xC0, - 0x01, 0xC7, 0xC0, 0x01, 0xC7, 0xC0, 0x01, 0xC3, 0xC0, 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, 0xE1, 0xC0, 0x01, 0xE1, 0xC0, 0x01, + 0xE1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xD9, + 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xCD, 0xC0, 0x01, 0xCF, 0xC0, 0x01, 0xCF, 0xC0, + 0x01, 0xC7, 0xC0, 0x01, 0xC7, 0xC0, 0x01, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4F 'O' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, - 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, + 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 'P' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xFF, 0x80, 0x01, - 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xFF, 0x80, 0x01, 0xFE, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 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, 0xFE, 0x00, 0x01, 0xFF, 0x80, 0x01, + 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xFF, 0x80, 0x01, 0xFE, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x51 'Q' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, - 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xE0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, + 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, + 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xE0 }, // 0x52 'R' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x03, - 0x87, 0x80, 0x03, 0x83, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0xFF, - 0x00, 0x03, 0xFE, 0x00, 0x03, 0x9E, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x87, 0x00, - 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x03, + 0x87, 0x80, 0x03, 0x83, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0xFF, + 0x00, 0x03, 0xFE, 0x00, 0x03, 0x9E, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x87, 0x00, + 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x53 'S' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC0, 0x00, 0x01, 0xF8, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, - 0x03, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, + 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC0, 0x00, 0x01, 0xF8, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, + 0x03, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x54 'T' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 'U' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, - 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, - 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 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, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, + 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, + 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x56 'V' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x01, 0xC0, 0x07, 0x03, 0xC0, 0x07, - 0x03, 0xC0, 0x07, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xC7, - 0x00, 0x01, 0xCF, 0x00, 0x01, 0xCE, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x01, 0xC0, 0x07, 0x03, 0xC0, 0x07, + 0x03, 0xC0, 0x07, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xC7, + 0x00, 0x01, 0xCF, 0x00, 0x01, 0xCE, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x57 'W' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, - 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x07, 0x31, 0xC0, 0x07, 0x39, 0xC0, 0x07, 0x79, 0x80, 0x07, 0x7B, - 0x80, 0x07, 0x7F, 0x80, 0x07, 0xEF, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, 0x03, 0xCF, 0x00, - 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, + 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x07, 0x31, 0xC0, 0x07, 0x39, 0xC0, 0x07, 0x79, 0x80, 0x07, 0x7B, + 0x80, 0x07, 0x7F, 0x80, 0x07, 0xEF, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, 0x03, 0xCF, 0x00, + 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x58 'X' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0xC0, 0x07, 0x87, 0x80, 0x03, - 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xCE, 0x00, 0x03, 0xC7, 0x00, - 0x03, 0x87, 0x80, 0x07, 0x83, 0x80, 0x0F, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0xC0, 0x07, 0x87, 0x80, 0x03, + 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xCE, 0x00, 0x03, 0xC7, 0x00, + 0x03, 0x87, 0x80, 0x07, 0x83, 0x80, 0x0F, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x59 'Y' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xC0, 0x07, 0x03, 0x80, 0x03, - 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xC0, 0x07, 0x03, 0x80, 0x03, + 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5A 'Z' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, - 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 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, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, + 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5B '[' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00 }, // 0x5C '\\' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5D ']' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00 }, // 0x5E '^' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x7E, 0x00, 0x00, 0x66, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC3, 0x00, 0x01, 0xC3, 0x80, 0x01, 0x81, - 0x80, 0x03, 0x81, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x66, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC3, 0x00, 0x01, 0xC3, 0x80, 0x01, 0x81, + 0x80, 0x03, 0x81, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5F '_' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 '`' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x61 'a' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x00, 0x03, - 0x80, 0x00, 0x7F, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0x80, 0x03, 0xC7, 0x80, - 0x03, 0xCF, 0x80, 0x01, 0xFB, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x00, 0x03, + 0x80, 0x00, 0x7F, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0x80, 0x03, 0xC7, 0x80, + 0x03, 0xCF, 0x80, 0x01, 0xFB, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x62 'b' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xE3, 0xC0, - 0x01, 0xE3, 0x80, 0x01, 0xDF, 0x80, 0x01, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xE3, 0xC0, + 0x01, 0xE3, 0x80, 0x01, 0xDF, 0x80, 0x01, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x63 'c' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC0, - 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC0, + 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x64 'd' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, - 0x03, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, - 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, + 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x65 'e' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x01, 0xC1, 0xC0, 0x03, 0xC1, - 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x01, 0xC1, 0xC0, 0x03, 0xC1, + 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x66 'f' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x38, 0x00, 0x00, - 0x78, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x38, 0x00, 0x00, + 0x78, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x67 'g' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFD, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFD, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x01, 0xC0, 0x01, 0xC3, 0xC0, 0x01, - 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFD, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0xC0, 0x00, 0xFD, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x01, 0xC0, 0x01, 0xC3, 0xC0, 0x01, + 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00 }, // 0x68 'h' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x69 'i' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6A 'j' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x1E, 0x00, 0x03, 0xFC, 0x00, 0x01, 0xF0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x1E, 0x00, 0x03, 0xFC, 0x00, 0x01, 0xF0, 0x00 }, // 0x6B 'k' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xC7, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xDC, - 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xC7, 0x00, 0x01, 0xC7, 0x80, - 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xC7, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xDC, + 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xC7, 0x00, 0x01, 0xC7, 0x80, + 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6C 'l' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6D 'm' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x33, 0x80, 0x03, 0xFB, 0xC0, 0x03, 0xBD, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, - 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, - 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x33, 0x80, 0x03, 0xFB, 0xC0, 0x03, 0xBD, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, + 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, + 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6E 'n' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 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, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, + 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6F 'o' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, - 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, + 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x70 'p' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xCF, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC1, + 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE3, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xCF, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00 }, // 0x71 'q' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, - 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, + 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0 }, // 0x72 'r' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0xEF, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0xEF, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x73 's' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xC3, 0x80, 0x01, 0xC1, 0x80, 0x01, 0xE0, - 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0x81, 0xC0, - 0x01, 0xC3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xC3, 0x80, 0x01, 0xC1, 0x80, 0x01, 0xE0, + 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0x81, 0xC0, + 0x01, 0xC3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x74 't' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x70, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x70, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x75 'u' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x71, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 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, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, + 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, + 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x71, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x76 'v' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, - 0x80, 0x01, 0xE3, 0x80, 0x00, 0xE7, 0x80, 0x00, 0xE7, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, + 0x80, 0x01, 0xE3, 0x80, 0x00, 0xE7, 0x80, 0x00, 0xE7, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x77 'w' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x06, 0x31, 0xC0, 0x06, 0x39, - 0xC0, 0x07, 0x79, 0x80, 0x07, 0x79, 0x80, 0x07, 0x6D, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, - 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x06, 0x31, 0xC0, 0x06, 0x39, + 0xC0, 0x07, 0x79, 0x80, 0x07, 0x79, 0x80, 0x07, 0x6D, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, + 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x78 'x' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x7E, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, - 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x7E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, + 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x79 'y' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xE3, - 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xE3, + 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x00 }, // 0x7A 'z' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 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, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x7B '{' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x3C, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0x80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x3C, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0x80 }, // 0x7C '|' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00 }, // 0x7D '}' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xF8, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xF8, 0x00 }, // 0x7E '~' { - 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, 0xE0, 0x00, 0x03, 0xF0, 0x00, 0x03, 0x1C, - 0x40, 0x02, 0x0F, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 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, 0xE0, 0x00, 0x03, 0xF0, 0x00, 0x03, 0x1C, + 0x40, 0x02, 0x0F, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h index 8039ebe5edef8..6d3181a97acac 100644 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h +++ b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h @@ -18,857 +18,857 @@ static const uint8_t rm690b0_font_24x32_data[95][96] = { // 0x20 ' ' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x21 '!' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x22 '\"' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, - 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC3, - 0x80, 0x03, 0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, + 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC3, + 0x80, 0x03, 0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x23 '#' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x00, - 0x60, 0xC0, 0x00, 0xE0, 0xC0, 0x00, 0xE1, 0xC0, 0x00, 0xC1, 0x80, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x01, 0xC3, 0x80, 0x01, 0x83, 0x80, 0x01, 0x83, 0x00, 0x03, 0x83, 0x00, 0x03, 0x87, 0x00, - 0x1F, 0xFF, 0xE0, 0x1F, 0xFF, 0xE0, 0x03, 0x06, 0x00, 0x07, 0x06, 0x00, 0x07, 0x0E, 0x00, 0x06, - 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x00, + 0x60, 0xC0, 0x00, 0xE0, 0xC0, 0x00, 0xE1, 0xC0, 0x00, 0xC1, 0x80, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, + 0xF0, 0x01, 0xC3, 0x80, 0x01, 0x83, 0x80, 0x01, 0x83, 0x00, 0x03, 0x83, 0x00, 0x03, 0x87, 0x00, + 0x1F, 0xFF, 0xE0, 0x1F, 0xFF, 0xE0, 0x03, 0x06, 0x00, 0x07, 0x06, 0x00, 0x07, 0x0E, 0x00, 0x06, + 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x24 '$' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x9B, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x10, - 0x00, 0x0F, 0x90, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, - 0x00, 0x1F, 0xF0, 0x00, 0x11, 0xF0, 0x0E, 0x10, 0xF0, 0x1E, 0x10, 0xF0, 0x0F, 0x10, 0xF0, 0x0F, - 0x9B, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x9B, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x10, + 0x00, 0x0F, 0x90, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, + 0x00, 0x1F, 0xF0, 0x00, 0x11, 0xF0, 0x0E, 0x10, 0xF0, 0x1E, 0x10, 0xF0, 0x0F, 0x10, 0xF0, 0x0F, + 0x9B, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x25 '%' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x70, 0x1F, - 0xC0, 0xE0, 0x39, 0xC0, 0xE0, 0x38, 0xE1, 0xC0, 0x38, 0xE3, 0x80, 0x38, 0xE3, 0x00, 0x38, 0xE7, - 0x00, 0x38, 0xEE, 0x00, 0x1D, 0xCC, 0x00, 0x1F, 0xDC, 0x00, 0x0F, 0xBB, 0xE0, 0x00, 0x37, 0xF0, - 0x00, 0x77, 0x38, 0x00, 0xEE, 0x38, 0x01, 0xCE, 0x38, 0x01, 0xCE, 0x38, 0x03, 0x8E, 0x38, 0x07, - 0x0E, 0x38, 0x06, 0x07, 0x38, 0x0E, 0x07, 0xF0, 0x1C, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x70, 0x1F, + 0xC0, 0xE0, 0x39, 0xC0, 0xE0, 0x38, 0xE1, 0xC0, 0x38, 0xE3, 0x80, 0x38, 0xE3, 0x00, 0x38, 0xE7, + 0x00, 0x38, 0xEE, 0x00, 0x1D, 0xCC, 0x00, 0x1F, 0xDC, 0x00, 0x0F, 0xBB, 0xE0, 0x00, 0x37, 0xF0, + 0x00, 0x77, 0x38, 0x00, 0xEE, 0x38, 0x01, 0xCE, 0x38, 0x01, 0xCE, 0x38, 0x03, 0x8E, 0x38, 0x07, + 0x0E, 0x38, 0x06, 0x07, 0x38, 0x0E, 0x07, 0xF0, 0x1C, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x26 '&' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01, - 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, - 0x00, 0x03, 0xDF, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xE0, 0xE0, 0x0F, 0xF0, 0xE0, - 0x1E, 0x78, 0xE0, 0x1E, 0x39, 0xE0, 0x3C, 0x3F, 0xC0, 0x3C, 0x1F, 0xC0, 0x1E, 0x0F, 0x80, 0x1F, - 0x0F, 0xE8, 0x1F, 0xFF, 0xF8, 0x0F, 0xFD, 0xF8, 0x03, 0xF0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01, + 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, + 0x00, 0x03, 0xDF, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xE0, 0xE0, 0x0F, 0xF0, 0xE0, + 0x1E, 0x78, 0xE0, 0x1E, 0x39, 0xE0, 0x3C, 0x3F, 0xC0, 0x3C, 0x1F, 0xC0, 0x1E, 0x0F, 0x80, 0x1F, + 0x0F, 0xE8, 0x1F, 0xFF, 0xF8, 0x0F, 0xFD, 0xF8, 0x03, 0xF0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x27 '\'' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x28 '(' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, - 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00 }, // 0x29 ')' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00 }, // 0x2A '*' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x03, - 0x39, 0x80, 0x03, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xEE, - 0x00, 0x01, 0xEF, 0x00, 0x01, 0xC7, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x03, + 0x39, 0x80, 0x03, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xEE, + 0x00, 0x01, 0xEF, 0x00, 0x01, 0xC7, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2B '+' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, - 0x0F, 0xFF, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, + 0x0F, 0xFF, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2C ',' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, - 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2D '-' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0x00, - 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 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, 0x01, 0xFF, 0x00, + 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 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 }, // 0x2E '.' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2F '/' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, - 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, + 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x30 '0' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, - 0x0F, 0x39, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, - 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, + 0x0F, 0x39, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, + 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x31 '1' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xBE, 0x00, 0x0E, 0x3E, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, - 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x3E, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xBE, 0x00, 0x0E, 0x3E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, + 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x3E, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x32 '2' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x03, - 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0xFC, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x03, + 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0xFC, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x33 '3' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x87, 0xE0, 0x0F, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, - 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0xC0, - 0x00, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, - 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x87, 0xE0, 0x0F, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, + 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0xC0, + 0x00, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, + 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x34 '4' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, - 0x1F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x80, 0x00, 0xF7, 0x80, 0x00, 0xF7, - 0x80, 0x01, 0xE7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x07, 0x87, 0x80, 0x0F, 0x07, 0x80, - 0x1E, 0x07, 0x80, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x07, 0x80, 0x00, - 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x1F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x80, 0x00, 0xF7, 0x80, 0x00, 0xF7, + 0x80, 0x01, 0xE7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x07, 0x87, 0x80, 0x0F, 0x07, 0x80, + 0x1E, 0x07, 0x80, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x07, 0x80, 0x00, + 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x35 '5' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, - 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, - 0x00, 0x07, 0xBE, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x87, 0xE0, - 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, + 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, + 0x00, 0x07, 0xBE, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x87, 0xE0, + 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x36 '6' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 0xE7, 0xC0, 0x07, 0xC3, 0xE0, 0x07, 0x81, 0xC0, 0x0F, 0x80, - 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x1F, 0x00, 0x0F, 0x7F, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xC3, 0xE0, - 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xE0, 0x03, - 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 0xE7, 0xC0, 0x07, 0xC3, 0xE0, 0x07, 0x81, 0xC0, 0x0F, 0x80, + 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x1F, 0x00, 0x0F, 0x7F, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xC3, 0xE0, + 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xE0, 0x03, + 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x37 '7' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x38 '8' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, - 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC3, 0xC0, - 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC3, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, + 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC3, 0xC0, + 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC3, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x39 '9' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x03, - 0xFF, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, - 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, 0xFF, 0xE0, - 0x03, 0xFD, 0xE0, 0x00, 0xF9, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x07, 0x83, 0xC0, 0x07, - 0x87, 0xC0, 0x07, 0xFF, 0x80, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x03, + 0xFF, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, + 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, 0xFF, 0xE0, + 0x03, 0xFD, 0xE0, 0x00, 0xF9, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x07, 0x83, 0xC0, 0x07, + 0x87, 0xC0, 0x07, 0xFF, 0x80, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3A ':' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3B ';' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, - 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3C '<' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0xF0, 0x03, 0xFF, - 0xE0, 0x0F, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x0F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, - 0x01, 0xF0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0xF0, 0x03, 0xFF, + 0xE0, 0x0F, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x0F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3D '=' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, + 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3E '>' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFF, - 0x80, 0x00, 0xFF, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xF0, - 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x0F, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFF, + 0x80, 0x00, 0xFF, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xF0, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x0F, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3F '?' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x1F, 0x01, 0xE0, 0x1F, 0x01, - 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3E, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x1F, 0x01, 0xE0, 0x1F, 0x01, + 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3E, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x40 '@' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xC1, 0xC0, 0x03, - 0x80, 0xE0, 0x07, 0x00, 0x60, 0x06, 0x00, 0x70, 0x0C, 0x39, 0xB0, 0x0C, 0x7D, 0xB0, 0x1C, 0xE7, - 0xB0, 0x18, 0xC3, 0xB0, 0x19, 0xC3, 0x38, 0x19, 0x83, 0x18, 0x19, 0x83, 0x38, 0x1B, 0x87, 0x30, - 0x1B, 0x87, 0x30, 0x1B, 0x86, 0x30, 0x1B, 0x86, 0x30, 0x19, 0x8E, 0x30, 0x19, 0x9E, 0x60, 0x19, - 0xFB, 0xE0, 0x0C, 0xE3, 0x80, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x03, 0x83, - 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xC1, 0xC0, 0x03, + 0x80, 0xE0, 0x07, 0x00, 0x60, 0x06, 0x00, 0x70, 0x0C, 0x39, 0xB0, 0x0C, 0x7D, 0xB0, 0x1C, 0xE7, + 0xB0, 0x18, 0xC3, 0xB0, 0x19, 0xC3, 0x38, 0x19, 0x83, 0x18, 0x19, 0x83, 0x38, 0x1B, 0x87, 0x30, + 0x1B, 0x87, 0x30, 0x1B, 0x86, 0x30, 0x1B, 0x86, 0x30, 0x19, 0x8E, 0x30, 0x19, 0x9E, 0x60, 0x19, + 0xFB, 0xE0, 0x0C, 0xE3, 0x80, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x03, 0x83, + 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x41 'A' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xE7, - 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, - 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x1F, 0x01, 0xF0, 0x1F, - 0x00, 0xF0, 0x1E, 0x00, 0xF0, 0x3E, 0x00, 0xF8, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xE7, + 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, + 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x1F, 0x01, 0xF0, 0x1F, + 0x00, 0xF0, 0x1E, 0x00, 0xF0, 0x3E, 0x00, 0xF8, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x42 'B' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, - 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, - 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, - 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, - 0xFF, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 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, 0x0F, 0xFF, 0x00, 0x0F, + 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, + 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, + 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, + 0xFF, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x43 'C' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, - 0xC0, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x80, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0xC3, 0xF0, 0x07, - 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, + 0xC0, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x80, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0xC3, 0xF0, 0x07, + 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x44 'D' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x0F, - 0xFF, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0x8F, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, - 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, - 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xE0, 0x0F, - 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x0F, + 0xFF, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0x8F, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, + 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, + 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xE0, 0x0F, + 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x45 'E' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x0F, 0x80, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, - 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x0F, 0x80, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, + 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x46 'F' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, - 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, - 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, - 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, - 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, + 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, + 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, + 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, + 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x47 'G' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0x80, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, - 0x1F, 0x1F, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0xC1, 0xF0, 0x07, - 0xFF, 0xF0, 0x03, 0xFF, 0xE0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0x80, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, + 0x1F, 0x1F, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0xC1, 0xF0, 0x07, + 0xFF, 0xF0, 0x03, 0xFF, 0xE0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48 'H' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xE0, 0x0F, - 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, - 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, - 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xE0, 0x0F, + 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, + 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, + 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x49 'I' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x0F, + 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4A 'J' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, - 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, - 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x07, 0x07, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0xC0, 0x07, - 0xFF, 0x80, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, + 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x07, 0x07, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0xC0, 0x07, + 0xFF, 0x80, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4B 'K' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xF8, 0x0F, - 0x83, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x9F, - 0x00, 0x0F, 0xBE, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xFE, 0x00, - 0x0F, 0xFF, 0x00, 0x0F, 0xDF, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, - 0x83, 0xE0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xF8, 0x0F, + 0x83, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x9F, + 0x00, 0x0F, 0xBE, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xFE, 0x00, + 0x0F, 0xFF, 0x00, 0x0F, 0xDF, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, + 0x83, 0xE0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4C 'L' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, - 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, - 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, + 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, + 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4D 'M' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xF0, 0x0F, - 0x83, 0xF0, 0x0F, 0xC3, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xE7, 0xF0, 0x0E, 0xE7, - 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xFE, 0xF0, 0x0E, 0x7E, 0xF0, 0x0E, 0x7C, 0xF0, - 0x0E, 0x7C, 0xF0, 0x0E, 0x3C, 0xF0, 0x0E, 0x38, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, - 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xF0, 0x0F, + 0x83, 0xF0, 0x0F, 0xC3, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xE7, 0xF0, 0x0E, 0xE7, + 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xFE, 0xF0, 0x0E, 0x7E, 0xF0, 0x0E, 0x7C, 0xF0, + 0x0E, 0x7C, 0xF0, 0x0E, 0x3C, 0xF0, 0x0E, 0x38, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, + 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4E 'N' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC1, 0xE0, 0x0F, - 0xC1, 0xE0, 0x0F, 0xC1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xF1, - 0xE0, 0x0F, 0x71, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x3D, 0xE0, - 0x0F, 0x3D, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, - 0x0F, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC1, 0xE0, 0x0F, + 0xC1, 0xE0, 0x0F, 0xC1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xF1, + 0xE0, 0x0F, 0x71, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x3D, 0xE0, + 0x0F, 0x3D, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, + 0x0F, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4F 'O' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, - 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, - 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, + 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, + 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50 'P' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x0F, - 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, - 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, - 0x0F, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x0F, + 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, + 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, + 0x0F, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x51 'Q' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, - 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, - 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, + 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, + 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, + 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, + 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00 }, // 0x52 'R' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, - 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, - 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, - 0x0F, 0xFF, 0x00, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, - 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, + 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, + 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, + 0x0F, 0xFF, 0x00, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, + 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x53 'S' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x0F, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, - 0x00, 0x07, 0xF0, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x81, 0xF0, 0x0F, - 0xFF, 0xF0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x03, + 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x0F, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, + 0x00, 0x07, 0xF0, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x81, 0xF0, 0x0F, + 0xFF, 0xF0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x54 'T' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x1F, - 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x1F, + 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55 'U' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, - 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, - 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0xC7, 0xE0, 0x07, - 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, + 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, + 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0xC7, 0xE0, 0x07, + 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x56 'V' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1E, - 0x00, 0xF8, 0x1F, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, - 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xC7, 0x80, - 0x03, 0xE7, 0x80, 0x01, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1E, + 0x00, 0xF8, 0x1F, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, + 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xC7, 0x80, + 0x03, 0xE7, 0x80, 0x01, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x57 'W' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, - 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, 0x78, 0x1E, 0x00, 0x70, 0x1E, 0x00, 0xF0, 0x1E, 0x38, - 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x7C, 0xF0, 0x1E, 0x7C, 0xF0, 0x0E, 0x7C, 0xF0, 0x0E, 0xFE, 0xE0, - 0x0F, 0xEE, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xE7, 0xE0, 0x07, 0xC7, 0xE0, 0x07, - 0xC7, 0xC0, 0x07, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, + 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, 0x78, 0x1E, 0x00, 0x70, 0x1E, 0x00, 0xF0, 0x1E, 0x38, + 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x7C, 0xF0, 0x1E, 0x7C, 0xF0, 0x0E, 0x7C, 0xF0, 0x0E, 0xFE, 0xE0, + 0x0F, 0xEE, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xE7, 0xE0, 0x07, 0xC7, 0xE0, 0x07, + 0xC7, 0xC0, 0x07, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x58 'X' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, - 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xEF, 0x80, 0x01, 0xFF, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, - 0x00, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xEF, 0x80, 0x03, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x0F, - 0x83, 0xE0, 0x0F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, + 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xEF, 0x80, 0x01, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, + 0x00, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xEF, 0x80, 0x03, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x0F, + 0x83, 0xE0, 0x0F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x59 'Y' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1F, - 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, 0x03, 0xC7, - 0x80, 0x01, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1F, + 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, 0x03, 0xC7, + 0x80, 0x01, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5A 'Z' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, - 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, - 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, - 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, - 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, + 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, + 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, + 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, + 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5B '[' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80 }, // 0x5C '\\' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, - 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, + 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, + 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5D ']' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00 }, // 0x5E '^' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, - 0x80, 0x03, 0x83, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0E, 0x01, 0xE0, - 0x1E, 0x00, 0xE0, 0x1C, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, + 0x80, 0x03, 0x83, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0E, 0x01, 0xE0, + 0x1E, 0x00, 0xE0, 0x1C, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x5F '_' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60 '`' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x61 'a' { - 0x00, 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, 0x00, 0x03, 0xFF, 0x00, 0x07, 0xFF, - 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x87, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0xFF, 0xC0, - 0x07, 0xFF, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, - 0x8F, 0xC0, 0x0F, 0xFF, 0xF0, 0x07, 0xF9, 0xF0, 0x03, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 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, 0x00, 0x03, 0xFF, 0x00, 0x07, 0xFF, + 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x87, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0xFF, 0xC0, + 0x07, 0xFF, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, + 0x8F, 0xC0, 0x0F, 0xFF, 0xF0, 0x07, 0xF9, 0xF0, 0x03, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x62 'b' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, - 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, - 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, - 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, + 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, + 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, + 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x63 'c' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, - 0xC0, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, + 0xC0, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x64 'd' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x01, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, - 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, - 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x01, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, + 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, + 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x65 'e' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xFF, - 0x80, 0x07, 0xC3, 0xC0, 0x0F, 0x81, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0xFF, 0xE0, - 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x07, - 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xFF, + 0x80, 0x07, 0xC3, 0xC0, 0x0F, 0x81, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0xFF, 0xE0, + 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x07, + 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x66 'f' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, - 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, - 0xE0, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, + 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, + 0xE0, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x67 'g' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x03, 0xFD, 0xE0, 0x07, 0xFF, - 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFD, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, - 0xE0, 0x07, 0x83, 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x03, 0xFD, 0xE0, 0x07, 0xFF, + 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFD, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0xE0, 0x07, 0x83, 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00 }, // 0x68 'h' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x8F, 0x00, 0x0F, 0xBF, 0xC0, 0x0F, 0xFF, - 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, - 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, + 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x8F, 0x00, 0x0F, 0xBF, 0xC0, 0x0F, 0xFF, + 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, + 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x69 'i' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6A 'j' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xE0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xE0, 0x00 }, // 0x6B 'k' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, - 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0x87, - 0xC0, 0x07, 0x8F, 0x80, 0x07, 0x9F, 0x00, 0x07, 0xBE, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, - 0x07, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x07, 0x8F, 0x00, 0x07, 0x8F, 0x80, 0x07, 0x87, 0xC0, 0x07, - 0x87, 0xC0, 0x07, 0x83, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x81, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, + 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0x87, + 0xC0, 0x07, 0x8F, 0x80, 0x07, 0x9F, 0x00, 0x07, 0xBE, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, + 0x07, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x07, 0x8F, 0x00, 0x07, 0x8F, 0x80, 0x07, 0x87, 0xC0, 0x07, + 0x87, 0xC0, 0x07, 0x83, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x81, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6C 'l' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6D 'm' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE1, 0xC0, 0x1D, 0xF3, 0xE0, 0x1F, 0xFF, - 0xF0, 0x1F, 0x7C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, - 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, - 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE1, 0xC0, 0x1D, 0xF3, 0xE0, 0x1F, 0xFF, + 0xF0, 0x1F, 0x7C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, + 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, + 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6E 'n' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x0F, 0x3F, 0xC0, 0x0F, 0x7F, - 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, - 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x0F, 0x3F, 0xC0, 0x0F, 0x7F, + 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, + 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, + 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x6F 'o' { - 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, - 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, - 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, + 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, + 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x70 'p' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, - 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, - 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, + 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, + 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00 }, // 0x71 'q' { - 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, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, - 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, - 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, - 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, + 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, + 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0 }, // 0x72 'r' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0xE0, 0x07, 0xCF, 0xE0, 0x03, 0xDF, - 0xE0, 0x03, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, - 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0xE0, 0x07, 0xCF, 0xE0, 0x03, 0xDF, + 0xE0, 0x03, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x73 's' { - 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, - 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x81, 0xC0, 0x07, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFF, 0x00, - 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, - 0x83, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, + 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x81, 0xC0, 0x07, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFF, 0x00, + 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, + 0x83, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x74 't' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0x07, 0xFF, - 0x80, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, - 0xF0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0x07, 0xFF, + 0x80, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, + 0xF0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x75 'u' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, - 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, - 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x07, 0xFD, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xE1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, + 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, + 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, + 0xC7, 0xE0, 0x07, 0xFD, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xE1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x76 'v' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x01, - 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, - 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x01, + 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, + 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x77 'w' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, - 0x78, 0x1C, 0x00, 0x70, 0x1C, 0x38, 0x70, 0x1C, 0x3C, 0x70, 0x1E, 0x7C, 0x70, 0x1E, 0x7C, 0xF0, - 0x0E, 0x7C, 0xF0, 0x0E, 0xEE, 0xE0, 0x0E, 0xEE, 0xE0, 0x0E, 0xE7, 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, + 0x78, 0x1C, 0x00, 0x70, 0x1C, 0x38, 0x70, 0x1C, 0x3C, 0x70, 0x1E, 0x7C, 0x70, 0x1E, 0x7C, 0xF0, + 0x0E, 0x7C, 0xF0, 0x0E, 0xEE, 0xE0, 0x0E, 0xEE, 0xE0, 0x0E, 0xE7, 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, + 0xC7, 0xE0, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x78 'x' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, - 0xC0, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xEF, 0x00, 0x03, 0xC7, 0x80, 0x07, - 0xC7, 0xC0, 0x07, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x1F, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, + 0xC0, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xEF, 0x00, 0x03, 0xC7, 0x80, 0x07, + 0xC7, 0xC0, 0x07, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x1F, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x79 'y' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, - 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, - 0x03, 0xC7, 0x80, 0x01, 0xE7, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, - 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xC0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, + 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, + 0x03, 0xC7, 0x80, 0x01, 0xE7, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, + 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xC0, 0x00 }, // 0x7A 'z' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xC0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0xFF, + 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x7B '{' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, - 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x07, 0xE0, 0x00, - 0x07, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, + 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x07, 0xE0, 0x00, + 0x07, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0 }, // 0x7C '|' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00 }, // 0x7D '}' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF0, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF0, 0x00 }, // 0x7E '~' { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x0F, 0xF8, 0x30, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, - 0x18, 0x3F, 0xF0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x0F, 0xF8, 0x30, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, + 0x18, 0x3F, 0xF0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; From 9f5c7f06faa34d649affc62a742376f2fb648d38 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 30 Jan 2026 20:02:32 +0100 Subject: [PATCH 03/38] Copilot suggested changes (after verification) --- lib/esp_jpeg/src/esp_jpeg.c | 60 +++++++++++++++-- ports/espressif/bindings/espsdcard/SDCard.c | 18 +++-- .../mpconfigboard.h | 2 +- ports/espressif/common-hal/espsdcard/SDCard.c | 18 +++-- ports/espressif/common-hal/rm690b0/RM690B0.c | 4 +- .../common-hal/rm690b0/esp_lcd_rm690b0.c | 15 +++-- py/circuitpy_defns.mk | 6 +- shared-bindings/rm690b0/__init__.c | 26 ++++--- shared-bindings/rm690b0/image_converter.c | 67 +++++++++++++++++-- shared-bindings/rm690b0/image_converter.h | 37 ++++++++-- 10 files changed, 199 insertions(+), 54 deletions(-) diff --git a/lib/esp_jpeg/src/esp_jpeg.c b/lib/esp_jpeg/src/esp_jpeg.c index 07ff497ed97c6..fe41599403206 100644 --- a/lib/esp_jpeg/src/esp_jpeg.c +++ b/lib/esp_jpeg/src/esp_jpeg.c @@ -15,7 +15,13 @@ #include "esp_heap_caps.h" #endif +// TJpgDec work buffer size (heap allocated) #define ESP_JPEG_TJPGD_WORK_BUFFER_SIZE 4096 + +// Maximum pixels per decoded block for on_block callback mode. +// This determines the stack usage of esp_jpeg_output(): +// Stack usage = ESP_JPEG_MAX_BLOCK_PIXELS * sizeof(uint16_t) = 512 bytes +// Ensure sufficient stack space when using on_block callback in deeply nested contexts. #define ESP_JPEG_MAX_BLOCK_PIXELS 256 typedef struct { @@ -53,6 +59,30 @@ static void esp_jpeg_free(void *ptr) { #endif } +/** + * @brief Calculate RGB565 buffer size with overflow protection. + * + * @param width Image width in pixels + * @param height Image height in pixels + * @param out_size Output: buffer size in bytes (only valid if function returns true) + * @return true if calculation succeeded, false if overflow detected + */ +static bool esp_jpeg_calc_rgb565_size(uint32_t width, uint32_t height, size_t *out_size) { + // Check for overflow: width * height must fit in size_t + if (width != 0 && height > SIZE_MAX / width) { + return false; + } + size_t pixel_count = (size_t)width * height; + + // Check for overflow when multiplying by 2 (bytes per pixel) + if (pixel_count > SIZE_MAX / 2) { + return false; + } + + *out_size = pixel_count * 2; + return true; +} + static size_t esp_jpeg_input(JDEC *jd, uint8_t *buff, size_t ndata) { esp_jpeg_tjpgd_ctx_t *ctx = (esp_jpeg_tjpgd_ctx_t *)jd->device; @@ -103,12 +133,24 @@ static int esp_jpeg_output(JDEC *jd, void *bitmap, JRECT *rect) { } else if (ctx->on_block != NULL) { uint32_t width = (uint32_t)rect->right - (uint32_t)rect->left + 1; uint32_t height = (uint32_t)rect->bottom - (uint32_t)rect->top + 1; - uint32_t total = width * height; - if (total == 0 || total > ESP_JPEG_MAX_BLOCK_PIXELS) { + + // Validate dimensions individually to prevent overflow in multiplication. + // Since ESP_JPEG_MAX_BLOCK_PIXELS is 256, if either dimension exceeds it, + // the total would exceed the limit anyway. + if (width == 0 || height == 0 || + width > ESP_JPEG_MAX_BLOCK_PIXELS || height > ESP_JPEG_MAX_BLOCK_PIXELS) { ctx->last_error = ESP_ERR_INVALID_SIZE; return 0; } + uint32_t total = width * height; // Safe: max is 256 * 256 = 65536 + if (total > ESP_JPEG_MAX_BLOCK_PIXELS) { + ctx->last_error = ESP_ERR_INVALID_SIZE; + return 0; + } + + // Stack-allocated buffer for pixel conversion (512 bytes). + // See ESP_JPEG_MAX_BLOCK_PIXELS definition for stack usage notes. uint16_t block_pixels[ESP_JPEG_MAX_BLOCK_PIXELS]; const uint8_t *block_src = (const uint8_t *)bitmap; for (uint32_t i = 0; i < total; i++) { @@ -193,7 +235,12 @@ esp_err_t esp_jpeg_get_image_info(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_imag out->width = jdec.width; out->height = jdec.height; out->outbuf = NULL; - out->outbuf_size = (size_t)jdec.width * jdec.height * 2; + + // Calculate buffer size with overflow protection + if (!esp_jpeg_calc_rgb565_size(jdec.width, jdec.height, &out->outbuf_size)) { + esp_jpeg_free(work); + return ESP_ERR_INVALID_SIZE; + } esp_jpeg_free(work); return ESP_OK; @@ -216,7 +263,12 @@ esp_err_t esp_jpeg_decode(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output return err; } - size_t required_size = (size_t)jdec.width * jdec.height * 2; + // Calculate required buffer size with overflow protection + size_t required_size; + if (!esp_jpeg_calc_rgb565_size(jdec.width, jdec.height, &required_size)) { + esp_jpeg_free(work); + return ESP_ERR_INVALID_SIZE; + } if (cfg->outbuf != NULL && cfg->outbuf_size < required_size) { esp_jpeg_free(work); return ESP_ERR_NO_MEM; diff --git a/ports/espressif/bindings/espsdcard/SDCard.c b/ports/espressif/bindings/espsdcard/SDCard.c index df7a53503fe2d..e9575d30c99a3 100644 --- a/ports/espressif/bindings/espsdcard/SDCard.c +++ b/ports/espressif/bindings/espsdcard/SDCard.c @@ -26,9 +26,15 @@ //| import busio //| import espsdcard as sdcardio //| spi = busio.SPI(board.SD_CLK, MOSI=board.SD_MOSI, MISO=board.SD_MISO) -//| sd = sdcardio.SDCard(spi, board.SD_CS) +//| sd = sdcardio.SDCard(spi, cs=board.SD_CS) //| -//| Pattern 2 (espsdcard native):: +//| Pattern 2 (espsdcard native with positional CS):: +//| +//| import espsdcard +//| sd = espsdcard.SDCard(board.SD_CS, miso=board.SD_MISO, +//| mosi=board.SD_MOSI, clk=board.SD_CLK) +//| +//| Pattern 2b (espsdcard native with keyword-only pins):: //| //| import espsdcard //| sd = espsdcard.SDCard(cs=board.SD_CS, miso=board.SD_MISO, @@ -113,12 +119,16 @@ static mp_obj_t espsdcard_sdcard_make_new(const mp_obj_type_t *type, size_t n_ar } cs_pin = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); - // Extract pins from SPI object + // IMPORTANT: Extract pin references BEFORE deinitializing the SPI object. + // The pin pointers reference static mcu_pin_obj_t objects that remain valid + // after SPI deinit, but we extract them first for clarity and safety. + // After deinit, the spi object's pin fields may be set to NULL. clk_pin = spi->clock; mosi_pin = spi->MOSI; miso_pin = spi->MISO; - // Deinit the user's SPI (we're taking over the bus) + // Deinit the user's SPI - we're taking over the bus with ESP-IDF drivers. + // This releases CircuitPython's claim on the pins so we can reconfigure them. common_hal_busio_spi_deinit(spi); } else if (args[ARG_spi_or_cs].u_obj != mp_const_none) { diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h index 883262bfe03d2..bfd4e93362fdb 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -28,7 +28,7 @@ #define CIRCUITPY_RM690B0_QSPI_D3 (&pin_GPIO14) #define CIRCUITPY_RM690B0_RESET (&pin_GPIO21) #define CIRCUITPY_RM690B0_POWER (&pin_GPIO16) -#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (true) +#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low #define CIRCUITPY_RM690B0_WIDTH (600) #define CIRCUITPY_RM690B0_HEIGHT (450) #define CIRCUITPY_RM690B0_BITS_PER_PIXEL (16) diff --git a/ports/espressif/common-hal/espsdcard/SDCard.c b/ports/espressif/common-hal/espsdcard/SDCard.c index 65b291f0d967b..805a5bb81a0ac 100644 --- a/ports/espressif/common-hal/espsdcard/SDCard.c +++ b/ports/espressif/common-hal/espsdcard/SDCard.c @@ -76,7 +76,10 @@ void common_hal_espsdcard_sdcard_construct( // Allocate card structure self->card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); if (self->card == NULL) { - spi_bus_free((spi_host_device_t)spi_host); + if (self->spi_bus_initialized) { + spi_bus_free((spi_host_device_t)spi_host); + self->spi_bus_initialized = false; + } mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory for SD card structure")); return; } @@ -155,15 +158,10 @@ void common_hal_espsdcard_sdcard_deinit(espsdcard_sdcard_obj_t *self) { // Free SPI bus only if we initialized it if (self->spi_bus_initialized) { - esp_err_t ret = spi_bus_free((spi_host_device_t)self->spi_host); - if (ret == ESP_OK) { - self->spi_bus_initialized = false; - } - // If it fails, it might be in use - just mark as not initialized - // to prevent double-free attempts - else { - self->spi_bus_initialized = false; - } + // If spi_bus_free fails, it might be in use by another component. + // Mark as not initialized regardless to prevent double-free attempts. + (void)spi_bus_free((spi_host_device_t)self->spi_host); + self->spi_bus_initialized = false; } // Release pins diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.c b/ports/espressif/common-hal/rm690b0/RM690B0.c index 8623505d5aa6a..0ab3d5bcf77d2 100644 --- a/ports/espressif/common-hal/rm690b0/RM690B0.c +++ b/ports/espressif/common-hal/rm690b0/RM690B0.c @@ -51,7 +51,7 @@ static const char *TAG = "rm690b0"; #endif #ifndef CIRCUITPY_RM690B0_POWER_ON_LEVEL -#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (true) +#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low #endif #ifndef CIRCUITPY_RM690B0_USE_QSPI @@ -80,7 +80,7 @@ static const char *TAG = "rm690b0"; #define LCD_D3_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D3) #define LCD_RST_PIN PIN_GPIO(CIRCUITPY_RM690B0_RESET) #define LCD_PWR_PIN PIN_GPIO(CIRCUITPY_RM690B0_POWER) -#define LCD_PWR_ON_LEVEL ((CIRCUITPY_RM690B0_POWER_ON_LEVEL) ? 1 : 0) +#define LCD_PWR_ON_LEVEL (CIRCUITPY_RM690B0_POWER_ON_LEVEL) #define LCD_H_RES (CIRCUITPY_RM690B0_WIDTH) #define LCD_V_RES (CIRCUITPY_RM690B0_HEIGHT) diff --git a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c index e22d6a6a2855b..4aed54a261801 100644 --- a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c +++ b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c @@ -42,7 +42,7 @@ typedef struct { int y_gap; uint8_t fb_bits_per_pixel; uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_val; // save surrent value of LCD_CMD_COLMOD register + uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register const rm690b0_lcd_init_cmd_t *init_cmds; uint16_t init_cmds_size; struct { @@ -297,21 +297,22 @@ static esp_err_t panel_rm690b0_invert_color(esp_lcd_panel_t *panel, bool invert_ static esp_err_t panel_rm690b0_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) { rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); esp_lcd_panel_io_handle_t io = rm690b0->io; - esp_err_t ret = ESP_OK; + + if (mirror_y) { + ESP_LOGE(TAG, "mirror_y is not supported by this panel"); + return ESP_ERR_NOT_SUPPORTED; + } if (mirror_x) { rm690b0->madctl_val |= BIT(6); } else { rm690b0->madctl_val &= ~BIT(6); } - if (mirror_y) { - ESP_LOGE(TAG, "mirror_y is not supported by this panel"); - ret = ESP_ERR_NOT_SUPPORTED; - } + ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_MADCTL, (uint8_t[]) { rm690b0->madctl_val }, 1), TAG, "send command failed"); - return ret; + return ESP_OK; } static esp_err_t panel_rm690b0_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) { diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 029d5c385af71..d99054a5cec64 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -901,12 +901,10 @@ SRC_MOD += $(addprefix lib/AnimatedGIF/, \ $(BUILD)/lib/AnimatedGIF/gif.o: CFLAGS += -DCIRCUITPY endif -ifeq ($(CIRCUITPY_JPEGIO),1) +# tjpgd library is needed for both JPEGIO and RM690B0 JPEG support +ifneq ($(filter 1,$(CIRCUITPY_JPEGIO) $(CIRCUITPY_RM690B0)),) SRC_MOD += lib/tjpgd/src/tjpgd.c $(BUILD)/lib/tjpgd/src/tjpgd.o: CFLAGS += -Wno-shadow -Wno-cast-align -endif - -ifneq ($(filter 1,$(CIRCUITPY_JPEGIO) $(CIRCUITPY_RM690B0)),) SRC_MOD += lib/esp_jpeg/src/esp_jpeg.c CFLAGS_MOD += -I$(TOP)/lib/tjpgd/src -I$(TOP)/lib/esp_jpeg/include endif diff --git a/shared-bindings/rm690b0/__init__.c b/shared-bindings/rm690b0/__init__.c index 57665e0bfc412..0a6674d97f26b 100644 --- a/shared-bindings/rm690b0/__init__.c +++ b/shared-bindings/rm690b0/__init__.c @@ -99,13 +99,14 @@ static mp_obj_t rm690b0_bmp_to_rgb565(mp_obj_t bmp_data_obj) { vstr_t vstr; vstr_init_len(&vstr, buffer_size); - // Convert + // Convert - store error string before cleanup to preserve error context err = img_bmp_to_rgb565(bufinfo.buf, bufinfo.len, (uint8_t *)vstr.buf, buffer_size, &info); if (err != IMG_OK) { + const char *error_text = img_error_string(err); vstr_clear(&vstr); mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("BMP conversion failed (%s)"), img_error_string(err)); + MP_ERROR_TEXT("BMP conversion failed (%s)"), error_text); } // Create info dict @@ -145,17 +146,22 @@ static mp_obj_t rm690b0_jpg_to_rgb565(mp_obj_t jpg_data_obj) { err = img_jpg_to_rgb565(bufinfo.buf, bufinfo.len, (uint8_t *)vstr.buf, buffer_size, &info); - // If function returns unsupported, JPEG support was not compiled in - if (err == IMG_ERR_UNSUPPORTED) { - vstr_clear(&vstr); - mp_raise_NotImplementedError(MP_ERROR_TEXT("JPEG support not compiled in")); - } - + // Handle errors with centralized cleanup if (err != IMG_OK) { + // Capture error info before cleanup const char *error_text = img_error_string(err); + bool is_unsupported = (err == IMG_ERR_UNSUPPORTED); + + // Cleanup vstr_clear(&vstr); - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("JPEG conversion failed (%s)"), error_text); + + // Raise appropriate exception + if (is_unsupported) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("JPEG support not compiled in")); + } else { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("JPEG conversion failed (%s)"), error_text); + } } // Create info dict diff --git a/shared-bindings/rm690b0/image_converter.c b/shared-bindings/rm690b0/image_converter.c index c5dff0e19f913..565f14e9973d1 100644 --- a/shared-bindings/rm690b0/image_converter.c +++ b/shared-bindings/rm690b0/image_converter.c @@ -5,6 +5,7 @@ #include "image_converter.h" #include #include +#include #ifdef CIRCUITPY #include "py/misc.h" @@ -24,9 +25,34 @@ #define USE_ESP_JPEG 0 #endif +// ============================================================================= +// Platform-Specific Memory Allocation +// ============================================================================= +// +// IMAGE_MALLOC/IMAGE_FREE provide platform-appropriate memory allocation for +// temporary buffers used during image decoding. Behavior varies by platform: +// +// ESP_PLATFORM (ESP32, ESP32-S3, etc.): +// - Priority: SPIRAM (PSRAM) first, then internal RAM +// - Rationale: Image buffers can be large; SPIRAM preserves precious internal RAM +// - Failure: Returns NULL if both allocations fail +// +// CIRCUITPY (CircuitPython runtime): +// - Uses m_malloc_maybe() which is GC-aware and returns NULL on failure +// - Memory is tracked by the garbage collector +// - Failure: Returns NULL (does not raise exception) +// +// Other platforms (desktop, testing): +// - Uses standard malloc()/free() +// - Failure: Returns NULL per C standard +// +// All platforms: Caller MUST check for NULL return and handle gracefully. +// ============================================================================= + #if !USE_ESP_JPEG #if defined(ESP_PLATFORM) static void *image_malloc(size_t size) { + // Try SPIRAM first (larger, slower), fall back to internal RAM (faster, limited) void *ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (!ptr) { ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); @@ -69,11 +95,11 @@ const char *img_error_string(img_error_t error) { case IMG_ERR_BUFFER_TOO_SMALL: return "Buffer too small"; case IMG_ERR_INVALID_FORMAT: - return "Invalid format"; + return \"Malformed data\"; case IMG_ERR_CORRUPTED_DATA: - return "Corrupted data"; + return \"Corrupted data\"; case IMG_ERR_UNSUPPORTED: - return "Unsupported feature"; + return \"Unsupported format\"; case IMG_ERR_OUT_OF_MEMORY: return "Out of memory"; case IMG_ERR_IO_ERROR: @@ -163,6 +189,9 @@ img_error_t img_bmp_parse_header( info->width = (uint32_t)width; info->height = (uint32_t)(height > 0 ? height : -height); info->data_size = img_rgb565_buffer_size(info->width, info->height); + if (info->data_size == SIZE_MAX) { + return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation + } info->bit_depth = bit_count; info->channels = (bit_count == 32) ? 4 : 3; info->has_alpha = (bit_count == 32); @@ -208,12 +237,29 @@ img_error_t img_bmp_to_rgb565( // Determine if image is bottom-up (positive height) or top-down (negative height) bool bottom_up = (height_signed > 0); - // Calculate bytes per pixel and row stride + // Calculate bytes per pixel and row stride with overflow checking uint32_t bytes_per_pixel = bit_count / 8; + + // Check for overflow in width * bytes_per_pixel + if (bytes_per_pixel != 0 && width > (UINT32_MAX - 3) / bytes_per_pixel) { + return IMG_ERR_INVALID_SIZE; + } + uint32_t row_stride = ((width * bytes_per_pixel + 3) & ~3); // Rows padded to 4-byte boundary + // Check for overflow in row_stride * height + if (height != 0 && row_stride > UINT32_MAX / height) { + return IMG_ERR_INVALID_SIZE; + } + uint32_t total_data_size = row_stride * height; + + // Check for overflow in data_offset + total_data_size + if (data_offset > UINT32_MAX - total_data_size) { + return IMG_ERR_INVALID_SIZE; + } + // Verify we have enough data - if (data_offset + (row_stride * height) > bmp_size) { + if (data_offset + total_data_size > bmp_size) { return IMG_ERR_CORRUPTED_DATA; } @@ -307,6 +353,9 @@ img_error_t img_jpg_parse_header( info->width = out.width; info->height = out.height; info->data_size = img_rgb565_buffer_size(out.width, out.height); + if (info->data_size == SIZE_MAX) { + return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation + } info->bit_depth = 8; info->channels = 3; info->has_alpha = false; @@ -453,6 +502,10 @@ img_error_t img_jpg_to_rgb565( } size_t required_size = img_rgb565_buffer_size(jdec.width, jdec.height); + if (required_size == SIZE_MAX) { + IMAGE_FREE(work_buffer); + return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation + } if (buffer_size < required_size) { IMAGE_FREE(work_buffer); return IMG_ERR_BUFFER_TOO_SMALL; @@ -518,6 +571,10 @@ img_error_t img_jpg_parse_header( info->width = jdec.width; info->height = jdec.height; info->data_size = img_rgb565_buffer_size(jdec.width, jdec.height); + if (info->data_size == SIZE_MAX) { + IMAGE_FREE(work_buffer); + return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation + } info->bit_depth = 8; info->channels = 3; info->has_alpha = false; diff --git a/shared-bindings/rm690b0/image_converter.h b/shared-bindings/rm690b0/image_converter.h index 1d285ad825857..0a8c1d57c984d 100644 --- a/shared-bindings/rm690b0/image_converter.h +++ b/shared-bindings/rm690b0/image_converter.h @@ -18,9 +18,9 @@ typedef enum { IMG_ERR_NULL_POINTER = -1, // NULL pointer passed IMG_ERR_INVALID_SIZE = -2, // Invalid image dimensions IMG_ERR_BUFFER_TOO_SMALL = -3, // Output buffer too small - IMG_ERR_INVALID_FORMAT = -4, // Invalid or unsupported format - IMG_ERR_CORRUPTED_DATA = -5, // Corrupted image data - IMG_ERR_UNSUPPORTED = -6, // Unsupported feature + IMG_ERR_INVALID_FORMAT = -4, // Malformed data (bad signature, corrupted headers) + IMG_ERR_CORRUPTED_DATA = -5, // Corrupted image data (truncated, checksum mismatch) + IMG_ERR_UNSUPPORTED = -6, // Valid format but unsupported feature (bit depth, compression) IMG_ERR_OUT_OF_MEMORY = -7, // Memory allocation failed IMG_ERR_IO_ERROR = -8 // File I/O error } img_error_t; @@ -42,12 +42,20 @@ typedef struct { // RGB Conversion Macros // ============================================================================= -// Convert 24-bit RGB to 16-bit RGB565 +// Convert 24-bit RGB888 to 16-bit RGB565 // Format: RRRR RGGG GGGB BBBB (5 bits R, 6 bits G, 5 bits B) +// +// This is an intentional lossy conversion: +// - Red: 8 bits → 5 bits (loses 3 LSBs, 0xF8 mask keeps bits 7:3) +// - Green: 8 bits → 6 bits (loses 2 LSBs, 0xFC mask keeps bits 7:2) +// - Blue: 8 bits → 5 bits (loses 3 LSBs, right-shift discards bits 2:0) +// +// Color precision is reduced from 16.7M colors (24-bit) to 65K colors (16-bit). #define RGB888_TO_RGB565(r, g, b) \ ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3)) -// Extract components from RGB565 +// Extract components from RGB565 back to 8-bit (with zero-filled LSBs) +// Note: Extracted values have lower bits set to 0, not interpolated #define RGB565_TO_R(rgb565) (((rgb565) >> 8) & 0xF8) #define RGB565_TO_G(rgb565) (((rgb565) >> 3) & 0xFC) #define RGB565_TO_B(rgb565) (((rgb565) << 3) & 0xF8) @@ -147,10 +155,25 @@ img_error_t img_jpg_parse_header( * * @param width Image width in pixels * @param height Image height in pixels - * @return Required buffer size in bytes + * @return Required buffer size in bytes, or SIZE_MAX on overflow + * + * @note Caller should check if return value == SIZE_MAX to detect overflow. + * RGB565 uses 2 bytes per pixel, so buffer size = width * height * 2. */ static inline size_t img_rgb565_buffer_size(uint32_t width, uint32_t height) { - return (size_t)width * height * 2; + // Check for overflow: width * height must not exceed SIZE_MAX / 2 + // First check width * height overflow + if (width != 0 && height > SIZE_MAX / width) { + return SIZE_MAX; // Overflow in width * height + } + size_t pixel_count = (size_t)width * height; + + // Check for overflow when multiplying by 2 (bytes per pixel) + if (pixel_count > SIZE_MAX / 2) { + return SIZE_MAX; // Overflow in pixel_count * 2 + } + + return pixel_count * 2; } /** From 42b7eb9d73be407577cc6d65ba6edc8e23cad0a3 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 30 Jan 2026 20:05:12 +0100 Subject: [PATCH 04/38] Typo fix --- shared-bindings/rm690b0/image_converter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared-bindings/rm690b0/image_converter.c b/shared-bindings/rm690b0/image_converter.c index 565f14e9973d1..fb961b24a57ba 100644 --- a/shared-bindings/rm690b0/image_converter.c +++ b/shared-bindings/rm690b0/image_converter.c @@ -95,11 +95,11 @@ const char *img_error_string(img_error_t error) { case IMG_ERR_BUFFER_TOO_SMALL: return "Buffer too small"; case IMG_ERR_INVALID_FORMAT: - return \"Malformed data\"; + return "Malformed data"; case IMG_ERR_CORRUPTED_DATA: - return \"Corrupted data\"; + return "Corrupted data"; case IMG_ERR_UNSUPPORTED: - return \"Unsupported format\"; + return "Unsupported format"; case IMG_ERR_OUT_OF_MEMORY: return "Out of memory"; case IMG_ERR_IO_ERROR: From c232b45396c304ae04e35d2caa2f696c4936d927 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 31 Jan 2026 15:44:44 +0100 Subject: [PATCH 05/38] Drop espsdcard in favour of sdcardio with standard API --- ports/espressif/Makefile | 7 +- ports/espressif/bindings/espsdcard/SDCard.c | 346 ------------------ ports/espressif/bindings/espsdcard/SDCard.h | 12 - ports/espressif/bindings/espsdcard/__init__.c | 103 ------ ports/espressif/bindings/espsdcard/__init__.h | 7 - .../mpconfigboard.mk | 4 +- ports/espressif/common-hal/espsdcard/SDCard.c | 285 --------------- ports/espressif/common-hal/espsdcard/SDCard.h | 55 --- ports/espressif/common-hal/sdcardio/SDCard.c | 341 +++++++++++++++++ ports/espressif/common-hal/sdcardio/SDCard.h | 35 ++ .../espressif/common-hal/sdcardio/__init__.c | 125 +++++++ .../espressif/common-hal/sdcardio/__init__.h | 9 + ports/espressif/mpconfigport.mk | 1 + py/circuitpy_defns.mk | 14 +- py/circuitpy_mpconfig.mk | 8 +- shared-bindings/sdcardio/SDCard.c | 1 - shared-bindings/sdcardio/SDCard.h | 9 + 17 files changed, 539 insertions(+), 823 deletions(-) delete mode 100644 ports/espressif/bindings/espsdcard/SDCard.c delete mode 100644 ports/espressif/bindings/espsdcard/SDCard.h delete mode 100644 ports/espressif/bindings/espsdcard/__init__.c delete mode 100644 ports/espressif/bindings/espsdcard/__init__.h delete mode 100644 ports/espressif/common-hal/espsdcard/SDCard.c delete mode 100644 ports/espressif/common-hal/espsdcard/SDCard.h create mode 100644 ports/espressif/common-hal/sdcardio/SDCard.c create mode 100644 ports/espressif/common-hal/sdcardio/SDCard.h create mode 100644 ports/espressif/common-hal/sdcardio/__init__.c create mode 100644 ports/espressif/common-hal/sdcardio/__init__.h diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 42703e95cc924..25b23f88fb230 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -503,15 +503,10 @@ SRC_ESPNOW := \ SRC_C += $(SRC_ESPNOW) endif -ifneq ($(CIRCUITPY_ESPSDCARD),0) -SRC_ESPSDCARD := \ - $(wildcard common-hal/espsdcard/*.c) \ - $(wildcard bindings/espsdcard/*.c) -SRC_C += $(SRC_ESPSDCARD) +ifneq ($(CIRCUITPY_SDCARDIO),0) INC += -isystem esp-idf/components/sdmmc/include INC += -isystem esp-idf/components/esp_driver_sdmmc/include INC += -isystem esp-idf/components/esp_driver_sdspi/include -INC += -isystem esp-idf/components/driver/spi/include endif ifneq ($(CIRCUITPY_ESPULP),0) diff --git a/ports/espressif/bindings/espsdcard/SDCard.c b/ports/espressif/bindings/espsdcard/SDCard.c deleted file mode 100644 index e9575d30c99a3..0000000000000 --- a/ports/espressif/bindings/espsdcard/SDCard.c +++ /dev/null @@ -1,346 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include - -#include "py/obj.h" -#include "py/runtime.h" -#include "py/objproperty.h" - -#include "bindings/espsdcard/SDCard.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/util.h" -#include "shared-bindings/busio/SPI.h" -#include "common-hal/busio/SPI.h" - -//| class SDCard: -//| """ESP32-native SD card interface using ESP-IDF drivers -//| -//| This module is API-compatible with sdcardio for easy migration! -//| -//| You can use either pattern: -//| -//| Pattern 1 (sdcardio-compatible):: -//| -//| import busio -//| import espsdcard as sdcardio -//| spi = busio.SPI(board.SD_CLK, MOSI=board.SD_MOSI, MISO=board.SD_MISO) -//| sd = sdcardio.SDCard(spi, cs=board.SD_CS) -//| -//| Pattern 2 (espsdcard native with positional CS):: -//| -//| import espsdcard -//| sd = espsdcard.SDCard(board.SD_CS, miso=board.SD_MISO, -//| mosi=board.SD_MOSI, clk=board.SD_CLK) -//| -//| Pattern 2b (espsdcard native with keyword-only pins):: -//| -//| import espsdcard -//| sd = espsdcard.SDCard(cs=board.SD_CS, miso=board.SD_MISO, -//| mosi=board.SD_MOSI, clk=board.SD_CLK) -//| """ -//| -//| def __init__( -//| self, -//| spi_or_cs: Union[busio.SPI, microcontroller.Pin], -//| cs: Optional[microcontroller.Pin] = None, -//| *, -//| miso: Optional[microcontroller.Pin] = None, -//| mosi: Optional[microcontroller.Pin] = None, -//| clk: Optional[microcontroller.Pin] = None, -//| baudrate: int = 4000000, -//| spi_host: int = 2, -//| max_transfer_size: int = 4000, -//| allocation_unit_size: int = 16384, -//| max_files: int = 5, -//| format_if_mount_failed: bool = False, -//| dma_channel: int = -1 -//| ) -> None: -//| """Initialize SD card with ESP-IDF drivers -//| -//| :param spi_or_cs: Either a busio.SPI object (Pattern 1) or CS pin (Pattern 2) -//| :param cs: CS pin (required for Pattern 1 with busio.SPI) -//| :param miso: MISO pin (required for Pattern 2) -//| :param mosi: MOSI pin (required for Pattern 2) -//| :param clk: Clock pin (required for Pattern 2) -//| :param baudrate: SPI frequency in Hz (currently unused, ESP-IDF manages speed) -//| :param spi_host: SPI host (1=SPI2_HOST, 2=SPI3_HOST) -//| :param max_transfer_size: Maximum DMA transfer size in bytes (default 4000) -//| :param allocation_unit_size: FAT allocation unit size (default 16384) -//| :param max_files: Maximum number of open files (default 5) -//| :param format_if_mount_failed: Auto-format card if mount fails (default False) -//| :param dma_channel: DMA channel (-1 for automatic) -//| """ -//| ... -//| - -static mp_obj_t espsdcard_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { - ARG_spi_or_cs, ARG_cs, - ARG_miso, ARG_mosi, ARG_clk, - ARG_baudrate, ARG_spi_host, ARG_max_transfer_size, ARG_allocation_unit_size, - ARG_max_files, ARG_format_if_mount_failed, ARG_dma_channel - }; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_spi_or_cs, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4000000} }, - { MP_QSTR_spi_host, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_max_transfer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4000} }, - { MP_QSTR_allocation_unit_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16384} }, - { MP_QSTR_max_files, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_format_if_mount_failed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_dma_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - }; - - 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); - - // Detect API pattern and extract pins - const mcu_pin_obj_t *cs_pin; - const mcu_pin_obj_t *miso_pin; - const mcu_pin_obj_t *mosi_pin; - const mcu_pin_obj_t *clk_pin; - - // Check if first argument is a busio.SPI object (sdcardio compatibility) - if (args[ARG_spi_or_cs].u_obj != mp_const_none && - mp_obj_is_type(args[ARG_spi_or_cs].u_obj, &busio_spi_type)) { - // Pattern 1: sdcardio-compatible (spi, cs) - busio_spi_obj_t *spi = MP_OBJ_TO_PTR(args[ARG_spi_or_cs].u_obj); - - // CS must be provided as second argument - if (args[ARG_cs].u_obj == mp_const_none) { - mp_raise_TypeError(MP_ERROR_TEXT("cs pin required when using busio.SPI")); - } - cs_pin = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); - - // IMPORTANT: Extract pin references BEFORE deinitializing the SPI object. - // The pin pointers reference static mcu_pin_obj_t objects that remain valid - // after SPI deinit, but we extract them first for clarity and safety. - // After deinit, the spi object's pin fields may be set to NULL. - clk_pin = spi->clock; - mosi_pin = spi->MOSI; - miso_pin = spi->MISO; - - // Deinit the user's SPI - we're taking over the bus with ESP-IDF drivers. - // This releases CircuitPython's claim on the pins so we can reconfigure them. - common_hal_busio_spi_deinit(spi); - - } else if (args[ARG_spi_or_cs].u_obj != mp_const_none) { - // Pattern 2a: espsdcard native with positional cs (cs_pin, miso=, mosi=, clk=) - cs_pin = validate_obj_is_free_pin(args[ARG_spi_or_cs].u_obj, MP_QSTR_spi_or_cs); - - // miso, mosi, clk must be provided - if (args[ARG_miso].u_obj == mp_const_none || - args[ARG_mosi].u_obj == mp_const_none || - args[ARG_clk].u_obj == mp_const_none) { - mp_raise_TypeError(MP_ERROR_TEXT("miso, mosi, and clk pins required")); - } - - miso_pin = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso); - mosi_pin = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); - clk_pin = validate_obj_is_free_pin(args[ARG_clk].u_obj, MP_QSTR_clk); - - } else { - // Pattern 2b: espsdcard native with keyword-only (cs=, miso=, mosi=, clk=) - if (args[ARG_cs].u_obj == mp_const_none) { - mp_raise_TypeError(MP_ERROR_TEXT("cs pin required")); - } - if (args[ARG_miso].u_obj == mp_const_none || - args[ARG_mosi].u_obj == mp_const_none || - args[ARG_clk].u_obj == mp_const_none) { - mp_raise_TypeError(MP_ERROR_TEXT("cs, miso, mosi, and clk pins required")); - } - - cs_pin = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); - miso_pin = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso); - mosi_pin = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); - clk_pin = validate_obj_is_free_pin(args[ARG_clk].u_obj, MP_QSTR_clk); - } - - // Create object - espsdcard_sdcard_obj_t *self = mp_obj_malloc(espsdcard_sdcard_obj_t, &espsdcard_sdcard_type); - - // Initialize with ESP-IDF (same for both patterns) - common_hal_espsdcard_sdcard_construct( - self, - cs_pin, miso_pin, mosi_pin, clk_pin, - args[ARG_spi_host].u_int, - args[ARG_max_transfer_size].u_int, - args[ARG_allocation_unit_size].u_int, - args[ARG_max_files].u_int, - args[ARG_format_if_mount_failed].u_bool, - args[ARG_dma_channel].u_int - ); - - return MP_OBJ_FROM_PTR(self); -} - -//| def deinit(self) -> None: -//| """Deinitialize the SD card and free resources""" -//| ... -//| -static mp_obj_t espsdcard_sdcard_deinit(mp_obj_t self_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_espsdcard_sdcard_deinit(self); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_deinit_obj, espsdcard_sdcard_deinit); - -//| def __enter__(self) -> SDCard: -//| """Context manager entry""" -//| ... -//| -static mp_obj_t espsdcard_sdcard___enter__(mp_obj_t self_in) { - return self_in; -} -static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard___enter___obj, espsdcard_sdcard___enter__); - -//| def __exit__(self) -> None: -//| """Context manager exit""" -//| ... -//| -static mp_obj_t espsdcard_sdcard___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_espsdcard_sdcard_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espsdcard_sdcard___exit___obj, 4, 4, espsdcard_sdcard___exit__); - -//| def is_present(self) -> bool: -//| """Check if card is present and responding""" -//| ... -//| -static mp_obj_t espsdcard_sdcard_is_present(mp_obj_t self_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_bool(common_hal_espsdcard_sdcard_is_present(self)); -} -static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_is_present_obj, espsdcard_sdcard_is_present); - -//| def get_status(self) -> int: -//| """Get card status (0=OK, 1=ERROR, 2=NOT_PRESENT)""" -//| ... -//| -static mp_obj_t espsdcard_sdcard_get_status(mp_obj_t self_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_espsdcard_sdcard_get_status(self)); -} -static MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_status_obj, espsdcard_sdcard_get_status); - -//| capacity_mb: float -//| """Card capacity in megabytes""" -static mp_obj_t espsdcard_sdcard_get_capacity_mb(mp_obj_t self_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_float(common_hal_espsdcard_sdcard_get_capacity_mb(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_capacity_mb_obj, espsdcard_sdcard_get_capacity_mb); - -MP_PROPERTY_GETTER(espsdcard_sdcard_capacity_mb_obj, - (mp_obj_t)&espsdcard_sdcard_get_capacity_mb_obj); - -//| card_type: str -//| """Card type ('SD', 'SDHC/SDXC', or 'Unknown')""" -static mp_obj_t espsdcard_sdcard_get_card_type(mp_obj_t self_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - return common_hal_espsdcard_sdcard_get_card_type(self); -} -MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_card_type_obj, espsdcard_sdcard_get_card_type); - -MP_PROPERTY_GETTER(espsdcard_sdcard_card_type_obj, - (mp_obj_t)&espsdcard_sdcard_get_card_type_obj); - -//| count: int -//| """Number of 512-byte blocks (required by storage.VfsFat)""" -static mp_obj_t espsdcard_sdcard_get_count(mp_obj_t self_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int_from_uint(common_hal_espsdcard_sdcard_get_count(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(espsdcard_sdcard_get_count_obj, espsdcard_sdcard_get_count); - -MP_PROPERTY_GETTER(espsdcard_sdcard_count_obj, - (mp_obj_t)&espsdcard_sdcard_get_count_obj); - -//| def readblocks(self, block_num: int, buf: WriteableBuffer) -> None: -//| """Read blocks from SD card (required by storage.VfsFat)""" -//| ... -//| -static mp_obj_t espsdcard_sdcard_readblocks(mp_obj_t self_in, mp_obj_t block_num_in, mp_obj_t buf_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint32_t block_num = mp_obj_get_int(block_num_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); - common_hal_espsdcard_sdcard_readblocks(self, block_num, &bufinfo); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_3(espsdcard_sdcard_readblocks_obj, espsdcard_sdcard_readblocks); - -//| def writeblocks(self, block_num: int, buf: ReadableBuffer) -> None: -//| """Write blocks to SD card (required by storage.VfsFat)""" -//| ... -//| -static mp_obj_t espsdcard_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t block_num_in, mp_obj_t buf_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint32_t block_num = mp_obj_get_int(block_num_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - common_hal_espsdcard_sdcard_writeblocks(self, block_num, &bufinfo); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_3(espsdcard_sdcard_writeblocks_obj, espsdcard_sdcard_writeblocks); - -//| def ioctl(self, op: int, arg: int) -> Optional[int]: -//| """Control operations (required by storage.VfsFat)""" -//| ... -//| -static mp_obj_t espsdcard_sdcard_ioctl(mp_obj_t self_in, mp_obj_t op_in, mp_obj_t arg_in) { - espsdcard_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_int_t op = mp_obj_get_int(op_in); - - switch (op) { - case 1: // BP_IOCTL_INIT - return mp_const_none; - case 2: // BP_IOCTL_DEINIT - common_hal_espsdcard_sdcard_deinit(self); - return mp_const_none; - case 3: // BP_IOCTL_SYNC - return mp_obj_new_int(common_hal_espsdcard_sdcard_writeblocks_sync(self)); - case 4: // BP_IOCTL_SEC_COUNT - return mp_obj_new_int_from_uint(common_hal_espsdcard_sdcard_get_count(self)); - case 5: // BP_IOCTL_SEC_SIZE - return mp_obj_new_int(512); - default: - return mp_const_none; - } -} -static MP_DEFINE_CONST_FUN_OBJ_3(espsdcard_sdcard_ioctl_obj, espsdcard_sdcard_ioctl); - -static const mp_rom_map_elem_t espsdcard_sdcard_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espsdcard_sdcard_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&espsdcard_sdcard___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espsdcard_sdcard___exit___obj) }, - - { MP_ROM_QSTR(MP_QSTR_is_present), MP_ROM_PTR(&espsdcard_sdcard_is_present_obj) }, - { MP_ROM_QSTR(MP_QSTR_get_status), MP_ROM_PTR(&espsdcard_sdcard_get_status_obj) }, - - { MP_ROM_QSTR(MP_QSTR_capacity_mb), MP_ROM_PTR(&espsdcard_sdcard_capacity_mb_obj) }, - { MP_ROM_QSTR(MP_QSTR_card_type), MP_ROM_PTR(&espsdcard_sdcard_card_type_obj) }, - { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&espsdcard_sdcard_count_obj) }, - - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&espsdcard_sdcard_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&espsdcard_sdcard_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&espsdcard_sdcard_ioctl_obj) }, -}; -static MP_DEFINE_CONST_DICT(espsdcard_sdcard_locals_dict, espsdcard_sdcard_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - espsdcard_sdcard_type, - MP_QSTR_SDCard, - MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, - make_new, espsdcard_sdcard_make_new, - locals_dict, &espsdcard_sdcard_locals_dict - ); diff --git a/ports/espressif/bindings/espsdcard/SDCard.h b/ports/espressif/bindings/espsdcard/SDCard.h deleted file mode 100644 index 3f559e1a73689..0000000000000 --- a/ports/espressif/bindings/espsdcard/SDCard.h +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "common-hal/espsdcard/SDCard.h" - -extern const mp_obj_type_t espsdcard_sdcard_type; - -// Module-level deinit for convenience (static method support) -void espsdcard_sdcard_deinit_all(void); diff --git a/ports/espressif/bindings/espsdcard/__init__.c b/ports/espressif/bindings/espsdcard/__init__.c deleted file mode 100644 index 9cc3477603112..0000000000000 --- a/ports/espressif/bindings/espsdcard/__init__.c +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include "py/obj.h" -#include "py/runtime.h" -#include "bindings/espsdcard/SDCard.h" - -//| """ESP32-native SD card interface using ESP-IDF drivers -//| -//| This module provides reliable SD card access on ESP32 boards using -//| native ESP-IDF drivers. It is a drop-in replacement for the generic -//| sdcardio module with better reliability and performance. -//| -//| API Compatibility: -//| This module is fully compatible with sdcardio. Existing code using -//| sdcardio can simply import espsdcard instead: -//| -//| import espsdcard as sdcardio -//| -//| All sdcardio code will work without modifications. -//| -//| Native API: -//| For new code, the native API is cleaner and exposes ESP-IDF features: -//| -//| sd = espsdcard.SDCard( -//| cs=board.SD_CS, -//| miso=board.SD_MISO, -//| mosi=board.SD_MOSI, -//| clk=board.SD_CLK -//| ) -//| -//| Example (sdcardio-compatible):: -//| -//| import board -//| import busio -//| import espsdcard as sdcardio -//| import storage -//| -//| spi = busio.SPI(board.SD_CLK, MOSI=board.SD_MOSI, MISO=board.SD_MISO) -//| sd = sdcardio.SDCard(spi, board.SD_CS) -//| vfs = storage.VfsFat(sd) -//| storage.mount(vfs, "/sd") -//| -//| Example (espsdcard native):: -//| -//| import board -//| import espsdcard -//| import storage -//| -//| sd = espsdcard.SDCard( -//| cs=board.SD_CS, -//| miso=board.SD_MISO, -//| mosi=board.SD_MOSI, -//| clk=board.SD_CLK -//| ) -//| vfs = storage.VfsFat(sd) -//| storage.mount(vfs, "/sd") -//| """ - -//| SPI2_HOST: int -//| """SPI2 host constant""" -//| -//| SPI3_HOST: int -//| """SPI3 host constant""" -//| -//| DMA_AUTO: int -//| """Automatic DMA channel selection""" -//| -//| STATUS_OK: int -//| """Card status: OK""" -//| -//| STATUS_ERROR: int -//| """Card status: Error""" -//| -//| STATUS_NOT_PRESENT: int -//| """Card status: Not present""" -//| - -static const mp_rom_map_elem_t espsdcard_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espsdcard) }, - { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&espsdcard_sdcard_type) }, - - // SPI host constants - { MP_ROM_QSTR(MP_QSTR_SPI2_HOST), MP_ROM_INT(1) }, - { MP_ROM_QSTR(MP_QSTR_SPI3_HOST), MP_ROM_INT(2) }, - - // DMA constants - { MP_ROM_QSTR(MP_QSTR_DMA_AUTO), MP_ROM_INT(-1) }, - - // Status constants - { MP_ROM_QSTR(MP_QSTR_STATUS_OK), MP_ROM_INT(0) }, - { MP_ROM_QSTR(MP_QSTR_STATUS_ERROR), MP_ROM_INT(1) }, - { MP_ROM_QSTR(MP_QSTR_STATUS_NOT_PRESENT), MP_ROM_INT(2) }, -}; -static MP_DEFINE_CONST_DICT(espsdcard_module_globals, espsdcard_module_globals_table); - -const mp_obj_module_t espsdcard_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&espsdcard_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_espsdcard, espsdcard_module); diff --git a/ports/espressif/bindings/espsdcard/__init__.h b/ports/espressif/bindings/espsdcard/__init__.h deleted file mode 100644 index 0966ff424fd63..0000000000000 --- a/ports/espressif/bindings/espsdcard/__init__.h +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -// Module registration is handled in __init__.c via MP_REGISTER_MODULE diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index 1503ef6d6e94b..81b8b1277f68b 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -40,9 +40,6 @@ CIRCUITPY_JPEGIO = 1 CIRCUITPY_FRAMEBUFFERIO = 1 CIRCUITPY_RM690B0 = 1 -# Enable SD card support with native ESP-IDF drivers -CIRCUITPY_ESPSDCARD = 1 - # Enable ESP-NOW for peer-to-peer wireless communication CIRCUITPY_ESPNOW = 1 @@ -75,6 +72,7 @@ CIRCUITPY_USB_MIDI = 1 # Storage configuration CIRCUITPY_STORAGE = 1 CIRCUITPY_NVM = 1 +CIRCUITPY_SDCARDIO = 1 # Enable touch support CIRCUITPY_TOUCHIO = 0 diff --git a/ports/espressif/common-hal/espsdcard/SDCard.c b/ports/espressif/common-hal/espsdcard/SDCard.c deleted file mode 100644 index 805a5bb81a0ac..0000000000000 --- a/ports/espressif/common-hal/espsdcard/SDCard.c +++ /dev/null @@ -1,285 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include "common-hal/espsdcard/SDCard.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "py/runtime.h" -#include "py/mperrno.h" - -#include "sdmmc_cmd.h" -#include "sd_protocol_defs.h" -#include "driver/sdmmc_host.h" -#include "driver/sdspi_host.h" -#include "esp_log.h" -#include -#include - -static const char *TAG = "espsdcard"; - -// Singleton tracker for cleanup -static espsdcard_sdcard_obj_t *espsdcard_singleton = NULL; - -void common_hal_espsdcard_sdcard_construct( - espsdcard_sdcard_obj_t *self, - const mcu_pin_obj_t *cs, - const mcu_pin_obj_t *miso, - const mcu_pin_obj_t *mosi, - const mcu_pin_obj_t *clk, - int spi_host, - int max_transfer_size, - int allocation_unit_size, - int max_files, - bool format_if_mount_failed, - int dma_channel - ) { - // Store pin assignments - self->cs_pin = cs->number; - self->miso_pin = miso->number; - self->mosi_pin = mosi->number; - self->clk_pin = clk->number; - self->spi_host = spi_host; - self->slot = -1; - self->mounted = false; - self->spi_bus_initialized = false; - self->card = NULL; - - // Configure SPI bus - spi_bus_config_t bus_cfg = { - .mosi_io_num = mosi->number, - .miso_io_num = miso->number, - .sclk_io_num = clk->number, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = max_transfer_size, - }; - - // Initialize SPI bus with DMA - spi_dma_chan_t dma = (dma_channel < 0) ? SPI_DMA_CH_AUTO : (spi_dma_chan_t)dma_channel; - esp_err_t ret = spi_bus_initialize((spi_host_device_t)spi_host, &bus_cfg, dma); - if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SPI bus init failed: %d"), ret); - return; - } - // Track if we initialized the bus (not if it was already initialized) - self->spi_bus_initialized = (ret == ESP_OK); - - // Configure SD card slot - sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); - slot_config.gpio_cs = (gpio_num_t)cs->number; - slot_config.host_id = (spi_host_device_t)spi_host; - - // Configure host - sdmmc_host_t host = SDSPI_HOST_DEFAULT(); - host.slot = spi_host; - - // Allocate card structure - self->card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); - if (self->card == NULL) { - if (self->spi_bus_initialized) { - spi_bus_free((spi_host_device_t)spi_host); - self->spi_bus_initialized = false; - } - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory for SD card structure")); - return; - } - - // Initialize the card - ret = sdspi_host_init_device(&slot_config, &self->slot); - if (ret != ESP_OK) { - free(self->card); - self->card = NULL; - if (self->spi_bus_initialized) { - spi_bus_free((spi_host_device_t)spi_host); - self->spi_bus_initialized = false; - } - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD host init failed: %d"), ret); - return; - } - - // Probe and initialize the card - ret = sdmmc_card_init(&host, self->card); - - if (ret != ESP_OK) { - if (self->slot >= 0) { - sdspi_host_remove_device(self->slot); - self->slot = -1; - } - free(self->card); - self->card = NULL; - if (self->spi_bus_initialized) { - spi_bus_free((spi_host_device_t)spi_host); - self->spi_bus_initialized = false; - } - if (ret == ESP_ERR_TIMEOUT) { - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not responding")); - } else if (ret == ESP_ERR_NOT_FOUND) { - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not found")); - } else { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD card init failed: %d"), ret); - } - return; - } - - // Mark as mounted - self->mounted = true; - - // Claim pins - claim_pin(cs); - claim_pin(miso); - claim_pin(mosi); - claim_pin(clk); - - // Set singleton for cleanup - espsdcard_singleton = self; - - ESP_LOGI(TAG, "SD card mounted successfully"); - if (self->card != NULL) { - sdmmc_card_print_info(stdout, self->card); - } -} - -void common_hal_espsdcard_sdcard_deinit(espsdcard_sdcard_obj_t *self) { - if (!self->mounted) { - return; - } - - // Remove device from SPI slot - if (self->slot >= 0) { - sdspi_host_remove_device(self->slot); - self->slot = -1; - } - - // Free card structure - if (self->card != NULL) { - free(self->card); - self->card = NULL; - } - - // Free SPI bus only if we initialized it - if (self->spi_bus_initialized) { - // If spi_bus_free fails, it might be in use by another component. - // Mark as not initialized regardless to prevent double-free attempts. - (void)spi_bus_free((spi_host_device_t)self->spi_host); - self->spi_bus_initialized = false; - } - - // Release pins - reset_pin_number(self->cs_pin); - reset_pin_number(self->miso_pin); - reset_pin_number(self->mosi_pin); - reset_pin_number(self->clk_pin); - - self->mounted = false; - - // Clear singleton if this was it - if (espsdcard_singleton == self) { - espsdcard_singleton = NULL; - } - - ESP_LOGI(TAG, "SD card deinitialized"); -} - -bool common_hal_espsdcard_sdcard_deinited(espsdcard_sdcard_obj_t *self) { - return !self->mounted; -} - -bool common_hal_espsdcard_sdcard_is_present(espsdcard_sdcard_obj_t *self) { - if (!self->mounted || self->card == NULL) { - return false; - } - - esp_err_t err = sdmmc_get_status(self->card); - return err == ESP_OK; -} - -int common_hal_espsdcard_sdcard_get_status(espsdcard_sdcard_obj_t *self) { - if (!self->mounted || self->card == NULL) { - return 2; // STATUS_NOT_PRESENT - } - - esp_err_t err = sdmmc_get_status(self->card); - return (err == ESP_OK) ? 0 : 1; // STATUS_OK or STATUS_ERROR -} - -uint32_t common_hal_espsdcard_sdcard_get_count(espsdcard_sdcard_obj_t *self) { - if (!self->mounted || self->card == NULL) { - return 0; - } - - // Return number of 512-byte blocks - return (uint32_t)self->card->csd.capacity; -} - -void common_hal_espsdcard_sdcard_readblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { - if (!self->mounted || self->card == NULL) { - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not mounted")); - return; - } - - if (buf->len % 512 != 0) { - mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Buffer must be multiple of 512 bytes")); - return; - } - - uint32_t block_count = buf->len / 512; - - esp_err_t err = sdmmc_read_sectors(self->card, buf->buf, start_block, block_count); - if (err != ESP_OK) { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("Read failed: %d"), err); - } -} - -void common_hal_espsdcard_sdcard_writeblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { - if (!self->mounted || self->card == NULL) { - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SD card not mounted")); - return; - } - - if (buf->len % 512 != 0) { - mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Buffer must be multiple of 512 bytes")); - return; - } - - uint32_t block_count = buf->len / 512; - - esp_err_t err = sdmmc_write_sectors(self->card, buf->buf, start_block, block_count); - if (err != ESP_OK) { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("Write failed: %d"), err); - } -} - -int common_hal_espsdcard_sdcard_writeblocks_sync(espsdcard_sdcard_obj_t *self) { - // ESP-IDF handles synchronization internally - // Return 0 for success - return 0; -} - -float common_hal_espsdcard_sdcard_get_capacity_mb(espsdcard_sdcard_obj_t *self) { - if (!self->mounted || self->card == NULL) { - return 0.0f; - } - - // Capacity is in 512-byte sectors - uint64_t capacity_bytes = (uint64_t)self->card->csd.capacity * 512; - return (float)capacity_bytes / (1024.0f * 1024.0f); -} - -mp_obj_t common_hal_espsdcard_sdcard_get_card_type(espsdcard_sdcard_obj_t *self) { - if (!self->mounted || self->card == NULL) { - return mp_obj_new_str("Unknown", 7); - } - - if (self->card->ocr & SD_OCR_SDHC_CAP) { - return mp_obj_new_str("SDHC/SDXC", 9); - } else { - return mp_obj_new_str("SD", 2); - } -} - -// Module-level deinit for convenience -void espsdcard_sdcard_deinit_all(void) { - if (espsdcard_singleton != NULL) { - common_hal_espsdcard_sdcard_deinit(espsdcard_singleton); - } -} diff --git a/ports/espressif/common-hal/espsdcard/SDCard.h b/ports/espressif/common-hal/espsdcard/SDCard.h deleted file mode 100644 index 5ea1c13b742e1..0000000000000 --- a/ports/espressif/common-hal/espsdcard/SDCard.h +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "py/obj.h" -#include "sdmmc_cmd.h" -#include "driver/gpio.h" -#include "common-hal/microcontroller/Pin.h" - -typedef struct { - mp_obj_base_t base; - sdmmc_card_t *card; - int spi_host; - int slot; - gpio_num_t cs_pin; - gpio_num_t miso_pin; - gpio_num_t mosi_pin; - gpio_num_t clk_pin; - bool mounted; - bool spi_bus_initialized; - const char *mount_point; -} espsdcard_sdcard_obj_t; - -extern const mp_obj_type_t espsdcard_sdcard_type; - -// Function declarations -void common_hal_espsdcard_sdcard_construct( - espsdcard_sdcard_obj_t *self, - const mcu_pin_obj_t *cs, - const mcu_pin_obj_t *miso, - const mcu_pin_obj_t *mosi, - const mcu_pin_obj_t *clk, - int spi_host, - int max_transfer_size, - int allocation_unit_size, - int max_files, - bool format_if_mount_failed, - int dma_channel - ); - -void common_hal_espsdcard_sdcard_deinit(espsdcard_sdcard_obj_t *self); -bool common_hal_espsdcard_sdcard_deinited(espsdcard_sdcard_obj_t *self); -bool common_hal_espsdcard_sdcard_is_present(espsdcard_sdcard_obj_t *self); -int common_hal_espsdcard_sdcard_get_status(espsdcard_sdcard_obj_t *self); -uint32_t common_hal_espsdcard_sdcard_get_count(espsdcard_sdcard_obj_t *self); -void common_hal_espsdcard_sdcard_readblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); -void common_hal_espsdcard_sdcard_writeblocks(espsdcard_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); -int common_hal_espsdcard_sdcard_writeblocks_sync(espsdcard_sdcard_obj_t *self); -float common_hal_espsdcard_sdcard_get_capacity_mb(espsdcard_sdcard_obj_t *self); -mp_obj_t common_hal_espsdcard_sdcard_get_card_type(espsdcard_sdcard_obj_t *self); - -// Reset function -void espsdcard_sdcard_deinit_all(void); diff --git a/ports/espressif/common-hal/sdcardio/SDCard.c b/ports/espressif/common-hal/sdcardio/SDCard.c new file mode 100644 index 0000000000000..1a4a8f09ae208 --- /dev/null +++ b/ports/espressif/common-hal/sdcardio/SDCard.c @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +// ESP-specific sdcardio implementation using ESP-IDF's sdspi_host driver. +// This provides significantly better performance (~2x) compared to the generic +// shared-module implementation by using hardware-optimized SD protocol handling. +// +// The key design decision is to "borrow" the busio.SPI object passed in, +// extract its pins, deinitialize it, and then initialize sdspi_host with +// those same pins. This is necessary because ESP-IDF's SD host driver and +// CircuitPython's busio.SPI cannot share the same SPI peripheral. + +#include "common-hal/sdcardio/SDCard.h" +#include "shared-bindings/sdcardio/SDCard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "common-hal/busio/SPI.h" + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" + +#include "sdmmc_cmd.h" +#include "sd_protocol_defs.h" +#include "driver/sdmmc_host.h" +#include "driver/sdspi_host.h" +#include "esp_log.h" + +#include + +static const char *TAG = "sdcardio"; + +// Singleton tracker for cleanup during reset +static sdcardio_sdcard_obj_t *sdcardio_singleton = NULL; + +// Forward declarations +static void check_for_deinit(sdcardio_sdcard_obj_t *self); + +void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, + busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { + + // Extract pin information from busio.SPI before we deinitialize it + if (common_hal_busio_spi_deinited(bus)) { + mp_raise_ValueError(MP_ERROR_TEXT("SPI bus already deinitialized")); + } + + // Get pin numbers from the busio.SPI object + const mcu_pin_obj_t *mosi_pin = bus->MOSI; + const mcu_pin_obj_t *miso_pin = bus->MISO; + const mcu_pin_obj_t *clk_pin = bus->clock; + spi_host_device_t spi_host = bus->host_id; + + if (mosi_pin == NULL || miso_pin == NULL || clk_pin == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("SPI bus must have MOSI, MISO, and CLK pins")); + } + + // Store pin numbers + self->mosi_pin = mosi_pin->number; + self->miso_pin = miso_pin->number; + self->clk_pin = clk_pin->number; + self->cs_pin = cs->number; + self->spi_host = spi_host; + self->slot = -1; + self->mounted = false; + self->spi_bus_initialized = false; + self->card = NULL; + + // Deinitialize the busio.SPI to release the SPI bus + // This is necessary because ESP-IDF's sdspi_host needs exclusive access + ESP_LOGI(TAG, "Taking over SPI bus from busio.SPI (host=%d)", spi_host); + common_hal_busio_spi_deinit(bus); + + // Configure SPI bus for SD card + spi_bus_config_t bus_cfg = { + .mosi_io_num = self->mosi_pin, + .miso_io_num = self->miso_pin, + .sclk_io_num = self->clk_pin, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 65536, // 64KB for optimal performance + }; + + // Initialize SPI bus with DMA + esp_err_t ret = spi_bus_initialize(spi_host, &bus_cfg, SPI_DMA_CH_AUTO); + if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SPI bus init failed: %d"), ret); + return; + } + // Track if we initialized the bus (not if it was already initialized by something else) + self->spi_bus_initialized = (ret == ESP_OK); + + // Configure SD card slot + sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); + slot_config.gpio_cs = self->cs_pin; + slot_config.host_id = spi_host; + + // Configure host - use the provided baudrate + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + host.slot = spi_host; + // Convert baudrate to kHz for ESP-IDF + host.max_freq_khz = baudrate / 1000; + if (host.max_freq_khz > SDMMC_FREQ_DEFAULT) { + host.max_freq_khz = SDMMC_FREQ_DEFAULT; // Cap at safe default + } + + // Allocate card structure + self->card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); + if (self->card == NULL) { + if (self->spi_bus_initialized) { + spi_bus_free(spi_host); + self->spi_bus_initialized = false; + } + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory for SD card structure")); + return; + } + + // Initialize the SD SPI device + ret = sdspi_host_init_device(&slot_config, &self->slot); + if (ret != ESP_OK) { + free(self->card); + self->card = NULL; + if (self->spi_bus_initialized) { + spi_bus_free(spi_host); + self->spi_bus_initialized = false; + } + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD host init failed: %d"), ret); + return; + } + + // Probe and initialize the card + ret = sdmmc_card_init(&host, self->card); + if (ret != ESP_OK) { + if (self->slot >= 0) { + sdspi_host_remove_device(self->slot); + self->slot = -1; + } + free(self->card); + self->card = NULL; + if (self->spi_bus_initialized) { + spi_bus_free(spi_host); + self->spi_bus_initialized = false; + } + if (ret == ESP_ERR_TIMEOUT) { + mp_raise_OSError_msg(MP_ERROR_TEXT("no SD card")); + } else if (ret == ESP_ERR_NOT_FOUND) { + mp_raise_OSError_msg(MP_ERROR_TEXT("no SD card")); + } else { + mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD card init failed: %d"), ret); + } + return; + } + + // Mark as mounted + self->mounted = true; + + // Claim the CS pin (SPI pins were already released by busio.SPI deinit, + // but we need to claim them for our use) + claim_pin(cs); + + // Set singleton for cleanup + sdcardio_singleton = self; + + ESP_LOGI(TAG, "SD card initialized successfully [NATIVE BLOCKDEV v2]"); + if (self->card != NULL) { + ESP_LOGI(TAG, "Card: %s, capacity: %llu sectors", + self->card->cid.name, + (unsigned long long)self->card->csd.capacity); + } +} + +void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) { + if (!self->mounted) { + return; + } + + // Remove device from SPI slot + if (self->slot >= 0) { + sdspi_host_remove_device(self->slot); + self->slot = -1; + } + + // Free card structure + if (self->card != NULL) { + free(self->card); + self->card = NULL; + } + + // Free SPI bus only if we initialized it + if (self->spi_bus_initialized) { + (void)spi_bus_free((spi_host_device_t)self->spi_host); + self->spi_bus_initialized = false; + } + + // Release CS pin + reset_pin_number(self->cs_pin); + + self->mounted = false; + + // Clear singleton if this was it + if (sdcardio_singleton == self) { + sdcardio_singleton = NULL; + } + + ESP_LOGI(TAG, "SD card deinitialized"); +} + +static void check_for_deinit(sdcardio_sdcard_obj_t *self) { + if (!self->mounted || self->card == NULL) { + raise_deinited_error(); + } +} + +void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self) { + check_for_deinit(self); +} + +int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { + check_for_deinit(self); + return (int)self->card->csd.capacity; +} + +int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, + uint32_t start_block, mp_buffer_info_t *buf) { + + check_for_deinit(self); + + if (buf->len % 512 != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("Buffer must be a multiple of 512 bytes")); + } + + uint32_t block_count = buf->len / 512; + + esp_err_t err = sdmmc_read_sectors(self->card, buf->buf, start_block, block_count); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Read failed at block %lu, count %lu: %d", + (unsigned long)start_block, (unsigned long)block_count, err); + return -MP_EIO; + } + + return 0; +} + +int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, + uint32_t start_block, mp_buffer_info_t *buf) { + + check_for_deinit(self); + + if (buf->len % 512 != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("Buffer must be a multiple of 512 bytes")); + } + + uint32_t block_count = buf->len / 512; + + esp_err_t err = sdmmc_write_sectors(self->card, buf->buf, start_block, block_count); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Write failed at block %lu, count %lu: %d", + (unsigned long)start_block, (unsigned long)block_count, err); + return -MP_EIO; + } + + return 0; +} + +int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { + // ESP-IDF handles synchronization internally + // Just verify the card is still mounted + if (!self->mounted) { + return -MP_ENODEV; + } + return 0; +} + +// VFS block device interface functions + +mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t nblocks) { + + sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->mounted || self->card == NULL) { + return MP_ENODEV; + } + + esp_err_t err = sdmmc_read_sectors(self->card, buf, start_block, nblocks); + if (err != ESP_OK) { + return MP_EIO; + } + + return 0; +} + +mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t nblocks) { + + sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->mounted || self->card == NULL) { + return MP_ENODEV; + } + + esp_err_t err = sdmmc_write_sectors(self->card, buf, start_block, nblocks); + if (err != ESP_OK) { + return MP_EIO; + } + + return 0; +} + +bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { + sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + // Sync is handled by ESP-IDF internally + break; + case MP_BLOCKDEV_IOCTL_SYNC: + // ESP-IDF handles sync internally + break; + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + if (self->mounted && self->card != NULL) { + *out_value = (mp_int_t)self->card->csd.capacity; + } + break; + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; + break; + default: + return false; + } + return true; +} + +// Module reset function +void sdcardio_reset(void) { + if (sdcardio_singleton != NULL) { + common_hal_sdcardio_sdcard_deinit(sdcardio_singleton); + } +} diff --git a/ports/espressif/common-hal/sdcardio/SDCard.h b/ports/espressif/common-hal/sdcardio/SDCard.h new file mode 100644 index 0000000000000..a6dfd284dbcae --- /dev/null +++ b/ports/espressif/common-hal/sdcardio/SDCard.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "sdmmc_cmd.h" +#include "driver/sdspi_host.h" + +// ESP-specific sdcardio implementation using ESP-IDF's sdspi_host driver. +// This provides ~2x better performance compared to the generic shared-module +// implementation by using hardware-optimized SD protocol handling. + +typedef struct { + mp_obj_base_t base; + + // SD card state + sdmmc_card_t *card; + sdspi_dev_handle_t slot; + int spi_host; + + // Pin storage (for cleanup) + gpio_num_t cs_pin; + gpio_num_t miso_pin; + gpio_num_t mosi_pin; + gpio_num_t clk_pin; + + // State flags + bool mounted; + bool spi_bus_initialized; +} sdcardio_sdcard_obj_t; + +// Reset function for module cleanup +void sdcardio_reset(void); diff --git a/ports/espressif/common-hal/sdcardio/__init__.c b/ports/espressif/common-hal/sdcardio/__init__.c new file mode 100644 index 0000000000000..557da9c3868fa --- /dev/null +++ b/ports/espressif/common-hal/sdcardio/__init__.c @@ -0,0 +1,125 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +// ESP-specific sdcardio module initialization. +// These functions are called by the filesystem subsystem for auto-mounting. +// Currently, auto-mounting is not implemented for the native ESP sdcardio +// since the ESP-IDF driver requires different initialization timing. + +#include "common-hal/sdcardio/__init__.h" +#include "common-hal/sdcardio/SDCard.h" + +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/sdcardio/SDCard.h" +#include "supervisor/filesystem.h" + +#include "extmod/vfs_fat.h" + +#ifdef DEFAULT_SD_CARD_DETECT +static digitalio_digitalinout_obj_t sd_card_detect_pin; +static sdcardio_sdcard_obj_t sdcard; + +static mp_vfs_mount_t _sdcard_vfs; +static fs_user_mount_t _sdcard_usermount; + +static bool _init_error = false; +static bool _mounted = false; + +#include "shared-bindings/busio/SPI.h" +#include "common-hal/busio/SPI.h" + +#ifdef DEFAULT_SD_MOSI +static busio_spi_obj_t busio_spi_obj; +#else +#include "shared-bindings/board/__init__.h" +#endif +#endif + +void sdcardio_init(void) { + #ifdef DEFAULT_SD_CARD_DETECT + sd_card_detect_pin.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT); + common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP); + common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin); + #endif +} + +void automount_sd_card(void) { + #ifdef DEFAULT_SD_CARD_DETECT + if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) { + // No card. + _init_error = false; + if (_mounted) { + // Unmount the card. + mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table); + if (cur == &_sdcard_vfs) { + MP_STATE_VM(vfs_mount_table) = cur->next; + } else { + while (cur->next != &_sdcard_vfs && cur != NULL) { + cur = cur->next; + } + if (cur != NULL) { + cur->next = _sdcard_vfs.next; + } + } + _sdcard_vfs.next = NULL; + _mounted = false; + } + return; + } else if (_init_error || _mounted) { + // We've already tried and failed to init the card. Don't try again. + return; + } + + busio_spi_obj_t *spi_obj; + #ifndef DEFAULT_SD_MOSI + spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0)); + #else + spi_obj = &busio_spi_obj; + spi_obj->base.type = &busio_spi_type; + common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false); + common_hal_busio_spi_never_reset(spi_obj); + #endif + + sdcard.base.type = &sdcardio_SDCard_type; + + // For native ESP sdcardio, use the common_hal constructor which takes over the SPI bus + common_hal_sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000); + + // Check if initialization succeeded + if (!sdcard.mounted) { + _mounted = false; + _init_error = true; + return; + } + + fs_user_mount_t *vfs = &_sdcard_usermount; + vfs->base.type = &mp_fat_vfs_type; + vfs->fatfs.drv = vfs; + + // Initialise underlying block device + vfs->blockdev.block_size = FF_MIN_SS; + mp_vfs_blockdev_init(&vfs->blockdev, &sdcard); + + // mount the block device so the VFS methods can be used + FRESULT res = f_mount(&vfs->fatfs); + if (res != FR_OK) { + _mounted = false; + _init_error = true; + common_hal_sdcardio_sdcard_deinit(&sdcard); + return; + } + + filesystem_set_concurrent_write_protection(vfs, true); + filesystem_set_writable_by_usb(vfs, false); + + mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; + sdcard_vfs->str = "/sd"; + sdcard_vfs->len = 3; + sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); + sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); + MP_STATE_VM(vfs_mount_table) = sdcard_vfs; + _mounted = true; + #endif // DEFAULT_SD_CARD_DETECT +} diff --git a/ports/espressif/common-hal/sdcardio/__init__.h b/ports/espressif/common-hal/sdcardio/__init__.h new file mode 100644 index 0000000000000..ac04b071bbd21 --- /dev/null +++ b/ports/espressif/common-hal/sdcardio/__init__.h @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Module initialization functions required by the filesystem subsystem +void sdcardio_init(void); +void automount_sd_card(void); diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 42bf3418f9639..bdab7bc10c30d 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -85,6 +85,7 @@ CIRCUITPY_SDIOIO ?= 1 CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY ?= 1 CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 +CIRCUITPY_SDCARDIO_USE_NATIVE ?= 1 CIRCUITPY_WATCHDOG ?= 1 CIRCUITPY_WIFI ?= 1 CIRCUITPY_SOCKETPOOL_IPV6 ?= 1 diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index d99054a5cec64..149e8e99fb1b9 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -772,8 +772,6 @@ SRC_SHARED_MODULE_ALL = \ rgbmatrix/RGBMatrix.c \ rgbmatrix/__init__.c \ rotaryio/IncrementalEncoder.c \ - sdcardio/SDCard.c \ - sdcardio/__init__.c \ sharpdisplay/SharpMemoryFramebuffer.c \ sharpdisplay/__init__.c \ socket/__init__.c \ @@ -840,6 +838,18 @@ SRC_SHARED_MODULE_ALL += \ touchio/__init__.c endif +# Use the native sdcardio if requested. This provides ESP-IDF sdspi_host-based +# SD card access with significantly better performance than the shared-module. +ifeq ($(CIRCUITPY_SDCARDIO_USE_NATIVE),1) +SRC_COMMON_HAL_ALL += \ + sdcardio/SDCard.c \ + sdcardio/__init__.c +else +SRC_SHARED_MODULE_ALL += \ + sdcardio/SDCard.c \ + sdcardio/__init__.c +endif + ifeq ($(CIRCUITPY_SSL_MBEDTLS),0) SRC_COMMON_HAL_ALL += \ ssl/__init__.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 4c4587dd23a0c..adf5c5026b538 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -306,9 +306,6 @@ CFLAGS += -DCIRCUITPY_ESP_USB_SERIAL_JTAG=$(CIRCUITPY_ESP_USB_SERIAL_JTAG) CIRCUITPY_ESPCAMERA ?= 0 CFLAGS += -DCIRCUITPY_ESPCAMERA=$(CIRCUITPY_ESPCAMERA) -CIRCUITPY_ESPSDCARD ?= 0 -CFLAGS += -DCIRCUITPY_ESPSDCARD=$(CIRCUITPY_ESPSDCARD) - CIRCUITPY__EVE ?= 0 CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE) @@ -594,6 +591,11 @@ CFLAGS += -DCIRCUITPY_TIME=$(CIRCUITPY_TIME) CIRCUITPY_TOUCHIO_USE_NATIVE ?= 0 CFLAGS += -DCIRCUITPY_TOUCHIO_USE_NATIVE=$(CIRCUITPY_TOUCHIO_USE_NATIVE) +# sdcardio might be native or generic. See circuitpy_defns.mk. +# When native, uses ESP-IDF sdspi_host for better performance. +CIRCUITPY_SDCARDIO_USE_NATIVE ?= 0 +CFLAGS += -DCIRCUITPY_SDCARDIO_USE_NATIVE=$(CIRCUITPY_SDCARDIO_USE_NATIVE) + CIRCUITPY_TOUCHIO ?= 1 CFLAGS += -DCIRCUITPY_TOUCHIO=$(CIRCUITPY_TOUCHIO) diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c index e6d8453eae108..02b6a230f47e9 100644 --- a/shared-bindings/sdcardio/SDCard.c +++ b/shared-bindings/sdcardio/SDCard.c @@ -9,7 +9,6 @@ #include "py/objarray.h" #include "shared-bindings/sdcardio/SDCard.h" -#include "shared-module/sdcardio/SDCard.h" #include "common-hal/busio/SPI.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/microcontroller/Pin.h" diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h index ac27b47aa4d21..58a16db6880bd 100644 --- a/shared-bindings/sdcardio/SDCard.h +++ b/shared-bindings/sdcardio/SDCard.h @@ -7,7 +7,16 @@ #pragma once +#include "common-hal/busio/SPI.h" +#include "common-hal/microcontroller/Pin.h" + +// Include port-specific common-hal or shared-module implementation based on build config. +// When CIRCUITPY_SDCARDIO_USE_NATIVE is set, the port provides a common-hal implementation. +#ifdef CIRCUITPY_SDCARDIO_USE_NATIVE +#include "common-hal/sdcardio/SDCard.h" +#else #include "shared-module/sdcardio/SDCard.h" +#endif extern const mp_obj_type_t sdcardio_SDCard_type; From c37c43cf7c3e8a29824bdc6e3f0e02a8f3739131 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 31 Jan 2026 16:13:30 +0100 Subject: [PATCH 06/38] Pre-commit hook fixes --- locale/circuitpython.pot | 64 +++++-------------- .../espressif/common-hal/sdcardio/__init__.c | 4 +- 2 files changed, 17 insertions(+), 51 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index b9162693ceadf..0ebd949afdd85 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -710,8 +710,8 @@ msgstr "" msgid "Buffer must be a multiple of %d bytes" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c -msgid "Buffer must be multiple of 512 bytes" +#: ports/espressif/common-hal/sdcardio/SDCard.c +msgid "Buffer must be a multiple of 512 bytes" msgstr "" #: shared-bindings/_bleio/PacketBuffer.c @@ -1744,7 +1744,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c +#: ports/espressif/common-hal/sdcardio/SDCard.c msgid "No memory for SD card structure" msgstr "" @@ -2104,11 +2104,6 @@ msgstr "" msgid "Random number generation error" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c -#, c-format -msgid "Read failed: %d" -msgstr "" - #: shared-bindings/_bleio/__init__.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c shared-module/bitmaptools/__init__.c @@ -2164,24 +2159,12 @@ msgstr "" msgid "SD card CSD format not supported" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c +#: ports/espressif/common-hal/sdcardio/SDCard.c #, c-format msgid "SD card init failed: %d" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c -msgid "SD card not found" -msgstr "" - -#: ports/espressif/common-hal/espsdcard/SDCard.c -msgid "SD card not mounted" -msgstr "" - -#: ports/espressif/common-hal/espsdcard/SDCard.c -msgid "SD card not responding" -msgstr "" - -#: ports/espressif/common-hal/espsdcard/SDCard.c +#: ports/espressif/common-hal/sdcardio/SDCard.c #, c-format msgid "SD host init failed: %d" msgstr "" @@ -2201,11 +2184,19 @@ msgstr "" msgid "SDIO Init Error %x" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c +#: ports/espressif/common-hal/sdcardio/SDCard.c +msgid "SPI bus already deinitialized" +msgstr "" + +#: ports/espressif/common-hal/sdcardio/SDCard.c #, c-format msgid "SPI bus init failed: %d" msgstr "" +#: ports/espressif/common-hal/sdcardio/SDCard.c +msgid "SPI bus must have MOSI, MISO, and CLK pins" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" msgstr "" @@ -2655,11 +2646,6 @@ msgstr "" msgid "Woken up by alarm.\n" msgstr "" -#: ports/espressif/common-hal/espsdcard/SDCard.c -#, c-format -msgid "Write failed: %d" -msgstr "" - #: ports/espressif/common-hal/_bleio/PacketBuffer.c #: ports/nordic/common-hal/_bleio/PacketBuffer.c msgid "Writes not supported on Characteristic" @@ -3232,18 +3218,6 @@ msgstr "" msgid "cross is defined for 1D arrays of length 3" msgstr "" -#: ports/espressif/bindings/espsdcard/SDCard.c -msgid "cs pin required" -msgstr "" - -#: ports/espressif/bindings/espsdcard/SDCard.c -msgid "cs pin required when using busio.SPI" -msgstr "" - -#: ports/espressif/bindings/espsdcard/SDCard.c -msgid "cs, miso, mosi, and clk pins required" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be iterable" msgstr "" @@ -3410,10 +3384,6 @@ msgstr "" msgid "fill_color: unable to allocate DMA buffer" msgstr "" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3889,10 +3859,6 @@ msgstr "" msgid "memoryview: length is not a multiple of itemsize" msgstr "" -#: ports/espressif/bindings/espsdcard/SDCard.c -msgid "miso, mosi, and clk pins required" -msgstr "" - #: extmod/modtime.c msgid "mktime needs a tuple of length 8 or 9" msgstr "" @@ -3982,7 +3948,7 @@ msgstr "" msgid "nested index must be int" msgstr "" -#: shared-module/sdcardio/SDCard.c +#: ports/espressif/common-hal/sdcardio/SDCard.c shared-module/sdcardio/SDCard.c msgid "no SD card" msgstr "" diff --git a/ports/espressif/common-hal/sdcardio/__init__.c b/ports/espressif/common-hal/sdcardio/__init__.c index 557da9c3868fa..ab88e5cc7d8cb 100644 --- a/ports/espressif/common-hal/sdcardio/__init__.c +++ b/ports/espressif/common-hal/sdcardio/__init__.c @@ -83,10 +83,10 @@ void automount_sd_card(void) { #endif sdcard.base.type = &sdcardio_SDCard_type; - + // For native ESP sdcardio, use the common_hal constructor which takes over the SPI bus common_hal_sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000); - + // Check if initialization succeeded if (!sdcard.mounted) { _mounted = false; From 3cfebc29b614417628ad229cd1092d36fbc4501f Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 31 Jan 2026 18:35:22 +0100 Subject: [PATCH 07/38] Cleanup --- ports/espressif/Makefile | 2 +- .../boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk | 1 + ports/espressif/mpconfigport.mk | 1 - py/circuitpy_defns.mk | 2 +- py/circuitpy_mpconfig.mk | 4 ++-- shared-bindings/sdcardio/SDCard.h | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 25b23f88fb230..c085c596c7bf3 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -503,7 +503,7 @@ SRC_ESPNOW := \ SRC_C += $(SRC_ESPNOW) endif -ifneq ($(CIRCUITPY_SDCARDIO),0) +ifneq ($(CIRCUITPY_SDCARDIO_ESPRESSIF),0) INC += -isystem esp-idf/components/sdmmc/include INC += -isystem esp-idf/components/esp_driver_sdmmc/include INC += -isystem esp-idf/components/esp_driver_sdspi/include diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index 81b8b1277f68b..4851d3561a0d8 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -73,6 +73,7 @@ CIRCUITPY_USB_MIDI = 1 CIRCUITPY_STORAGE = 1 CIRCUITPY_NVM = 1 CIRCUITPY_SDCARDIO = 1 +CIRCUITPY_SDCARDIO_ESPRESSIF = 1 # Enable touch support CIRCUITPY_TOUCHIO = 0 diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index bdab7bc10c30d..42bf3418f9639 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -85,7 +85,6 @@ CIRCUITPY_SDIOIO ?= 1 CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY ?= 1 CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 -CIRCUITPY_SDCARDIO_USE_NATIVE ?= 1 CIRCUITPY_WATCHDOG ?= 1 CIRCUITPY_WIFI ?= 1 CIRCUITPY_SOCKETPOOL_IPV6 ?= 1 diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 149e8e99fb1b9..af21b7dac1b70 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -840,7 +840,7 @@ endif # Use the native sdcardio if requested. This provides ESP-IDF sdspi_host-based # SD card access with significantly better performance than the shared-module. -ifeq ($(CIRCUITPY_SDCARDIO_USE_NATIVE),1) +ifeq ($(CIRCUITPY_SDCARDIO_ESPRESSIF),1) SRC_COMMON_HAL_ALL += \ sdcardio/SDCard.c \ sdcardio/__init__.c diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index adf5c5026b538..d71a3264186ad 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -593,8 +593,8 @@ CFLAGS += -DCIRCUITPY_TOUCHIO_USE_NATIVE=$(CIRCUITPY_TOUCHIO_USE_NATIVE) # sdcardio might be native or generic. See circuitpy_defns.mk. # When native, uses ESP-IDF sdspi_host for better performance. -CIRCUITPY_SDCARDIO_USE_NATIVE ?= 0 -CFLAGS += -DCIRCUITPY_SDCARDIO_USE_NATIVE=$(CIRCUITPY_SDCARDIO_USE_NATIVE) +CIRCUITPY_SDCARDIO_ESPRESSIF ?= 0 +CFLAGS += -DCIRCUITPY_SDCARDIO_ESPRESSIF=$(CIRCUITPY_SDCARDIO_ESPRESSIF) CIRCUITPY_TOUCHIO ?= 1 CFLAGS += -DCIRCUITPY_TOUCHIO=$(CIRCUITPY_TOUCHIO) diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h index 58a16db6880bd..243eee7ee274f 100644 --- a/shared-bindings/sdcardio/SDCard.h +++ b/shared-bindings/sdcardio/SDCard.h @@ -11,8 +11,8 @@ #include "common-hal/microcontroller/Pin.h" // Include port-specific common-hal or shared-module implementation based on build config. -// When CIRCUITPY_SDCARDIO_USE_NATIVE is set, the port provides a common-hal implementation. -#ifdef CIRCUITPY_SDCARDIO_USE_NATIVE +// When CIRCUITPY_SDCARDIO_ESPRESSIF is set, the port provides a common-hal implementation. +#ifdef CIRCUITPY_SDCARDIO_ESPRESSIF #include "common-hal/sdcardio/SDCard.h" #else #include "shared-module/sdcardio/SDCard.h" From 0aba2d285386987af75bd85e1c7dba242d0cd4f5 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 31 Jan 2026 18:49:46 +0100 Subject: [PATCH 08/38] ESP_JPEG location --- ports/espressif/Makefile | 6 +++++- ports/espressif/common-hal/rm690b0/RM690B0.c | 2 +- .../espressif/common-hal/rm690b0/esp_jpeg}/esp_jpeg.c | 2 +- .../espressif/common-hal/rm690b0}/esp_jpeg/esp_jpeg.h | 0 4 files changed, 7 insertions(+), 3 deletions(-) rename {lib/esp_jpeg/src => ports/espressif/common-hal/rm690b0/esp_jpeg}/esp_jpeg.c (99%) rename {lib/esp_jpeg/include => ports/espressif/common-hal/rm690b0}/esp_jpeg/esp_jpeg.h (100%) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index c085c596c7bf3..d42c6cf22fcfa 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -518,8 +518,12 @@ endif ifneq ($(CIRCUITPY_RM690B0),0) SRC_RM690B0 := \ - $(wildcard common-hal/rm690b0/*.c) + $(wildcard common-hal/rm690b0/*.c) \ + $(wildcard common-hal/rm690b0/esp_jpeg/*.c) SRC_C += $(SRC_RM690B0) +INC += -Icommon-hal/rm690b0/esp_jpeg +# TJpgDec is needed for the esp_jpeg shim +INC += -I../../lib/tjpgd endif ifneq ($(CIRCUITPY_NEOPIXEL_WRITE),0) diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.c b/ports/espressif/common-hal/rm690b0/RM690B0.c index 0ab3d5bcf77d2..2df4a6248af01 100644 --- a/ports/espressif/common-hal/rm690b0/RM690B0.c +++ b/ports/espressif/common-hal/rm690b0/RM690B0.c @@ -29,7 +29,7 @@ static const char *TAG = "rm690b0"; #include #include #include "esp_attr.h" -#include "esp_jpeg/esp_jpeg.h" +#include "esp_jpeg.h" #include "fonts/rm690b0_font_8x8.h" #include "fonts/rm690b0_font_16x16.h" #include "fonts/rm690b0_font_16x24.h" diff --git a/lib/esp_jpeg/src/esp_jpeg.c b/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c similarity index 99% rename from lib/esp_jpeg/src/esp_jpeg.c rename to ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c index fe41599403206..7d48113dc8381 100644 --- a/lib/esp_jpeg/src/esp_jpeg.c +++ b/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c @@ -4,7 +4,7 @@ // // Minimal esp_jpeg implementation backed by TJpgDec. -#include "esp_jpeg/esp_jpeg.h" +#include "esp_jpeg.h" #include #include diff --git a/lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h b/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.h similarity index 100% rename from lib/esp_jpeg/include/esp_jpeg/esp_jpeg.h rename to ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.h From 83b925cda9cd3487d8507549edc63b602803247b Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 1 Feb 2026 18:03:22 +0100 Subject: [PATCH 09/38] Get rid of image_converter --- ports/espressif/common-hal/rm690b0/RM690B0.c | 115 +++- ports/espressif/common-hal/rm690b0/RM690B0.h | 2 +- py/circuitpy_defns.mk | 4 +- shared-bindings/rm690b0/RM690B0.c | 48 +- shared-bindings/rm690b0/RM690B0.h | 3 +- shared-bindings/rm690b0/__init__.c | 148 +---- shared-bindings/rm690b0/image_converter.c | 586 ------------------- shared-bindings/rm690b0/image_converter.h | 187 ------ 8 files changed, 155 insertions(+), 938 deletions(-) delete mode 100644 shared-bindings/rm690b0/image_converter.c delete mode 100644 shared-bindings/rm690b0/image_converter.h diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.c b/ports/espressif/common-hal/rm690b0/RM690B0.c index 2df4a6248af01..76415f34945ba 100644 --- a/ports/espressif/common-hal/rm690b0/RM690B0.c +++ b/ports/espressif/common-hal/rm690b0/RM690B0.c @@ -2894,6 +2894,21 @@ void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, m common_hal_rm690b0_rm690b0_fill_rect(self, x, y, 1, height, color); } +//| def blit_buffer(self, x: int, y: int, width: int, height: int, bitmap_data: bytearray, *, dest_is_swapped: bool = False) -> None: +//| """Draw a bitmap +//| +//| :param int x: X coordinate of the top-left corner +//| :param int y: Y coordinate of the top-left corner +//| :param int width: Width of the bitmap +//| :param int height: Height of the bitmap +//| :param bytearray bitmap_data: Bitmap data (buffer protocol) +//| :param bool dest_is_swapped: If True, data is assumed to be in destination byte order (Big Endian) and will not be swapped. +//| Useful for JpegDecoder output which is already swapped. Default is False (Little Endian input). +//| """ +//| ... +//| + + void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color) { common_hal_rm690b0_rm690b0_hline(self, x, y, width, color); common_hal_rm690b0_rm690b0_hline(self, x, y + height - 1, width, color); @@ -3434,7 +3449,7 @@ mp_float_t common_hal_rm690b0_rm690b0_get_brightness(const rm690b0_rm690b0_obj_t return (mp_float_t)raw / 255.0f; } -void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data) { +void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data, bool dest_is_swapped) { CHECK_INITIALIZED(); if (width <= 0 || height <= 0) { @@ -3503,13 +3518,22 @@ void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_ uint16_t *framebuffer = impl->framebuffer; size_t fb_stride = RM690B0_PANEL_WIDTH; + // If source is already swapped (BE) and we need BE for display, we skip the swap. + // If source is normal (LE) and we need BE (display), we swap. + // Standard blit_buffer assumes LE input and swaps to BE. + // IF dest_is_swapped is TRUE, it means the SOURCE is already in destination format (BE). + switch (self->rotation) { case 0: for (mp_int_t row = 0; row < logical_h; row++) { const uint16_t *src_row = src_pixels + (size_t)row * src_stride; uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; - for (mp_int_t col = 0; col < logical_w; col++) { - dst_row[col] = RGB565_SWAP_GB(src_row[col]); + if (dest_is_swapped) { + memcpy(dst_row, src_row, logical_w * sizeof(uint16_t)); + } else { + for (mp_int_t col = 0; col < logical_w; col++) { + dst_row[col] = RGB565_SWAP_GB(src_row[col]); + } } } break; @@ -3518,7 +3542,8 @@ void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_ const uint16_t *src_row = src_pixels + (size_t)(logical_h - 1 - row) * src_stride; uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; for (mp_int_t col = 0; col < logical_w; col++) { - dst_row[col] = RGB565_SWAP_GB(src_row[logical_w - 1 - col]); + uint16_t val = src_row[logical_w - 1 - col]; + dst_row[col] = dest_is_swapped ? val : RGB565_SWAP_GB(val); } } break; @@ -3531,7 +3556,8 @@ void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_ mp_int_t src_row_idx = logical_h - 1 - col; mp_int_t src_col_idx = row; const uint16_t *src_row = src_pixels + (size_t)src_row_idx * src_stride; - dst_row[col] = RGB565_SWAP_GB(src_row[src_col_idx]); + uint16_t val = src_row[src_col_idx]; + dst_row[col] = dest_is_swapped ? val : RGB565_SWAP_GB(val); } } break; @@ -3545,7 +3571,8 @@ void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_ mp_int_t src_row_idx = col; mp_int_t src_col_idx = logical_w - 1 - row; const uint16_t *src_row = src_pixels + (size_t)src_row_idx * src_stride; - dst_row[col] = RGB565_SWAP_GB(src_row[src_col_idx]); + uint16_t val = src_row[src_col_idx]; + dst_row[col] = dest_is_swapped ? val : RGB565_SWAP_GB(val); } } break; @@ -3657,3 +3684,79 @@ void common_hal_rm690b0_rm690b0_swap_buffers(rm690b0_rm690b0_obj_t *self, bool c esp_err_to_name(ret), ret); } } + +void common_hal_rm690b0_rm690b0_convert_bmp(rm690b0_rm690b0_obj_t *self, mp_obj_t src_data, mp_obj_t dest_bitmap) { + mp_buffer_info_t src_info; + mp_get_buffer_raise(src_data, &src_info, MP_BUFFER_READ); + + mp_buffer_info_t dest_info; + mp_get_buffer_raise(dest_bitmap, &dest_info, MP_BUFFER_WRITE); + + if (src_info.len < sizeof(bmp_header_t)) { + mp_raise_ValueError(MP_ERROR_TEXT("BMP data too small")); + return; + } + + const bmp_header_t *header = (const bmp_header_t *)src_info.buf; + + if (header->type != 0x4D42) { // 'BM' + mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP header")); + return; + } + + if (header->bpp != 24 && header->bpp != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("Only 16-bit and 24-bit BMP supported")); + return; + } + + if (header->compression != 0 && header->compression != 3) { + mp_raise_ValueError(MP_ERROR_TEXT("Compressed BMP not supported")); + return; + } + + mp_int_t width = header->width; + mp_int_t height = abs(header->height); + bool top_down = (header->height < 0); + size_t data_offset = header->offset; + + if (data_offset >= src_info.len) { + mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP data offset")); + return; + } + + // Check destination size implicitly by buffer length + // We assume the user created the bitmap correctly. We will not overflow the buffer. + size_t max_dest_pixels = dest_info.len / sizeof(uint16_t); + if ((size_t)(width * height) > max_dest_pixels) { + mp_raise_ValueError(MP_ERROR_TEXT("Destination bitmap too small")); + return; + } + + // Pointers + uint16_t *dest_buf = (uint16_t *)dest_info.buf; + const uint8_t *src_pixels = (const uint8_t *)src_info.buf + data_offset; + + int row_padding = (4 - ((width * (header->bpp / 8)) % 4)) % 4; + int src_stride = width * (header->bpp / 8) + row_padding; + + for (int row = 0; row < height; row++) { + int src_row_idx = top_down ? row : (height - 1 - row); + const uint8_t *row_ptr = src_pixels + (size_t)src_row_idx * src_stride; + uint16_t *dst_row_ptr = dest_buf + (size_t)row * width; // Dense packing in Bitmap + + if (header->bpp == 24) { + for (int col = 0; col < width; col++) { + uint8_t b = row_ptr[col * 3]; + uint8_t g = row_ptr[col * 3 + 1]; + uint8_t r = row_ptr[col * 3 + 2]; + uint16_t rgb = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); + dst_row_ptr[col] = RGB565_SWAP_GB(rgb); + } + } else { + for (int col = 0; col < width; col++) { + uint16_t val = row_ptr[col * 2] | (row_ptr[col * 2 + 1] << 8); + dst_row_ptr[col] = RGB565_SWAP_GB(val); + } + } + } +} diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.h b/ports/espressif/common-hal/rm690b0/RM690B0.h index f0b14305f6eac..771c8364a8571 100644 --- a/ports/espressif/common-hal/rm690b0/RM690B0.h +++ b/ports/espressif/common-hal/rm690b0/RM690B0.h @@ -17,7 +17,7 @@ void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees); void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t value); -void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data); +void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data, bool dest_is_swapped); void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data); void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data); void common_hal_rm690b0_rm690b0_deinit_all(void); diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index af21b7dac1b70..e1afb3ebb4413 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -632,7 +632,6 @@ $(filter $(SRC_PATTERNS), \ wifi/Packet.c \ wifi/PowerManagement.c \ rm690b0/__init__.c \ - rm690b0/image_converter.c \ ) ifeq ($(CIRCUITPY_BLEIO_HCI),1) @@ -915,8 +914,7 @@ endif ifneq ($(filter 1,$(CIRCUITPY_JPEGIO) $(CIRCUITPY_RM690B0)),) SRC_MOD += lib/tjpgd/src/tjpgd.c $(BUILD)/lib/tjpgd/src/tjpgd.o: CFLAGS += -Wno-shadow -Wno-cast-align -SRC_MOD += lib/esp_jpeg/src/esp_jpeg.c -CFLAGS_MOD += -I$(TOP)/lib/tjpgd/src -I$(TOP)/lib/esp_jpeg/include +CFLAGS_MOD += -I$(TOP)/lib/tjpgd/src endif ifeq ($(CIRCUITPY_HASHLIB_MBEDTLS_ONLY),1) diff --git a/shared-bindings/rm690b0/RM690B0.c b/shared-bindings/rm690b0/RM690B0.c index ccd94b28da374..33e2950a4f115 100644 --- a/shared-bindings/rm690b0/RM690B0.c +++ b/shared-bindings/rm690b0/RM690B0.c @@ -332,17 +332,48 @@ static mp_obj_t rm690b0_rm690b0_blit_jpeg(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_jpeg_obj, 4, 4, rm690b0_rm690b0_blit_jpeg); -static mp_obj_t rm690b0_rm690b0_blit_buffer(size_t n_args, const mp_obj_t *args) { +//| def convert_bmp(self, src_data: readablebuffer, dest_bitmap: displayio.Bitmap) -> None: +//| """Convert a BMP file (internal buffer) to a displayio.Bitmap in RGB565 format (RGB/BGR swapped for display). +//| +//| :param readablebuffer src_data: The full BMP file data +//| :param displayio.Bitmap dest_bitmap: The destination bitmap (must be correct size)""" +//| ... +static mp_obj_t rm690b0_rm690b0_convert_bmp(size_t n_args, const mp_obj_t *args) { rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t width = mp_obj_get_int(args[3]); - mp_int_t height = mp_obj_get_int(args[4]); - mp_obj_t bitmap_data = args[5]; - common_hal_rm690b0_rm690b0_blit_buffer(self, x, y, width, height, bitmap_data); + mp_obj_t src_data = args[1]; + mp_obj_t dest_bitmap = args[2]; + common_hal_rm690b0_rm690b0_convert_bmp(self, src_data, dest_bitmap); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_convert_bmp_obj, 3, 3, rm690b0_rm690b0_convert_bmp); + + +static mp_obj_t rm690b0_rm690b0_blit_buffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_width, ARG_height, ARG_bitmap_data, ARG_dest_is_swapped }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_bitmap_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_dest_is_swapped, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + common_hal_rm690b0_rm690b0_blit_buffer(self, + args[ARG_x].u_int, + args[ARG_y].u_int, + args[ARG_width].u_int, + args[ARG_height].u_int, + args[ARG_bitmap_data].u_obj, + args[ARG_dest_is_swapped].u_bool + ); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_buffer_obj, 6, 6, rm690b0_rm690b0_blit_buffer); +MP_DEFINE_CONST_FUN_OBJ_KW(rm690b0_rm690b0_blit_buffer_obj, 1, rm690b0_rm690b0_blit_buffer); //| def swap_buffers(self, copy: bool = True) -> None: //| """Swap the front and back framebuffers and display the result @@ -465,6 +496,7 @@ static const mp_rom_map_elem_t rm690b0_rm690b0_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_blit_buffer), MP_ROM_PTR(&rm690b0_rm690b0_blit_buffer_obj) }, { MP_ROM_QSTR(MP_QSTR_blit_bmp), MP_ROM_PTR(&rm690b0_rm690b0_blit_bmp_obj) }, { MP_ROM_QSTR(MP_QSTR_blit_jpeg), MP_ROM_PTR(&rm690b0_rm690b0_blit_jpeg_obj) }, + { MP_ROM_QSTR(MP_QSTR_convert_bmp), MP_ROM_PTR(&rm690b0_rm690b0_convert_bmp_obj) }, { MP_ROM_QSTR(MP_QSTR_swap_buffers), MP_ROM_PTR(&rm690b0_rm690b0_swap_buffers_obj) }, { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&rm690b0_rm690b0_width_obj) }, diff --git a/shared-bindings/rm690b0/RM690B0.h b/shared-bindings/rm690b0/RM690B0.h index ec65b008a2d2b..6af661b085fae 100644 --- a/shared-bindings/rm690b0/RM690B0.h +++ b/shared-bindings/rm690b0/RM690B0.h @@ -39,9 +39,10 @@ void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees); mp_int_t common_hal_rm690b0_rm690b0_get_rotation(const rm690b0_rm690b0_obj_t *self); -void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data); +void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data, bool dest_is_swapped); void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data); void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data); +void common_hal_rm690b0_rm690b0_convert_bmp(rm690b0_rm690b0_obj_t *self, mp_obj_t src_data, mp_obj_t dest_bitmap); void common_hal_rm690b0_rm690b0_swap_buffers(rm690b0_rm690b0_obj_t *self, bool copy); void common_hal_rm690b0_rm690b0_deinit_all(void); void common_hal_rm690b0_rm690b0_set_font(rm690b0_rm690b0_obj_t *self, mp_int_t font_id); diff --git a/shared-bindings/rm690b0/__init__.c b/shared-bindings/rm690b0/__init__.c index 0a6674d97f26b..0fa627804b848 100644 --- a/shared-bindings/rm690b0/__init__.c +++ b/shared-bindings/rm690b0/__init__.c @@ -6,12 +6,10 @@ #include "py/runtime.h" #include "shared-bindings/rm690b0/RM690B0.h" -#include "image_converter.h" -//| """RM690B0 AMOLED display driver with image conversion support +//| """RM690B0 AMOLED display driver //| -//| This module provides direct control of the RM690B0 AMOLED display controller -//| along with hardware-accelerated image format conversion (RAW, BMP, JPEG). +//| This module provides direct control of the RM690B0 AMOLED display controller. //| //| **Font Constants** //| @@ -44,152 +42,10 @@ //| """ //| -//| def jpg_to_rgb565(jpg_data: bytes) -> tuple[bytearray, dict]: -//| """Convert JPEG image data to RGB565 format -//| -//| :param bytes jpg_data: JPEG file data including headers -//| :return: Tuple of (rgb565_buffer, info_dict) -//| :rtype: tuple[bytearray, dict] -//| -//| The info_dict contains: width, height, data_size, bit_depth, channels, has_alpha -//| -//| Example:: -//| -//| import rm690b0 -//| with open("/image.jpg", "rb") as f: -//| jpg_data = f.read() -//| rgb565_buffer, info = rm690b0.jpg_to_rgb565(jpg_data) -//| print(f"Image: {info['width']}x{info['height']}") -//| """ -//| ... -//| -//| def bmp_to_rgb565(bmp_data: bytes) -> tuple[bytearray, dict]: -//| """Convert BMP image data to RGB565 format -//| -//| :param bytes bmp_data: BMP file data including headers -//| :return: Tuple of (rgb565_buffer, info_dict) -//| :rtype: tuple[bytearray, dict] -//| -//| The info_dict contains: width, height, data_size, bit_depth, channels, has_alpha -//| -//| Example:: -//| -//| import rm690b0 -//| with open("/image.bmp", "rb") as f: -//| bmp_data = f.read() -//| rgb565_buffer, info = rm690b0.bmp_to_rgb565(bmp_data) -//| print(f"Image: {info['width']}x{info['height']}") -//| """ -//| ... -//| -static mp_obj_t rm690b0_bmp_to_rgb565(mp_obj_t bmp_data_obj) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(bmp_data_obj, &bufinfo, MP_BUFFER_READ); - - // Parse header to get dimensions - img_info_t info; - img_error_t err = img_bmp_parse_header(bufinfo.buf, bufinfo.len, &info); - if (err != IMG_OK) { - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("Invalid BMP format (%s)"), img_error_string(err)); - } - - // Allocate output buffer - size_t buffer_size = info.width * info.height * 2; - vstr_t vstr; - vstr_init_len(&vstr, buffer_size); - - // Convert - store error string before cleanup to preserve error context - err = img_bmp_to_rgb565(bufinfo.buf, bufinfo.len, - (uint8_t *)vstr.buf, buffer_size, &info); - if (err != IMG_OK) { - const char *error_text = img_error_string(err); - vstr_clear(&vstr); - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("BMP conversion failed (%s)"), error_text); - } - - // Create info dict - mp_obj_t info_dict = mp_obj_new_dict(6); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_width), MP_OBJ_NEW_SMALL_INT(info.width)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_height), MP_OBJ_NEW_SMALL_INT(info.height)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_data_size), MP_OBJ_NEW_SMALL_INT(info.data_size)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_bit_depth), MP_OBJ_NEW_SMALL_INT(info.bit_depth)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_channels), MP_OBJ_NEW_SMALL_INT(info.channels)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_has_alpha), mp_obj_new_bool(info.has_alpha)); - - // Return tuple of (buffer, info) - mp_obj_t buffer_obj = mp_obj_new_bytes_from_vstr(&vstr); - mp_obj_t tuple[2] = {buffer_obj, info_dict}; - return mp_obj_new_tuple(2, tuple); -} -static MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_bmp_to_rgb565_obj, rm690b0_bmp_to_rgb565); - -static mp_obj_t rm690b0_jpg_to_rgb565(mp_obj_t jpg_data_obj) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(jpg_data_obj, &bufinfo, MP_BUFFER_READ); - - // Parse header to get dimensions - img_info_t info; - img_error_t err = img_jpg_parse_header(bufinfo.buf, bufinfo.len, &info); - if (err != IMG_OK) { - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("Invalid JPEG format (%s)"), img_error_string(err)); - } - - // Allocate output buffer - size_t buffer_size = info.width * info.height * 2; - vstr_t vstr; - vstr_init_len(&vstr, buffer_size); - - // Convert - err = img_jpg_to_rgb565(bufinfo.buf, bufinfo.len, - (uint8_t *)vstr.buf, buffer_size, &info); - - // Handle errors with centralized cleanup - if (err != IMG_OK) { - // Capture error info before cleanup - const char *error_text = img_error_string(err); - bool is_unsupported = (err == IMG_ERR_UNSUPPORTED); - - // Cleanup - vstr_clear(&vstr); - - // Raise appropriate exception - if (is_unsupported) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("JPEG support not compiled in")); - } else { - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("JPEG conversion failed (%s)"), error_text); - } - } - - // Create info dict - mp_obj_t info_dict = mp_obj_new_dict(6); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_width), MP_OBJ_NEW_SMALL_INT(info.width)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_height), MP_OBJ_NEW_SMALL_INT(info.height)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_data_size), MP_OBJ_NEW_SMALL_INT(info.data_size)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_bit_depth), MP_OBJ_NEW_SMALL_INT(info.bit_depth)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_channels), MP_OBJ_NEW_SMALL_INT(info.channels)); - mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_has_alpha), mp_obj_new_bool(info.has_alpha)); - - // Return tuple of (buffer, info) - mp_obj_t buffer_obj = mp_obj_new_bytes_from_vstr(&vstr); - mp_obj_t tuple[2] = {buffer_obj, info_dict}; - return mp_obj_new_tuple(2, tuple); -} -static MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_jpg_to_rgb565_obj, rm690b0_jpg_to_rgb565); - - - static const mp_rom_map_elem_t rm690b0_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rm690b0) }, { MP_ROM_QSTR(MP_QSTR_RM690B0), MP_ROM_PTR(&rm690b0_rm690b0_type) }, - // Image conversion functions - { MP_ROM_QSTR(MP_QSTR_bmp_to_rgb565), MP_ROM_PTR(&rm690b0_bmp_to_rgb565_obj) }, - { MP_ROM_QSTR(MP_QSTR_jpg_to_rgb565), MP_ROM_PTR(&rm690b0_jpg_to_rgb565_obj) }, - // RGB565 convenience constants { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(0xFFFF) }, { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(0x0000) }, diff --git a/shared-bindings/rm690b0/image_converter.c b/shared-bindings/rm690b0/image_converter.c deleted file mode 100644 index fb961b24a57ba..0000000000000 --- a/shared-bindings/rm690b0/image_converter.c +++ /dev/null @@ -1,586 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include "image_converter.h" -#include -#include -#include - -#ifdef CIRCUITPY -#include "py/misc.h" -#include "py/runtime.h" -#endif - -#if defined(ESP_PLATFORM) -#include "esp_heap_caps.h" -#include "esp_err.h" -#if __has_include("esp_jpeg/esp_jpeg.h") -#include "esp_jpeg/esp_jpeg.h" -#define USE_ESP_JPEG 1 -#else -#define USE_ESP_JPEG 0 -#endif -#else -#define USE_ESP_JPEG 0 -#endif - -// ============================================================================= -// Platform-Specific Memory Allocation -// ============================================================================= -// -// IMAGE_MALLOC/IMAGE_FREE provide platform-appropriate memory allocation for -// temporary buffers used during image decoding. Behavior varies by platform: -// -// ESP_PLATFORM (ESP32, ESP32-S3, etc.): -// - Priority: SPIRAM (PSRAM) first, then internal RAM -// - Rationale: Image buffers can be large; SPIRAM preserves precious internal RAM -// - Failure: Returns NULL if both allocations fail -// -// CIRCUITPY (CircuitPython runtime): -// - Uses m_malloc_maybe() which is GC-aware and returns NULL on failure -// - Memory is tracked by the garbage collector -// - Failure: Returns NULL (does not raise exception) -// -// Other platforms (desktop, testing): -// - Uses standard malloc()/free() -// - Failure: Returns NULL per C standard -// -// All platforms: Caller MUST check for NULL return and handle gracefully. -// ============================================================================= - -#if !USE_ESP_JPEG -#if defined(ESP_PLATFORM) -static void *image_malloc(size_t size) { - // Try SPIRAM first (larger, slower), fall back to internal RAM (faster, limited) - void *ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!ptr) { - ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - } - return ptr; -} -static void image_free(void *ptr) { - if (ptr) { - heap_caps_free(ptr); - } -} -#define IMAGE_MALLOC(size) image_malloc(size) -#define IMAGE_FREE(ptr) image_free(ptr) -#elif defined(CIRCUITPY) -#define IMAGE_MALLOC(size) m_malloc_maybe(size) -#define IMAGE_FREE(ptr) m_free(ptr) -#else -#define IMAGE_MALLOC(size) malloc(size) -#define IMAGE_FREE(ptr) free(ptr) -#endif -#endif - - -#if !USE_ESP_JPEG -#include "tjpgd.h" -#endif - -// ============================================================================= -// Utility Functions -// ============================================================================= - -const char *img_error_string(img_error_t error) { - switch (error) { - case IMG_OK: - return "Success"; - case IMG_ERR_NULL_POINTER: - return "NULL pointer"; - case IMG_ERR_INVALID_SIZE: - return "Invalid size"; - case IMG_ERR_BUFFER_TOO_SMALL: - return "Buffer too small"; - case IMG_ERR_INVALID_FORMAT: - return "Malformed data"; - case IMG_ERR_CORRUPTED_DATA: - return "Corrupted data"; - case IMG_ERR_UNSUPPORTED: - return "Unsupported format"; - case IMG_ERR_OUT_OF_MEMORY: - return "Out of memory"; - case IMG_ERR_IO_ERROR: - return "I/O error"; - default: - return "Unknown error"; - } -} - -// Read 16-bit little-endian value -static inline uint16_t read_le16(const uint8_t *data) { - return (uint16_t)data[0] | ((uint16_t)data[1] << 8); -} - -// Read 32-bit little-endian value -static inline uint32_t read_le32(const uint8_t *data) { - return (uint32_t)data[0] | ((uint32_t)data[1] << 8) | - ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24); -} - -// Read 32-bit signed little-endian value -static inline int32_t read_le32_signed(const uint8_t *data) { - return (int32_t)read_le32(data); -} - - - -// ============================================================================= -// BMP Format Converter -// ============================================================================= - -img_error_t img_bmp_parse_header( - const uint8_t *bmp_data, - size_t bmp_size, - img_info_t *info - ) { - if (bmp_data == NULL || info == NULL) { - return IMG_ERR_NULL_POINTER; - } - - // Check minimum size for headers (14 byte file header + 40 byte info header) - if (bmp_size < 54) { - return IMG_ERR_INVALID_FORMAT; - } - - // Check BMP signature ('BM') - if (bmp_data[0] != 'B' || bmp_data[1] != 'M') { - return IMG_ERR_INVALID_FORMAT; - } - - // Parse info header size - uint32_t header_size = read_le32(bmp_data + 14); - if (header_size < 40) { - return IMG_ERR_INVALID_FORMAT; - } - - // Parse dimensions - int32_t width = read_le32_signed(bmp_data + 18); - int32_t height = read_le32_signed(bmp_data + 22); - - // Validate dimensions - if (width <= 0 || height == 0) { - return IMG_ERR_INVALID_SIZE; - } - - // Parse format information - uint16_t planes = read_le16(bmp_data + 26); - uint16_t bit_count = read_le16(bmp_data + 28); - uint32_t compression = read_le32(bmp_data + 30); - - // Validate format - if (planes != 1) { - return IMG_ERR_INVALID_FORMAT; - } - - // Check for supported bit depths - if (bit_count != 16 && bit_count != 24 && bit_count != 32) { - return IMG_ERR_UNSUPPORTED; - } - - // Check compression (0 = BI_RGB uncompressed, 3 = BI_BITFIELDS) - if (compression != 0 && compression != 3) { - return IMG_ERR_UNSUPPORTED; - } - - // Fill info structure - info->width = (uint32_t)width; - info->height = (uint32_t)(height > 0 ? height : -height); - info->data_size = img_rgb565_buffer_size(info->width, info->height); - if (info->data_size == SIZE_MAX) { - return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation - } - info->bit_depth = bit_count; - info->channels = (bit_count == 32) ? 4 : 3; - info->has_alpha = (bit_count == 32); - - return IMG_OK; -} - -img_error_t img_bmp_to_rgb565( - const uint8_t *bmp_data, - size_t bmp_size, - uint8_t *rgb565_buffer, - size_t buffer_size, - img_info_t *info - ) { - if (bmp_data == NULL || rgb565_buffer == NULL) { - return IMG_ERR_NULL_POINTER; - } - - // Parse header - img_info_t local_info; - img_error_t err = img_bmp_parse_header(bmp_data, bmp_size, &local_info); - if (err != IMG_OK) { - return err; - } - - // Check buffer size - if (buffer_size < local_info.data_size) { - return IMG_ERR_BUFFER_TOO_SMALL; - } - - // Get parameters - uint32_t width = local_info.width; - uint32_t height = local_info.height; - uint32_t data_offset = read_le32(bmp_data + 10); - int32_t height_signed = read_le32_signed(bmp_data + 22); - uint16_t bit_count = read_le16(bmp_data + 28); - - // Check if we have enough data - if (data_offset >= bmp_size) { - return IMG_ERR_CORRUPTED_DATA; - } - - // Determine if image is bottom-up (positive height) or top-down (negative height) - bool bottom_up = (height_signed > 0); - - // Calculate bytes per pixel and row stride with overflow checking - uint32_t bytes_per_pixel = bit_count / 8; - - // Check for overflow in width * bytes_per_pixel - if (bytes_per_pixel != 0 && width > (UINT32_MAX - 3) / bytes_per_pixel) { - return IMG_ERR_INVALID_SIZE; - } - - uint32_t row_stride = ((width * bytes_per_pixel + 3) & ~3); // Rows padded to 4-byte boundary - - // Check for overflow in row_stride * height - if (height != 0 && row_stride > UINT32_MAX / height) { - return IMG_ERR_INVALID_SIZE; - } - uint32_t total_data_size = row_stride * height; - - // Check for overflow in data_offset + total_data_size - if (data_offset > UINT32_MAX - total_data_size) { - return IMG_ERR_INVALID_SIZE; - } - - // Verify we have enough data - if (data_offset + total_data_size > bmp_size) { - return IMG_ERR_CORRUPTED_DATA; - } - - // Convert pixel data - const uint8_t *src_base = bmp_data + data_offset; - uint8_t *dst = rgb565_buffer; - - for (uint32_t y = 0; y < height; y++) { - // Calculate source row based on orientation - uint32_t src_row = bottom_up ? (height - 1 - y) : y; - const uint8_t *src = src_base + src_row * row_stride; - - for (uint32_t x = 0; x < width; x++) { - uint8_t r, g, b; - - if (bit_count == 24) { - // 24-bit BGR format - b = src[0]; - g = src[1]; - r = src[2]; - src += 3; - } else if (bit_count == 32) { - // 32-bit BGRA format - b = src[0]; - g = src[1]; - r = src[2]; - // src[3] is alpha (ignored for now) - src += 4; - } else if (bit_count == 16) { - // 16-bit format (assume RGB565) - uint16_t pixel = read_le16(src); - r = RGB565_TO_R(pixel); - g = RGB565_TO_G(pixel); - b = RGB565_TO_B(pixel); - src += 2; - } else { - // Should not reach here due to earlier validation - return IMG_ERR_UNSUPPORTED; - } - - // Convert to RGB565 and store (byte-by-byte to avoid alignment issues) - uint16_t rgb565 = RGB888_TO_RGB565(r, g, b); - dst[0] = rgb565 & 0xFF; // Low byte - dst[1] = (rgb565 >> 8) & 0xFF; // High byte - dst += 2; - } - } - - // Copy info if requested - if (info != NULL) { - *info = local_info; - } - - return IMG_OK; -} - -// ============================================================================= -// JPEG Format Converter -// ============================================================================= - -#if USE_ESP_JPEG - -img_error_t img_jpg_parse_header( - const uint8_t *jpg_data, - size_t jpg_size, - img_info_t *info - ) { - if (jpg_data == NULL || info == NULL) { - return IMG_ERR_NULL_POINTER; - } - - esp_jpeg_image_cfg_t cfg = { - .indata = jpg_data, - .indata_size = jpg_size, - .outbuf = NULL, - .outbuf_size = 0, - .out_format = JPEG_IMAGE_FORMAT_RGB565, - .out_scale = JPEG_IMAGE_SCALE_0, - .flags = { - .swap_color_bytes = false, - .use_scaler = false, - }, - }; - - esp_jpeg_image_output_t out; - esp_err_t err = esp_jpeg_get_image_info(&cfg, &out); - if (err != ESP_OK) { - return IMG_ERR_INVALID_FORMAT; - } - - info->width = out.width; - info->height = out.height; - info->data_size = img_rgb565_buffer_size(out.width, out.height); - if (info->data_size == SIZE_MAX) { - return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation - } - info->bit_depth = 8; - info->channels = 3; - info->has_alpha = false; - - return IMG_OK; -} - -img_error_t img_jpg_to_rgb565( - const uint8_t *jpg_data, - size_t jpg_size, - uint8_t *rgb565_buffer, - size_t buffer_size, - img_info_t *info - ) { - if (jpg_data == NULL || rgb565_buffer == NULL) { - return IMG_ERR_NULL_POINTER; - } - - esp_jpeg_image_cfg_t cfg = { - .indata = jpg_data, - .indata_size = jpg_size, - .outbuf = rgb565_buffer, - .outbuf_size = buffer_size, - .out_format = JPEG_IMAGE_FORMAT_RGB565, - .out_scale = JPEG_IMAGE_SCALE_0, - .flags = { - .swap_color_bytes = false, - .use_scaler = false, - }, - }; - - esp_jpeg_image_output_t out_info; - esp_err_t err = esp_jpeg_decode(&cfg, &out_info); - if (err == ESP_ERR_NO_MEM) { - return IMG_ERR_BUFFER_TOO_SMALL; - } - if (err != ESP_OK) { - return IMG_ERR_CORRUPTED_DATA; - } - - if (info != NULL) { - info->width = out_info.width; - info->height = out_info.height; - info->data_size = out_info.outbuf_size; - info->bit_depth = 8; - info->channels = 3; - info->has_alpha = false; - } - - return IMG_OK; -} - -#else // USE_ESP_JPEG - -#define TJPGD_WORK_BUFFER_SIZE 4096 - -typedef struct { - uint8_t *rgb565_buffer; - uint32_t width; - const uint8_t *jpg_data; - size_t jpg_size; - size_t jpg_offset; -} tjpgd_context_t; - -static size_t tjpgd_input_func(JDEC *jd, uint8_t *buff, size_t ndata) { - tjpgd_context_t *ctx = (tjpgd_context_t *)jd->device; - - if (!buff) { - size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; - size_t bytes_to_skip = ndata; - if (bytes_to_skip > bytes_available) { - bytes_to_skip = bytes_available; - } - ctx->jpg_offset += bytes_to_skip; - return bytes_to_skip; - } - - size_t bytes_to_read = ndata; - size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; - if (bytes_to_read > bytes_available) { - bytes_to_read = bytes_available; - } - - if (bytes_to_read > 0) { - memcpy(buff, ctx->jpg_data + ctx->jpg_offset, bytes_to_read); - ctx->jpg_offset += bytes_to_read; - } - - return bytes_to_read; -} - -static int tjpgd_output_func(JDEC *jd, void *bitmap, JRECT *rect) { - tjpgd_context_t *ctx = (tjpgd_context_t *)jd->device; - uint8_t *src = (uint8_t *)bitmap; - - for (int y = rect->top; y <= rect->bottom; y++) { - uint32_t row_base = (uint32_t)y * ctx->width; - for (int x = rect->left; x <= rect->right; x++) { - uint16_t rgb565 = ((uint16_t)src[0] << 8) | src[1]; - src += 2; - uint32_t offset = (row_base + x) * 2; - ctx->rgb565_buffer[offset] = rgb565 & 0xFF; - ctx->rgb565_buffer[offset + 1] = (rgb565 >> 8) & 0xFF; - } - } - - return 1; -} - -img_error_t img_jpg_to_rgb565( - const uint8_t *jpg_data, - size_t jpg_size, - uint8_t *rgb565_buffer, - size_t buffer_size, - img_info_t *info - ) { - if (jpg_data == NULL || rgb565_buffer == NULL) { - return IMG_ERR_NULL_POINTER; - } - - void *work_buffer = IMAGE_MALLOC(TJPGD_WORK_BUFFER_SIZE); - if (work_buffer == NULL) { - return IMG_ERR_OUT_OF_MEMORY; - } - - JDEC jdec; - tjpgd_context_t ctx = { - .rgb565_buffer = NULL, - .width = 0, - .jpg_data = jpg_data, - .jpg_size = jpg_size, - .jpg_offset = 0, - }; - - JRESULT res = jd_prepare(&jdec, tjpgd_input_func, work_buffer, TJPGD_WORK_BUFFER_SIZE, (void *)&ctx); - if (res != JDR_OK) { - IMAGE_FREE(work_buffer); - return IMG_ERR_INVALID_FORMAT; - } - - if (jdec.width == 0 || jdec.height == 0) { - IMAGE_FREE(work_buffer); - return IMG_ERR_INVALID_SIZE; - } - - size_t required_size = img_rgb565_buffer_size(jdec.width, jdec.height); - if (required_size == SIZE_MAX) { - IMAGE_FREE(work_buffer); - return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation - } - if (buffer_size < required_size) { - IMAGE_FREE(work_buffer); - return IMG_ERR_BUFFER_TOO_SMALL; - } - - ctx.rgb565_buffer = rgb565_buffer; - ctx.width = jdec.width; - - res = jd_decomp(&jdec, tjpgd_output_func, 0); - - IMAGE_FREE(work_buffer); - - if (res != JDR_OK) { - return IMG_ERR_CORRUPTED_DATA; - } - - if (info != NULL) { - info->width = jdec.width; - info->height = jdec.height; - info->data_size = required_size; - info->bit_depth = 8; - info->channels = 3; - info->has_alpha = false; - } - - return IMG_OK; -} - -img_error_t img_jpg_parse_header( - const uint8_t *jpg_data, - size_t jpg_size, - img_info_t *info - ) { - if (jpg_data == NULL || info == NULL) { - return IMG_ERR_NULL_POINTER; - } - - void *work_buffer = IMAGE_MALLOC(TJPGD_WORK_BUFFER_SIZE); - if (work_buffer == NULL) { - return IMG_ERR_OUT_OF_MEMORY; - } - - JDEC jdec; - tjpgd_context_t ctx = { - .rgb565_buffer = NULL, - .width = 0, - .jpg_data = jpg_data, - .jpg_size = jpg_size, - .jpg_offset = 0, - }; - - JRESULT res = jd_prepare(&jdec, tjpgd_input_func, work_buffer, TJPGD_WORK_BUFFER_SIZE, (void *)&ctx); - if (res != JDR_OK) { - IMAGE_FREE(work_buffer); - return IMG_ERR_INVALID_FORMAT; - } - - if (jdec.width == 0 || jdec.height == 0) { - IMAGE_FREE(work_buffer); - return IMG_ERR_INVALID_SIZE; - } - - info->width = jdec.width; - info->height = jdec.height; - info->data_size = img_rgb565_buffer_size(jdec.width, jdec.height); - if (info->data_size == SIZE_MAX) { - IMAGE_FREE(work_buffer); - return IMG_ERR_INVALID_SIZE; // Overflow in buffer size calculation - } - info->bit_depth = 8; - info->channels = 3; - info->has_alpha = false; - - IMAGE_FREE(work_buffer); - return IMG_OK; -} - -#endif // USE_ESP_JPEG diff --git a/shared-bindings/rm690b0/image_converter.h b/shared-bindings/rm690b0/image_converter.h deleted file mode 100644 index 0a8c1d57c984d..0000000000000 --- a/shared-bindings/rm690b0/image_converter.h +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_RM690B0_IMAGE_CONVERTER_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_RM690B0_IMAGE_CONVERTER_H - -#include -#include -#include - -// ============================================================================= -// Error Codes -// ============================================================================= - -typedef enum { - IMG_OK = 0, // Success - IMG_ERR_NULL_POINTER = -1, // NULL pointer passed - IMG_ERR_INVALID_SIZE = -2, // Invalid image dimensions - IMG_ERR_BUFFER_TOO_SMALL = -3, // Output buffer too small - IMG_ERR_INVALID_FORMAT = -4, // Malformed data (bad signature, corrupted headers) - IMG_ERR_CORRUPTED_DATA = -5, // Corrupted image data (truncated, checksum mismatch) - IMG_ERR_UNSUPPORTED = -6, // Valid format but unsupported feature (bit depth, compression) - IMG_ERR_OUT_OF_MEMORY = -7, // Memory allocation failed - IMG_ERR_IO_ERROR = -8 // File I/O error -} img_error_t; - -// ============================================================================= -// Image Information Structure -// ============================================================================= - -typedef struct { - uint32_t width; // Image width in pixels - uint32_t height; // Image height in pixels - uint32_t data_size; // Size of RGB565 data in bytes - uint8_t bit_depth; // Original bit depth - uint8_t channels; // Number of color channels - bool has_alpha; // Whether image has alpha channel -} img_info_t; - -// ============================================================================= -// RGB Conversion Macros -// ============================================================================= - -// Convert 24-bit RGB888 to 16-bit RGB565 -// Format: RRRR RGGG GGGB BBBB (5 bits R, 6 bits G, 5 bits B) -// -// This is an intentional lossy conversion: -// - Red: 8 bits → 5 bits (loses 3 LSBs, 0xF8 mask keeps bits 7:3) -// - Green: 8 bits → 6 bits (loses 2 LSBs, 0xFC mask keeps bits 7:2) -// - Blue: 8 bits → 5 bits (loses 3 LSBs, right-shift discards bits 2:0) -// -// Color precision is reduced from 16.7M colors (24-bit) to 65K colors (16-bit). -#define RGB888_TO_RGB565(r, g, b) \ - ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3)) - -// Extract components from RGB565 back to 8-bit (with zero-filled LSBs) -// Note: Extracted values have lower bits set to 0, not interpolated -#define RGB565_TO_R(rgb565) (((rgb565) >> 8) & 0xF8) -#define RGB565_TO_G(rgb565) (((rgb565) >> 3) & 0xFC) -#define RGB565_TO_B(rgb565) (((rgb565) << 3) & 0xF8) - -// Note: RGB565 data is stored in little-endian byte order: -// byte[0] = low byte (GGGBBBBB) -// byte[1] = high byte (RRRRRGGG) -// This matches the byte order expected by most display controllers. - - - -// ============================================================================= -// BMP Format Converter -// ============================================================================= - -/** - * @brief Convert BMP image to RGB565 buffer - * - * Supports uncompressed BMP files with 16, 24, or 32 bits per pixel. - * Handles bottom-up and top-down orientations. - * - * @param bmp_data Pointer to BMP file data (including headers) - * @param bmp_size Size of BMP data in bytes - * @param rgb565_buffer Output buffer for RGB565 data - * @param buffer_size Size of output buffer in bytes - * @param info Optional pointer to receive image info (can be NULL) - * @return IMG_OK on success, error code otherwise - */ -img_error_t img_bmp_to_rgb565( - const uint8_t *bmp_data, - size_t bmp_size, - uint8_t *rgb565_buffer, - size_t buffer_size, - img_info_t *info - ); - -/** - * @brief Parse BMP header and extract image information - * - * @param bmp_data Pointer to BMP file data - * @param bmp_size Size of BMP data in bytes - * @param info Pointer to receive image info - * @return IMG_OK on success, error code otherwise - */ -img_error_t img_bmp_parse_header( - const uint8_t *bmp_data, - size_t bmp_size, - img_info_t *info - ); - -// ============================================================================= -// JPEG Format Converter -// ============================================================================= - -/** - * @brief Convert JPEG image to RGB565 buffer - * - * Uses the ESP-IDF `esp_jpeg` decoder on supported ESP32-class ports. Builds without the esp_jpeg headers will - * return IMG_ERR_UNSUPPORTED for JPEG requests. - * - * @param jpg_data Pointer to JPEG file data - * @param jpg_size Size of JPEG data in bytes - * @param rgb565_buffer Output buffer for RGB565 data - * @param buffer_size Size of output buffer in bytes - * @param info Optional pointer to receive image info (can be NULL) - * @return IMG_OK on success, IMG_ERR_UNSUPPORTED if not compiled with JPEG support - */ - -img_error_t img_jpg_to_rgb565( - const uint8_t *jpg_data, - size_t jpg_size, - uint8_t *rgb565_buffer, - size_t buffer_size, - img_info_t *info - ); - -/** - * @brief Parse JPEG header and extract image information - * - * @param jpg_data Pointer to JPEG file data - * @param jpg_size Size of JPEG data in bytes - * @param info Pointer to receive image info - * @return IMG_OK on success, error code otherwise - */ -img_error_t img_jpg_parse_header( - const uint8_t *jpg_data, - size_t jpg_size, - img_info_t *info - ); - -// ============================================================================= -// Utility Functions -// ============================================================================= - -/** - * @brief Calculate required buffer size for RGB565 data - * - * @param width Image width in pixels - * @param height Image height in pixels - * @return Required buffer size in bytes, or SIZE_MAX on overflow - * - * @note Caller should check if return value == SIZE_MAX to detect overflow. - * RGB565 uses 2 bytes per pixel, so buffer size = width * height * 2. - */ -static inline size_t img_rgb565_buffer_size(uint32_t width, uint32_t height) { - // Check for overflow: width * height must not exceed SIZE_MAX / 2 - // First check width * height overflow - if (width != 0 && height > SIZE_MAX / width) { - return SIZE_MAX; // Overflow in width * height - } - size_t pixel_count = (size_t)width * height; - - // Check for overflow when multiplying by 2 (bytes per pixel) - if (pixel_count > SIZE_MAX / 2) { - return SIZE_MAX; // Overflow in pixel_count * 2 - } - - return pixel_count * 2; -} - -/** - * @brief Get error message string - * - * @param error Error code - * @return Human-readable error message - */ -const char *img_error_string(img_error_t error); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_RM690B0_IMAGE_CONVERTER_H From 824ba5289337651c375cd31f4c2117dfdd8710d1 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 6 Feb 2026 14:09:13 +0100 Subject: [PATCH 10/38] Phase 1: migrate from custom sdcardio to sdioio --- .../mpconfigboard.mk | 8 +- ports/espressif/common-hal/sdcardio/SDCard.c | 341 ------------ ports/espressif/common-hal/sdcardio/SDCard.h | 35 -- .../espressif/common-hal/sdcardio/__init__.c | 125 ----- .../espressif/common-hal/sdcardio/__init__.h | 9 - shared-bindings/sdcardio/SDCard.c | 187 ------- shared-bindings/sdcardio/SDCard.h | 34 -- shared-bindings/sdcardio/__init__.c | 29 - shared-bindings/sdcardio/__init__.h | 7 - shared-module/sdcardio/SDCard.c | 522 ------------------ shared-module/sdcardio/SDCard.h | 28 - shared-module/sdcardio/__init__.c | 127 ----- shared-module/sdcardio/__init__.h | 10 - 13 files changed, 6 insertions(+), 1456 deletions(-) delete mode 100644 ports/espressif/common-hal/sdcardio/SDCard.c delete mode 100644 ports/espressif/common-hal/sdcardio/SDCard.h delete mode 100644 ports/espressif/common-hal/sdcardio/__init__.c delete mode 100644 ports/espressif/common-hal/sdcardio/__init__.h delete mode 100644 shared-bindings/sdcardio/SDCard.c delete mode 100644 shared-bindings/sdcardio/SDCard.h delete mode 100644 shared-bindings/sdcardio/__init__.c delete mode 100644 shared-bindings/sdcardio/__init__.h delete mode 100644 shared-module/sdcardio/SDCard.c delete mode 100644 shared-module/sdcardio/SDCard.h delete mode 100644 shared-module/sdcardio/__init__.c delete mode 100644 shared-module/sdcardio/__init__.h diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index 4851d3561a0d8..dc5c33b9c69a0 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -72,8 +72,12 @@ CIRCUITPY_USB_MIDI = 1 # Storage configuration CIRCUITPY_STORAGE = 1 CIRCUITPY_NVM = 1 -CIRCUITPY_SDCARDIO = 1 -CIRCUITPY_SDCARDIO_ESPRESSIF = 1 +# Use existing sdioio instead of custom sdcardio +# CIRCUITPY_SDCARDIO = 1 # REMOVED - using sdioio +# CIRCUITPY_SDCARDIO_ESPRESSIF = 1 # REMOVED +CIRCUITPY_SDCARDIO = 0 +CIRCUITPY_SDCARDIO_ESPRESSIF = 0 +CIRCUITPY_SDIOIO = 1 # Enable touch support CIRCUITPY_TOUCHIO = 0 diff --git a/ports/espressif/common-hal/sdcardio/SDCard.c b/ports/espressif/common-hal/sdcardio/SDCard.c deleted file mode 100644 index 1a4a8f09ae208..0000000000000 --- a/ports/espressif/common-hal/sdcardio/SDCard.c +++ /dev/null @@ -1,341 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -// ESP-specific sdcardio implementation using ESP-IDF's sdspi_host driver. -// This provides significantly better performance (~2x) compared to the generic -// shared-module implementation by using hardware-optimized SD protocol handling. -// -// The key design decision is to "borrow" the busio.SPI object passed in, -// extract its pins, deinitialize it, and then initialize sdspi_host with -// those same pins. This is necessary because ESP-IDF's SD host driver and -// CircuitPython's busio.SPI cannot share the same SPI peripheral. - -#include "common-hal/sdcardio/SDCard.h" -#include "shared-bindings/sdcardio/SDCard.h" -#include "shared-bindings/busio/SPI.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/util.h" -#include "common-hal/busio/SPI.h" - -#include "py/runtime.h" -#include "py/mperrno.h" -#include "extmod/vfs.h" - -#include "sdmmc_cmd.h" -#include "sd_protocol_defs.h" -#include "driver/sdmmc_host.h" -#include "driver/sdspi_host.h" -#include "esp_log.h" - -#include - -static const char *TAG = "sdcardio"; - -// Singleton tracker for cleanup during reset -static sdcardio_sdcard_obj_t *sdcardio_singleton = NULL; - -// Forward declarations -static void check_for_deinit(sdcardio_sdcard_obj_t *self); - -void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, - busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { - - // Extract pin information from busio.SPI before we deinitialize it - if (common_hal_busio_spi_deinited(bus)) { - mp_raise_ValueError(MP_ERROR_TEXT("SPI bus already deinitialized")); - } - - // Get pin numbers from the busio.SPI object - const mcu_pin_obj_t *mosi_pin = bus->MOSI; - const mcu_pin_obj_t *miso_pin = bus->MISO; - const mcu_pin_obj_t *clk_pin = bus->clock; - spi_host_device_t spi_host = bus->host_id; - - if (mosi_pin == NULL || miso_pin == NULL || clk_pin == NULL) { - mp_raise_ValueError(MP_ERROR_TEXT("SPI bus must have MOSI, MISO, and CLK pins")); - } - - // Store pin numbers - self->mosi_pin = mosi_pin->number; - self->miso_pin = miso_pin->number; - self->clk_pin = clk_pin->number; - self->cs_pin = cs->number; - self->spi_host = spi_host; - self->slot = -1; - self->mounted = false; - self->spi_bus_initialized = false; - self->card = NULL; - - // Deinitialize the busio.SPI to release the SPI bus - // This is necessary because ESP-IDF's sdspi_host needs exclusive access - ESP_LOGI(TAG, "Taking over SPI bus from busio.SPI (host=%d)", spi_host); - common_hal_busio_spi_deinit(bus); - - // Configure SPI bus for SD card - spi_bus_config_t bus_cfg = { - .mosi_io_num = self->mosi_pin, - .miso_io_num = self->miso_pin, - .sclk_io_num = self->clk_pin, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 65536, // 64KB for optimal performance - }; - - // Initialize SPI bus with DMA - esp_err_t ret = spi_bus_initialize(spi_host, &bus_cfg, SPI_DMA_CH_AUTO); - if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SPI bus init failed: %d"), ret); - return; - } - // Track if we initialized the bus (not if it was already initialized by something else) - self->spi_bus_initialized = (ret == ESP_OK); - - // Configure SD card slot - sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); - slot_config.gpio_cs = self->cs_pin; - slot_config.host_id = spi_host; - - // Configure host - use the provided baudrate - sdmmc_host_t host = SDSPI_HOST_DEFAULT(); - host.slot = spi_host; - // Convert baudrate to kHz for ESP-IDF - host.max_freq_khz = baudrate / 1000; - if (host.max_freq_khz > SDMMC_FREQ_DEFAULT) { - host.max_freq_khz = SDMMC_FREQ_DEFAULT; // Cap at safe default - } - - // Allocate card structure - self->card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); - if (self->card == NULL) { - if (self->spi_bus_initialized) { - spi_bus_free(spi_host); - self->spi_bus_initialized = false; - } - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory for SD card structure")); - return; - } - - // Initialize the SD SPI device - ret = sdspi_host_init_device(&slot_config, &self->slot); - if (ret != ESP_OK) { - free(self->card); - self->card = NULL; - if (self->spi_bus_initialized) { - spi_bus_free(spi_host); - self->spi_bus_initialized = false; - } - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD host init failed: %d"), ret); - return; - } - - // Probe and initialize the card - ret = sdmmc_card_init(&host, self->card); - if (ret != ESP_OK) { - if (self->slot >= 0) { - sdspi_host_remove_device(self->slot); - self->slot = -1; - } - free(self->card); - self->card = NULL; - if (self->spi_bus_initialized) { - spi_bus_free(spi_host); - self->spi_bus_initialized = false; - } - if (ret == ESP_ERR_TIMEOUT) { - mp_raise_OSError_msg(MP_ERROR_TEXT("no SD card")); - } else if (ret == ESP_ERR_NOT_FOUND) { - mp_raise_OSError_msg(MP_ERROR_TEXT("no SD card")); - } else { - mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("SD card init failed: %d"), ret); - } - return; - } - - // Mark as mounted - self->mounted = true; - - // Claim the CS pin (SPI pins were already released by busio.SPI deinit, - // but we need to claim them for our use) - claim_pin(cs); - - // Set singleton for cleanup - sdcardio_singleton = self; - - ESP_LOGI(TAG, "SD card initialized successfully [NATIVE BLOCKDEV v2]"); - if (self->card != NULL) { - ESP_LOGI(TAG, "Card: %s, capacity: %llu sectors", - self->card->cid.name, - (unsigned long long)self->card->csd.capacity); - } -} - -void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) { - if (!self->mounted) { - return; - } - - // Remove device from SPI slot - if (self->slot >= 0) { - sdspi_host_remove_device(self->slot); - self->slot = -1; - } - - // Free card structure - if (self->card != NULL) { - free(self->card); - self->card = NULL; - } - - // Free SPI bus only if we initialized it - if (self->spi_bus_initialized) { - (void)spi_bus_free((spi_host_device_t)self->spi_host); - self->spi_bus_initialized = false; - } - - // Release CS pin - reset_pin_number(self->cs_pin); - - self->mounted = false; - - // Clear singleton if this was it - if (sdcardio_singleton == self) { - sdcardio_singleton = NULL; - } - - ESP_LOGI(TAG, "SD card deinitialized"); -} - -static void check_for_deinit(sdcardio_sdcard_obj_t *self) { - if (!self->mounted || self->card == NULL) { - raise_deinited_error(); - } -} - -void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self) { - check_for_deinit(self); -} - -int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { - check_for_deinit(self); - return (int)self->card->csd.capacity; -} - -int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, - uint32_t start_block, mp_buffer_info_t *buf) { - - check_for_deinit(self); - - if (buf->len % 512 != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer must be a multiple of 512 bytes")); - } - - uint32_t block_count = buf->len / 512; - - esp_err_t err = sdmmc_read_sectors(self->card, buf->buf, start_block, block_count); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Read failed at block %lu, count %lu: %d", - (unsigned long)start_block, (unsigned long)block_count, err); - return -MP_EIO; - } - - return 0; -} - -int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, - uint32_t start_block, mp_buffer_info_t *buf) { - - check_for_deinit(self); - - if (buf->len % 512 != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer must be a multiple of 512 bytes")); - } - - uint32_t block_count = buf->len / 512; - - esp_err_t err = sdmmc_write_sectors(self->card, buf->buf, start_block, block_count); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Write failed at block %lu, count %lu: %d", - (unsigned long)start_block, (unsigned long)block_count, err); - return -MP_EIO; - } - - return 0; -} - -int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { - // ESP-IDF handles synchronization internally - // Just verify the card is still mounted - if (!self->mounted) { - return -MP_ENODEV; - } - return 0; -} - -// VFS block device interface functions - -mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, - uint32_t start_block, uint32_t nblocks) { - - sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (!self->mounted || self->card == NULL) { - return MP_ENODEV; - } - - esp_err_t err = sdmmc_read_sectors(self->card, buf, start_block, nblocks); - if (err != ESP_OK) { - return MP_EIO; - } - - return 0; -} - -mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, - uint32_t start_block, uint32_t nblocks) { - - sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (!self->mounted || self->card == NULL) { - return MP_ENODEV; - } - - esp_err_t err = sdmmc_write_sectors(self->card, buf, start_block, nblocks); - if (err != ESP_OK) { - return MP_EIO; - } - - return 0; -} - -bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { - sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - *out_value = 0; - - switch (cmd) { - case MP_BLOCKDEV_IOCTL_DEINIT: - // Sync is handled by ESP-IDF internally - break; - case MP_BLOCKDEV_IOCTL_SYNC: - // ESP-IDF handles sync internally - break; - case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: - if (self->mounted && self->card != NULL) { - *out_value = (mp_int_t)self->card->csd.capacity; - } - break; - case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: - *out_value = 512; - break; - default: - return false; - } - return true; -} - -// Module reset function -void sdcardio_reset(void) { - if (sdcardio_singleton != NULL) { - common_hal_sdcardio_sdcard_deinit(sdcardio_singleton); - } -} diff --git a/ports/espressif/common-hal/sdcardio/SDCard.h b/ports/espressif/common-hal/sdcardio/SDCard.h deleted file mode 100644 index a6dfd284dbcae..0000000000000 --- a/ports/espressif/common-hal/sdcardio/SDCard.h +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "py/obj.h" -#include "sdmmc_cmd.h" -#include "driver/sdspi_host.h" - -// ESP-specific sdcardio implementation using ESP-IDF's sdspi_host driver. -// This provides ~2x better performance compared to the generic shared-module -// implementation by using hardware-optimized SD protocol handling. - -typedef struct { - mp_obj_base_t base; - - // SD card state - sdmmc_card_t *card; - sdspi_dev_handle_t slot; - int spi_host; - - // Pin storage (for cleanup) - gpio_num_t cs_pin; - gpio_num_t miso_pin; - gpio_num_t mosi_pin; - gpio_num_t clk_pin; - - // State flags - bool mounted; - bool spi_bus_initialized; -} sdcardio_sdcard_obj_t; - -// Reset function for module cleanup -void sdcardio_reset(void); diff --git a/ports/espressif/common-hal/sdcardio/__init__.c b/ports/espressif/common-hal/sdcardio/__init__.c deleted file mode 100644 index ab88e5cc7d8cb..0000000000000 --- a/ports/espressif/common-hal/sdcardio/__init__.c +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -// ESP-specific sdcardio module initialization. -// These functions are called by the filesystem subsystem for auto-mounting. -// Currently, auto-mounting is not implemented for the native ESP sdcardio -// since the ESP-IDF driver requires different initialization timing. - -#include "common-hal/sdcardio/__init__.h" -#include "common-hal/sdcardio/SDCard.h" - -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "shared-bindings/sdcardio/SDCard.h" -#include "supervisor/filesystem.h" - -#include "extmod/vfs_fat.h" - -#ifdef DEFAULT_SD_CARD_DETECT -static digitalio_digitalinout_obj_t sd_card_detect_pin; -static sdcardio_sdcard_obj_t sdcard; - -static mp_vfs_mount_t _sdcard_vfs; -static fs_user_mount_t _sdcard_usermount; - -static bool _init_error = false; -static bool _mounted = false; - -#include "shared-bindings/busio/SPI.h" -#include "common-hal/busio/SPI.h" - -#ifdef DEFAULT_SD_MOSI -static busio_spi_obj_t busio_spi_obj; -#else -#include "shared-bindings/board/__init__.h" -#endif -#endif - -void sdcardio_init(void) { - #ifdef DEFAULT_SD_CARD_DETECT - sd_card_detect_pin.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT); - common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP); - common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin); - #endif -} - -void automount_sd_card(void) { - #ifdef DEFAULT_SD_CARD_DETECT - if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) { - // No card. - _init_error = false; - if (_mounted) { - // Unmount the card. - mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table); - if (cur == &_sdcard_vfs) { - MP_STATE_VM(vfs_mount_table) = cur->next; - } else { - while (cur->next != &_sdcard_vfs && cur != NULL) { - cur = cur->next; - } - if (cur != NULL) { - cur->next = _sdcard_vfs.next; - } - } - _sdcard_vfs.next = NULL; - _mounted = false; - } - return; - } else if (_init_error || _mounted) { - // We've already tried and failed to init the card. Don't try again. - return; - } - - busio_spi_obj_t *spi_obj; - #ifndef DEFAULT_SD_MOSI - spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0)); - #else - spi_obj = &busio_spi_obj; - spi_obj->base.type = &busio_spi_type; - common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false); - common_hal_busio_spi_never_reset(spi_obj); - #endif - - sdcard.base.type = &sdcardio_SDCard_type; - - // For native ESP sdcardio, use the common_hal constructor which takes over the SPI bus - common_hal_sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000); - - // Check if initialization succeeded - if (!sdcard.mounted) { - _mounted = false; - _init_error = true; - return; - } - - fs_user_mount_t *vfs = &_sdcard_usermount; - vfs->base.type = &mp_fat_vfs_type; - vfs->fatfs.drv = vfs; - - // Initialise underlying block device - vfs->blockdev.block_size = FF_MIN_SS; - mp_vfs_blockdev_init(&vfs->blockdev, &sdcard); - - // mount the block device so the VFS methods can be used - FRESULT res = f_mount(&vfs->fatfs); - if (res != FR_OK) { - _mounted = false; - _init_error = true; - common_hal_sdcardio_sdcard_deinit(&sdcard); - return; - } - - filesystem_set_concurrent_write_protection(vfs, true); - filesystem_set_writable_by_usb(vfs, false); - - mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; - sdcard_vfs->str = "/sd"; - sdcard_vfs->len = 3; - sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); - sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); - MP_STATE_VM(vfs_mount_table) = sdcard_vfs; - _mounted = true; - #endif // DEFAULT_SD_CARD_DETECT -} diff --git a/ports/espressif/common-hal/sdcardio/__init__.h b/ports/espressif/common-hal/sdcardio/__init__.h deleted file mode 100644 index ac04b071bbd21..0000000000000 --- a/ports/espressif/common-hal/sdcardio/__init__.h +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -// Module initialization functions required by the filesystem subsystem -void sdcardio_init(void); -void automount_sd_card(void); diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c deleted file mode 100644 index 02b6a230f47e9..0000000000000 --- a/shared-bindings/sdcardio/SDCard.c +++ /dev/null @@ -1,187 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#include "py/obj.h" -#include "py/runtime.h" -#include "py/objarray.h" - -#include "shared-bindings/sdcardio/SDCard.h" -#include "common-hal/busio/SPI.h" -#include "shared-bindings/busio/SPI.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/flash.h" - -//| class SDCard: -//| """SD Card Block Interface -//| -//| Controls an SD card over SPI. This built-in module has higher read -//| performance than the library adafruit_sdcard, but it is only compatible with -//| `busio.SPI`, not `bitbangio.SPI`. Usually an SDCard object is used -//| with ``storage.VfsFat`` to allow file I/O to an SD card.""" -//| -//| def __init__( -//| self, bus: busio.SPI, cs: microcontroller.Pin, baudrate: int = 8000000 -//| ) -> None: -//| """Construct an SPI SD Card object with the given properties -//| -//| :param busio.SPI spi: The SPI bus -//| :param microcontroller.Pin cs: The chip select connected to the card -//| :param int baudrate: The SPI data rate to use after card setup -//| -//| Note that during detection and configuration, a hard-coded low baudrate is used. -//| Data transfers use the specified baurate (rounded down to one that is supported by -//| the microcontroller) -//| -//| .. important:: -//| If the same SPI bus is shared with other peripherals, it is important that -//| the SD card be initialized before accessing any other peripheral on the bus. -//| Failure to do so can prevent the SD card from being recognized until it is -//| powered off or re-inserted. -//| -//| Example usage: -//| -//| .. code-block:: python -//| -//| import os -//| -//| import board -//| import sdcardio -//| import storage -//| -//| sd = sdcardio.SDCard(board.SPI(), board.SD_CS) -//| vfs = storage.VfsFat(sd) -//| storage.mount(vfs, '/sd') -//| os.listdir('/sd')""" -//| - -static mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_spi, ARG_cs, ARG_baudrate, NUM_ARGS }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = mp_const_none } }, - { MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = mp_const_none } }, - { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 8000000} }, - }; - MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_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); - - busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj, MP_QSTR_spi); - const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); - - sdcardio_sdcard_obj_t *self = mp_obj_malloc(sdcardio_sdcard_obj_t, &sdcardio_SDCard_type); - - common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int); - - return self; -} - - -//| def count(self) -> int: -//| """Returns the total number of sectors -//| -//| Due to technical limitations, this is a function and not a property. -//| -//| :return: The number of 512-byte blocks, as a number""" -//| -static mp_obj_t sdcardio_sdcard_count(mp_obj_t self_in) { - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; - return mp_obj_new_int_from_ull(common_hal_sdcardio_sdcard_get_blockcount(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count); - -//| def deinit(self) -> None: -//| """Disable permanently. -//| -//| :return: None""" -//| -static mp_obj_t sdcardio_sdcard_deinit(mp_obj_t self_in) { - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; - common_hal_sdcardio_sdcard_deinit(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit); - - -//| def readblocks(self, start_block: int, buf: WriteableBuffer) -> None: -//| """Read one or more blocks from the card -//| -//| :param int start_block: The block to start reading from -//| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512. -//| -//| :return: None""" -//| - -static mp_obj_t _sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { - uint32_t start_block = mp_obj_get_int(start_block_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; - int result = common_hal_sdcardio_sdcard_readblocks(self, start_block, &bufinfo); - if (result < 0) { - mp_raise_OSError(-result); - } - return mp_const_none; -} - -MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, _sdcardio_sdcard_readblocks); - -//| def sync(self) -> None: -//| """Ensure all blocks written are actually committed to the SD card -//| -//| :return: None""" -//| ... -//| -static mp_obj_t sdcardio_sdcard_sync(mp_obj_t self_in) { - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; - int result = common_hal_sdcardio_sdcard_sync(self); - if (result < 0) { - mp_raise_OSError(-result); - } - return mp_const_none; -} - -MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_sync_obj, sdcardio_sdcard_sync); - - -//| def writeblocks(self, start_block: int, buf: ReadableBuffer) -> None: -//| """Write one or more blocks to the card -//| -//| :param int start_block: The block to start writing from -//| :param ~circuitpython_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512. -//| -//| :return: None""" -//| -//| - -static mp_obj_t _sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { - uint32_t start_block = mp_obj_get_int(start_block_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; - int result = common_hal_sdcardio_sdcard_writeblocks(self, start_block, &bufinfo); - if (result < 0) { - mp_raise_OSError(-result); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, _sdcardio_sdcard_writeblocks); - -static const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdcardio_sdcard_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&sdcardio_sdcard_sync_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdcardio_sdcard_writeblocks_obj) }, -}; -static MP_DEFINE_CONST_DICT(sdcardio_sdcard_locals_dict, sdcardio_sdcard_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - sdcardio_SDCard_type, - MP_QSTR_SDCard, - MP_TYPE_FLAG_NONE, - make_new, sdcardio_sdcard_make_new, - locals_dict, &sdcardio_sdcard_locals_dict - ); diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h deleted file mode 100644 index 243eee7ee274f..0000000000000 --- a/shared-bindings/sdcardio/SDCard.h +++ /dev/null @@ -1,34 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries -// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "common-hal/busio/SPI.h" -#include "common-hal/microcontroller/Pin.h" - -// Include port-specific common-hal or shared-module implementation based on build config. -// When CIRCUITPY_SDCARDIO_ESPRESSIF is set, the port provides a common-hal implementation. -#ifdef CIRCUITPY_SDCARDIO_ESPRESSIF -#include "common-hal/sdcardio/SDCard.h" -#else -#include "shared-module/sdcardio/SDCard.h" -#endif - -extern const mp_obj_type_t sdcardio_SDCard_type; - -void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate); -void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self); -void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self); -int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self); -int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); -int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self); -int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); - -// Used by native vfs blockdev. -mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); -mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); -bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value); diff --git a/shared-bindings/sdcardio/__init__.c b/shared-bindings/sdcardio/__init__.c deleted file mode 100644 index 7fb230189788f..0000000000000 --- a/shared-bindings/sdcardio/__init__.c +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries -// -// SPDX-License-Identifier: MIT - - -#include - -#include "py/obj.h" -#include "py/runtime.h" - -#include "shared-bindings/sdcardio/SDCard.h" - -//| """Interface to an SD card via the SPI bus""" - -static const mp_rom_map_elem_t sdcardio_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdcardio) }, - { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdcardio_SDCard_type) }, -}; - -static MP_DEFINE_CONST_DICT(sdcardio_module_globals, sdcardio_module_globals_table); - -const mp_obj_module_t sdcardio_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&sdcardio_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_sdcardio, sdcardio_module); diff --git a/shared-bindings/sdcardio/__init__.h b/shared-bindings/sdcardio/__init__.h deleted file mode 100644 index c9069db9fd7d5..0000000000000 --- a/shared-bindings/sdcardio/__init__.h +++ /dev/null @@ -1,7 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC -// -// SPDX-License-Identifier: MIT - -#pragma once diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c deleted file mode 100644 index bd3ea62d141e5..0000000000000 --- a/shared-module/sdcardio/SDCard.c +++ /dev/null @@ -1,522 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -// This implementation largely follows the structure of adafruit_sdcard.py - -#include "extmod/vfs.h" - -#include "shared-bindings/busio/SPI.h" -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "shared-bindings/sdcardio/SDCard.h" -#include "shared-bindings/time/__init__.h" -#include "shared-bindings/util.h" -#include "shared-module/sdcardio/SDCard.h" - -#include "py/mperrno.h" - -#if 0 -#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print,##__VA_ARGS__)) -#else -#define DEBUG_PRINT(...) ((void)0) -#endif - -#define CMD_TIMEOUT (200) - -#define R1_IDLE_STATE (1 << 0) -#define R1_ILLEGAL_COMMAND (1 << 2) - -#define TOKEN_CMD25 (0xFC) -#define TOKEN_STOP_TRAN (0xFD) -#define TOKEN_DATA (0xFE) - -static void common_hal_sdcardio_check_for_deinit(sdcardio_sdcard_obj_t *self) { - if (!self->bus) { - raise_deinited_error(); - } -} - -static bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) { - common_hal_sdcardio_check_for_deinit(self); - - if (!common_hal_busio_spi_try_lock(self->bus)) { - return false; - } - common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8); - common_hal_digitalio_digitalinout_set_value(&self->cs, false); - return true; -} - -static void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) { - if (!lock_and_configure_bus(self)) { - mp_raise_OSError(EAGAIN); - } -} - -static void clock_card(sdcardio_sdcard_obj_t *self, int bytes) { - uint8_t buf[] = {0xff}; - common_hal_digitalio_digitalinout_set_value(&self->cs, true); - for (int i = 0; i < bytes; i++) { - common_hal_busio_spi_write(self->bus, buf, 1); - } -} - -static void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) { - clock_card(self, 1); - common_hal_busio_spi_unlock(self->bus); -} - -static uint8_t CRC7(const uint8_t *data, uint8_t n) { - uint8_t crc = 0; - for (uint8_t i = 0; i < n; i++) { - uint8_t d = data[i]; - for (uint8_t j = 0; j < 8; j++) { - crc <<= 1; - if ((d & 0x80) ^ (crc & 0x80)) { - crc ^= 0x09; - } - d <<= 1; - } - } - return (crc << 1) | 1; -} - -#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms -static int wait_for_ready(sdcardio_sdcard_obj_t *self) { - uint64_t deadline = common_hal_time_monotonic_ns() + READY_TIMEOUT_NS; - while (common_hal_time_monotonic_ns() < deadline) { - uint8_t b; - common_hal_busio_spi_read(self->bus, &b, 1, 0xff); - if (b == 0xff) { - return 0; - } - } - return -ETIMEDOUT; -} - -// Note: this is never called while "in cmd25" (in fact, it's only used by `exit_cmd25`) -static bool cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { - uint8_t cmdbuf[2] = {cmd, 0xff}; - - assert(!self->in_cmd25); - - common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); - - // Wait for the response (response[7] == response) - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); - if (cmdbuf[0] == response) { - return 0; - } - } - return -EIO; -} - - -static int exit_cmd25(sdcardio_sdcard_obj_t *self) { - if (self->in_cmd25) { - DEBUG_PRINT("exit cmd25\n"); - self->in_cmd25 = false; - return cmd_nodata(self, TOKEN_STOP_TRAN, 0); - } - return 0; -} - -// In Python API, defaults are response=None, data_block=True, wait=True -static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf, size_t response_len, bool data_block, bool wait) { - int r = exit_cmd25(self); - if (r < 0) { - return r; - } - - DEBUG_PRINT("cmd % 3d [%02x] arg=% 11d [%08x] len=%d%s%s\n", cmd, cmd, arg, arg, response_len, data_block ? " data" : "", wait ? " wait" : ""); - uint8_t cmdbuf[6]; - cmdbuf[0] = cmd | 0x40; - cmdbuf[1] = (arg >> 24) & 0xff; - cmdbuf[2] = (arg >> 16) & 0xff; - cmdbuf[3] = (arg >> 8) & 0xff; - cmdbuf[4] = arg & 0xff; - cmdbuf[5] = CRC7(cmdbuf, 5); - - if (wait) { - r = wait_for_ready(self); - if (r < 0) { - return r; - } - } - - common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); - - // Wait for the response (response[7] == 0) - bool response_received = false; - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); - if ((cmdbuf[0] & 0x80) == 0) { - response_received = true; - break; - } - } - - if (!response_received) { - return -EIO; - } - - if (response_buf) { - - if (data_block) { - cmdbuf[1] = 0xff; - do { - // Wait for the start block byte - common_hal_busio_spi_read(self->bus, cmdbuf + 1, 1, 0xff); - } while (cmdbuf[1] != 0xfe); - } - - common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff); - - if (data_block) { - // Read and discard the CRC-CCITT checksum - common_hal_busio_spi_read(self->bus, cmdbuf + 1, 2, 0xff); - } - - } - - return cmdbuf[0]; -} - -static int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *response_buf, size_t response_len, bool data_block, bool wait) { - return cmd(self, cmd_, block * self->cdv, response_buf, response_len, true, true); -} - -static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) { - for (int i = 0; i < CMD_TIMEOUT; i++) { - if (cmd(self, 41, 0, NULL, 0, true, true) == 0) { - return NULL; - } - } - return MP_ERROR_TEXT("timeout waiting for v1 card"); -} - -static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) { - for (int i = 0; i < CMD_TIMEOUT; i++) { - uint8_t ocr[4]; - common_hal_time_delay_ms(50); - cmd(self, 58, 0, ocr, sizeof(ocr), false, true); - cmd(self, 55, 0, NULL, 0, true, true); - if (cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) { - cmd(self, 58, 0, ocr, sizeof(ocr), false, true); - if ((ocr[0] & 0x40) != 0) { - self->cdv = 1; - } - return NULL; - } - } - return MP_ERROR_TEXT("timeout waiting for v2 card"); -} - -static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) { - clock_card(self, 10); - - common_hal_digitalio_digitalinout_set_value(&self->cs, false); - - assert(!self->in_cmd25); - self->in_cmd25 = false; // should be false already - - // CMD0: init card: should return _R1_IDLE_STATE (allow 5 attempts) - { - bool reached_idle_state = false; - for (int i = 0; i < 5; i++) { - // do not call cmd with wait=true, because that will return - // prematurely if the idle state is not reached. we can't depend on - // this when the card is not yet in SPI mode - (void)wait_for_ready(self); - if (cmd(self, 0, 0, NULL, 0, true, false) == R1_IDLE_STATE) { - reached_idle_state = true; - break; - } - } - if (!reached_idle_state) { - return MP_ERROR_TEXT("no SD card"); - } - } - - // CMD8: determine card version - { - uint8_t rb7[4]; - int response = cmd(self, 8, 0x1AA, rb7, sizeof(rb7), false, true); - if (response == R1_IDLE_STATE) { - mp_rom_error_text_t result = init_card_v2(self); - if (result != NULL) { - return result; - } - } else if (response == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { - mp_rom_error_text_t result = init_card_v1(self); - if (result != NULL) { - return result; - } - } else { - DEBUG_PRINT("Reading card version, response=0x%02x\n", response); - return MP_ERROR_TEXT("couldn't determine SD card version"); - } - } - - // CMD9: get number of sectors - { - uint8_t csd[16]; - int response = cmd(self, 9, 0, csd, sizeof(csd), true, true); - if (response != 0) { - return MP_ERROR_TEXT("no response from SD card"); - } - int csd_version = (csd[0] & 0xC0) >> 6; - if (csd_version >= 2) { - return MP_ERROR_TEXT("SD card CSD format not supported"); - } - - if (csd_version == 1) { - self->sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024; - } else { - uint32_t block_length = 1 << (csd[5] & 0xF); - uint32_t c_size = ((csd[6] & 0x3) << 10) | (csd[7] << 2) | ((csd[8] & 0xC) >> 6); - uint32_t mult = 1 << (((csd[9] & 0x3) << 1 | (csd[10] & 0x80) >> 7) + 2); - self->sectors = block_length / 512 * mult * (c_size + 1); - } - } - - // CMD16: set block length to 512 bytes - { - int response = cmd(self, 16, 512, NULL, 0, true, true); - if (response != 0) { - return MP_ERROR_TEXT("can't set 512 block size"); - } - } - - return NULL; -} - -mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { - self->bus = bus; - common_hal_digitalio_digitalinout_construct(&self->cs, cs); - common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL); - - self->cdv = 512; - self->sectors = 0; - self->baudrate = 250000; - - lock_bus_or_throw(self); - mp_rom_error_text_t result = init_card(self); - extraclock_and_unlock_bus(self); - - if (result != NULL) { - common_hal_digitalio_digitalinout_deinit(&self->cs); - return result; - } - - self->baudrate = baudrate; - return NULL; -} - - -void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { - mp_rom_error_text_t result = sdcardio_sdcard_construct(self, bus, cs, baudrate); - if (result != NULL) { - mp_raise_OSError_msg(result); - } -} - -void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) { - if (!self->bus) { - return; - } - common_hal_sdcardio_sdcard_sync(self); - self->bus = 0; - common_hal_digitalio_digitalinout_deinit(&self->cs); -} - -int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { - common_hal_sdcardio_check_for_deinit(self); - return self->sectors; -} - -static int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) { - uint8_t aux[2] = {0, 0}; - while (aux[0] != 0xfe) { - common_hal_busio_spi_read(self->bus, aux, 1, 0xff); - } - - common_hal_busio_spi_read(self->bus, buf, size, 0xff); - - // Read checksum and throw it away - common_hal_busio_spi_read(self->bus, aux, sizeof(aux), 0xff); - return 0; -} - -mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) { - // deinit check is in lock_and_configure_bus() - sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (!lock_and_configure_bus(self)) { - return MP_EAGAIN; - } - int r = 0; - size_t buflen = 512 * nblocks; - if (nblocks == 1) { - // Use CMD17 to read a single block - r = block_cmd(self, 17, start_block, buf, buflen, true, true); - } else { - // Use CMD18 to read multiple blocks - r = block_cmd(self, 18, start_block, NULL, 0, true, true); - uint8_t *ptr = buf; - while (nblocks-- && r >= 0) { - r = readinto(self, ptr, 512); - if (r != 0) { - break; - } - ptr += 512; - } - - // End the multi-block read - r = cmd(self, 12, 0, NULL, 0, true, false); - - // Return first status 0 or last before card ready (0xff) - while (r != 0) { - uint8_t single_byte; - common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff); - if (single_byte & 0x80) { - break; - } - r = single_byte; - } - } - extraclock_and_unlock_bus(self); - return r; -} - -int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { - if (buf->len % 512 != 0) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); - } - - return sdcardio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); -} - -static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) { - wait_for_ready(self); - - uint8_t cmd[2]; - cmd[0] = token; - - common_hal_busio_spi_write(self->bus, cmd, 1); - common_hal_busio_spi_write(self->bus, buf, size); - - cmd[0] = cmd[1] = 0xff; - common_hal_busio_spi_write(self->bus, cmd, 2); - - // Check the response - // This differs from the traditional adafruit_sdcard handling, - // but adafruit_sdcard also ignored the return value of SDCard._write(!) - // so nobody noticed - // - // - // Response is as follows: - // x x x 0 STAT 1 - // 7 6 5 4 3..1 0 - // with STATUS 010 indicating "data accepted", and other status bit - // combinations indicating failure. - // In practice, I was seeing cmd[0] as 0xe5, indicating success - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); - DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]); - if ((cmd[0] & 0b00010001) == 0b00000001) { - if ((cmd[0] & 0x1f) != 0x5) { - return -EIO; - } else { - break; - } - } - } - - // Wait for the write to finish - do { - common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); - } while (cmd[0] == 0); - - // Success - return 0; -} - -mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) { - // deinit check is in lock_and_configure_bus() - sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (!lock_and_configure_bus(self)) { - return MP_EAGAIN; - } - - if (!self->in_cmd25 || start_block != self->next_block) { - DEBUG_PRINT("entering CMD25 at %d\n", (int)start_block); - // Use CMD25 to write multiple block - int r = block_cmd(self, 25, start_block, NULL, 0, true, true); - if (r < 0) { - extraclock_and_unlock_bus(self); - return r; - } - self->in_cmd25 = true; - } - - self->next_block = start_block; - - uint8_t *ptr = buf; - while (nblocks--) { - int r = _write(self, TOKEN_CMD25, ptr, 512); - if (r < 0) { - self->in_cmd25 = false; - extraclock_and_unlock_bus(self); - return r; - } - self->next_block++; - ptr += 512; - } - - extraclock_and_unlock_bus(self); - return 0; -} - -int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { - // deinit check is in lock_and_configure_bus() - lock_and_configure_bus(self); - int r = exit_cmd25(self); - extraclock_and_unlock_bus(self); - return r; -} - -int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { - // deinit check is in lock_and_configure_bus() - if (buf->len % 512 != 0) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); - } - lock_and_configure_bus(self); - int r = sdcardio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); - extraclock_and_unlock_bus(self); - return r; -} - -bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { - sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); - *out_value = 0; - switch (cmd) { - case MP_BLOCKDEV_IOCTL_DEINIT: - common_hal_sdcardio_sdcard_sync(self); - break; // TODO properly - case MP_BLOCKDEV_IOCTL_SYNC: - common_hal_sdcardio_sdcard_sync(self); - break; - case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: - *out_value = common_hal_sdcardio_sdcard_get_blockcount(self); - break; - case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: - *out_value = 512; - break; - default: - return false; - } - return true; -} diff --git a/shared-module/sdcardio/SDCard.h b/shared-module/sdcardio/SDCard.h deleted file mode 100644 index f9cd64b812532..0000000000000 --- a/shared-module/sdcardio/SDCard.h +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "py/obj.h" -#include "py/objproperty.h" -#include "py/runtime.h" -#include "py/objarray.h" - -#include "common-hal/busio/SPI.h" -#include "common-hal/digitalio/DigitalInOut.h" - -typedef struct { - mp_obj_base_t base; - busio_spi_obj_t *bus; - digitalio_digitalinout_obj_t cs; - int cdv; - int baudrate; - uint32_t sectors; - uint32_t next_block; - bool in_cmd25; -} sdcardio_sdcard_obj_t; - -mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate); diff --git a/shared-module/sdcardio/__init__.c b/shared-module/sdcardio/__init__.c deleted file mode 100644 index 29c890c6870c1..0000000000000 --- a/shared-module/sdcardio/__init__.c +++ /dev/null @@ -1,127 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC -// -// SPDX-License-Identifier: MIT - -#include "shared-module/sdcardio/__init__.h" - -#include "extmod/vfs_fat.h" - -#include "shared-bindings/busio/SPI.h" -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "shared-bindings/sdcardio/SDCard.h" - -#include "supervisor/filesystem.h" - -#ifdef DEFAULT_SD_CARD_DETECT -static digitalio_digitalinout_obj_t sd_card_detect_pin; -static sdcardio_sdcard_obj_t sdcard; - -static mp_vfs_mount_t _sdcard_vfs; -fs_user_mount_t _sdcard_usermount; - -static bool _init_error = false; -static bool _mounted = false; - -#ifdef DEFAULT_SD_MOSI -static busio_spi_obj_t busio_spi_obj; -#else -#include "shared-bindings/board/__init__.h" -#endif -#endif - -void sdcardio_init(void) { - #ifdef DEFAULT_SD_CARD_DETECT - sd_card_detect_pin.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT); - common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP); - common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin); - #endif -} - -void automount_sd_card(void) { - #ifdef DEFAULT_SD_CARD_DETECT - if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) { - // No card. - _init_error = false; - if (_mounted) { - // Unmount the card. - mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table); - if (cur == &_sdcard_vfs) { - MP_STATE_VM(vfs_mount_table) = cur->next; - } else { - while (cur->next != &_sdcard_vfs && cur != NULL) { - cur = cur->next; - } - if (cur != NULL) { - cur->next = _sdcard_vfs.next; - } - } - _sdcard_vfs.next = NULL; - - #ifdef DEFAULT_SD_MOSI - common_hal_busio_spi_deinit(&busio_spi_obj); - #endif - _mounted = false; - } - return; - } else if (_init_error || _mounted) { - // We've already tried and failed to init the card. Don't try again. - return; - } - - busio_spi_obj_t *spi_obj; - #ifndef DEFAULT_SD_MOSI - spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0)); - #else - spi_obj = &busio_spi_obj; - spi_obj->base.type = &busio_spi_type; - common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false); - common_hal_busio_spi_never_reset(spi_obj); - #endif - sdcard.base.type = &sdcardio_SDCard_type; - mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000); - if (error != NULL) { - // Failed to communicate with the card. - _mounted = false; - _init_error = true; - #ifdef DEFAULT_SD_MOSI - common_hal_busio_spi_deinit(spi_obj); - #endif - return; - } - common_hal_digitalio_digitalinout_never_reset(&sdcard.cs); - - fs_user_mount_t *vfs = &_sdcard_usermount; - vfs->base.type = &mp_fat_vfs_type; - vfs->fatfs.drv = vfs; - - // Initialise underlying block device - vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE - mp_vfs_blockdev_init(&vfs->blockdev, &sdcard); - - // mount the block device so the VFS methods can be used - FRESULT res = f_mount(&vfs->fatfs); - if (res != FR_OK) { - _mounted = false; - _init_error = true; - common_hal_sdcardio_sdcard_deinit(&sdcard); - #ifdef DEFAULT_SD_MOSI - common_hal_busio_spi_deinit(spi_obj); - #endif - return; - } - - filesystem_set_concurrent_write_protection(vfs, true); - filesystem_set_writable_by_usb(vfs, false); - - mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; - sdcard_vfs->str = "/sd"; - sdcard_vfs->len = 3; - sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); - sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); - MP_STATE_VM(vfs_mount_table) = sdcard_vfs; - _mounted = true; - #endif // DEFAULT_SD_CARD_DETECT -} diff --git a/shared-module/sdcardio/__init__.h b/shared-module/sdcardio/__init__.h deleted file mode 100644 index 59b4cf892f29b..0000000000000 --- a/shared-module/sdcardio/__init__.h +++ /dev/null @@ -1,10 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC -// -// SPDX-License-Identifier: MIT - -#pragma once - -void sdcardio_init(void); -void automount_sd_card(void); From 24f5a0e4b3cc1b8cbf23b6aa54cf28e3c0e9f27d Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 6 Feb 2026 14:42:28 +0100 Subject: [PATCH 11/38] Phase 2: add qspibus module for ESP32-S3 displays - add shared bindings for qspibus.QSPIBus\n- add ESP32-S3 common-hal implementation\n- integrate CIRCUITPY_QSPIBUS into build config\n- enable qspibus for waveshare_esp32_s3_amoled_241 --- .../mpconfigboard.mk | 2 + ports/espressif/common-hal/qspibus/QSPIBus.c | 179 ++++++++++++++++++ ports/espressif/common-hal/qspibus/QSPIBus.h | 40 ++++ ports/espressif/common-hal/qspibus/__init__.c | 3 + ports/espressif/common-hal/qspibus/__init__.h | 3 + ports/espressif/mpconfigport.mk | 1 + py/circuitpy_defns.mk | 5 + py/circuitpy_mpconfig.mk | 4 + shared-bindings/qspibus/QSPIBus.c | 123 ++++++++++++ shared-bindings/qspibus/QSPIBus.h | 37 ++++ shared-bindings/qspibus/__init__.c | 50 +++++ shared-bindings/qspibus/__init__.h | 8 + 12 files changed, 455 insertions(+) create mode 100644 ports/espressif/common-hal/qspibus/QSPIBus.c create mode 100644 ports/espressif/common-hal/qspibus/QSPIBus.h create mode 100644 ports/espressif/common-hal/qspibus/__init__.c create mode 100644 ports/espressif/common-hal/qspibus/__init__.h create mode 100644 shared-bindings/qspibus/QSPIBus.c create mode 100644 shared-bindings/qspibus/QSPIBus.h create mode 100644 shared-bindings/qspibus/__init__.c create mode 100644 shared-bindings/qspibus/__init__.h diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index dc5c33b9c69a0..c8675ebc13d96 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -33,6 +33,8 @@ OPTIMIZATION_FLAGS = -Os # Enable features for this board CIRCUITPY_DISPLAYIO = 1 +# QSPI bus for RM690B0 AMOLED display +CIRCUITPY_QSPIBUS = 1 CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_BITMAPTOOLS = 1 diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c new file mode 100644 index 0000000000000..dea2676b3bc79 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -0,0 +1,179 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/qspibus/QSPIBus.h" + +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "py/runtime.h" + +#include "driver/gpio.h" +#include "soc/soc_caps.h" + +#define QSPI_OPCODE_WRITE_CMD (0x02U) + +static bool IRAM_ATTR qspibus_on_color_trans_done( + esp_lcd_panel_io_handle_t io_handle, + esp_lcd_panel_io_event_data_t *event_data, + void *user_ctx) { + (void)io_handle; + (void)event_data; + + qspibus_qspibus_obj_t *self = (qspibus_qspibus_obj_t *)user_ctx; + BaseType_t x_higher_priority_task_woken = pdFALSE; + + xSemaphoreGiveFromISR(self->transfer_done_sem, &x_higher_priority_task_woken); + return x_higher_priority_task_woken == pdTRUE; +} + +void common_hal_qspibus_qspibus_construct( + qspibus_qspibus_obj_t *self, + const mcu_pin_obj_t *clock, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data1, + const mcu_pin_obj_t *data2, + const mcu_pin_obj_t *data3, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *reset, + uint32_t frequency) { + + self->io_handle = NULL; + self->host_id = SPI2_HOST; + self->clock_pin = clock->number; + self->data0_pin = data0->number; + self->data1_pin = data1->number; + self->data2_pin = data2->number; + self->data3_pin = data3->number; + self->cs_pin = cs->number; + self->reset_pin = (reset != NULL) ? reset->number : -1; + self->frequency = frequency; + self->bus_initialized = false; + self->transfer_done_sem = NULL; + + self->transfer_done_sem = xSemaphoreCreateBinary(); + if (self->transfer_done_sem == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to create semaphore")); + } + + const spi_bus_config_t bus_config = { + .sclk_io_num = self->clock_pin, + .data0_io_num = self->data0_pin, + .data1_io_num = self->data1_pin, + .data2_io_num = self->data2_pin, + .data3_io_num = self->data3_pin, + .max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE, + .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS, + }; + + esp_err_t err = spi_bus_initialize(self->host_id, &bus_config, SPI_DMA_CH_AUTO); + if (err != ESP_OK) { + vSemaphoreDelete(self->transfer_done_sem); + self->transfer_done_sem = NULL; + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SPI bus init failed: %d"), err); + } + + const esp_lcd_panel_io_spi_config_t io_config = { + .cs_gpio_num = self->cs_pin, + .dc_gpio_num = -1, + .spi_mode = 0, + .pclk_hz = self->frequency, + .trans_queue_depth = 1, + .on_color_trans_done = qspibus_on_color_trans_done, + .user_ctx = self, + .lcd_cmd_bits = 32, + .lcd_param_bits = 8, + .flags = { + .quad_mode = 1, + }, + }; + + err = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)self->host_id, &io_config, &self->io_handle); + if (err != ESP_OK) { + spi_bus_free(self->host_id); + vSemaphoreDelete(self->transfer_done_sem); + self->transfer_done_sem = NULL; + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("Panel IO init failed: %d"), err); + } + + claim_pin(clock); + claim_pin(data0); + claim_pin(data1); + claim_pin(data2); + claim_pin(data3); + claim_pin(cs); + + if (reset != NULL) { + claim_pin(reset); + + gpio_set_direction((gpio_num_t)self->reset_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level((gpio_num_t)self->reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(120)); + } + + self->bus_initialized = true; +} + +void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { + if (!self->bus_initialized) { + return; + } + + if (self->io_handle != NULL) { + esp_lcd_panel_io_del(self->io_handle); + self->io_handle = NULL; + } + + spi_bus_free(self->host_id); + + if (self->transfer_done_sem != NULL) { + vSemaphoreDelete(self->transfer_done_sem); + self->transfer_done_sem = NULL; + } + + reset_pin_number(self->clock_pin); + reset_pin_number(self->data0_pin); + reset_pin_number(self->data1_pin); + reset_pin_number(self->data2_pin); + reset_pin_number(self->data3_pin); + reset_pin_number(self->cs_pin); + if (self->reset_pin >= 0) { + reset_pin_number(self->reset_pin); + } + + self->bus_initialized = false; +} + +bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self) { + return !self->bus_initialized; +} + +void common_hal_qspibus_qspibus_send( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + } + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); + + esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); + if (err != ESP_OK) { + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send failed: %d"), err); + } + + // Some ESP-IDF paths complete tx_param synchronously and may not invoke + // the callback for parameter transfers. Try to sync via semaphore when + // available, but do not fail if no callback is emitted. + (void)xSemaphoreTake(self->transfer_done_sem, pdMS_TO_TICKS(1000)); +} + +bool common_hal_qspibus_qspibus_bus_free(qspibus_qspibus_obj_t *self) { + return self->bus_initialized; +} diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.h b/ports/espressif/common-hal/qspibus/QSPIBus.h new file mode 100644 index 0000000000000..f789aa3fd3485 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/QSPIBus.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" + +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include "driver/spi_master.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +typedef struct { + mp_obj_base_t base; + + // ESP LCD panel IO handle used for QSPI transactions. + esp_lcd_panel_io_handle_t io_handle; + + // SPI host (SPI2_HOST on ESP32-S3). + spi_host_device_t host_id; + + // Claimed GPIO numbers. + int8_t clock_pin; + int8_t data0_pin; + int8_t data1_pin; + int8_t data2_pin; + int8_t data3_pin; + int8_t cs_pin; + int8_t reset_pin; // -1 when reset line is not provided. + + uint32_t frequency; + bool bus_initialized; + + // Signaled from ISR when panel IO transfer completes. + SemaphoreHandle_t transfer_done_sem; +} qspibus_qspibus_obj_t; diff --git a/ports/espressif/common-hal/qspibus/__init__.c b/ports/espressif/common-hal/qspibus/__init__.c new file mode 100644 index 0000000000000..4ac7203fd289b --- /dev/null +++ b/ports/espressif/common-hal/qspibus/__init__.c @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/common-hal/qspibus/__init__.h b/ports/espressif/common-hal/qspibus/__init__.h new file mode 100644 index 0000000000000..4ac7203fd289b --- /dev/null +++ b/ports/espressif/common-hal/qspibus/__init__.h @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 42bf3418f9639..3515bb3d6a69c 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -78,6 +78,7 @@ CIRCUITPY_MEMORYMAP ?= 1 CIRCUITPY_RCLCPY ?= 0 CIRCUITPY_NVM ?= 1 CIRCUITPY_PARALLELDISPLAYBUS ?= 1 +CIRCUITPY_QSPIBUS ?= 1 CIRCUITPY_PS2IO ?= 1 CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_ROTARYIO ?= 1 diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index e1afb3ebb4413..a7b34b44a6f9c 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -228,6 +228,9 @@ endif ifeq ($(CIRCUITPY_FOURWIRE),1) SRC_PATTERNS += fourwire/% endif +ifeq ($(CIRCUITPY_QSPIBUS),1) +SRC_PATTERNS += qspibus/% +endif ifeq ($(CIRCUITPY_FRAMEBUFFERIO),1) SRC_PATTERNS += framebufferio/% endif @@ -546,6 +549,8 @@ SRC_COMMON_HAL_ALL = \ pulseio/__init__.c \ pwmio/PWMOut.c \ pwmio/__init__.c \ + qspibus/QSPIBus.c \ + qspibus/__init__.c \ rclcpy/__init__.c \ rclcpy/Node.c \ rclcpy/Publisher.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index d71a3264186ad..4ab7d00e5e742 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -247,6 +247,10 @@ CFLAGS += -DCIRCUITPY_BUSDISPLAY=$(CIRCUITPY_BUSDISPLAY) CIRCUITPY_FOURWIRE ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_FOURWIRE=$(CIRCUITPY_FOURWIRE) +# QSPI bus protocol for quad-SPI displays (like RM690B0) +CIRCUITPY_QSPIBUS ?= 0 +CFLAGS += -DCIRCUITPY_QSPIBUS=$(CIRCUITPY_QSPIBUS) + CIRCUITPY_EPAPERDISPLAY ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_EPAPERDISPLAY=$(CIRCUITPY_EPAPERDISPLAY) diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c new file mode 100644 index 0000000000000..8778dae23cf5f --- /dev/null +++ b/shared-bindings/qspibus/QSPIBus.c @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/qspibus/QSPIBus.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" + +#include "py/obj.h" +#include "py/runtime.h" + +//| class QSPIBus: +//| """QSPI bus for quad-SPI displays.""" +//| +//| def __init__( +//| self, +//| *, +//| clock: microcontroller.Pin, +//| data0: microcontroller.Pin, +//| data1: microcontroller.Pin, +//| data2: microcontroller.Pin, +//| data3: microcontroller.Pin, +//| cs: microcontroller.Pin, +//| reset: Optional[microcontroller.Pin] = None, +//| frequency: int = 80_000_000, +//| ) -> None: +//| """Create a QSPIBus object for quad-SPI display communication. +//| +//| :param ~microcontroller.Pin clock: QSPI clock pin +//| :param ~microcontroller.Pin data0: QSPI data line 0 +//| :param ~microcontroller.Pin data1: QSPI data line 1 +//| :param ~microcontroller.Pin data2: QSPI data line 2 +//| :param ~microcontroller.Pin data3: QSPI data line 3 +//| :param ~microcontroller.Pin cs: Chip select pin +//| :param ~microcontroller.Pin reset: Optional reset pin +//| :param int frequency: Bus frequency in Hz (1-80MHz) +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) { + + enum { ARG_clock, ARG_data0, ARG_data1, ARG_data2, ARG_data3, ARG_cs, ARG_reset, ARG_frequency }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data0, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data1, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data2, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data3, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 80000000} }, + }; + + 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); + + const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); + const mcu_pin_obj_t *data0 = validate_obj_is_free_pin(args[ARG_data0].u_obj, MP_QSTR_data0); + const mcu_pin_obj_t *data1 = validate_obj_is_free_pin(args[ARG_data1].u_obj, MP_QSTR_data1); + const mcu_pin_obj_t *data2 = validate_obj_is_free_pin(args[ARG_data2].u_obj, MP_QSTR_data2); + const mcu_pin_obj_t *data3 = validate_obj_is_free_pin(args[ARG_data3].u_obj, MP_QSTR_data3); + const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + const mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset); + + uint32_t frequency = (uint32_t)mp_arg_validate_int_range(args[ARG_frequency].u_int, 1, 80000000, MP_QSTR_frequency); + + qspibus_qspibus_obj_t *self = mp_obj_malloc(qspibus_qspibus_obj_t, &qspibus_qspibus_type); + common_hal_qspibus_qspibus_construct(self, clock, data0, data1, data2, data3, cs, reset, frequency); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Release QSPI bus resources and claimed pins.""" +//| ... +//| +static mp_obj_t qspibus_qspibus_deinit(mp_obj_t self_in) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_qspibus_qspibus_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(qspibus_qspibus_deinit_obj, qspibus_qspibus_deinit); + +//| def __enter__(self) -> QSPIBus: +//| """No-op context manager entry.""" +//| ... +//| +static mp_obj_t qspibus_qspibus___enter__(mp_obj_t self_in) { + return self_in; +} +static MP_DEFINE_CONST_FUN_OBJ_1(qspibus_qspibus___enter___obj, qspibus_qspibus___enter__); + +//| def __exit__(self) -> None: +//| """Deinitialize on context manager exit.""" +//| ... +//| +static mp_obj_t qspibus_qspibus___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_qspibus_qspibus_deinit(MP_OBJ_TO_PTR(args[0])); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qspibus_qspibus___exit___obj, 4, 4, qspibus_qspibus___exit__); + +// send() intentionally remains C-only for display drivers. + +static const mp_rom_map_elem_t qspibus_qspibus_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&qspibus_qspibus_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&qspibus_qspibus___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&qspibus_qspibus___exit___obj) }, +}; +static MP_DEFINE_CONST_DICT(qspibus_qspibus_locals_dict, qspibus_qspibus_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + qspibus_qspibus_type, + MP_QSTR_QSPIBus, + MP_TYPE_FLAG_NONE, + make_new, qspibus_qspibus_make_new, + locals_dict, &qspibus_qspibus_locals_dict + ); diff --git a/shared-bindings/qspibus/QSPIBus.h b/shared-bindings/qspibus/QSPIBus.h new file mode 100644 index 0000000000000..51a3e9f6c9631 --- /dev/null +++ b/shared-bindings/qspibus/QSPIBus.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/qspibus/QSPIBus.h" + +extern const mp_obj_type_t qspibus_qspibus_type; + +void common_hal_qspibus_qspibus_construct( + qspibus_qspibus_obj_t *self, + const mcu_pin_obj_t *clock, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data1, + const mcu_pin_obj_t *data2, + const mcu_pin_obj_t *data3, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *reset, + uint32_t frequency); + +void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self); +bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self); + +void common_hal_qspibus_qspibus_send( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len); + +bool common_hal_qspibus_qspibus_bus_free(qspibus_qspibus_obj_t *self); diff --git a/shared-bindings/qspibus/__init__.c b/shared-bindings/qspibus/__init__.c new file mode 100644 index 0000000000000..51a5267e30a73 --- /dev/null +++ b/shared-bindings/qspibus/__init__.c @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/qspibus/__init__.h" +#include "shared-bindings/qspibus/QSPIBus.h" + +//| """QSPI bus protocol for quad-SPI displays +//| +//| The `qspibus` module provides a low-level QSPI bus interface for displays +//| that use four data lines. It is analogous to `fourwire` for standard SPI. +//| +//| Use :class:`qspibus.QSPIBus` to create a bus instance. +//| +//| Example usage:: +//| +//| import board +//| import qspibus +//| import displayio +//| +//| displayio.release_displays() +//| +//| bus = qspibus.QSPIBus( +//| clock=board.LCD_CLK, +//| data0=board.LCD_D0, +//| data1=board.LCD_D1, +//| data2=board.LCD_D2, +//| data3=board.LCD_D3, +//| cs=board.LCD_CS, +//| reset=board.LCD_RESET, +//| frequency=80_000_000, +//| ) +//| """ + +static const mp_rom_map_elem_t qspibus_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_qspibus) }, + { MP_ROM_QSTR(MP_QSTR_QSPIBus), MP_ROM_PTR(&qspibus_qspibus_type) }, +}; + +static MP_DEFINE_CONST_DICT(qspibus_module_globals, qspibus_module_globals_table); + +const mp_obj_module_t qspibus_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&qspibus_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_qspibus, qspibus_module); diff --git a/shared-bindings/qspibus/__init__.h b/shared-bindings/qspibus/__init__.h new file mode 100644 index 0000000000000..3604bf04c0e22 --- /dev/null +++ b/shared-bindings/qspibus/__init__.h @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/qspibus/QSPIBus.h" From 4e58173176c1ea467f6c13117144b3d6b7f6dc67 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 6 Feb 2026 15:54:18 +0100 Subject: [PATCH 12/38] qspibus/displayio: stabilize RM690B0 refresh and deinit --- ports/espressif/common-hal/qspibus/QSPIBus.c | 197 +++++++++++++++++-- ports/espressif/common-hal/qspibus/QSPIBus.h | 4 + shared-bindings/qspibus/QSPIBus.h | 16 +- shared-module/busdisplay/BusDisplay.c | 24 +++ shared-module/displayio/bus_core.c | 13 ++ 5 files changed, 241 insertions(+), 13 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index dea2676b3bc79..02eb03a6ba7be 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -7,12 +7,88 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" +#include "py/gc.h" #include "py/runtime.h" #include "driver/gpio.h" #include "soc/soc_caps.h" #define QSPI_OPCODE_WRITE_CMD (0x02U) +#define QSPI_OPCODE_WRITE_COLOR (0x32U) +#define LCD_CMD_RAMWR (0x2CU) +#define LCD_CMD_RAMWRC (0x3CU) +#define LCD_CMD_DISPOFF (0x28U) +#define LCD_CMD_SLPIN (0x10U) +#ifndef CIRCUITPY_RM690B0_POWER_ON_LEVEL +#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (1) +#endif + +static void qspibus_send_command_bytes( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + } + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); + esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); + if (err != ESP_OK) { + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send failed: %d"), err); + } +} + +static void qspibus_send_color_bytes( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + } + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)command << 8); + // Drop stale completion events if any. + while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + } + + esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, data, len); + if (err != ESP_OK) { + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send color failed: %d"), err); + } + if (xSemaphoreTake(self->transfer_done_sem, pdMS_TO_TICKS(1000)) != pdTRUE) { + mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); + } +} + +static bool qspibus_is_color_payload_command(uint8_t command) { + return command == LCD_CMD_RAMWR || command == LCD_CMD_RAMWRC; +} + +static void qspibus_panel_sleep_best_effort(qspibus_qspibus_obj_t *self) { + if (!self->bus_initialized || self->io_handle == NULL) { + return; + } + + // If a command is buffered, flush it first so the panel state machine + // doesn't get a truncated transaction before sleep. + if (self->has_pending_command) { + uint32_t pending = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)self->pending_command << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, pending, NULL, 0); + self->has_pending_command = false; + } + + uint32_t disp_off = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)LCD_CMD_DISPOFF << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, disp_off, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(20)); + + uint32_t sleep_in = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)LCD_CMD_SLPIN << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, sleep_in, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(120)); +} static bool IRAM_ATTR qspibus_on_color_trans_done( esp_lcd_panel_io_handle_t io_handle, @@ -48,8 +124,12 @@ void common_hal_qspibus_qspibus_construct( self->data3_pin = data3->number; self->cs_pin = cs->number; self->reset_pin = (reset != NULL) ? reset->number : -1; + self->power_pin = -1; self->frequency = frequency; self->bus_initialized = false; + self->in_transaction = false; + self->has_pending_command = false; + self->pending_command = 0; self->transfer_done_sem = NULL; self->transfer_done_sem = xSemaphoreCreateBinary(); @@ -104,6 +184,18 @@ void common_hal_qspibus_qspibus_construct( claim_pin(data3); claim_pin(cs); + #ifdef CIRCUITPY_RM690B0_POWER + const mcu_pin_obj_t *power = CIRCUITPY_RM690B0_POWER; + if (power != NULL) { + self->power_pin = power->number; + claim_pin(power); + gpio_set_direction((gpio_num_t)self->power_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->power_pin, CIRCUITPY_RM690B0_POWER_ON_LEVEL ? 1 : 0); + // Panel power rail needs extra settle time before reset/init commands. + vTaskDelay(pdMS_TO_TICKS(200)); + } + #endif + if (reset != NULL) { claim_pin(reset); @@ -122,6 +214,9 @@ void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { return; } + qspibus_panel_sleep_best_effort(self); + self->in_transaction = false; + if (self->io_handle != NULL) { esp_lcd_panel_io_del(self->io_handle); self->io_handle = NULL; @@ -140,40 +235,120 @@ void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { reset_pin_number(self->data2_pin); reset_pin_number(self->data3_pin); reset_pin_number(self->cs_pin); + if (self->power_pin >= 0) { + reset_pin_number(self->power_pin); + } if (self->reset_pin >= 0) { reset_pin_number(self->reset_pin); } self->bus_initialized = false; + self->in_transaction = false; + self->has_pending_command = false; + self->pending_command = 0; } bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self) { return !self->bus_initialized; } -void common_hal_qspibus_qspibus_send( +void common_hal_qspibus_qspibus_send_command( qspibus_qspibus_obj_t *self, uint8_t command, const uint8_t *data, size_t len) { + qspibus_send_command_bytes(self, command, data, len); +} +bool common_hal_qspibus_qspibus_reset(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized || self->reset_pin < 0) { + return false; + } + + gpio_set_level((gpio_num_t)self->reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level((gpio_num_t)self->reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(120)); + return true; +} + +bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + return self->bus_initialized && !self->in_transaction; +} + +bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized || self->in_transaction) { + return false; + } + self->in_transaction = true; + self->has_pending_command = false; + self->pending_command = 0; + return true; +} + +void common_hal_qspibus_qspibus_send( + mp_obj_t obj, + display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, + const uint8_t *data, + uint32_t data_length) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + (void)chip_select; if (!self->bus_initialized) { mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); } + if (!self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Begin transaction first")); + } - uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); + if (data_type == DISPLAY_COMMAND) { + for (uint32_t i = 0; i < data_length; i++) { + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + } + self->pending_command = data[i]; + self->has_pending_command = true; + } + return; + } - esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); - if (err != ESP_OK) { - mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send failed: %d"), err); + if (!self->has_pending_command) { + if (data_length == 0) { + // Zero-length data write after a no-data command is benign. + return; + } + mp_raise_ValueError(MP_ERROR_TEXT("No pending command")); + } + + if (data_length == 0) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + return; } - // Some ESP-IDF paths complete tx_param synchronously and may not invoke - // the callback for parameter transfers. Try to sync via semaphore when - // available, but do not fail if no callback is emitted. - (void)xSemaphoreTake(self->transfer_done_sem, pdMS_TO_TICKS(1000)); + if (qspibus_is_color_payload_command(self->pending_command)) { + qspibus_send_color_bytes(self, self->pending_command, data, data_length); + } else { + qspibus_send_command_bytes(self, self->pending_command, data, data_length); + } + self->has_pending_command = false; +} + +void common_hal_qspibus_qspibus_end_transaction(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized) { + return; + } + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } + self->in_transaction = false; } -bool common_hal_qspibus_qspibus_bus_free(qspibus_qspibus_obj_t *self) { - return self->bus_initialized; +void common_hal_qspibus_qspibus_collect_ptrs(mp_obj_t obj) { + (void)obj; } diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.h b/ports/espressif/common-hal/qspibus/QSPIBus.h index f789aa3fd3485..ddca0809a781f 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.h +++ b/ports/espressif/common-hal/qspibus/QSPIBus.h @@ -31,9 +31,13 @@ typedef struct { int8_t data3_pin; int8_t cs_pin; int8_t reset_pin; // -1 when reset line is not provided. + int8_t power_pin; // -1 when board has no explicit display power pin. uint32_t frequency; bool bus_initialized; + bool in_transaction; + bool has_pending_command; + uint8_t pending_command; // Signaled from ISR when panel IO transfer completes. SemaphoreHandle_t transfer_done_sem; diff --git a/shared-bindings/qspibus/QSPIBus.h b/shared-bindings/qspibus/QSPIBus.h index 51a3e9f6c9631..608e81d1311b2 100644 --- a/shared-bindings/qspibus/QSPIBus.h +++ b/shared-bindings/qspibus/QSPIBus.h @@ -9,6 +9,8 @@ #include "py/obj.h" +#include "shared-bindings/displayio/__init__.h" + #include "common-hal/microcontroller/Pin.h" #include "common-hal/qspibus/QSPIBus.h" @@ -28,10 +30,20 @@ void common_hal_qspibus_qspibus_construct( void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self); bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self); -void common_hal_qspibus_qspibus_send( +void common_hal_qspibus_qspibus_send_command( qspibus_qspibus_obj_t *self, uint8_t command, const uint8_t *data, size_t len); -bool common_hal_qspibus_qspibus_bus_free(qspibus_qspibus_obj_t *self); +bool common_hal_qspibus_qspibus_reset(mp_obj_t obj); +bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj); +bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj); +void common_hal_qspibus_qspibus_send( + mp_obj_t obj, + display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, + const uint8_t *data, + uint32_t data_length); +void common_hal_qspibus_qspibus_end_transaction(mp_obj_t obj); +void common_hal_qspibus_qspibus_collect_ptrs(mp_obj_t obj); diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index ac57f3bf3e019..39bceb7eba494 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -16,6 +16,9 @@ #if CIRCUITPY_PARALLELDISPLAYBUS #include "shared-bindings/paralleldisplaybus/ParallelBus.h" #endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" @@ -254,6 +257,27 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are } } + #if CIRCUITPY_QSPIBUS + // RM690B0 over qspibus is unstable with single-row bursts. Keep chunks at + // two rows minimum when possible. + if (mp_obj_is_type(self->bus.bus, &qspibus_qspibus_type) && + self->core.colorspace.depth == 16 && + !self->bus.data_as_commands && + displayio_area_height(&clipped) > 1 && + rows_per_buffer < 2) { + rows_per_buffer = 2; + subrectangles = displayio_area_height(&clipped) / rows_per_buffer; + if (displayio_area_height(&clipped) % rows_per_buffer != 0) { + subrectangles++; + } + pixels_per_buffer = rows_per_buffer * displayio_area_width(&clipped); + buffer_size = pixels_per_buffer / pixels_per_word; + if (pixels_per_buffer % pixels_per_word) { + buffer_size += 1; + } + } + #endif + // Allocated and shared as a uint32_t array so the compiler knows the // alignment everywhere. uint32_t buffer[buffer_size]; diff --git a/shared-module/displayio/bus_core.c b/shared-module/displayio/bus_core.c index e01b9d9eef685..05e83f358ad21 100644 --- a/shared-module/displayio/bus_core.c +++ b/shared-module/displayio/bus_core.c @@ -17,6 +17,9 @@ #if CIRCUITPY_PARALLELDISPLAYBUS #include "shared-bindings/paralleldisplaybus/ParallelBus.h" #endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" @@ -69,6 +72,16 @@ void displayio_display_bus_construct(displayio_display_bus_t *self, self->collect_ptrs = common_hal_fourwire_fourwire_collect_ptrs; } else #endif + #if CIRCUITPY_QSPIBUS + if (mp_obj_is_type(bus, &qspibus_qspibus_type)) { + self->bus_reset = common_hal_qspibus_qspibus_reset; + self->bus_free = common_hal_qspibus_qspibus_bus_free; + self->begin_transaction = common_hal_qspibus_qspibus_begin_transaction; + self->send = common_hal_qspibus_qspibus_send; + self->end_transaction = common_hal_qspibus_qspibus_end_transaction; + self->collect_ptrs = common_hal_qspibus_qspibus_collect_ptrs; + } else + #endif #if CIRCUITPY_I2CDISPLAYBUS if (mp_obj_is_type(bus, &i2cdisplaybus_i2cdisplaybus_type)) { self->bus_reset = common_hal_i2cdisplaybus_i2cdisplaybus_reset; From 0bc16e1ec552f329c1b53ad5fc9cb714641df9eb Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 6 Feb 2026 16:29:08 +0100 Subject: [PATCH 13/38] Phase 4: remove standalone rm690b0 module and keep displayio path BREAKING CHANGE: standalone rm690b0 API removed from firmware. - removed shared-bindings/common-hal standalone sources and built-in fonts - retained vendor files: esp_lcd_rm690b0.* and esp_jpeg/* - updated build config and board pin aliases to LCD_* + qspibus path - verified firmware: no rm690b0 module strings, qspibus present --- README.rst | 38 + ports/espressif/Makefile | 10 - .../mpconfigboard.h | 28 +- .../mpconfigboard.mk | 5 +- .../waveshare_esp32_s3_amoled_241/pins.c | 17 +- ports/espressif/common-hal/qspibus/QSPIBus.c | 20 +- ports/espressif/common-hal/rm690b0/RM690B0.c | 3762 ----------------- ports/espressif/common-hal/rm690b0/RM690B0.h | 26 - .../rm690b0/fonts/rm690b0_font_16x16.h | 494 --- .../rm690b0/fonts/rm690b0_font_16x24.h | 589 --- .../rm690b0/fonts/rm690b0_font_24x24.h | 779 ---- .../rm690b0/fonts/rm690b0_font_24x32.h | 874 ---- .../rm690b0/fonts/rm690b0_font_32x32.h | 1064 ----- .../rm690b0/fonts/rm690b0_font_32x48.h | 1444 ------- .../rm690b0/fonts/rm690b0_font_8x8.h | 205 - py/circuitpy_defns.mk | 9 +- py/circuitpy_mpconfig.mk | 4 +- shared-bindings/rm690b0/RM690B0.c | 513 --- shared-bindings/rm690b0/RM690B0.h | 50 - shared-bindings/rm690b0/__init__.c | 93 - 20 files changed, 81 insertions(+), 9943 deletions(-) delete mode 100644 ports/espressif/common-hal/rm690b0/RM690B0.c delete mode 100644 ports/espressif/common-hal/rm690b0/RM690B0.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x16.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h delete mode 100644 ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h delete mode 100644 shared-bindings/rm690b0/RM690B0.c delete mode 100644 shared-bindings/rm690b0/RM690B0.h delete mode 100644 shared-bindings/rm690b0/__init__.c diff --git a/README.rst b/README.rst index 80aa1b2aee282..d7e549bd817d8 100644 --- a/README.rst +++ b/README.rst @@ -10,6 +10,44 @@ CircuitPython `Branding <#branding>`__ \| `Differences from Micropython <#differences-from-micropython>`__ \| `Project Structure <#project-structure>`__ +Breaking Changes (v2.0) +----------------------- + +The standalone ``rm690b0`` module was removed in favor of ``displayio + qspibus`` integration. + +Migration is required for all code that used ``import rm690b0``. + +Old API (no longer available):: + + import rm690b0 + rm690b0.init_display() + rm690b0.fill_color(rm690b0.RED) + rm690b0.swap_buffers() + +New API (v2.0+):: + + import board + import displayio + import qspibus + from adafruit_rm690b0 import RM690B0 + + displayio.release_displays() + bus = qspibus.QSPIBus( + clock=board.LCD_CLK, + data0=board.LCD_D0, + data1=board.LCD_D1, + data2=board.LCD_D2, + data3=board.LCD_D3, + cs=board.LCD_CS, + reset=board.LCD_RESET, + frequency=40_000_000, + ) + panel = RM690B0(bus, width=600, height=450) + display = displayio.Display(panel, width=600, height=450) + +For migration details, see: +``/home/pps/Downloads/__ai__/repos/ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md``. + **CircuitPython** is a *beginner friendly*, open source version of Python for tiny, inexpensive computers called microcontrollers. Microcontrollers are the brains of many electronics including a wide variety of development boards used to build hobby projects and prototypes. CircuitPython in diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index d42c6cf22fcfa..5d2a9cb3eda61 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -516,16 +516,6 @@ SRC_ULP := \ SRC_C += $(SRC_ULP) endif -ifneq ($(CIRCUITPY_RM690B0),0) -SRC_RM690B0 := \ - $(wildcard common-hal/rm690b0/*.c) \ - $(wildcard common-hal/rm690b0/esp_jpeg/*.c) -SRC_C += $(SRC_RM690B0) -INC += -Icommon-hal/rm690b0/esp_jpeg -# TJpgDec is needed for the esp_jpeg shim -INC += -I../../lib/tjpgd -endif - ifneq ($(CIRCUITPY_NEOPIXEL_WRITE),0) CHIP_COMPONENTS += esp_driver_rmt endif diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h index bfd4e93362fdb..7844a6eb5f486 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -17,23 +17,17 @@ #define CIRCUITPY_BOARD_I2C (0) #define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}} -// AMOLED Display -#define CIRCUITPY_BOARD_DISPLAY 1 -#define CIRCUITPY_DISPLAY_INIT_SEQUENCE rm690b0_rm690b0_init_sequence -#define CIRCUITPY_RM690B0_QSPI_CS (&pin_GPIO9) -#define CIRCUITPY_RM690B0_QSPI_CLK (&pin_GPIO10) -#define CIRCUITPY_RM690B0_QSPI_D0 (&pin_GPIO11) -#define CIRCUITPY_RM690B0_QSPI_D1 (&pin_GPIO12) -#define CIRCUITPY_RM690B0_QSPI_D2 (&pin_GPIO13) -#define CIRCUITPY_RM690B0_QSPI_D3 (&pin_GPIO14) -#define CIRCUITPY_RM690B0_RESET (&pin_GPIO21) -#define CIRCUITPY_RM690B0_POWER (&pin_GPIO16) -#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low -#define CIRCUITPY_RM690B0_WIDTH (600) -#define CIRCUITPY_RM690B0_HEIGHT (450) -#define CIRCUITPY_RM690B0_BITS_PER_PIXEL (16) -#define CIRCUITPY_RM690B0_USE_QSPI (1) -#define CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ (80 * 1000 * 1000) +// AMOLED Display (displayio + qspibus path) +#define CIRCUITPY_BOARD_DISPLAY (0) +#define CIRCUITPY_LCD_CS (&pin_GPIO9) +#define CIRCUITPY_LCD_CLK (&pin_GPIO10) +#define CIRCUITPY_LCD_D0 (&pin_GPIO11) +#define CIRCUITPY_LCD_D1 (&pin_GPIO12) +#define CIRCUITPY_LCD_D2 (&pin_GPIO13) +#define CIRCUITPY_LCD_D3 (&pin_GPIO14) +#define CIRCUITPY_LCD_RESET (&pin_GPIO21) +#define CIRCUITPY_LCD_POWER (&pin_GPIO16) +#define CIRCUITPY_LCD_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low // SPI bus for SD Card #define CIRCUITPY_BOARD_SPI (1) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index c8675ebc13d96..ffd216538b830 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -25,7 +25,7 @@ CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m -# Add extra ESP-IDF components needed for board_init.c and rm690b0 module +# Add extra ESP-IDF components needed for board bring-up and display stack ESP_IDF_EXTRA_COMPONENTS += driver freertos esp_lcd sdmmc esp_driver_sdmmc esp_driver_sdspi # Build optimization @@ -40,7 +40,8 @@ CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_BITMAPTOOLS = 1 CIRCUITPY_JPEGIO = 1 CIRCUITPY_FRAMEBUFFERIO = 1 -CIRCUITPY_RM690B0 = 1 +# RM690B0 standalone module removed in Phase 4. +# Display path is now: qspibus + displayio + user-space panel driver. # Enable ESP-NOW for peer-to-peer wireless communication CIRCUITPY_ESPNOW = 1 diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c index 0098ecfc64fa0..8f24f8b067cd9 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -5,14 +5,8 @@ #include "py/obj.h" #include "py/mphal.h" #include "shared-bindings/board/__init__.h" -#include "shared-bindings/fourwire/FourWire.h" -#include "shared-bindings/rm690b0/RM690B0.h" #include "shared-bindings/microcontroller/Pin.h" -const rm690b0_rm690b0_obj_t rm690b0_rm690b0_init_sequence = { - .base = {&rm690b0_rm690b0_type}, -}; - static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS @@ -58,7 +52,16 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, - // QSPI Display (RM690B0) + // QSPI Display (RM690B0) - canonical generic LCD aliases. + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO21) }, + + // Backward-compatible aliases used by existing tests/scripts. { MP_ROM_QSTR(MP_QSTR_QSPI_CS), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_QSPI_CLK), MP_ROM_PTR(&pin_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_QSPI_D0), MP_ROM_PTR(&pin_GPIO11) }, diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 02eb03a6ba7be..a36f4cee6da7d 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -19,8 +19,18 @@ #define LCD_CMD_RAMWRC (0x3CU) #define LCD_CMD_DISPOFF (0x28U) #define LCD_CMD_SLPIN (0x10U) -#ifndef CIRCUITPY_RM690B0_POWER_ON_LEVEL -#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (1) +#if defined(CIRCUITPY_LCD_POWER) +#define CIRCUITPY_QSPIBUS_PANEL_POWER_PIN CIRCUITPY_LCD_POWER +#elif defined(CIRCUITPY_RM690B0_POWER) +#define CIRCUITPY_QSPIBUS_PANEL_POWER_PIN CIRCUITPY_RM690B0_POWER +#endif + +#ifndef CIRCUITPY_LCD_POWER_ON_LEVEL + #if defined(CIRCUITPY_RM690B0_POWER_ON_LEVEL) + #define CIRCUITPY_LCD_POWER_ON_LEVEL CIRCUITPY_RM690B0_POWER_ON_LEVEL + #else + #define CIRCUITPY_LCD_POWER_ON_LEVEL (1) + #endif #endif static void qspibus_send_command_bytes( @@ -184,13 +194,13 @@ void common_hal_qspibus_qspibus_construct( claim_pin(data3); claim_pin(cs); - #ifdef CIRCUITPY_RM690B0_POWER - const mcu_pin_obj_t *power = CIRCUITPY_RM690B0_POWER; + #ifdef CIRCUITPY_QSPIBUS_PANEL_POWER_PIN + const mcu_pin_obj_t *power = CIRCUITPY_QSPIBUS_PANEL_POWER_PIN; if (power != NULL) { self->power_pin = power->number; claim_pin(power); gpio_set_direction((gpio_num_t)self->power_pin, GPIO_MODE_OUTPUT); - gpio_set_level((gpio_num_t)self->power_pin, CIRCUITPY_RM690B0_POWER_ON_LEVEL ? 1 : 0); + gpio_set_level((gpio_num_t)self->power_pin, CIRCUITPY_LCD_POWER_ON_LEVEL ? 1 : 0); // Panel power rail needs extra settle time before reset/init commands. vTaskDelay(pdMS_TO_TICKS(200)); } diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.c b/ports/espressif/common-hal/rm690b0/RM690B0.c deleted file mode 100644 index 76415f34945ba..0000000000000 --- a/ports/espressif/common-hal/rm690b0/RM690B0.c +++ /dev/null @@ -1,3762 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include "shared-bindings/rm690b0/RM690B0.h" -#include "common-hal/rm690b0/RM690B0.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "py/runtime.h" -#include "py/mperrno.h" - -#include "esp_log.h" -#include "driver/gpio.h" -#include "driver/spi_master.h" -#include "esp_heap_caps.h" -#include "esp_rom_sys.h" - -static const char *TAG = "rm690b0"; - -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_vendor.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_ops.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_commands.h" -#include "esp_lcd_rm690b0.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include -#include -#include -#include -#include "esp_attr.h" -#include "esp_jpeg.h" -#include "fonts/rm690b0_font_8x8.h" -#include "fonts/rm690b0_font_16x16.h" -#include "fonts/rm690b0_font_16x24.h" -#include "fonts/rm690b0_font_24x24.h" -#include "fonts/rm690b0_font_24x32.h" -#include "fonts/rm690b0_font_32x32.h" -#include "fonts/rm690b0_font_32x48.h" - -#if !defined(CIRCUITPY_RM690B0_QSPI_CS) || !defined(CIRCUITPY_RM690B0_QSPI_CLK) || \ - !defined(CIRCUITPY_RM690B0_QSPI_D0) || !defined(CIRCUITPY_RM690B0_QSPI_D1) || \ - !defined(CIRCUITPY_RM690B0_QSPI_D2) || !defined(CIRCUITPY_RM690B0_QSPI_D3) || \ - !defined(CIRCUITPY_RM690B0_RESET) || !defined(CIRCUITPY_RM690B0_WIDTH) || \ - !defined(CIRCUITPY_RM690B0_HEIGHT) || !defined(CIRCUITPY_RM690B0_BITS_PER_PIXEL) -#error "Board must define CIRCUITPY_RM690B0_* macros to describe the RM690B0 hardware" -#endif - -#ifndef CIRCUITPY_RM690B0_POWER -#define CIRCUITPY_RM690B0_POWER (NULL) -#endif - -#ifndef CIRCUITPY_RM690B0_POWER_ON_LEVEL -#define CIRCUITPY_RM690B0_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low -#endif - -#ifndef CIRCUITPY_RM690B0_USE_QSPI -#define CIRCUITPY_RM690B0_USE_QSPI (0) -#endif - -#ifndef CIRCUITPY_RM690B0_X_GAP -#define CIRCUITPY_RM690B0_X_GAP (0) -#endif - -#ifndef CIRCUITPY_RM690B0_Y_GAP -#define CIRCUITPY_RM690B0_Y_GAP (16) -#endif - -#ifndef CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ -#define CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ (80 * 1000 * 1000) -#endif - -#define PIN_GPIO(pin_obj) ((pin_obj) == NULL ? (gpio_num_t)GPIO_NUM_NC : (gpio_num_t)(pin_obj)->number) - -#define LCD_CS_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_CS) -#define LCD_SCK_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_CLK) -#define LCD_D0_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D0) -#define LCD_D1_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D1) -#define LCD_D2_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D2) -#define LCD_D3_PIN PIN_GPIO(CIRCUITPY_RM690B0_QSPI_D3) -#define LCD_RST_PIN PIN_GPIO(CIRCUITPY_RM690B0_RESET) -#define LCD_PWR_PIN PIN_GPIO(CIRCUITPY_RM690B0_POWER) -#define LCD_PWR_ON_LEVEL (CIRCUITPY_RM690B0_POWER_ON_LEVEL) - -#define LCD_H_RES (CIRCUITPY_RM690B0_WIDTH) -#define LCD_V_RES (CIRCUITPY_RM690B0_HEIGHT) -#define LCD_BIT_PER_PIXEL (CIRCUITPY_RM690B0_BITS_PER_PIXEL) -#define LCD_USE_QSPI (CIRCUITPY_RM690B0_USE_QSPI) -#define LCD_PIXEL_CLOCK_HZ (CIRCUITPY_RM690B0_PIXEL_CLOCK_HZ) - -#define RGB565_SWAP_GB(c) (__builtin_bswap16(c)) - -#define RM690B0_OPCODE_WRITE_CMD (0x02U) - -#define RM690B0_PANEL_WIDTH LCD_H_RES -#define RM690B0_PANEL_HEIGHT LCD_V_RES -#define RM690B0_X_GAP (CIRCUITPY_RM690B0_X_GAP) -#define RM690B0_Y_GAP (CIRCUITPY_RM690B0_Y_GAP) -#define RM690B0_MAX_CHUNK_ROWS (24) -#define RM690B0_MAX_CHUNK_PIXELS (LCD_H_RES * RM690B0_MAX_CHUNK_ROWS) -#define RM690B0_MAX_DIAMETER ((RM690B0_PANEL_WIDTH * 2) + 1) -#define RM690B0_PANEL_IO_QUEUE_DEPTH (10) - -#define RM690B0_PENDING_BUFFER_FRAMEBUFFER (0xFF) -#define RM690B0_PENDING_BUFFER_ALLOC (0xFE) -#define RM690B0_PENDING_BUFFER_TEMP (0xFD) - -// Built-in font identifiers (must match shared-bindings docs) -#define RM690B0_FONT_8x8_MONO (0) -#define RM690B0_FONT_16x16_MONO (1) -#define RM690B0_FONT_16x24_MONO (2) -#define RM690B0_FONT_24x24_MONO (3) -#define RM690B0_FONT_24x32_MONO (4) -#define RM690B0_FONT_32x32_MONO (5) -#define RM690B0_FONT_32x48_MONO (6) - -// Macro to check if display is initialized -#define CHECK_INITIALIZED() \ - do { \ - if (!self->initialized) { \ - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Display not initialized. Call init_display() first")); \ - return; \ - } \ - } while (0) - -// Internal implementation structure -typedef struct { - mp_int_t top; - mp_int_t row_count; - int16_t *left; - int16_t *right; -} rm690b0_span_accumulator_t; - -typedef struct { - size_t head; - size_t tail; - size_t count; - uint8_t ids[RM690B0_PANEL_IO_QUEUE_DEPTH]; -} rm690b0_dma_pending_list_t; - -typedef struct rm690b0_impl { - esp_lcd_panel_io_handle_t io_handle; - esp_lcd_panel_handle_t panel_handle; - bool bus_initialized; - uint16_t *chunk_buffers[2]; - size_t chunk_buffer_pixels; - uint16_t *framebuffer; - size_t framebuffer_pixels; - uint16_t *framebuffer_front; - bool double_buffered; - bool dirty_region_valid; - mp_int_t dirty_x; - mp_int_t dirty_y; - mp_int_t dirty_w; - mp_int_t dirty_h; - SemaphoreHandle_t transfer_done_sem; - bool dma_buffer_in_use[2]; - bool dma_alloc_buffer_in_use; - size_t dma_inflight; - rm690b0_dma_pending_list_t dma_pending; - int16_t *circle_span_cache; - size_t circle_span_capacity; -} rm690b0_impl_t; -typedef struct { - rm690b0_rm690b0_obj_t *self; - rm690b0_impl_t *impl; - mp_int_t origin_x; - mp_int_t origin_y; - mp_int_t clip_x; - mp_int_t clip_y; - mp_int_t clip_w; - mp_int_t clip_h; - bool rotation_zero; -} rm690b0_jpeg_draw_ctx_t; - - -static portMUX_TYPE rm690b0_spinlock = portMUX_INITIALIZER_UNLOCKED; - -static inline void rm690b0_dma_pending_init(rm690b0_dma_pending_list_t *list) { - list->head = 0; - list->tail = 0; - list->count = 0; -} - -static inline void rm690b0_dma_pending_push(rm690b0_dma_pending_list_t *list, uint8_t id) { - portENTER_CRITICAL(&rm690b0_spinlock); - list->ids[list->tail] = id; - list->tail = (list->tail + 1) % RM690B0_PANEL_IO_QUEUE_DEPTH; - list->count++; - portEXIT_CRITICAL(&rm690b0_spinlock); -} - -static inline uint8_t rm690b0_dma_pending_pop(rm690b0_dma_pending_list_t *list) { - portENTER_CRITICAL(&rm690b0_spinlock); - uint8_t id = list->ids[list->head]; - list->head = (list->head + 1) % RM690B0_PANEL_IO_QUEUE_DEPTH; - list->count--; - portEXIT_CRITICAL(&rm690b0_spinlock); - return id; -} - -static inline void rm690b0_wait_for_dma_completion(rm690b0_impl_t *impl) { - if (impl->dma_inflight == 0) { - return; - } - - if (impl->transfer_done_sem) { - if (xSemaphoreTake(impl->transfer_done_sem, pdMS_TO_TICKS(1000)) != pdTRUE) { - ESP_LOGE("RM690B0", "DMA wait timeout! Halting to prevent memory corruption."); - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("DMA transfer timed out - hardware requires reset")); - return; - } - } else { - // Fallback - should not happen because semaphore allocation is mandatory - esp_rom_delay_us(50); - } - - if (impl->dma_inflight > 0) { - impl->dma_inflight--; - } - - if (impl->dma_pending.count > 0) { - uint8_t id = rm690b0_dma_pending_pop(&impl->dma_pending); - if (id < 2) { - impl->dma_buffer_in_use[id] = false; - } else if (id == RM690B0_PENDING_BUFFER_ALLOC) { - impl->dma_alloc_buffer_in_use = false; - } - // RM690B0_PENDING_BUFFER_TEMP is explicitly ignored - it's locally managed - } - -} - -static inline void rm690b0_wait_for_dma_slot(rm690b0_impl_t *impl) { - while (impl->dma_inflight >= RM690B0_PANEL_IO_QUEUE_DEPTH) { - rm690b0_wait_for_dma_completion(impl); - } -} - -static inline void rm690b0_wait_for_all_dma(rm690b0_impl_t *impl) { - while (impl->dma_inflight > 0) { - rm690b0_wait_for_dma_completion(impl); - } -} - -// (rm690b0_text_state_t typedefs removed – not used yet) - -// Forward declarations for functions used by font rendering -static void mark_dirty_region(rm690b0_impl_t *impl, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h); -static esp_err_t rm690b0_flush_region(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, bool skip_final_delay); -static void rm690b0_fill_rect_framebuffer(rm690b0_impl_t *impl, - mp_int_t bx, mp_int_t by, mp_int_t bw, mp_int_t bh, uint16_t swapped_color); - -// Callback for LCD IO transfer completion -static bool IRAM_ATTR rm690b0_on_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) { - rm690b0_impl_t *impl = (rm690b0_impl_t *)user_ctx; - BaseType_t high_task_awoken = pdFALSE; - xSemaphoreGiveFromISR(impl->transfer_done_sem, &high_task_awoken); - return high_task_awoken == pdTRUE; -} - - - -static inline void rm690b0_span_update(rm690b0_span_accumulator_t *acc, mp_int_t row_y, mp_int_t x_val) { - mp_int_t idx = row_y - acc->top; - if (idx < 0 || idx >= acc->row_count) { - return; - } - if (x_val < acc->left[idx]) { - acc->left[idx] = (int16_t)x_val; - } - if (x_val > acc->right[idx]) { - acc->right[idx] = (int16_t)x_val; - } -} - -static inline int16_t *rm690b0_acquire_span_cache(rm690b0_impl_t *impl, size_t needed_rows) { - if (impl == NULL || needed_rows == 0) { - return NULL; - } - - if (impl->circle_span_capacity < needed_rows) { - size_t new_capacity = needed_rows; - size_t total_entries = new_capacity * 2; - int16_t *new_cache = (int16_t *)heap_caps_realloc( - impl->circle_span_cache, - total_entries * sizeof(int16_t), - MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - if (new_cache == NULL) { - return NULL; - } - impl->circle_span_cache = new_cache; - impl->circle_span_capacity = new_capacity; - } - return impl->circle_span_cache; -} - -static inline void rm690b0_fill_span_fast(uint16_t *dest, size_t span_width, uint16_t color) { - if (span_width == 0) { - return; - } - - if (((uintptr_t)dest & 0x2) != 0) { - *dest++ = color; - span_width--; - if (span_width == 0) { - return; - } - } - - while (span_width >= 2) { - dest[0] = color; - dest[1] = color; - dest += 2; - span_width -= 2; - } - - if (span_width & 1) { - *dest = color; - } -} - -static bool map_rect_for_rotation(const rm690b0_rm690b0_obj_t *self, - mp_int_t *x, mp_int_t *y, - mp_int_t *width, mp_int_t *height) { - mp_int_t rx = *x; - mp_int_t ry = *y; - mp_int_t rw = *width; - mp_int_t rh = *height; - - switch (self->rotation) { - case 0: - break; - case 90: - *x = RM690B0_PANEL_WIDTH - (ry + rh); - *y = rx; - *width = rh; - *height = rw; - break; - case 180: - *x = RM690B0_PANEL_WIDTH - (rx + rw); - *y = RM690B0_PANEL_HEIGHT - (ry + rh); - break; - case 270: - *x = ry; - *y = RM690B0_PANEL_HEIGHT - (rx + rw); - *width = rh; - *height = rw; - break; - default: - return false; - } - - if (*width <= 0 || *height <= 0) { - return false; - } - return true; -} - -// Helper function to safely check bitmap size and detect overflow -// Uses 64-bit arithmetic to accurately detect overflow on both 32-bit and 64-bit systems -static inline bool check_bitmap_size(size_t width, size_t height, size_t *out_bytes) { - // Use 64-bit arithmetic for accurate overflow detection - uint64_t pixels = (uint64_t)width * (uint64_t)height; - uint64_t bytes = pixels * sizeof(uint16_t); - - // Check if result fits in size_t - if (bytes > SIZE_MAX) { - return false; - } - - *out_bytes = (size_t)bytes; - return true; -} - -static bool clip_logical_rect(const rm690b0_rm690b0_obj_t *self, - mp_int_t *x, mp_int_t *y, - mp_int_t *width, mp_int_t *height) { - if (*width <= 0 || *height <= 0) { - return false; - } - - mp_int_t x0 = *x; - mp_int_t y0 = *y; - mp_int_t x1 = x0 + *width; - mp_int_t y1 = y0 + *height; - - if (x1 <= 0 || y1 <= 0 || x0 >= self->width || y0 >= self->height) { - return false; - } - - if (x0 < 0) { - x0 = 0; - } - if (y0 < 0) { - y0 = 0; - } - if (x1 > self->width) { - x1 = self->width; - } - if (y1 > self->height) { - y1 = self->height; - } - - mp_int_t new_width = x1 - x0; - mp_int_t new_height = y1 - y0; - if (new_width <= 0 || new_height <= 0) { - return false; - } - - *x = x0; - *y = y0; - *width = new_width; - *height = new_height; - return true; -} - -static inline mp_int_t clamp_int(mp_int_t v, mp_int_t lo, mp_int_t hi) { - return v < lo ? lo : (v > hi ? hi : v); -} - -// Compile-time assertions to ensure fallback character '?' exists in all fonts -_Static_assert('?' >= 32 && '?' <= 127, "Fallback character '?' must be in font range"); -_Static_assert(sizeof(rm690b0_font_8x8_data) / sizeof(rm690b0_font_8x8_data[0]) == 96, - "Font 8x8 must have exactly 96 glyphs (0x20-0x7F)"); -_Static_assert(sizeof(rm690b0_font_16x16_data) / sizeof(rm690b0_font_16x16_data[0]) == 95, - "Font 16x16 must have exactly 95 glyphs (0x20-0x7E)"); - -static inline const uint8_t *rm690b0_get_8x8_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7F (127) = 96 characters - if (codepoint < 32 || codepoint > 127) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 127] - } - // Safe array access: index range [0, 95] - return rm690b0_font_8x8_data[codepoint - 32]; -} - -static inline const uint8_t *rm690b0_get_16x16_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7E (126) = 95 characters - if (codepoint < 32 || codepoint > 126) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] - } - // Safe array access: index range [0, 94] - return rm690b0_font_16x16_data[codepoint - 32]; -} - -static inline const uint8_t *rm690b0_get_16x24_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7E (126) = 95 characters - if (codepoint < 32 || codepoint > 126) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] - } - // Safe array access: index range [0, 94] - return rm690b0_font_16x24_data[codepoint - 32]; -} - -static inline const uint8_t *rm690b0_get_24x24_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7E (126) = 95 characters - if (codepoint < 32 || codepoint > 126) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] - } - // Safe array access: index range [0, 94] - return rm690b0_font_24x24_data[codepoint - 32]; -} - -static inline const uint8_t *rm690b0_get_24x32_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7E (126) = 95 characters - if (codepoint < 32 || codepoint > 126) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] - } - // Safe array access: index range [0, 94] - return rm690b0_font_24x32_data[codepoint - 32]; -} - -static inline const uint8_t *rm690b0_get_32x32_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7E (126) = 95 characters - if (codepoint < 32 || codepoint > 126) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] - } - // Safe array access: index range [0, 94] - return rm690b0_font_32x32_data[codepoint - 32]; -} - -static inline const uint8_t *rm690b0_get_32x48_glyph(uint32_t codepoint) { - // Validate codepoint range and use fallback for invalid characters - // Font range: 0x20 (32) to 0x7E (126) = 95 characters - if (codepoint < 32 || codepoint > 126) { - codepoint = '?'; // ASCII 63, guaranteed to be in range [32, 126] - } - // Safe array access: index range [0, 94] - return rm690b0_font_32x48_data[codepoint - 32]; -} - -// ============================================================================ -// OPTIMIZED FONT RENDERING - Universal rotation-aware batch write -// ============================================================================ - -/** - * Write a pixel to framebuffer with rotation support. - * This inline helper handles all 4 rotations in one place. - * Compiler will optimize this heavily for rotation=0 case. - */ -static inline void rm690b0_write_pixel_rotated( - rm690b0_rm690b0_obj_t *self, - rm690b0_impl_t *impl, - mp_int_t logical_x, mp_int_t logical_y, - uint16_t color) { - - uint16_t *framebuffer = impl->framebuffer; - size_t fb_stride = RM690B0_PANEL_WIDTH; - - mp_int_t phys_x, phys_y; - - // Transform logical coordinates to physical based on rotation - switch (self->rotation) { - case 0: - phys_x = logical_x; - phys_y = logical_y; - break; - case 90: - phys_x = RM690B0_PANEL_WIDTH - logical_y - 1; - phys_y = logical_x; - break; - case 180: - phys_x = RM690B0_PANEL_WIDTH - logical_x - 1; - phys_y = RM690B0_PANEL_HEIGHT - logical_y - 1; - break; - case 270: - phys_x = logical_y; - phys_y = RM690B0_PANEL_HEIGHT - logical_x - 1; - break; - default: - return; // Invalid rotation - } - - // Bounds check - if (phys_x < 0 || phys_x >= RM690B0_PANEL_WIDTH || - phys_y < 0 || phys_y >= RM690B0_PANEL_HEIGHT) { - return; - } - - // Direct write to framebuffer - framebuffer[phys_y * fb_stride + phys_x] = color; -} - -static void rm690b0_draw_glyph_8x8(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 8 <= 0 || y + 8 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 8 > self->width) ? (self->width - x) : 8; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 8 > self->height) ? (self->height - y) : 8; - - // Pre-swap colors once (not per-pixel) - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - // Batch write to framebuffer with rotation support (only visible pixels) - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint8_t bits = glyph[row]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - - // 90deg: phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1 - // phys_y = x + col - // index = (x + col) * stride + (PANEL_WIDTH - y - row - 1) - - for (int row = row_start; row < row_end; row++) { - uint8_t bits = glyph[row]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - // Base index for col=0. As col increases, phys_y increases, so index increases by stride. - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; // phys_y increments - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - - // 180deg: phys_x = RM690B0_PANEL_WIDTH - (x + col) - 1 - // phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1 - - for (int row = row_start; row < row_end; row++) { - uint8_t bits = glyph[row]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - - // As col increases, phys_x decreases, index decreases by 1 - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; // phys_x decrements - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - - // 270deg: phys_x = y + row - // phys_y = RM690B0_PANEL_HEIGHT - (x + col) - 1 - - for (int row = row_start; row < row_end; row++) { - uint8_t bits = glyph[row]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - - // As col increases, phys_y decreases, index decreases by stride - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; // phys_y decrements - } - } - } - - // Mark dirty region and flush once (not per-pixel) - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 8, dirty_h = 8; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -static void rm690b0_draw_glyph_16x16(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 16 <= 0 || y + 16 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 16 > self->width) ? (self->width - x) : 16; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 16 > self->height) ? (self->height - y) : 16; - - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; - } - } - } - - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 16, dirty_h = 16; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph 16x16 flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -static void rm690b0_draw_glyph_16x24(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 16 <= 0 || y + 24 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 16 > self->width) ? (self->width - x) : 16; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 24 > self->height) ? (self->height - y) : 24; - - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint16_t bits = ((uint16_t)glyph[row * 2] << 8) | glyph[row * 2 + 1]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x8000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; - } - } - } - - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 16, dirty_h = 24; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph 16x24 flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -static void rm690b0_draw_glyph_24x24(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 24 <= 0 || y + 24 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 24 > self->width) ? (self->width - x) : 24; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 24 > self->height) ? (self->height - y) : 24; - - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; - } - } - } - - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 24, dirty_h = 24; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph 24x24 flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -static void rm690b0_draw_glyph_24x32(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 24 <= 0 || y + 32 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 24 > self->width) ? (self->width - x) : 24; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 32 > self->height) ? (self->height - y) : 32; - - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 3] << 16) | - ((uint32_t)glyph[row * 3 + 1] << 8) | - glyph[row * 3 + 2]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x800000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; - } - } - } - - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 24, dirty_h = 32; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph 24x32 flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -static void rm690b0_draw_glyph_32x32(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 32 <= 0 || y + 32 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 32 > self->width) ? (self->width - x) : 32; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 32 > self->height) ? (self->height - y) : 32; - - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; - } - } - } - - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 32, dirty_h = 32; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph 32x32 flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -static void rm690b0_draw_glyph_32x48(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, - const uint8_t *glyph, - uint16_t fg, bool has_bg, uint16_t bg, bool auto_flush) { - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - // Early exit: check if glyph is completely off-screen - if (x >= self->width || y >= self->height || x + 32 <= 0 || y + 48 <= 0) { - return; - } - - // Calculate clipping bounds - mp_int_t col_start = (x < 0) ? -x : 0; - mp_int_t col_end = (x + 32 > self->width) ? (self->width - x) : 32; - mp_int_t row_start = (y < 0) ? -y : 0; - mp_int_t row_end = (y + 48 > self->height) ? (self->height - y) : 48; - - uint16_t fg_swapped = RGB565_SWAP_GB(fg); - uint16_t bg_swapped = has_bg ? RGB565_SWAP_GB(bg) : 0; - - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - size_t row_offset = (size_t)(y + row) * fb_stride + (x + col_start); - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[row_offset + (col - col_start)] = fg_swapped; - } else if (has_bg) { - fb_ptr[row_offset + (col - col_start)] = bg_swapped; - } - } - } - } else if (self->rotation == 90) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - mp_int_t phys_x = RM690B0_PANEL_WIDTH - (y + row) - 1; - size_t start_index = (size_t)(x + col_start) * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index += fb_stride; - } - } - } else if (self->rotation == 180) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - mp_int_t phys_y = RM690B0_PANEL_HEIGHT - (y + row) - 1; - mp_int_t phys_x_start = RM690B0_PANEL_WIDTH - (x + col_start) - 1; - size_t start_index = (size_t)phys_y * fb_stride + phys_x_start; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index--; - } - } - } else if (self->rotation == 270) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb_ptr = impl->framebuffer; - for (int row = row_start; row < row_end; row++) { - uint32_t bits = ((uint32_t)glyph[row * 4] << 24) | - ((uint32_t)glyph[row * 4 + 1] << 16) | - ((uint32_t)glyph[row * 4 + 2] << 8) | - glyph[row * 4 + 3]; - mp_int_t phys_x = y + row; - mp_int_t phys_y_start = RM690B0_PANEL_HEIGHT - (x + col_start) - 1; - size_t start_index = (size_t)phys_y_start * fb_stride + phys_x; - for (int col = col_start; col < col_end; col++) { - bool on = (bits & (0x80000000 >> col)) != 0; - if (on) { - fb_ptr[start_index] = fg_swapped; - } else if (has_bg) { - fb_ptr[start_index] = bg_swapped; - } - start_index -= fb_stride; - } - } - } - - mp_int_t dirty_x = x, dirty_y = y, dirty_w = 32, dirty_h = 48; - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - mark_dirty_region(impl, dirty_x, dirty_y, dirty_w, dirty_h); - - if (auto_flush && !impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Glyph 32x48 flush failed: %s", esp_err_to_name(ret)); - } - } - } -} - -// NOTE: Text state is currently stateless per-instance in C; we use a static variable -// for font id to avoid changing struct layout. 0 = 8x8 monospace. -void common_hal_rm690b0_rm690b0_set_font(rm690b0_rm690b0_obj_t *self, mp_int_t font_id) { - // Clamp to known range - if (font_id < RM690B0_FONT_8x8_MONO || font_id > RM690B0_FONT_32x48_MONO) { - font_id = RM690B0_FONT_8x8_MONO; - } - // Store in object instance - self->font_id = font_id; -} - -static inline mp_int_t rm690b0_get_current_font(const rm690b0_rm690b0_obj_t *self) { - return self->font_id; -} - -void common_hal_rm690b0_rm690b0_text(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, - const char *text, size_t text_len, uint16_t fg, bool has_bg, uint16_t bg) { - - CHECK_INITIALIZED(); - - if (text_len == 0) { - return; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - mp_int_t font_id = rm690b0_get_current_font(self); - mp_int_t cursor_x = x; - mp_int_t cursor_y = y; - - // Determine font dimensions based on ID - mp_int_t font_width, font_height; - switch (font_id) { - case RM690B0_FONT_16x16_MONO: - font_width = 16; - font_height = 16; - break; - case RM690B0_FONT_16x24_MONO: - font_width = 16; - font_height = 24; - break; - case RM690B0_FONT_24x24_MONO: - font_width = 24; - font_height = 24; - break; - case RM690B0_FONT_24x32_MONO: - font_width = 24; - font_height = 32; - break; - case RM690B0_FONT_32x32_MONO: - font_width = 32; - font_height = 32; - break; - case RM690B0_FONT_32x48_MONO: - font_width = 32; - font_height = 48; - break; - default: // RM690B0_FONT_8x8_MONO - font_width = 8; - font_height = 8; - break; - } - - // Initialize bounding box for batch flushing - // min_x is always x because newlines reset cursor_x to x. - mp_int_t min_x = x; - mp_int_t max_x = x; - mp_int_t min_y = y; - mp_int_t max_y = y + font_height; - - for (size_t i = 0; i < text_len; i++) { - uint8_t ch = (uint8_t)text[i]; - - if (ch == '\n') { - cursor_x = x; - cursor_y += font_height; - // Extend bounding box height to cover the new line - if (cursor_y + font_height > max_y) { - max_y = cursor_y + font_height; - } - continue; - } else if (ch == '\r') { - // Ignore carriage return - continue; - } - - // Draw character based on font ID (no flush) - switch (font_id) { - case RM690B0_FONT_16x16_MONO: { - const uint8_t *glyph = rm690b0_get_16x16_glyph(ch); - rm690b0_draw_glyph_16x16(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - case RM690B0_FONT_16x24_MONO: { - const uint8_t *glyph = rm690b0_get_16x24_glyph(ch); - rm690b0_draw_glyph_16x24(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - case RM690B0_FONT_24x24_MONO: { - const uint8_t *glyph = rm690b0_get_24x24_glyph(ch); - rm690b0_draw_glyph_24x24(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - case RM690B0_FONT_24x32_MONO: { - const uint8_t *glyph = rm690b0_get_24x32_glyph(ch); - rm690b0_draw_glyph_24x32(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - case RM690B0_FONT_32x32_MONO: { - const uint8_t *glyph = rm690b0_get_32x32_glyph(ch); - rm690b0_draw_glyph_32x32(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - case RM690B0_FONT_32x48_MONO: { - const uint8_t *glyph = rm690b0_get_32x48_glyph(ch); - rm690b0_draw_glyph_32x48(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - default: { // RM690B0_FONT_8x8_MONO - const uint8_t *glyph = rm690b0_get_8x8_glyph(ch); - rm690b0_draw_glyph_8x8(self, cursor_x, cursor_y, glyph, fg, has_bg, bg, false); - break; - } - } - cursor_x += font_width; - - // Update bounding box width - if (cursor_x > max_x) { - max_x = cursor_x; - } - - if (cursor_x >= RM690B0_PANEL_WIDTH) { - cursor_x = x; - cursor_y += font_height; - if (cursor_y + font_height > max_y) { - max_y = cursor_y + font_height; - } - } - if (cursor_y >= RM690B0_PANEL_HEIGHT) { - break; - } - } - - // Final flush of the entire text bounding box - if (!impl->double_buffered) { - mp_int_t dirty_x = min_x; - mp_int_t dirty_y = min_y; - mp_int_t dirty_w = max_x - min_x; - mp_int_t dirty_h = max_y - min_y; - - if (dirty_w > 0 && dirty_h > 0) { - if (map_rect_for_rotation(self, &dirty_x, &dirty_y, &dirty_w, &dirty_h)) { - esp_err_t ret = rm690b0_flush_region(self, dirty_x, dirty_y, dirty_w, dirty_h, false); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Batch text flush failed: %s", esp_err_to_name(ret)); - } - } - } - } -} - -static bool expand_even_region(mp_int_t *x, mp_int_t *y, mp_int_t *width, mp_int_t *height) { - mp_int_t start_x = *x; - mp_int_t start_y = *y; - mp_int_t end_x = start_x + *width; - mp_int_t end_y = start_y + *height; - - if (start_x < 0) { - start_x = 0; - } - if (start_y < 0) { - start_y = 0; - } - if (end_x > RM690B0_PANEL_WIDTH) { - end_x = RM690B0_PANEL_WIDTH; - } - if (end_y > RM690B0_PANEL_HEIGHT) { - end_y = RM690B0_PANEL_HEIGHT; - } - - if (start_x >= end_x || start_y >= end_y) { - return false; - } - - if (start_x & 1) { - if (start_x > 0) { - start_x -= 1; - } else if (end_x < RM690B0_PANEL_WIDTH) { - end_x += 1; - } - } - if (end_x & 1) { - if (end_x < RM690B0_PANEL_WIDTH) { - end_x += 1; - } else if (start_x > 0) { - start_x -= 1; - } - } - if (((end_x - start_x) & 1) != 0) { - if (end_x < RM690B0_PANEL_WIDTH) { - end_x += 1; - } else if (start_x > 0) { - start_x -= 1; - } - } - - if (start_y & 1) { - if (start_y > 0) { - start_y -= 1; - } else if (end_y < RM690B0_PANEL_HEIGHT) { - end_y += 1; - } - } - if (end_y & 1) { - if (end_y < RM690B0_PANEL_HEIGHT) { - end_y += 1; - } else if (start_y > 0) { - start_y -= 1; - } - } - if (((end_y - start_y) & 1) != 0) { - if (end_y < RM690B0_PANEL_HEIGHT) { - end_y += 1; - } else if (start_y > 0) { - start_y -= 1; - } - } - - if ((end_y - start_y) < 2) { - if (end_y < RM690B0_PANEL_HEIGHT) { - end_y = start_y + 2; - } else if (start_y >= 1) { - start_y = end_y - 2; - } - } - - if (start_x >= end_x || start_y >= end_y) { - return false; - } - - *x = start_x; - *y = start_y; - *width = end_x - start_x; - *height = end_y - start_y; - return true; -} - - - -static const rm690b0_lcd_init_cmd_t lcd_init_cmds[] = { - {0xFE, (uint8_t []) {0x20}, 1, 0}, - {0x26, (uint8_t []) {0x0A}, 1, 0}, - {0x24, (uint8_t []) {0x80}, 1, 0}, - {0xFE, (uint8_t []) {0x13}, 1, 0}, - {0xEB, (uint8_t []) {0x0E}, 1, 0}, - {0xFE, (uint8_t []) {0x00}, 1, 0}, - {0x3A, (uint8_t []) {0x55}, 1, 0}, - {0xC2, (uint8_t []) {0x00}, 1, 10}, - {0x35, (uint8_t []) {0x00}, 0, 0}, - {0x51, (uint8_t []) {0x00}, 1, 10}, - {0x11, (uint8_t []) {0x00}, 0, 80}, - {0x2A, (uint8_t []) {0x00, 0x10, 0x01, 0xD1}, 4, 0}, - {0x2B, (uint8_t []) {0x00, 0x00, 0x02, 0x57}, 4, 0}, - {0x29, (uint8_t []) {0x00}, 0, 10}, - {0x36, (uint8_t []) {0x30}, 1, 10}, // MADCTL for Landscape with RGB color order - {0x51, (uint8_t []) {0xFF}, 1, 0}, -}; - -// rm690b0_impl_t structure is defined earlier in the file (before font rendering functions) - -// Singleton instance tracker for static deinit support -static rm690b0_rm690b0_obj_t *rm690b0_singleton = NULL; - -static esp_err_t rm690b0_tx_param(const rm690b0_impl_t *impl, uint8_t cmd, const void *param, size_t param_size) { - if (impl == NULL || impl->io_handle == NULL) { - return ESP_ERR_INVALID_ARG; - } - - uint32_t packed_cmd = ((uint32_t)RM690B0_OPCODE_WRITE_CMD << 24) | ((uint32_t)cmd << 8); - return esp_lcd_panel_io_tx_param(impl->io_handle, packed_cmd, param, param_size); -} - -// Mark a region as dirty for next swap_buffers() -static void mark_dirty_region(rm690b0_impl_t *impl, mp_int_t x, mp_int_t y, mp_int_t w, mp_int_t h) { - if (!impl->double_buffered) { - // Single-buffer mode: no dirty tracking needed (flush happens immediately) - return; - } - - if (w <= 0 || h <= 0) { - return; - } - - if (!impl->dirty_region_valid) { - // First dirty region - impl->dirty_x = x; - impl->dirty_y = y; - impl->dirty_w = w; - impl->dirty_h = h; - impl->dirty_region_valid = true; - } else { - // Expand to include new region - mp_int_t x1 = impl->dirty_x; - mp_int_t y1 = impl->dirty_y; - mp_int_t x2 = impl->dirty_x + impl->dirty_w; - mp_int_t y2 = impl->dirty_y + impl->dirty_h; - - mp_int_t new_x1 = (x < x1) ? x : x1; - mp_int_t new_y1 = (y < y1) ? y : y1; - mp_int_t new_x2 = (x + w > x2) ? x + w : x2; - mp_int_t new_y2 = (y + h > y2) ? y + h : y2; - - impl->dirty_x = new_x1; - impl->dirty_y = new_y1; - impl->dirty_w = new_x2 - new_x1; - impl->dirty_h = new_y2 - new_y1; - } -} - -static esp_err_t rm690b0_flush_region(rm690b0_rm690b0_obj_t *self, - mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, bool skip_final_delay) { - (void)skip_final_delay; - - if (width <= 0 || height <= 0) { - return ESP_OK; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->panel_handle == NULL || impl->framebuffer == NULL) { - return ESP_ERR_INVALID_STATE; - } - - mp_int_t fx = x; - mp_int_t fy = y; - mp_int_t fw = width; - mp_int_t fh = height; - - if (!expand_even_region(&fx, &fy, &fw, &fh)) { - return ESP_OK; - } - - size_t fb_stride = RM690B0_PANEL_WIDTH; - size_t fw_sz = (size_t)fw; - size_t fh_sz = (size_t)fh; - - size_t available_pixels = RM690B0_MAX_CHUNK_PIXELS; - if (impl->chunk_buffers[0] != NULL) { - available_pixels = impl->chunk_buffer_pixels; - } - - size_t max_chunk_height = available_pixels / fw_sz; - if (max_chunk_height == 0) { - max_chunk_height = 1; - } - - size_t chunk_height = fh_sz; - if (chunk_height > max_chunk_height) { - chunk_height = max_chunk_height; - } - if (chunk_height == 0) { - chunk_height = 1; - } - if (chunk_height & 1) { - if (chunk_height < fh_sz) { - chunk_height += 1; - } else if (chunk_height > 1) { - chunk_height -= 1; - } - } - - size_t max_chunk_pixels = fw_sz * chunk_height; - - bool use_static_buffers = (impl->chunk_buffers[0] != NULL && - impl->chunk_buffers[1] != NULL && - impl->chunk_buffer_pixels >= max_chunk_pixels); - - uint16_t *alloc_buffer = NULL; - if (!use_static_buffers) { - alloc_buffer = heap_caps_malloc(max_chunk_pixels * sizeof(uint16_t), MALLOC_CAP_DMA); - if (alloc_buffer == NULL) { - return ESP_ERR_NO_MEM; - } - } - - esp_err_t ret = ESP_OK; - uint16_t *framebuffer = impl->framebuffer; - int buf_idx = 0; - bool direct_dma = (fx == 0 && fw == RM690B0_PANEL_WIDTH && x == 0 && width == RM690B0_PANEL_WIDTH); - - for (mp_int_t start_y = fy; start_y < fy + fh && ret == ESP_OK; start_y += (mp_int_t)chunk_height) { - size_t rows_this_chunk = (size_t)((fy + fh) - start_y); - if (rows_this_chunk > chunk_height) { - rows_this_chunk = chunk_height; - } - - rm690b0_wait_for_dma_slot(impl); - - const void *dma_buffer = NULL; - uint8_t pending_id = RM690B0_PENDING_BUFFER_FRAMEBUFFER; - - if (direct_dma) { - dma_buffer = framebuffer + (size_t)start_y * fb_stride; - } else { - uint16_t *current_buffer = NULL; - if (use_static_buffers) { - uint8_t current_idx = (uint8_t)buf_idx; - while (impl->dma_buffer_in_use[current_idx]) { - rm690b0_wait_for_dma_completion(impl); - } - current_buffer = impl->chunk_buffers[current_idx]; - impl->dma_buffer_in_use[current_idx] = true; - pending_id = current_idx; - buf_idx = (buf_idx + 1) % 2; - } else { - while (impl->dma_alloc_buffer_in_use) { - rm690b0_wait_for_dma_completion(impl); - } - current_buffer = alloc_buffer; - impl->dma_alloc_buffer_in_use = true; - pending_id = RM690B0_PENDING_BUFFER_ALLOC; - } - - dma_buffer = current_buffer; - - if (x == 0 && width == RM690B0_PANEL_WIDTH) { - size_t bytes_per_row = fb_stride * sizeof(uint16_t); - size_t chunk_bytes = rows_this_chunk * bytes_per_row; - const uint16_t *src = framebuffer + (size_t)start_y * fb_stride; - memcpy(current_buffer, src, chunk_bytes); - } else { - size_t dest_index = 0; - for (size_t row = 0; row < rows_this_chunk; row++) { - mp_int_t phys_row = start_y + (mp_int_t)row; - mp_int_t src_row = phys_row; - if (src_row < 0) { - src_row = 0; - } else if (src_row >= RM690B0_PANEL_HEIGHT) { - src_row = RM690B0_PANEL_HEIGHT - 1; - } - - const uint16_t *row_base = framebuffer + (size_t)src_row * fb_stride; - mp_int_t dest_col = 0; - mp_int_t flush_end_x = fx + fw; - - mp_int_t src_left = x; - if (src_left < 0) { - src_left = 0; - } - mp_int_t src_right = x + width - 1; - if (src_right >= RM690B0_PANEL_WIDTH) { - src_right = RM690B0_PANEL_WIDTH - 1; - } - - for (mp_int_t phys_col = fx; phys_col < src_left; phys_col++) { - mp_int_t safe_col = (phys_col < 0) ? 0 : ((phys_col >= RM690B0_PANEL_WIDTH) ? RM690B0_PANEL_WIDTH - 1 : phys_col); - current_buffer[dest_index + dest_col++] = row_base[safe_col]; - } - - if (src_left <= src_right) { - size_t middle_len = (size_t)(src_right - src_left + 1); - memcpy(¤t_buffer[dest_index + dest_col], &row_base[src_left], middle_len * sizeof(uint16_t)); - dest_col += (mp_int_t)middle_len; - } - - for (mp_int_t phys_col = src_right + 1; phys_col < flush_end_x; phys_col++) { - mp_int_t safe_col = (phys_col < 0) ? 0 : ((phys_col >= RM690B0_PANEL_WIDTH) ? RM690B0_PANEL_WIDTH - 1 : phys_col); - current_buffer[dest_index + dest_col++] = row_base[safe_col]; - } - dest_index += fw_sz; - } - } - } - - ret = esp_lcd_panel_draw_bitmap( - impl->panel_handle, - fx, - start_y, - fx + fw, - start_y + (mp_int_t)rows_this_chunk, - dma_buffer); - - if (ret != ESP_OK) { - if (!direct_dma) { - if (pending_id < 2) { - impl->dma_buffer_in_use[pending_id] = false; - } else if (pending_id == RM690B0_PENDING_BUFFER_ALLOC) { - impl->dma_alloc_buffer_in_use = false; - } - } - break; - } - - rm690b0_dma_pending_push(&impl->dma_pending, pending_id); - impl->dma_inflight++; - if (!use_static_buffers && !direct_dma) { - rm690b0_wait_for_dma_completion(impl); - } - } - - if (!use_static_buffers && alloc_buffer != NULL) { - // Ensure the last dynamic transfer is complete before freeing. - while (impl->dma_alloc_buffer_in_use) { - rm690b0_wait_for_dma_completion(impl); - } - } - - if (alloc_buffer != NULL) { - heap_caps_free(alloc_buffer); - } - - return ret; -} - -void common_hal_rm690b0_rm690b0_construct(rm690b0_rm690b0_obj_t *self) { - self->initialized = false; - // Start in landscape mode (rotation 0) - display is 600x450 - self->width = RM690B0_PANEL_WIDTH; - self->height = RM690B0_PANEL_HEIGHT; - self->rotation = 0; - self->brightness_raw = 0xFF; - self->font_id = RM690B0_FONT_8x8_MONO; // Initialize with default font - self->impl = m_malloc(sizeof(rm690b0_impl_t)); - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - impl->io_handle = NULL; - impl->panel_handle = NULL; - impl->bus_initialized = false; - impl->chunk_buffers[0] = NULL; - impl->chunk_buffers[1] = NULL; - impl->chunk_buffer_pixels = 0; - impl->framebuffer = NULL; - impl->framebuffer_pixels = 0; - impl->framebuffer_front = NULL; - impl->double_buffered = false; - impl->circle_span_cache = NULL; - impl->circle_span_capacity = 0; - - // Initialize dirty region tracking - impl->dirty_region_valid = false; - impl->dirty_x = 0; - impl->dirty_y = 0; - impl->dirty_w = 0; - impl->dirty_h = 0; - - // Create synchronization semaphore (counting, one slot per queued transfer) - impl->transfer_done_sem = xSemaphoreCreateCounting(RM690B0_PANEL_IO_QUEUE_DEPTH, 0); - if (impl->transfer_done_sem == NULL) { - m_free(impl); - self->impl = NULL; - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to create DMA semaphore")); - } - impl->dma_buffer_in_use[0] = false; - impl->dma_buffer_in_use[1] = false; - impl->dma_alloc_buffer_in_use = false; - impl->dma_inflight = 0; - rm690b0_dma_pending_init(&impl->dma_pending); - - // Track this instance as the singleton - rm690b0_singleton = self; - - ESP_LOGI(TAG, "RM690B0 module constructed"); -} - -void common_hal_rm690b0_rm690b0_deinit(rm690b0_rm690b0_obj_t *self) { - // Early safety checks - if (!self) { - ESP_LOGW(TAG, "deinit called with NULL self pointer"); - return; - } - - if (!self->initialized) { - ESP_LOGI(TAG, "deinit called on already deinitialized instance"); - return; - } - - ESP_LOGI(TAG, "Starting RM690B0 deinit"); - - // Check if impl is valid - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (!impl) { - ESP_LOGW(TAG, "deinit: impl pointer is NULL, nothing to free"); - self->initialized = false; - if (rm690b0_singleton == self) { - rm690b0_singleton = NULL; - } - return; - } - - // Clear singleton reference - if (rm690b0_singleton == self) { - rm690b0_singleton = NULL; - } - - // Mark as uninitialized early to prevent re-entry - self->initialized = false; - - // Clear screen to black before freeing resources - if (impl->panel_handle != NULL && impl->framebuffer != NULL) { - ESP_LOGI(TAG, "Clearing display to black before deinit"); - - // Fill framebuffer with black - size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; - memset(impl->framebuffer, 0, framebuffer_pixels * sizeof(uint16_t)); - - // Flush to display - esp_err_t ret = rm690b0_flush_region(self, 0, 0, RM690B0_PANEL_WIDTH, RM690B0_PANEL_HEIGHT, false); - if (ret == ESP_OK) { - // Brief delay to ensure screen update completes - rm690b0_wait_for_all_dma(impl); - vTaskDelay(pdMS_TO_TICKS(10)); - ESP_LOGI(TAG, "Screen cleared successfully"); - } else { - ESP_LOGW(TAG, "Failed to clear screen before deinit (non-critical)"); - } - } - - // Free memory buffers - rm690b0_wait_for_all_dma(impl); - - if (impl->framebuffer_front) { - ESP_LOGI(TAG, "Freeing front framebuffer"); - heap_caps_free(impl->framebuffer_front); - impl->framebuffer_front = NULL; - impl->double_buffered = false; - } - - if (impl->framebuffer) { - ESP_LOGI(TAG, "Freeing back framebuffer"); - heap_caps_free(impl->framebuffer); - impl->framebuffer = NULL; - impl->framebuffer_pixels = 0; - } - - if (impl->chunk_buffers[0]) { - ESP_LOGI(TAG, "Freeing chunk buffer A"); - heap_caps_free(impl->chunk_buffers[0]); - impl->chunk_buffers[0] = NULL; - } - if (impl->chunk_buffers[1]) { - ESP_LOGI(TAG, "Freeing chunk buffer B"); - heap_caps_free(impl->chunk_buffers[1]); - impl->chunk_buffers[1] = NULL; - } - impl->chunk_buffer_pixels = 0; - - if (impl->circle_span_cache) { - ESP_LOGI(TAG, "Freeing cached circle spans"); - heap_caps_free(impl->circle_span_cache); - impl->circle_span_cache = NULL; - impl->circle_span_capacity = 0; - } - - if (impl->transfer_done_sem) { - vSemaphoreDelete(impl->transfer_done_sem); - impl->transfer_done_sem = NULL; - } - - // Turn off display power before freeing hardware resources - if (LCD_PWR_PIN != GPIO_NUM_NC) { - ESP_LOGI(TAG, "Turning off display power"); - int off_level = LCD_PWR_ON_LEVEL ? 0 : 1; - gpio_set_level(LCD_PWR_PIN, off_level); - vTaskDelay(pdMS_TO_TICKS(5)); - } - - // Delete LCD panel (must be before IO handle) - if (impl->panel_handle != NULL) { - ESP_LOGI(TAG, "Deleting LCD panel handle"); - esp_err_t ret = esp_lcd_panel_del(impl->panel_handle); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to delete LCD panel: %s", esp_err_to_name(ret)); - } - impl->panel_handle = NULL; - } - - // Delete LCD IO handle (must be before SPI bus) - if (impl->io_handle != NULL) { - ESP_LOGI(TAG, "Deleting LCD IO handle"); - esp_err_t ret = esp_lcd_panel_io_del(impl->io_handle); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to delete LCD IO: %s", esp_err_to_name(ret)); - } - impl->io_handle = NULL; - } - - // Free SPI bus (must be LAST, after all users are deleted) - if (impl->bus_initialized) { - ESP_LOGI(TAG, "Freeing SPI bus"); - esp_err_t ret = spi_bus_free(SPI2_HOST); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to free SPI bus: %s (may be in use)", esp_err_to_name(ret)); - } - impl->bus_initialized = false; - } - - // Prevent use-after-free - self->impl = NULL; - - ESP_LOGI(TAG, "RM690B0 deinit complete - all resources freed"); -} - -void common_hal_rm690b0_rm690b0_deinit_all(void) { - // Static deinit for REPL convenience - cleans up any active instance - if (rm690b0_singleton != NULL) { - ESP_LOGI(TAG, "Static deinit: cleaning up singleton instance"); - common_hal_rm690b0_rm690b0_deinit(rm690b0_singleton); - rm690b0_singleton = NULL; - ESP_LOGI(TAG, "Static deinit: singleton cleaned up"); - } else { - ESP_LOGI(TAG, "Static deinit: no active instance to clean up"); - } -} - -// Helper function to expose panel handle for LVGL integration -esp_lcd_panel_handle_t rm690b0_get_panel_handle(void) { - if (rm690b0_singleton == NULL) { - ESP_LOGW(TAG, "rm690b0_get_panel_handle: no active display instance"); - return NULL; - } - - if (!rm690b0_singleton->initialized) { - ESP_LOGW(TAG, "rm690b0_get_panel_handle: display not initialized"); - return NULL; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)rm690b0_singleton->impl; - if (impl == NULL) { - ESP_LOGE(TAG, "rm690b0_get_panel_handle: impl is NULL"); - return NULL; - } - - return impl->panel_handle; -} - -void common_hal_rm690b0_rm690b0_init_display(rm690b0_rm690b0_obj_t *self) { - if (self->initialized) { - ESP_LOGW(TAG, "Display already initialized"); - return; - } - - ESP_LOGI(TAG, "Initializing RM690B0 display (%s mode)", LCD_USE_QSPI ? "QSPI" : "SPI"); - - // Enable display power if a dedicated control pin is provided - if (LCD_PWR_PIN != GPIO_NUM_NC) { - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = (1ULL << LCD_PWR_PIN), - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .pull_up_en = GPIO_PULLUP_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - gpio_config(&io_conf); - gpio_set_level(LCD_PWR_PIN, LCD_PWR_ON_LEVEL); - ESP_LOGI(TAG, "Display power enabled on GPIO%d", LCD_PWR_PIN); - } else { - ESP_LOGI(TAG, "No display power control pin configured; assuming panel is already powered"); - } - - // Wait for power to stabilize (longer wait for display power-up) - vTaskDelay(pdMS_TO_TICKS(200)); - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - esp_err_t ret = ESP_OK; - - if (!impl->bus_initialized) { - // Initialize SPI bus using configuration macros from esp_lcd_rm690b0.h - // These macros correctly configure either QSPI (4 data lines) or standard SPI (1 data line) - // QSPI: Uses data0-data3 for 4-bit parallel data transfer (faster) - // SPI: Uses mosi (data0) for single-bit serial data transfer (compatible) - size_t max_transfer_bytes = RM690B0_MAX_CHUNK_PIXELS * sizeof(uint16_t); - const spi_bus_config_t buscfg = LCD_USE_QSPI ? - RM690B0_PANEL_BUS_QSPI_CONFIG(LCD_SCK_PIN, LCD_D0_PIN, LCD_D1_PIN, LCD_D2_PIN, LCD_D3_PIN, max_transfer_bytes) : - RM690B0_PANEL_BUS_SPI_CONFIG(LCD_SCK_PIN, LCD_D0_PIN, max_transfer_bytes); - ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to initialize SPI bus: %s"), esp_err_to_name(ret)); - return; - } - impl->bus_initialized = true; - ESP_LOGI(TAG, "%s bus initialized", LCD_USE_QSPI ? "QSPI" : "SPI"); - } - - // Configure panel I/O layer using macros from esp_lcd_rm690b0.h - // These macros set up the correct communication protocol: - // - QSPI mode: 32-bit commands, no DC pin, quad_mode flag enabled - // - SPI mode: 8-bit commands, DC pin required, standard SPI - // Both use 8-bit parameters and 10-depth transaction queue - // We provide a callback to release the semaphore when transfer completes - if (LCD_USE_QSPI) { - const esp_lcd_panel_io_spi_config_t io_config = RM690B0_PANEL_IO_QSPI_CONFIG(LCD_CS_PIN, rm690b0_on_color_trans_done, impl, LCD_PIXEL_CLOCK_HZ); - ret = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &impl->io_handle); - } else { - const esp_lcd_panel_io_spi_config_t io_config = RM690B0_PANEL_IO_SPI_CONFIG(LCD_CS_PIN, -1, rm690b0_on_color_trans_done, impl, LCD_PIXEL_CLOCK_HZ); - ret = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &impl->io_handle); - } - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to create panel I/O: %s", esp_err_to_name(ret)); - spi_bus_free(SPI2_HOST); - impl->bus_initialized = false; - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to create panel I/O")); - return; - } - ESP_LOGI(TAG, "Panel I/O created"); - - // Configure vendor-specific settings for RM690B0 - rm690b0_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(rm690b0_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = LCD_USE_QSPI, - }, - }; - - // Configure panel device - exact configuration from board.c.old - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = LCD_RST_PIN, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = LCD_BIT_PER_PIXEL, - .flags = { - .reset_active_high = false, - }, - .vendor_config = &vendor_config, - }; - - ret = esp_lcd_new_panel_rm690b0(impl->io_handle, &panel_config, &impl->panel_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to create RM690B0 panel: %s", esp_err_to_name(ret)); - esp_lcd_panel_io_del(impl->io_handle); - impl->io_handle = NULL; - spi_bus_free(SPI2_HOST); - impl->bus_initialized = false; - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to create RM690B0 panel")); - return; - } - ESP_LOGI(TAG, "RM690B0 panel created"); - - // Initialize the display - exact sequence from board.c.old - ret = esp_lcd_panel_reset(impl->panel_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to reset panel: %s", esp_err_to_name(ret)); - goto cleanup; - } - ESP_LOGI(TAG, "Panel reset complete"); - - ret = esp_lcd_panel_init(impl->panel_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize panel: %s", esp_err_to_name(ret)); - goto cleanup; - } - ESP_LOGI(TAG, "Panel initialization complete"); - - // Set the gap after init - exact values from board.c.old - esp_lcd_panel_set_gap(impl->panel_handle, RM690B0_X_GAP, RM690B0_Y_GAP); - ESP_LOGI(TAG, "Display gap set to (0, 16)"); - - // Turn on the display - ret = esp_lcd_panel_disp_on_off(impl->panel_handle, true); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to turn on display: %s", esp_err_to_name(ret)); - goto cleanup; - } - ESP_LOGI(TAG, "Display turned on"); - - // Attempt to allocate static chunk buffers with a downgrade strategy - // Priority 1: Full size in Internal RAM (fastest) - unlikely for 450px wide high colors - // Priority 2: Full size in PSRAM (standard) - // Priority 3: Reduced size in Internal RAM or PSRAM - if (impl->chunk_buffers[0] == NULL) { - size_t current_chunk_rows = RM690B0_MAX_CHUNK_ROWS; - - while (current_chunk_rows >= 2) { - size_t buf_pixels = (size_t)RM690B0_PANEL_WIDTH * current_chunk_rows; - size_t buf_size = buf_pixels * sizeof(uint16_t); - - // Try explicit internal first for smaller sizes or just best effort caps? - // We use MALLOC_CAP_DMA which allows both internal and PSRAM, but - // heap_caps_malloc usually prefers internal if available and small enough. - // For large buffers, we might want to let it go to PSRAM to save internal for stack/heap. - // Let's rely on MALLOC_CAP_DMA. - - impl->chunk_buffers[0] = heap_caps_malloc(buf_size, MALLOC_CAP_DMA); - impl->chunk_buffers[1] = heap_caps_malloc(buf_size, MALLOC_CAP_DMA); - - if (impl->chunk_buffers[0] != NULL && impl->chunk_buffers[1] != NULL) { - // Success - impl->chunk_buffer_pixels = buf_pixels; - ESP_LOGI(TAG, "Allocated dual DMA chunk buffers (%zu pixels each, %zu rows)", - impl->chunk_buffer_pixels, current_chunk_rows); - break; - } - - // Allocation failed, cleanup partial and try smaller - if (impl->chunk_buffers[0]) { - heap_caps_free(impl->chunk_buffers[0]); - } - if (impl->chunk_buffers[1]) { - heap_caps_free(impl->chunk_buffers[1]); - } - impl->chunk_buffers[0] = NULL; - impl->chunk_buffers[1] = NULL; - - // Reduce size - current_chunk_rows /= 2; - } - - if (impl->chunk_buffers[0] == NULL) { - impl->chunk_buffer_pixels = 0; - ESP_LOGW(TAG, "Unable to allocate dual DMA chunk buffers; operations will use slower allocation per draw"); - } - } - - size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; - if (impl->framebuffer == NULL) { - impl->framebuffer = heap_caps_malloc(framebuffer_pixels * sizeof(uint16_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (impl->framebuffer == NULL) { - ESP_LOGE(TAG, "Unable to allocate PSRAM framebuffer"); - goto cleanup; - } - impl->framebuffer_pixels = framebuffer_pixels; - ESP_LOGI(TAG, "Allocated back framebuffer (%zu pixels, %zu KB)", - framebuffer_pixels, (framebuffer_pixels * sizeof(uint16_t)) / 1024); - } - - // Front buffer will be allocated lazily on first swap_buffers() call - // This avoids 540KB memory overhead unless tear-free rendering is actually used - - // Initialize back buffer with black - for (size_t i = 0; i < framebuffer_pixels; i++) { - impl->framebuffer[i] = 0x0000; - } - esp_err_t clear_ret = rm690b0_flush_region(self, 0, 0, RM690B0_PANEL_WIDTH, RM690B0_PANEL_HEIGHT, false); - if (clear_ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to clear display: %s"), esp_err_to_name(clear_ret)); - return; - } - ESP_LOGI(TAG, "Display filled with black"); - - self->rotation = 0; - self->width = RM690B0_PANEL_WIDTH; - self->height = RM690B0_PANEL_HEIGHT; - self->brightness_raw = 0xFF; - self->initialized = true; - ESP_LOGI(TAG, "RM690B0 display initialization complete"); - return; - -cleanup: - // Free resources in reverse order - if (impl->chunk_buffers[0]) { - heap_caps_free(impl->chunk_buffers[0]); - impl->chunk_buffers[0] = NULL; - } - if (impl->chunk_buffers[1]) { - heap_caps_free(impl->chunk_buffers[1]); - impl->chunk_buffers[1] = NULL; - } - impl->chunk_buffer_pixels = 0; - - // Panel handle must be valid if we got here (checked before reset/init) - if (impl->panel_handle) { - esp_lcd_panel_del(impl->panel_handle); - impl->panel_handle = NULL; - } - - if (impl->io_handle) { - esp_lcd_panel_io_del(impl->io_handle); - impl->io_handle = NULL; - } - - if (impl->bus_initialized) { - spi_bus_free(SPI2_HOST); - impl->bus_initialized = false; - } - - if (ret == ESP_OK) { - // Must be memory error if ret is OK but we jumped to cleanup - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Display initialization failed: Out of memory")); - } else { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Display initialization failed: %s"), esp_err_to_name(ret)); - } -} - -static void rm690b0_fill_color_direct(rm690b0_rm690b0_obj_t *self, uint16_t color) { - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->panel_handle == NULL || impl->transfer_done_sem == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - uint16_t swapped = RGB565_SWAP_GB(color); - size_t dma_lines = RM690B0_MAX_CHUNK_ROWS; - if (dma_lines > RM690B0_PANEL_HEIGHT) { - dma_lines = RM690B0_PANEL_HEIGHT; - } - const size_t line_pixels = RM690B0_PANEL_WIDTH; - const size_t dma_pixels = line_pixels * dma_lines; - const size_t dma_bytes = dma_pixels * sizeof(uint16_t); - - uint16_t *dma_buffer = heap_caps_malloc(dma_bytes, MALLOC_CAP_DMA); - if (dma_buffer == NULL) { - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("fill_color: unable to allocate DMA buffer")); - return; - } - - for (size_t i = 0; i < dma_pixels; i++) { - dma_buffer[i] = swapped; - } - - size_t rows_remaining = RM690B0_PANEL_HEIGHT; - mp_int_t current_y = 0; - esp_err_t ret = ESP_OK; - - while (rows_remaining > 0 && ret == ESP_OK) { - size_t rows_this_pass = rows_remaining > dma_lines ? dma_lines : rows_remaining; - - // Wait for queue slot before submitting - rm690b0_wait_for_dma_slot(impl); - - ret = esp_lcd_panel_draw_bitmap( - impl->panel_handle, - 0, - current_y, - RM690B0_PANEL_WIDTH, - current_y + (mp_int_t)rows_this_pass, - dma_buffer); - - if (ret != ESP_OK) { - break; - } - - rm690b0_dma_pending_push(&impl->dma_pending, RM690B0_PENDING_BUFFER_TEMP); - impl->dma_inflight++; - current_y += (mp_int_t)rows_this_pass; - rows_remaining -= rows_this_pass; - } - - rm690b0_wait_for_all_dma(impl); - if (ret == ESP_OK && impl->framebuffer != NULL) { - rm690b0_fill_rect_framebuffer(impl, 0, 0, - RM690B0_PANEL_WIDTH, RM690B0_PANEL_HEIGHT, swapped); - impl->dirty_region_valid = false; - } - - heap_caps_free(dma_buffer); - - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("fill_color failed: %s"), esp_err_to_name(ret)); - } -} - -static esp_err_t rm690b0_fill_rect_direct_fullwidth(rm690b0_rm690b0_obj_t *self, - mp_int_t start_y, mp_int_t rows, uint16_t swapped_color) { - - if (rows <= 0) { - return ESP_OK; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->panel_handle == NULL || impl->transfer_done_sem == NULL) { - return ESP_ERR_INVALID_STATE; - } - - size_t dma_lines = RM690B0_MAX_CHUNK_ROWS; - if (dma_lines > (size_t)rows) { - dma_lines = rows; - } - const size_t line_pixels = RM690B0_PANEL_WIDTH; - const size_t dma_pixels = line_pixels * dma_lines; - const size_t dma_bytes = dma_pixels * sizeof(uint16_t); - - uint16_t *dma_buffer = heap_caps_malloc(dma_bytes, MALLOC_CAP_DMA); - if (dma_buffer == NULL) { - return ESP_ERR_NO_MEM; - } - - for (size_t i = 0; i < dma_pixels; i++) { - dma_buffer[i] = swapped_color; - } - - size_t rows_remaining = (size_t)rows; - mp_int_t current_y = start_y; - esp_err_t ret = ESP_OK; - - while (rows_remaining > 0 && ret == ESP_OK) { - size_t rows_this_pass = rows_remaining > dma_lines ? dma_lines : rows_remaining; - - rm690b0_wait_for_dma_slot(impl); - - ret = esp_lcd_panel_draw_bitmap( - impl->panel_handle, - 0, - current_y, - RM690B0_PANEL_WIDTH, - current_y + (mp_int_t)rows_this_pass, - dma_buffer); - - if (ret != ESP_OK) { - break; - } - - rm690b0_dma_pending_push(&impl->dma_pending, RM690B0_PENDING_BUFFER_TEMP); - impl->dma_inflight++; - current_y += (mp_int_t)rows_this_pass; - rows_remaining -= rows_this_pass; - } - - rm690b0_wait_for_all_dma(impl); - heap_caps_free(dma_buffer); - - if (ret == ESP_OK && impl->framebuffer != NULL) { - rm690b0_fill_rect_framebuffer(impl, 0, start_y, RM690B0_PANEL_WIDTH, rows, swapped_color); - } - - return ret; -} - -void common_hal_rm690b0_rm690b0_fill_color(rm690b0_rm690b0_obj_t *self, uint16_t color) { - CHECK_INITIALIZED(); - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl != NULL && !impl->double_buffered) { - rm690b0_fill_color_direct(self, color); - return; - } - - common_hal_rm690b0_rm690b0_fill_rect(self, 0, 0, self->width, self->height, color); -} - -void common_hal_rm690b0_rm690b0_pixel(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t color) { - CHECK_INITIALIZED(); - - mp_int_t bx = x; - mp_int_t by = y; - mp_int_t bw = 1; - mp_int_t bh = 1; - - if (!clip_logical_rect(self, &bx, &by, &bw, &bh)) { - return; - } - if (!map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { - return; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - uint16_t swapped_color = RGB565_SWAP_GB(color); - size_t fb_stride = RM690B0_PANEL_WIDTH; - impl->framebuffer[(size_t)by * fb_stride + bx] = swapped_color; - - // Mark region as dirty for next swap - mark_dirty_region(impl, bx, by, bw, bh); - - // Only flush immediately if not double-buffered - // When double-buffered, swap_buffers() will handle the flush - if (!impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, bx, by, bw, bh, false); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw pixel: %s"), esp_err_to_name(ret)); - } - } -} - -static void rm690b0_fill_rect_framebuffer(rm690b0_impl_t *impl, - mp_int_t bx, mp_int_t by, mp_int_t bw, mp_int_t bh, uint16_t swapped_color) { - - uint16_t *base_ptr = impl->framebuffer + (size_t)by * RM690B0_PANEL_WIDTH + bx; - - for (mp_int_t col = 0; col < bw; col++) { - base_ptr[col] = swapped_color; - } - - mp_int_t filled_rows = 1; - size_t row_bytes = (size_t)bw * sizeof(uint16_t); - size_t fb_stride = RM690B0_PANEL_WIDTH; - - while (filled_rows < bh) { - mp_int_t rows_to_copy = filled_rows; - if (filled_rows + rows_to_copy > bh) { - rows_to_copy = bh - filled_rows; - } - - for (mp_int_t i = 0; i < rows_to_copy; i++) { - uint16_t *src_row = base_ptr + (size_t)i * fb_stride; - uint16_t *dest_row = base_ptr + (size_t)(filled_rows + i) * fb_stride; - memcpy(dest_row, src_row, row_bytes); - } - - filled_rows += rows_to_copy; - } -} - -void common_hal_rm690b0_rm690b0_fill_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color) { - CHECK_INITIALIZED(); - - mp_int_t bx = x; - mp_int_t by = y; - mp_int_t bw = width; - mp_int_t bh = height; - - if (!clip_logical_rect(self, &bx, &by, &bw, &bh)) { - return; - } - if (!map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { - return; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - uint16_t swapped_color = RGB565_SWAP_GB(color); - - if (!impl->double_buffered && bx == 0 && bw == RM690B0_PANEL_WIDTH) { - esp_err_t direct_ret = rm690b0_fill_rect_direct_fullwidth(self, by, bh, swapped_color); - if (direct_ret == ESP_OK) { - mark_dirty_region(impl, bx, by, bw, bh); - return; - } - ESP_LOGW(TAG, "Full-width fast fill_rect path failed (%s) – falling back", - esp_err_to_name(direct_ret)); - } - - rm690b0_fill_rect_framebuffer(impl, bx, by, bw, bh, swapped_color); - - // Mark region as dirty for next swap - mark_dirty_region(impl, bx, by, bw, bh); - - // Only flush immediately if not double-buffered - // When double-buffered, swap_buffers() will handle the flush - if (!impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, bx, by, bw, bh, false); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw fill_rect: %s"), esp_err_to_name(ret)); - } - } -} - -// ============================================================================ -// IMAGE SUPPORT -// ============================================================================ - -#pragma pack(push, 1) -typedef struct { - uint16_t type; // Magic identifier: 0x4d42 - uint32_t size; // File size in bytes - uint16_t reserved1; - uint16_t reserved2; - uint32_t offset; // Offset to image data in bytes from beginning of file - uint32_t header_size; // Header size in bytes - int32_t width; // Width of the image - int32_t height; // Height of the image - uint16_t planes; // Number of color planes - uint16_t bpp; // Bits per pixel - uint32_t compression; // Compression type - uint32_t image_size; // Image size in bytes - int32_t x_res; // Pixels per meter - int32_t y_res; // Pixels per meter - uint32_t n_colors; // Number of colors - uint32_t important_colors; // Important colors -} bmp_header_t; -#pragma pack(pop) - -void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data) { - CHECK_INITIALIZED(); - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(bmp_data, &bufinfo, MP_BUFFER_READ); - - if (bufinfo.len < sizeof(bmp_header_t)) { - mp_raise_ValueError(MP_ERROR_TEXT("BMP data too small")); - return; - } - - const bmp_header_t *header = (const bmp_header_t *)bufinfo.buf; - - if (header->type != 0x4D42) { // 'BM' - mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP header")); - return; - } - - if (header->bpp != 24 && header->bpp != 16) { - mp_raise_ValueError(MP_ERROR_TEXT("Only 16-bit and 24-bit BMP supported")); - return; - } - - if (header->compression != 0 && header->compression != 3) { - mp_raise_ValueError(MP_ERROR_TEXT("Compressed BMP not supported")); - return; - } - - mp_int_t width = header->width; - mp_int_t height = abs(header->height); - bool top_down = (header->height < 0); - size_t data_offset = header->offset; - - if (data_offset >= bufinfo.len) { - mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP data offset")); - return; - } - - // Clip to screen (logical coordinates) - mp_int_t clip_x = x; - mp_int_t clip_y = y; - mp_int_t clip_w = width; - mp_int_t clip_h = height; - - if (!clip_logical_rect(self, &clip_x, &clip_y, &clip_w, &clip_h)) { - return; - } - - // Calculate source offset based on clipping - mp_int_t x_offset = clip_x - x; - mp_int_t y_offset = clip_y - y; - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - const uint8_t *src_data = (const uint8_t *)bufinfo.buf + data_offset; - - // BMP rows are padded to 4 bytes - int row_padding = (4 - ((width * (header->bpp / 8)) % 4)) % 4; - int src_stride = width * (header->bpp / 8) + row_padding; - - // Optimized path for rotation 0 - if (self->rotation == 0) { - size_t fb_stride = RM690B0_PANEL_WIDTH; - uint16_t *fb = impl->framebuffer; - - for (int row = 0; row < clip_h; row++) { - // Source row calculation - int src_y = y_offset + row; - int src_row_idx = top_down ? src_y : (height - 1 - src_y); - const uint8_t *row_ptr = src_data + (size_t)src_row_idx * src_stride + (size_t)x_offset * (header->bpp / 8); - - // Destination row - uint16_t *dst_ptr = fb + (size_t)(clip_y + row) * fb_stride + clip_x; - - if (header->bpp == 24) { - for (int col = 0; col < clip_w; col++) { - uint8_t b = row_ptr[col * 3]; - uint8_t g = row_ptr[col * 3 + 1]; - uint8_t r = row_ptr[col * 3 + 2]; - // Convert RGB888 to RGB565 (swapped for display) - uint16_t rgb = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); - dst_ptr[col] = RGB565_SWAP_GB(rgb); - } - } else { // 16-bit - for (int col = 0; col < clip_w; col++) { - uint16_t val = row_ptr[col * 2] | (row_ptr[col * 2 + 1] << 8); - dst_ptr[col] = RGB565_SWAP_GB(val); - } - } - } - } else { - // Rotated path (pixel by pixel, but clipped) - for (int row = 0; row < clip_h; row++) { - int src_y = y_offset + row; - int src_row_idx = top_down ? src_y : (height - 1 - src_y); - const uint8_t *row_ptr = src_data + (size_t)src_row_idx * src_stride + (size_t)x_offset * (header->bpp / 8); - - for (int col = 0; col < clip_w; col++) { - uint16_t color565; - if (header->bpp == 24) { - uint8_t b = row_ptr[col * 3]; - uint8_t g = row_ptr[col * 3 + 1]; - uint8_t r = row_ptr[col * 3 + 2]; - uint16_t rgb = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); - color565 = RGB565_SWAP_GB(rgb); - } else { - uint16_t val = row_ptr[col * 2] | (row_ptr[col * 2 + 1] << 8); - color565 = RGB565_SWAP_GB(val); - } - rm690b0_write_pixel_rotated(self, impl, clip_x + col, clip_y + row, color565); - } - } - } - - // Mark dirty region - mp_int_t bx = clip_x, by = clip_y, bw = clip_w, bh = clip_h; - if (map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { - mark_dirty_region(impl, bx, by, bw, bh); - if (!impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, bx, by, bw, bh, false); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw BMP: %s"), esp_err_to_name(ret)); - } - } - } -} - -static esp_err_t rm690b0_jpeg_on_block(intptr_t ctx_ptr, - uint32_t block_top, uint32_t block_left, - uint32_t block_bottom, uint32_t block_right, - const uint16_t *pixels) { - - rm690b0_jpeg_draw_ctx_t *ctx = (rm690b0_jpeg_draw_ctx_t *)ctx_ptr; - rm690b0_impl_t *impl = ctx->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return ESP_ERR_INVALID_ARG; - } - - mp_int_t dest_left = ctx->origin_x + (mp_int_t)block_left; - mp_int_t dest_top = ctx->origin_y + (mp_int_t)block_top; - mp_int_t dest_right = ctx->origin_x + (mp_int_t)block_right; - mp_int_t dest_bottom = ctx->origin_y + (mp_int_t)block_bottom; - - mp_int_t clip_right = ctx->clip_x + ctx->clip_w - 1; - mp_int_t clip_bottom = ctx->clip_y + ctx->clip_h - 1; - - mp_int_t draw_left = dest_left > ctx->clip_x ? dest_left : ctx->clip_x; - mp_int_t draw_top = dest_top > ctx->clip_y ? dest_top : ctx->clip_y; - mp_int_t draw_right = dest_right < clip_right ? dest_right : clip_right; - mp_int_t draw_bottom = dest_bottom < clip_bottom ? dest_bottom : clip_bottom; - - if (draw_left > draw_right || draw_top > draw_bottom) { - return ESP_OK; - } - - mp_int_t block_w = (mp_int_t)(block_right - block_left + 1); - if (block_w <= 0) { - return ESP_OK; - } - - size_t fb_stride = RM690B0_PANEL_WIDTH; - - for (mp_int_t row = draw_top; row <= draw_bottom; row++) { - mp_int_t src_row = row - dest_top; - const uint16_t *row_src = pixels + (size_t)src_row * block_w + (draw_left - dest_left); - - if (ctx->rotation_zero) { - uint16_t *dst = impl->framebuffer + (size_t)row * fb_stride + draw_left; - for (mp_int_t col = draw_left; col <= draw_right; col++) { - dst[col - draw_left] = RGB565_SWAP_GB(*row_src++); - } - } else { - for (mp_int_t col = draw_left; col <= draw_right; col++) { - uint16_t color = RGB565_SWAP_GB(*row_src++); - rm690b0_write_pixel_rotated(ctx->self, impl, col, row, color); - } - } - } - - return ESP_OK; -} - - -void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data) { - CHECK_INITIALIZED(); - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(jpeg_data, &bufinfo, MP_BUFFER_READ); - - esp_jpeg_image_cfg_t jpeg_cfg = { - .indata = (uint8_t *)bufinfo.buf, - .indata_size = bufinfo.len, - .out_format = JPEG_IMAGE_FORMAT_RGB565, - .out_scale = JPEG_IMAGE_SCALE_0, - .flags = { .swap_color_bytes = 0 }, // Do not swap in decoder, we handle it manually - .outbuf = NULL, - .outbuf_size = 0, - .user_data = 0, - .on_block = NULL, - }; - - esp_jpeg_image_output_t jpeg_out; - esp_err_t ret = esp_jpeg_get_image_info(&jpeg_cfg, &jpeg_out); - if (ret != ESP_OK) { - mp_raise_ValueError(MP_ERROR_TEXT("Invalid JPEG data")); - return; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - int width = jpeg_out.width; - int height = jpeg_out.height; - - // Clip to screen (logical coordinates) - mp_int_t clip_x = x; - mp_int_t clip_y = y; - mp_int_t clip_w = width; - mp_int_t clip_h = height; - - if (clip_logical_rect(self, &clip_x, &clip_y, &clip_w, &clip_h)) { - rm690b0_jpeg_draw_ctx_t draw_ctx = { - .self = self, - .impl = impl, - .origin_x = x, - .origin_y = y, - .clip_x = clip_x, - .clip_y = clip_y, - .clip_w = clip_w, - .clip_h = clip_h, - .rotation_zero = (self->rotation == 0), - }; - - jpeg_cfg.user_data = (intptr_t)&draw_ctx; - jpeg_cfg.on_block = rm690b0_jpeg_on_block; - - ret = esp_jpeg_decode(&jpeg_cfg, NULL); - if (ret != ESP_OK) { - mp_raise_ValueError(MP_ERROR_TEXT("JPEG decode failed")); - return; - } - - // Mark dirty - mp_int_t bx = clip_x, by = clip_y, bw = clip_w, bh = clip_h; - if (map_rect_for_rotation(self, &bx, &by, &bw, &bh)) { - mark_dirty_region(impl, bx, by, bw, bh); - if (!impl->double_buffered) { - esp_err_t flush_ret = rm690b0_flush_region(self, bx, by, bw, bh, false); - if (flush_ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw JPEG: %s"), esp_err_to_name(flush_ret)); - } - } - } - } -} - -void common_hal_rm690b0_rm690b0_hline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t color) { - common_hal_rm690b0_rm690b0_fill_rect(self, x, y, width, 1, color); -} - -void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t height, mp_int_t color) { - common_hal_rm690b0_rm690b0_fill_rect(self, x, y, 1, height, color); -} - -//| def blit_buffer(self, x: int, y: int, width: int, height: int, bitmap_data: bytearray, *, dest_is_swapped: bool = False) -> None: -//| """Draw a bitmap -//| -//| :param int x: X coordinate of the top-left corner -//| :param int y: Y coordinate of the top-left corner -//| :param int width: Width of the bitmap -//| :param int height: Height of the bitmap -//| :param bytearray bitmap_data: Bitmap data (buffer protocol) -//| :param bool dest_is_swapped: If True, data is assumed to be in destination byte order (Big Endian) and will not be swapped. -//| Useful for JpegDecoder output which is already swapped. Default is False (Little Endian input). -//| """ -//| ... -//| - - -void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color) { - common_hal_rm690b0_rm690b0_hline(self, x, y, width, color); - common_hal_rm690b0_rm690b0_hline(self, x, y + height - 1, width, color); - common_hal_rm690b0_rm690b0_vline(self, x, y, height, color); - common_hal_rm690b0_rm690b0_vline(self, x + width - 1, y, height, color); -} - -static void rm690b0_draw_line_segment(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color) { - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - return; - } - - uint16_t swapped_color = RGB565_SWAP_GB(color); - size_t fb_stride = RM690B0_PANEL_WIDTH; - - mp_int_t px0, py0, px1, py1; - switch (self->rotation) { - case 90: - px0 = RM690B0_PANEL_WIDTH - y0 - 1; - py0 = x0; - px1 = RM690B0_PANEL_WIDTH - y1 - 1; - py1 = x1; - break; - case 180: - px0 = RM690B0_PANEL_WIDTH - x0 - 1; - py0 = RM690B0_PANEL_HEIGHT - y0 - 1; - px1 = RM690B0_PANEL_WIDTH - x1 - 1; - py1 = RM690B0_PANEL_HEIGHT - y1 - 1; - break; - case 270: - px0 = y0; - py0 = RM690B0_PANEL_HEIGHT - x0 - 1; - px1 = y1; - py1 = RM690B0_PANEL_HEIGHT - x1 - 1; - break; - default: - px0 = x0; - py0 = y0; - px1 = x1; - py1 = y1; - break; - } - - mp_int_t pdx = labs(px1 - px0); - mp_int_t pdy = labs(py1 - py0); - mp_int_t sx = (px0 < px1) ? 1 : -1; - mp_int_t sy = (py0 < py1) ? 1 : -1; - mp_int_t err = pdx - pdy; - - mp_int_t x = px0; - mp_int_t y = py0; - mp_int_t dirty_min_x = x, dirty_min_y = y; - mp_int_t dirty_max_x = x, dirty_max_y = y; - - while (1) { - if (x < dirty_min_x) { - dirty_min_x = x; - } - if (x > dirty_max_x) { - dirty_max_x = x; - } - if (y < dirty_min_y) { - dirty_min_y = y; - } - if (y > dirty_max_y) { - dirty_max_y = y; - } - - if (x >= 0 && x < RM690B0_PANEL_WIDTH && y >= 0 && y < RM690B0_PANEL_HEIGHT) { - impl->framebuffer[(size_t)y * fb_stride + x] = swapped_color; - } - - if (x == px1 && y == py1) { - break; - } - mp_int_t e2 = 2 * err; - if (e2 > -pdy) { - err -= pdy; - x += sx; - } - if (e2 < pdx) { - err += pdx; - y += sy; - } - } - - mp_int_t bx = dirty_min_x; - mp_int_t by = dirty_min_y; - mp_int_t bw = dirty_max_x - dirty_min_x + 1; - mp_int_t bh = dirty_max_y - dirty_min_y + 1; - - if (bx < 0) { - bw += bx; - bx = 0; - } - if (by < 0) { - bh += by; - by = 0; - } - if (bx + bw > RM690B0_PANEL_WIDTH) { - bw = RM690B0_PANEL_WIDTH - bx; - } - if (by + bh > RM690B0_PANEL_HEIGHT) { - bh = RM690B0_PANEL_HEIGHT - by; - } - - if (bw > 0 && bh > 0) { - mark_dirty_region(impl, bx, by, bw, bh); - if (!impl->double_buffered) { - rm690b0_flush_region(self, bx, by, bw, bh, false); - } - } -} - -void common_hal_rm690b0_rm690b0_line(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color) { - CHECK_INITIALIZED(); - - if (x0 == x1) { - if (y1 < y0) { - mp_int_t tmp = y0; - y0 = y1; - y1 = tmp; - } - common_hal_rm690b0_rm690b0_vline(self, x0, y0, y1 - y0 + 1, color); - return; - } - if (y0 == y1) { - if (x1 < x0) { - mp_int_t tmp = x0; - x0 = x1; - x1 = tmp; - } - common_hal_rm690b0_rm690b0_hline(self, x0, y0, x1 - x0 + 1, color); - return; - } - - mp_int_t dx = labs(x1 - x0); - mp_int_t dy = labs(y1 - y0); - mp_int_t line_length = (dx > dy) ? dx : dy; - - const mp_int_t SPLIT_THRESHOLD = 100; - const mp_int_t TARGET_SEGMENT = 50; - - if (line_length > SPLIT_THRESHOLD) { - mp_int_t num_segments = (line_length + TARGET_SEGMENT - 1) / TARGET_SEGMENT; - for (mp_int_t i = 0; i < num_segments; i++) { - mp_int_t seg_x0 = x0 + (x1 - x0) * i / num_segments; - mp_int_t seg_y0 = y0 + (y1 - y0) * i / num_segments; - mp_int_t seg_x1 = x0 + (x1 - x0) * (i + 1) / num_segments; - mp_int_t seg_y1 = y0 + (y1 - y0) * (i + 1) / num_segments; - rm690b0_draw_line_segment(self, seg_x0, seg_y0, seg_x1, seg_y1, color); - } - return; - } - - rm690b0_draw_line_segment(self, x0, y0, x1, y1, color); -} - -void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color) { - CHECK_INITIALIZED(); - if (radius < 0) { - mp_raise_ValueError(MP_ERROR_TEXT("radius must be non-negative")); - return; - } - if (radius == 0) { - common_hal_rm690b0_rm690b0_pixel(self, x, y, color); - return; - } - - - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - uint16_t swapped_color = RGB565_SWAP_GB(color); - size_t fb_stride = RM690B0_PANEL_WIDTH; - - mp_int_t bx = x - radius; - mp_int_t by = y - radius; - mp_int_t bw = radius * 2 + 1; - mp_int_t bh = radius * 2 + 1; - bool circle_fully_inside = (bx >= 0 && by >= 0 && - bx + bw <= self->width && by + bh <= self->height); - - #define RM690B0_DRAW_CIRCLE_LOOP() \ - do { \ - mp_int_t x0 = 0; \ - mp_int_t y0 = radius; \ - mp_int_t d = 1 - radius; \ - while (x0 <= y0) { \ - WRITE_CIRCLE_PIXEL(x + x0, y + y0); \ - WRITE_CIRCLE_PIXEL(x - x0, y + y0); \ - WRITE_CIRCLE_PIXEL(x + x0, y - y0); \ - WRITE_CIRCLE_PIXEL(x - x0, y - y0); \ - WRITE_CIRCLE_PIXEL(x + y0, y + x0); \ - WRITE_CIRCLE_PIXEL(x - y0, y + x0); \ - WRITE_CIRCLE_PIXEL(x + y0, y - x0); \ - WRITE_CIRCLE_PIXEL(x - y0, y - x0); \ - x0 += 1; \ - if (d < 0) { \ - d += (x0 << 1) + 1; \ - } else { \ - y0 -= 1; \ - d += ((x0 - y0) << 1) + 1; \ - } \ - } \ - } while (0) - - if (circle_fully_inside) { - #define WRITE_CIRCLE_PIXEL(px, py) \ - impl->framebuffer[(size_t)(py) * fb_stride + (px)] = swapped_color - RM690B0_DRAW_CIRCLE_LOOP(); -#undef WRITE_CIRCLE_PIXEL - } else { - #define WRITE_CIRCLE_PIXEL(px, py) do { \ - mp_int_t px_val = (px); \ - mp_int_t py_val = (py); \ - if (px_val >= 0 && px_val < self->width && \ - py_val >= 0 && py_val < self->height) { \ - impl->framebuffer[(size_t)py_val * fb_stride + px_val] = swapped_color; \ - } \ -} while (0) - RM690B0_DRAW_CIRCLE_LOOP(); -#undef WRITE_CIRCLE_PIXEL - } - -#undef RM690B0_DRAW_CIRCLE_LOOP - - mp_int_t clip_bx = bx; - mp_int_t clip_by = by; - mp_int_t clip_bw = bw; - mp_int_t clip_bh = bh; - - if (!circle_fully_inside) { - if (clip_bx < 0) { - clip_bw += clip_bx; - clip_bx = 0; - } - if (clip_by < 0) { - clip_bh += clip_by; - clip_by = 0; - } - if (clip_bx + clip_bw > self->width) { - clip_bw = self->width - clip_bx; - } - if (clip_by + clip_bh > self->height) { - clip_bh = self->height - clip_by; - } - } - - if (clip_bw > 0 && clip_bh > 0) { - // Mark region as dirty for next swap - mark_dirty_region(impl, clip_bx, clip_by, clip_bw, clip_bh); - - // Only flush immediately if not double-buffered - // When double-buffered, swap_buffers() will handle the flush - if (!impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, clip_bx, clip_by, clip_bw, clip_bh, false); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw circle: %s"), esp_err_to_name(ret)); - } - } - } -} - -void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color) { - CHECK_INITIALIZED(); - if (radius < 0) { - mp_raise_ValueError(MP_ERROR_TEXT("radius must be non-negative")); - return; - } - if (radius == 0) { - common_hal_rm690b0_rm690b0_pixel(self, x, y, color); - return; - } - - - mp_int_t max_radius = (RM690B0_MAX_DIAMETER - 1) / 2; - if (radius > max_radius) { - radius = max_radius; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - mp_int_t top = y - radius; - mp_int_t row_count = radius * 2 + 1; - if (row_count <= 0) { - return; - } - - mp_int_t bx = x - radius; - mp_int_t by = y - radius; - mp_int_t bw = row_count; - mp_int_t bh = row_count; - bool circle_fully_inside = (bx >= 0 && by >= 0 && - bx + bw <= self->width && by + bh <= self->height); - - #define STACK_ALLOC_THRESHOLD 128 - int16_t left_stack[STACK_ALLOC_THRESHOLD]; - int16_t right_stack[STACK_ALLOC_THRESHOLD]; - int16_t *left = left_stack; - int16_t *right = right_stack; - int16_t *heap_span = NULL; - - if (row_count > STACK_ALLOC_THRESHOLD) { - int16_t *cache = rm690b0_acquire_span_cache(impl, (size_t)row_count); - if (cache != NULL) { - left = cache; - right = cache + (mp_int_t)impl->circle_span_capacity; - } else { - size_t span_entries = (size_t)row_count * 2; - heap_span = (int16_t *)heap_caps_malloc(span_entries * sizeof(int16_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - if (heap_span == NULL) { - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to allocate memory for circle")); - return; - } - left = heap_span; - right = heap_span + row_count; - } - } - - for (mp_int_t i = 0; i < row_count; i++) { - left[i] = INT16_MAX; - right[i] = INT16_MIN; - } - - rm690b0_span_accumulator_t acc = { - .top = top, - .row_count = row_count, - .left = left, - .right = right, - }; - - mp_int_t xi = 0; - mp_int_t yi = radius; - mp_int_t d = 1 - radius; - - while (xi <= yi) { - rm690b0_span_update(&acc, y + yi, x + xi); - rm690b0_span_update(&acc, y + yi, x - xi); - rm690b0_span_update(&acc, y - yi, x + xi); - rm690b0_span_update(&acc, y - yi, x - xi); - - if (yi != xi) { - rm690b0_span_update(&acc, y + xi, x + yi); - rm690b0_span_update(&acc, y + xi, x - yi); - rm690b0_span_update(&acc, y - xi, x + yi); - rm690b0_span_update(&acc, y - xi, x - yi); - } - - xi += 1; - if (d < 0) { - d += (xi << 1) + 1; - } else { - yi -= 1; - d += ((xi - yi) << 1) + 1; - } - } - - uint16_t swapped_color = RGB565_SWAP_GB(color); - size_t fb_stride = RM690B0_PANEL_WIDTH; - - if (circle_fully_inside) { - for (mp_int_t row = 0; row < row_count; row++) { - int16_t span_left = left[row]; - int16_t span_right = right[row]; - if (span_left > span_right) { - continue; - } - mp_int_t yy = top + row; - size_t span_width = (size_t)(span_right - span_left + 1); - uint16_t *dest = impl->framebuffer + (size_t)yy * fb_stride + span_left; - rm690b0_fill_span_fast(dest, span_width, swapped_color); - } - } else { - for (mp_int_t row = 0; row < row_count; row++) { - int16_t span_left = left[row]; - int16_t span_right = right[row]; - if (span_left > span_right) { - continue; - } - mp_int_t yy = top + row; - if (yy < 0 || yy >= self->height) { - continue; - } - mp_int_t span_left_i = (mp_int_t)span_left; - mp_int_t span_right_i = (mp_int_t)span_right; - - if (span_left_i < 0) { - span_left_i = 0; - } - if (span_right_i >= self->width) { - span_right_i = self->width - 1; - } - - mp_int_t span_width = span_right_i - span_left_i + 1; - if (span_width <= 0) { - continue; - } - - uint16_t *dest = impl->framebuffer + (size_t)yy * fb_stride + span_left_i; - rm690b0_fill_span_fast(dest, (size_t)span_width, swapped_color); - } - } - - mp_int_t clip_bx = bx; - mp_int_t clip_by = by; - mp_int_t clip_bw = bw; - mp_int_t clip_bh = bh; - - if (!circle_fully_inside) { - if (clip_bx < 0) { - clip_bw += clip_bx; - clip_bx = 0; - } - if (clip_by < 0) { - clip_bh += clip_by; - clip_by = 0; - } - if (clip_bx + clip_bw > self->width) { - clip_bw = self->width - clip_bx; - } - if (clip_by + clip_bh > self->height) { - clip_bh = self->height - clip_by; - } - } - - if (clip_bw > 0 && clip_bh > 0) { - // Mark region as dirty for next swap - mark_dirty_region(impl, clip_bx, clip_by, clip_bw, clip_bh); - - // Only flush immediately if not double-buffered - // When double-buffered, swap_buffers() will handle the flush - if (!impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, clip_bx, clip_by, clip_bw, clip_bh, false); - if (ret != ESP_OK) { - if (heap_span != NULL) { - heap_caps_free(heap_span); - } - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw fill_circle: %s"), esp_err_to_name(ret)); - } - } - } - - if (heap_span != NULL) { - heap_caps_free(heap_span); - } -} - -void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees) { - CHECK_INITIALIZED(); - - mp_int_t normalized = ((degrees % 360) + 360) % 360; - switch (normalized) { - case 0: - case 180: - self->width = RM690B0_PANEL_WIDTH; - self->height = RM690B0_PANEL_HEIGHT; - break; - case 90: - case 270: - self->width = RM690B0_PANEL_HEIGHT; - self->height = RM690B0_PANEL_WIDTH; - break; - default: - mp_raise_ValueError(MP_ERROR_TEXT("Rotation must be 0, 90, 180, or 270")); - return; - } - - self->rotation = normalized; - ESP_LOGI(TAG, "Display rotation set to %d (logical size %dx%d)", (int)normalized, (int)self->width, (int)self->height); -} - -mp_int_t common_hal_rm690b0_rm690b0_get_rotation(const rm690b0_rm690b0_obj_t *self) { - return self->rotation; -} - -void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t value) { - CHECK_INITIALIZED(); - if (value < 0.0f || value > 1.0f) { - mp_raise_ValueError(MP_ERROR_TEXT("Brightness must be between 0.0 and 1.0")); - return; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->io_handle == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - uint8_t brightness; - if (value <= 0.0f) { - brightness = 0; - } else if (value >= 1.0f) { - brightness = 0xFF; - } else { - brightness = (uint8_t)(value * 255.0f + 0.5f); - } - - if (brightness == self->brightness_raw) { - return; - } - - uint8_t page_cmd = 0x00; - esp_err_t err = rm690b0_tx_param(impl, 0xFE, &page_cmd, 1); - if (err != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to select brightness page: %s"), esp_err_to_name(err)); - return; - } - - err = rm690b0_tx_param(impl, 0x51, &brightness, 1); - if (err != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to write brightness: %s"), esp_err_to_name(err)); - return; - } - - uint8_t ctrl_display = (brightness == 0) ? 0x20 : 0x2C; - err = rm690b0_tx_param(impl, 0x53, &ctrl_display, 1); - if (err != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to latch brightness: %s"), esp_err_to_name(err)); - return; - } - - self->brightness_raw = brightness; - ESP_LOGI(TAG, "Set brightness to %u/255 (%.3f)", brightness, (double)value); -} - -mp_float_t common_hal_rm690b0_rm690b0_get_brightness(const rm690b0_rm690b0_obj_t *self) { - uint8_t raw = self->brightness_raw; - return (mp_float_t)raw / 255.0f; -} - -void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data, bool dest_is_swapped) { - CHECK_INITIALIZED(); - - if (width <= 0 || height <= 0) { - return; - } - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(bitmap_data, &bufinfo, MP_BUFFER_READ); - - size_t src_width = (size_t)width; - size_t src_height = (size_t)height; - - // Check for overflow in bitmap size calculation - size_t expected_bytes; - if (!check_bitmap_size(src_width, src_height, &expected_bytes)) { - mp_raise_ValueError(MP_ERROR_TEXT("Bitmap dimensions too large (max ~32767x32767 on 32-bit systems)")); - return; - } - - if (bufinfo.len < expected_bytes) { - mp_raise_ValueError(MP_ERROR_TEXT("Bitmap data too small for width * height")); - return; - } - - mp_int_t logical_x = x; - mp_int_t logical_y = y; - mp_int_t logical_w = width; - mp_int_t logical_h = height; - - if (!clip_logical_rect(self, &logical_x, &logical_y, &logical_w, &logical_h)) { - return; - } - - mp_int_t crop_left = logical_x - x; - mp_int_t crop_top = logical_y - y; - if (crop_left < 0) { - crop_left = 0; - } - if (crop_top < 0) { - crop_top = 0; - } - - mp_int_t phys_x = logical_x; - mp_int_t phys_y = logical_y; - mp_int_t phys_w = logical_w; - mp_int_t phys_h = logical_h; - - if (!map_rect_for_rotation(self, &phys_x, &phys_y, &phys_w, &phys_h)) { - return; - } - - if (phys_w <= 0 || phys_h <= 0) { - return; - } - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - if (impl == NULL || impl->framebuffer == NULL) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Invalid display handle")); - return; - } - - const uint16_t *src_base = (const uint16_t *)bufinfo.buf; - size_t src_stride = src_width; - const uint16_t *src_pixels = src_base + (size_t)crop_top * src_stride + (size_t)crop_left; - - uint16_t *framebuffer = impl->framebuffer; - size_t fb_stride = RM690B0_PANEL_WIDTH; - - // If source is already swapped (BE) and we need BE for display, we skip the swap. - // If source is normal (LE) and we need BE (display), we swap. - // Standard blit_buffer assumes LE input and swaps to BE. - // IF dest_is_swapped is TRUE, it means the SOURCE is already in destination format (BE). - - switch (self->rotation) { - case 0: - for (mp_int_t row = 0; row < logical_h; row++) { - const uint16_t *src_row = src_pixels + (size_t)row * src_stride; - uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; - if (dest_is_swapped) { - memcpy(dst_row, src_row, logical_w * sizeof(uint16_t)); - } else { - for (mp_int_t col = 0; col < logical_w; col++) { - dst_row[col] = RGB565_SWAP_GB(src_row[col]); - } - } - } - break; - case 180: - for (mp_int_t row = 0; row < logical_h; row++) { - const uint16_t *src_row = src_pixels + (size_t)(logical_h - 1 - row) * src_stride; - uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; - for (mp_int_t col = 0; col < logical_w; col++) { - uint16_t val = src_row[logical_w - 1 - col]; - dst_row[col] = dest_is_swapped ? val : RGB565_SWAP_GB(val); - } - } - break; - case 90: { - mp_int_t phys_h_rows = phys_h; - mp_int_t phys_w_cols = phys_w; - for (mp_int_t row = 0; row < phys_h_rows; row++) { - uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; - for (mp_int_t col = 0; col < phys_w_cols; col++) { - mp_int_t src_row_idx = logical_h - 1 - col; - mp_int_t src_col_idx = row; - const uint16_t *src_row = src_pixels + (size_t)src_row_idx * src_stride; - uint16_t val = src_row[src_col_idx]; - dst_row[col] = dest_is_swapped ? val : RGB565_SWAP_GB(val); - } - } - break; - } - case 270: { - mp_int_t phys_h_rows = phys_h; - mp_int_t phys_w_cols = phys_w; - for (mp_int_t row = 0; row < phys_h_rows; row++) { - uint16_t *dst_row = framebuffer + (size_t)(phys_y + row) * fb_stride + phys_x; - for (mp_int_t col = 0; col < phys_w_cols; col++) { - mp_int_t src_row_idx = col; - mp_int_t src_col_idx = logical_w - 1 - row; - const uint16_t *src_row = src_pixels + (size_t)src_row_idx * src_stride; - uint16_t val = src_row[src_col_idx]; - dst_row[col] = dest_is_swapped ? val : RGB565_SWAP_GB(val); - } - } - break; - } - default: - mp_raise_ValueError(MP_ERROR_TEXT("Unsupported rotation")); - return; - } - - // Mark region as dirty for next swap - mark_dirty_region(impl, phys_x, phys_y, phys_w, phys_h); - - // Only flush immediately if not double-buffered - // When double-buffered, swap_buffers() will handle the flush - if (!impl->double_buffered) { - esp_err_t ret = rm690b0_flush_region(self, phys_x, phys_y, phys_w, phys_h, false); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to draw bitmap: %s"), esp_err_to_name(ret)); - } - } -} - -void common_hal_rm690b0_rm690b0_swap_buffers(rm690b0_rm690b0_obj_t *self, bool copy) { - CHECK_INITIALIZED(); - - rm690b0_impl_t *impl = (rm690b0_impl_t *)self->impl; - - // Lazy allocation: allocate front buffer on first call - if (!impl->double_buffered && impl->framebuffer_front == NULL) { - size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; - impl->framebuffer_front = heap_caps_malloc(framebuffer_pixels * sizeof(uint16_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - - if (impl->framebuffer_front == NULL) { - ESP_LOGW(TAG, "Unable to allocate front framebuffer - falling back to single-buffered refresh"); - // Fall through to single-buffer mode below - } else { - impl->double_buffered = true; - ESP_LOGI(TAG, "Allocated front framebuffer (%zu KB) - double-buffering enabled", - (framebuffer_pixels * sizeof(uint16_t)) / 1024); - - // Copy current back buffer to front buffer so swap has valid data - memcpy(impl->framebuffer_front, impl->framebuffer, - framebuffer_pixels * sizeof(uint16_t)); - } - } - - if (!impl->double_buffered || impl->framebuffer_front == NULL) { - // Single-buffered mode - just flush current framebuffer - esp_err_t ret = rm690b0_flush_region(self, 0, 0, self->width, self->height, false); - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, - MP_ERROR_TEXT("Failed to refresh display: %s (0x%x)"), - esp_err_to_name(ret), ret); - } - return; - } - - // Double-buffered mode: flush dirty region - // If no dirty region, flush everything - mp_int_t flush_x = 0; - mp_int_t flush_y = 0; - mp_int_t flush_w = self->width; - mp_int_t flush_h = self->height; - - if (impl->dirty_region_valid) { - // Only flush the dirty region for better performance - flush_x = impl->dirty_x; - flush_y = impl->dirty_y; - flush_w = impl->dirty_w; - flush_h = impl->dirty_h; - ESP_LOGI(TAG, "Flushing dirty region: %d,%d %dx%d", flush_x, flush_y, flush_w, flush_h); - } else { - ESP_LOGI(TAG, "Flushing full screen (no dirty region)"); - } - - // Skip final delay if we're doing a copy - the memcpy will protect the SPI transfer - esp_err_t ret = rm690b0_flush_region(self, flush_x, flush_y, flush_w, flush_h, copy); - - - // Now swap the buffer pointers - // After swap: framebuffer becomes the old front buffer (ready for new drawing) - // framebuffer_front becomes the old back buffer (now being displayed) - uint16_t *temp = impl->framebuffer_front; - impl->framebuffer_front = impl->framebuffer; - impl->framebuffer = temp; - - // Reset dirty region after flush - impl->dirty_region_valid = false; - impl->dirty_x = 0; - impl->dirty_y = 0; - impl->dirty_w = 0; - impl->dirty_h = 0; - - // Optionally copy front buffer to back buffer for incremental drawing - // Standard double-buffering: back buffer inherits current display content - // Skip copy for better performance when doing full redraws (animations) - if (copy) { - size_t framebuffer_pixels = (size_t)RM690B0_PANEL_WIDTH * RM690B0_PANEL_HEIGHT; - memcpy(impl->framebuffer, impl->framebuffer_front, - framebuffer_pixels * sizeof(uint16_t)); - ESP_LOGI(TAG, "Buffers swapped and back buffer updated"); - } else { - ESP_LOGI(TAG, "Buffers swapped (no copy)"); - } - if (ret != ESP_OK) { - mp_raise_msg_varg(&mp_type_RuntimeError, - MP_ERROR_TEXT("Failed to refresh display: %s (0x%x)"), - esp_err_to_name(ret), ret); - } -} - -void common_hal_rm690b0_rm690b0_convert_bmp(rm690b0_rm690b0_obj_t *self, mp_obj_t src_data, mp_obj_t dest_bitmap) { - mp_buffer_info_t src_info; - mp_get_buffer_raise(src_data, &src_info, MP_BUFFER_READ); - - mp_buffer_info_t dest_info; - mp_get_buffer_raise(dest_bitmap, &dest_info, MP_BUFFER_WRITE); - - if (src_info.len < sizeof(bmp_header_t)) { - mp_raise_ValueError(MP_ERROR_TEXT("BMP data too small")); - return; - } - - const bmp_header_t *header = (const bmp_header_t *)src_info.buf; - - if (header->type != 0x4D42) { // 'BM' - mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP header")); - return; - } - - if (header->bpp != 24 && header->bpp != 16) { - mp_raise_ValueError(MP_ERROR_TEXT("Only 16-bit and 24-bit BMP supported")); - return; - } - - if (header->compression != 0 && header->compression != 3) { - mp_raise_ValueError(MP_ERROR_TEXT("Compressed BMP not supported")); - return; - } - - mp_int_t width = header->width; - mp_int_t height = abs(header->height); - bool top_down = (header->height < 0); - size_t data_offset = header->offset; - - if (data_offset >= src_info.len) { - mp_raise_ValueError(MP_ERROR_TEXT("Invalid BMP data offset")); - return; - } - - // Check destination size implicitly by buffer length - // We assume the user created the bitmap correctly. We will not overflow the buffer. - size_t max_dest_pixels = dest_info.len / sizeof(uint16_t); - if ((size_t)(width * height) > max_dest_pixels) { - mp_raise_ValueError(MP_ERROR_TEXT("Destination bitmap too small")); - return; - } - - // Pointers - uint16_t *dest_buf = (uint16_t *)dest_info.buf; - const uint8_t *src_pixels = (const uint8_t *)src_info.buf + data_offset; - - int row_padding = (4 - ((width * (header->bpp / 8)) % 4)) % 4; - int src_stride = width * (header->bpp / 8) + row_padding; - - for (int row = 0; row < height; row++) { - int src_row_idx = top_down ? row : (height - 1 - row); - const uint8_t *row_ptr = src_pixels + (size_t)src_row_idx * src_stride; - uint16_t *dst_row_ptr = dest_buf + (size_t)row * width; // Dense packing in Bitmap - - if (header->bpp == 24) { - for (int col = 0; col < width; col++) { - uint8_t b = row_ptr[col * 3]; - uint8_t g = row_ptr[col * 3 + 1]; - uint8_t r = row_ptr[col * 3 + 2]; - uint16_t rgb = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); - dst_row_ptr[col] = RGB565_SWAP_GB(rgb); - } - } else { - for (int col = 0; col < width; col++) { - uint16_t val = row_ptr[col * 2] | (row_ptr[col * 2 + 1] << 8); - dst_row_ptr[col] = RGB565_SWAP_GB(val); - } - } - } -} diff --git a/ports/espressif/common-hal/rm690b0/RM690B0.h b/ports/espressif/common-hal/rm690b0/RM690B0.h deleted file mode 100644 index 771c8364a8571..0000000000000 --- a/ports/espressif/common-hal/rm690b0/RM690B0.h +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "shared-bindings/rm690b0/RM690B0.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_types.h" - -void common_hal_rm690b0_rm690b0_pixel(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t color); -void common_hal_rm690b0_rm690b0_fill_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); -void common_hal_rm690b0_rm690b0_hline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t color); -void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t height, mp_int_t color); -void common_hal_rm690b0_rm690b0_line(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color); -void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); -void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); -void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); -void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees); -void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t value); -void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data, bool dest_is_swapped); -void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data); -void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data); -void common_hal_rm690b0_rm690b0_deinit_all(void); - -// Helper function to expose panel handle for LVGL integration -esp_lcd_panel_handle_t rm690b0_get_panel_handle(void); diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x16.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x16.h deleted file mode 100644 index 2cbdaae93f498..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x16.h +++ /dev/null @@ -1,494 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Font: LiberationMono-Bold.ttf -// Size: 16x16 pixels -// Characters: 0x20..0x7E (' '..'~') -// Each character: 32 bytes (16 rows × 2 bytes per row) -// Each row: 2 byte(s) for 16 pixels, MSB = leftmost pixel -// Indexing: glyph = rm690b0_font_16x16_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E -// -// Generated by ttf_to_rm690b0.py - -static const uint8_t rm690b0_font_16x16_data[95][32] = { - // 0x20 ' ' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x21 '!' - { - 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x22 '\"' - { - 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x40, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x23 '#' - { - 0x00, 0x00, 0x03, 0x20, 0x02, 0x20, 0x02, 0x20, 0x0F, 0xF0, 0x02, 0x40, 0x06, 0x40, 0x04, 0x40, - 0x1F, 0xF0, 0x04, 0xC0, 0x04, 0x80, 0x0C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x24 '$' - { - 0x01, 0x00, 0x07, 0xC0, 0x0F, 0xE0, 0x0D, 0x60, 0x0D, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x01, 0x70, - 0x01, 0x30, 0x0D, 0x30, 0x0F, 0xE0, 0x07, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x25 '%' - { - 0x00, 0x00, 0x0E, 0x30, 0x1A, 0x20, 0x12, 0x40, 0x12, 0xC0, 0x1A, 0x80, 0x0F, 0xF0, 0x03, 0xD0, - 0x02, 0xD8, 0x04, 0xD8, 0x0C, 0xD0, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x26 '&' - { - 0x00, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x06, 0x40, 0x06, 0xC0, 0x07, 0x80, 0x0F, 0x20, 0x0D, 0x20, - 0x19, 0xE0, 0x1C, 0xE0, 0x0F, 0xF8, 0x07, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x27 '\'' - { - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x28 '(' - { - 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x00, 0x00 - }, - // 0x29 ')' - { - 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, - 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00 - }, - // 0x2A '*' - { - 0x01, 0x80, 0x05, 0x80, 0x07, 0xE0, 0x03, 0xC0, 0x03, 0x80, 0x06, 0xC0, 0x02, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2B '+' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2C ',' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00 - }, - // 0x2D '-' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x03, 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2E '.' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2F '/' - { - 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x30 '0' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x70, 0x0D, 0xF0, 0x0D, 0xF0, 0x0C, 0x70, - 0x0C, 0x60, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x31 '1' - { - 0x00, 0x00, 0x01, 0x80, 0x03, 0x80, 0x0F, 0x80, 0x0D, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x32 '2' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x00, 0x60, 0x00, 0x60, 0x01, 0xC0, 0x03, 0x80, - 0x07, 0x00, 0x0E, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x33 '3' - { - 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xE0, 0x0C, 0x60, 0x00, 0x60, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0x60, - 0x00, 0x30, 0x0C, 0x70, 0x0F, 0xE0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x34 '4' - { - 0x00, 0x00, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x03, 0x60, 0x06, 0x60, 0x04, 0x60, 0x0C, 0x60, - 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x35 '5' - { - 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0C, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x00, 0x70, - 0x00, 0x70, 0x0C, 0x60, 0x0F, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x36 '6' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x00, 0x0D, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, - 0x0C, 0x70, 0x06, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x37 '7' - { - 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x60, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, - 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x38 '8' - { - 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xE0, 0x0E, 0x60, 0x0E, 0x60, 0x07, 0xC0, 0x07, 0xE0, 0x0E, 0x60, - 0x0C, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x39 '9' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0E, 0x70, 0x0F, 0xF0, 0x07, 0xF0, - 0x00, 0x60, 0x0C, 0x60, 0x07, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3A ':' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3B ';' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00 - }, - // 0x3C '<' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xF0, 0x07, 0xE0, 0x0F, 0x00, 0x0C, 0x00, 0x0F, 0x00, - 0x07, 0xE0, 0x00, 0xF0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3D '=' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3E '>' - { - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0F, 0x00, 0x07, 0xE0, 0x00, 0xF0, 0x00, 0x30, 0x00, 0xF0, - 0x07, 0xC0, 0x0F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3F '?' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x00, 0x60, 0x00, 0xE0, 0x01, 0x80, - 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x40 '@' - { - 0x03, 0xC0, 0x06, 0x20, 0x04, 0x30, 0x09, 0xB0, 0x0A, 0x50, 0x0A, 0x50, 0x1E, 0x50, 0x14, 0x50, - 0x14, 0x50, 0x1C, 0xD0, 0x0E, 0xD0, 0x0B, 0x60, 0x08, 0x00, 0x04, 0x20, 0x03, 0xC0, 0x00, 0x00 - }, - // 0x41 'A' - { - 0x00, 0x00, 0x03, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x06, 0xC0, 0x06, 0x60, 0x06, 0x60, 0x0F, 0xE0, - 0x0F, 0xF0, 0x0C, 0x30, 0x1C, 0x30, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x42 'B' - { - 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x0C, 0x70, 0x0C, 0x60, 0x0F, 0xE0, 0x0F, 0xE0, 0x0C, 0x30, - 0x0C, 0x30, 0x0C, 0x30, 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x43 'C' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x20, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, - 0x0C, 0x30, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x44 'D' - { - 0x00, 0x00, 0x0F, 0x80, 0x0F, 0xE0, 0x0C, 0x60, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, - 0x0C, 0x70, 0x0C, 0x60, 0x0F, 0xE0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x45 'E' - { - 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0C, 0x00, - 0x0C, 0x00, 0x0C, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x46 'F' - { - 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x00, 0x0E, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0E, 0x00, - 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x47 'G' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0C, 0x00, 0x0C, 0xF0, 0x0C, 0xF0, - 0x0C, 0x30, 0x0E, 0x70, 0x07, 0xF0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x48 'H' - { - 0x00, 0x00, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0F, 0xF0, 0x0F, 0xF0, 0x0C, 0x70, - 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x49 'I' - { - 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4A 'J' - { - 0x00, 0x00, 0x03, 0xE0, 0x03, 0xE0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, - 0x0C, 0x60, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4B 'K' - { - 0x00, 0x00, 0x0C, 0x70, 0x0C, 0x60, 0x0C, 0xE0, 0x0D, 0xC0, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0xC0, - 0x0E, 0xE0, 0x0C, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4C 'L' - { - 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4D 'M' - { - 0x00, 0x00, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0xF0, 0x0F, 0xF0, 0x0B, 0xB0, 0x09, 0xB0, - 0x09, 0xB0, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4E 'N' - { - 0x00, 0x00, 0x0E, 0x30, 0x0E, 0x30, 0x0F, 0x30, 0x0F, 0x30, 0x0F, 0x30, 0x0D, 0xB0, 0x0D, 0xB0, - 0x0C, 0xF0, 0x0C, 0xF0, 0x0C, 0xF0, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4F 'O' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, - 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x50 'P' - { - 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x70, 0x0F, 0xE0, 0x0F, 0xC0, - 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x51 'Q' - { - 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, - 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x00 - }, - // 0x52 'R' - { - 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xF0, 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x70, 0x0F, 0xE0, 0x0F, 0xC0, - 0x0C, 0xC0, 0x0C, 0x60, 0x0C, 0x70, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x53 'S' - { - 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xE0, 0x0C, 0x70, 0x0C, 0x00, 0x0F, 0x80, 0x07, 0xE0, 0x00, 0xF0, - 0x00, 0x30, 0x0C, 0x30, 0x0F, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x54 'T' - { - 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x55 'U' - { - 0x00, 0x00, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, - 0x0C, 0x70, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x56 'V' - { - 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x70, 0x0C, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0xC0, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x57 'W' - { - 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x18, 0x30, 0x09, 0xB0, 0x0D, 0xB0, 0x0F, 0xB0, 0x0F, 0xF0, - 0x0E, 0xE0, 0x0E, 0xE0, 0x0E, 0x60, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x58 'X' - { - 0x00, 0x00, 0x0C, 0x30, 0x0E, 0x60, 0x06, 0xE0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0xC0, - 0x07, 0xC0, 0x06, 0x60, 0x0C, 0x70, 0x1C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x59 'Y' - { - 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x06, 0xC0, 0x03, 0xC0, 0x03, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5A 'Z' - { - 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x60, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x00, - 0x06, 0x00, 0x0E, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5B '[' - { - 0x03, 0xE0, 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, 0xE0, 0x00, 0x00 - }, - // 0x5C '\\' - { - 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, - 0x00, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5D ']' - { - 0x07, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, - 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x07, 0xC0, 0x00, 0x00 - }, - // 0x5E '^' - { - 0x00, 0x00, 0x03, 0x80, 0x03, 0xC0, 0x06, 0xC0, 0x06, 0x40, 0x0C, 0x60, 0x0C, 0x20, 0x08, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5F '_' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00 - }, - // 0x60 '`' - { - 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x61 'a' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x07, 0xE0, 0x0F, 0xE0, - 0x0C, 0x60, 0x0C, 0xE0, 0x0F, 0xF0, 0x07, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x62 'b' - { - 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0D, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, - 0x0C, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x0D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x63 'c' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x60, 0x0C, 0x00, 0x0C, 0x00, - 0x0C, 0x00, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x64 'd' - { - 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x07, 0x60, 0x0F, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0C, 0x60, - 0x0C, 0x60, 0x0E, 0x60, 0x0F, 0xE0, 0x07, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x65 'e' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0C, 0x60, 0x0F, 0xF0, 0x0F, 0xF0, - 0x0C, 0x00, 0x0E, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x66 'f' - { - 0x01, 0xF0, 0x03, 0xF0, 0x03, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x67 'g' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xB0, 0x07, 0xF0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x70, - 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x60, 0x07, 0xE0, 0x07, 0xC0, 0x00, 0x00 - }, - // 0x68 'h' - { - 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0xE0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x70, - 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x69 'i' - { - 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x07, 0x80, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6A 'j' - { - 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x07, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, - 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x0F, 0x80, 0x0F, 0x00, 0x00, 0x00 - }, - // 0x6B 'k' - { - 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x60, 0x0E, 0xE0, 0x0E, 0xC0, 0x0F, 0x80, 0x0F, 0xC0, - 0x0E, 0xC0, 0x0E, 0xE0, 0x0E, 0x60, 0x0E, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6C 'l' - { - 0x07, 0x80, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6D 'm' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x60, 0x0F, 0xF0, 0x0D, 0xB0, 0x09, 0xB0, 0x09, 0xB0, - 0x09, 0xB0, 0x09, 0xB0, 0x09, 0xB0, 0x09, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6E 'n' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x70, - 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x0C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6F 'o' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, - 0x0C, 0x70, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x70 'p' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x0F, 0xE0, 0x0E, 0x70, 0x0C, 0x70, 0x0C, 0x30, - 0x0C, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x0D, 0xC0, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00 - }, - // 0x71 'q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x60, 0x0F, 0xE0, 0x0E, 0x60, 0x0C, 0x60, 0x0C, 0x60, - 0x0C, 0x60, 0x0E, 0x60, 0x0F, 0xE0, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00 - }, - // 0x72 'r' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE0, 0x07, 0xE0, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x73 's' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0C, 0x60, 0x0F, 0x00, 0x07, 0xE0, - 0x00, 0xE0, 0x0C, 0x70, 0x0F, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x74 't' - { - 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x03, 0xE0, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x75 'u' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, - 0x0C, 0x60, 0x0E, 0x60, 0x0F, 0xE0, 0x07, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x76 'v' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x0E, 0x60, 0x06, 0x60, - 0x06, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x77 'w' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x18, 0x10, 0x19, 0xB0, 0x09, 0xB0, 0x0B, 0xB0, - 0x0F, 0xF0, 0x0E, 0xE0, 0x0E, 0x60, 0x0E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x78 'x' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x06, 0x60, 0x06, 0xC0, 0x03, 0xC0, 0x03, 0x80, - 0x03, 0xC0, 0x06, 0xC0, 0x0E, 0x60, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x79 'y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x06, 0x60, 0x06, 0x60, - 0x06, 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00 - }, - // 0x7A 'z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, - 0x07, 0x00, 0x06, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x7B '{' - { - 0x01, 0xE0, 0x03, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0x00 - }, - // 0x7C '|' - { - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80 - }, - // 0x7D '}' - { - 0x0F, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x00, 0xE0, - 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0F, 0x00, 0x00, 0x00 - }, - // 0x7E '~' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0F, 0x90, 0x09, 0xF0, - 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, -}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h deleted file mode 100644 index b50d12521ffbf..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_16x24.h +++ /dev/null @@ -1,589 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Font: LiberationMono-Bold.ttf -// Size: 16x24 pixels -// Characters: 0x20..0x7E (' '..'~') -// Each character: 48 bytes (24 rows × 2 bytes per row) -// Each row: 2 byte(s) for 16 pixels, MSB = leftmost pixel -// Indexing: glyph = rm690b0_font_16x24_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E -// -// Generated by ttf_to_rm690b0.py - -static const uint8_t rm690b0_font_16x24_data[95][48] = { - // 0x20 ' ' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x21 '!' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x22 '\"' - { - 0x00, 0x00, 0x00, 0x00, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x30, 0x0E, 0x30, - 0x0E, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x23 '#' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x03, 0x18, 0x06, 0x18, 0x3F, 0xFE, 0x3F, 0xFE, - 0x06, 0x30, 0x04, 0x30, 0x0C, 0x30, 0x0C, 0x20, 0x3F, 0xFC, 0x3F, 0xFC, 0x08, 0x60, 0x18, 0x60, - 0x18, 0x40, 0x18, 0xC0, 0x18, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x24 '$' - { - 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x07, 0xF0, 0x1F, 0xF8, 0x1C, 0xBC, 0x3C, 0x9C, 0x3C, 0x80, - 0x1C, 0x80, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x9C, 0x38, 0x9C, 0x38, 0x9C, 0x38, 0x9C, - 0x1C, 0xBC, 0x0F, 0xF8, 0x07, 0xF0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x25 '%' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, 0x7C, 0x18, 0xCE, 0x30, 0xC6, 0x60, 0xC6, 0x60, - 0xCE, 0xC0, 0x7D, 0x80, 0x79, 0x80, 0x03, 0x78, 0x06, 0xFC, 0x0E, 0xCC, 0x0C, 0xCC, 0x18, 0xCC, - 0x30, 0xCC, 0x30, 0xFC, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x26 '&' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0F, 0xE0, 0x1C, 0xE0, 0x18, 0x60, 0x1C, 0xE0, - 0x1F, 0xC0, 0x0F, 0x00, 0x3E, 0x18, 0x7F, 0x38, 0x77, 0x30, 0xE3, 0xF0, 0xE1, 0xF0, 0xE0, 0xE0, - 0x71, 0xF0, 0x7F, 0xFC, 0x1F, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x27 '\'' - { - 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x80, - 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x28 '(' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x80, - 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, - 0x07, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0xE0 - }, - // 0x29 ')' - { - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xE0, - 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, - 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x07, 0x00 - }, - // 0x2A '*' - { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x09, 0x90, 0x0F, 0xF8, 0x0F, 0xF0, 0x03, 0xC0, - 0x07, 0xE0, 0x06, 0x70, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2B '+' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x3F, 0xFC, 0x3F, 0xFC, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2C ',' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x80, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x0C, 0x00 - }, - // 0x2D '-' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2E '.' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2F '/' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x38, 0x00, 0x30, 0x00, 0x70, 0x00, 0x60, - 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0E, 0x00, - 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x30 '0' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x38, 0x1C, 0x3C, - 0x1C, 0x1C, 0x3D, 0x9C, 0x3D, 0x9C, 0x3D, 0x9C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1C, 0x38, - 0x0E, 0x78, 0x0F, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x31 '1' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x03, 0xE0, 0x07, 0xE0, 0x1F, 0xE0, 0x19, 0xE0, - 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, - 0x01, 0xE0, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x32 '2' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x00, 0x3C, - 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF8, 0x01, 0xF0, 0x03, 0xE0, 0x07, 0xC0, 0x0F, 0x00, 0x1E, 0x00, - 0x1E, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x33 '3' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1E, 0x78, 0x1C, 0x3C, 0x00, 0x3C, - 0x00, 0x38, 0x00, 0x78, 0x03, 0xF0, 0x03, 0xF0, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x3C, 0x1C, - 0x1C, 0x3C, 0x1F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x34 '4' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x01, 0xF0, 0x03, 0xF0, 0x03, 0xF0, - 0x07, 0x70, 0x0E, 0x70, 0x0C, 0x70, 0x1C, 0x70, 0x38, 0x70, 0x3F, 0xFE, 0x3F, 0xFE, 0x00, 0x70, - 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x35 '5' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, - 0x1D, 0xE0, 0x1F, 0xF8, 0x1E, 0x38, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x3C, 0x3C, - 0x1C, 0x38, 0x1F, 0xF0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x36 '6' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x07, 0xF8, 0x0E, 0x38, 0x1E, 0x38, 0x1C, 0x00, - 0x1C, 0x00, 0x1D, 0xF0, 0x3F, 0xF8, 0x3E, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, - 0x0E, 0x38, 0x07, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x37 '7' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, - 0x00, 0xF0, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x07, 0x80, - 0x07, 0x80, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x38 '8' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x38, 0x1E, 0x38, 0x07, 0xF0, 0x0F, 0xF0, 0x1E, 0x38, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, - 0x1E, 0x3C, 0x0F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x39 '9' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, 0x1E, 0x78, 0x1C, 0x38, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x1C, 0x3C, 0x1E, 0x7C, 0x0F, 0xFC, 0x07, 0x9C, 0x00, 0x38, 0x1C, 0x38, - 0x1E, 0x78, 0x0F, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3A ':' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3B ';' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00 - }, - // 0x3C '<' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x78, - 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0x38, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0x78, - 0x00, 0x1C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3D '=' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, - 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3E '>' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x1F, 0x00, - 0x07, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1F, 0x00, - 0x3C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3F '?' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1E, 0x3C, 0x3C, 0x1C, 0x38, 0x1C, - 0x00, 0x3C, 0x00, 0xF8, 0x01, 0xE0, 0x03, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x40 '@' - { - 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x07, 0xF8, 0x0E, 0x18, 0x18, 0x0C, 0x19, 0xDC, 0x33, 0xF6, - 0x37, 0x76, 0x36, 0x36, 0x24, 0x36, 0x2C, 0x26, 0x2C, 0x66, 0x2C, 0x66, 0x2C, 0x64, 0x26, 0xEC, - 0x37, 0xBC, 0x33, 0x38, 0x18, 0x00, 0x1C, 0x18, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00 - }, - // 0x41 'A' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x07, 0xC0, 0x0F, 0xC0, 0x0E, 0xC0, 0x0E, 0xE0, - 0x1C, 0xE0, 0x1C, 0xE0, 0x1C, 0x70, 0x38, 0x70, 0x3F, 0xF0, 0x3F, 0xF8, 0x70, 0x38, 0x70, 0x38, - 0x70, 0x3C, 0xF0, 0x1C, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x42 'B' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF8, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x38, 0x1F, 0xF0, 0x1F, 0xF8, 0x1C, 0x3C, 0x1C, 0x1E, 0x1C, 0x1E, 0x1C, 0x1E, 0x1C, 0x1E, - 0x1C, 0x3C, 0x1F, 0xFC, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x43 'C' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF8, 0x1E, 0x3C, 0x1C, 0x1C, 0x3C, 0x18, - 0x3C, 0x00, 0x3C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x1C, 0x1C, 0x1C, - 0x1E, 0x3C, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x44 'D' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x1F, 0xF0, 0x1C, 0x78, 0x1C, 0x3C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x78, 0x1F, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x45 'E' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, - 0x1C, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, - 0x1C, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x46 'F' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, - 0x1C, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, - 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x47 'G' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x18, - 0x3C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0xFC, 0x3C, 0xFC, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, - 0x1E, 0x3C, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x48 'H' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x3C, 0x1F, 0xFC, 0x1F, 0xFC, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x49 'I' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4A 'J' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x03, 0xF8, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, - 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x1C, 0x78, 0x3C, 0x78, - 0x1E, 0x70, 0x0F, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4B 'K' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3C, 0x38, 0x78, 0x38, 0xF0, 0x38, 0xE0, 0x39, 0xE0, - 0x3B, 0xC0, 0x3F, 0x80, 0x3F, 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x3D, 0xE0, 0x38, 0xF0, 0x38, 0xF0, - 0x38, 0x78, 0x38, 0x78, 0x38, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4C 'L' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, - 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, - 0x1E, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4D 'M' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x3E, 0x3C, 0x3E, 0x3C, 0x3E, 0x7C, 0x3E, 0x7C, - 0x3F, 0x6C, 0x3B, 0x6C, 0x3B, 0xEC, 0x3B, 0xCC, 0x3B, 0xCC, 0x39, 0xCC, 0x39, 0xCC, 0x38, 0x0C, - 0x38, 0x0C, 0x38, 0x0C, 0x38, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4E 'N' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x1C, 0x1E, 0x1C, 0x1E, 0x1C, 0x1F, 0x1C, 0x1F, 0x1C, - 0x1F, 0x9C, 0x1F, 0x9C, 0x1D, 0x9C, 0x1D, 0xDC, 0x1D, 0xDC, 0x1C, 0xDC, 0x1C, 0xFC, 0x1C, 0xFC, - 0x1C, 0x7C, 0x1C, 0x7C, 0x1C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4F 'O' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x1C, - 0x3C, 0x1C, 0x38, 0x1C, 0x38, 0x1E, 0x38, 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x3C, - 0x1E, 0x38, 0x0F, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x50 'P' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x1F, 0xF8, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1F, 0xF8, 0x1F, 0xE0, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, - 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x51 'Q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x1C, - 0x3C, 0x1C, 0x38, 0x1C, 0x38, 0x1E, 0x38, 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x3C, - 0x1E, 0x38, 0x0F, 0xF8, 0x07, 0xE0, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0xFE, 0x00, 0x3E - }, - // 0x52 'R' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xF0, 0x38, 0x78, 0x38, 0x38, 0x38, 0x3C, - 0x38, 0x38, 0x38, 0x78, 0x3F, 0xF0, 0x3F, 0xE0, 0x39, 0xE0, 0x38, 0xE0, 0x38, 0xF0, 0x38, 0x70, - 0x38, 0x78, 0x38, 0x3C, 0x38, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x53 'S' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, 0x1C, 0x38, 0x3C, 0x3C, 0x3C, 0x1C, - 0x3C, 0x00, 0x1F, 0x80, 0x0F, 0xF0, 0x03, 0xFC, 0x00, 0x7C, 0x00, 0x1E, 0x38, 0x1E, 0x38, 0x1C, - 0x3C, 0x3C, 0x1F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x54 'T' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x3F, 0xFE, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x55 'U' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x38, - 0x1E, 0x78, 0x0F, 0xF0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x56 'V' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1C, 0x70, 0x3C, 0x70, 0x3C, 0x78, 0x38, 0x38, 0x78, - 0x38, 0x78, 0x3C, 0x70, 0x1C, 0x70, 0x1C, 0xF0, 0x1C, 0xE0, 0x0E, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, - 0x07, 0xC0, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x57 'W' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1C, 0xE0, 0x1C, 0xE0, 0x1C, 0x60, 0x1C, 0x73, 0x1C, - 0x73, 0x9C, 0x77, 0x98, 0x77, 0xB8, 0x77, 0xF8, 0x7E, 0xF8, 0x3E, 0xF8, 0x3C, 0xF8, 0x3C, 0xF0, - 0x3C, 0xF0, 0x3C, 0x70, 0x38, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x58 'X' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x3C, 0x78, 0x78, 0x3C, 0x70, 0x1C, 0xF0, 0x1E, 0xE0, - 0x0F, 0xC0, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0, 0x0F, 0xC0, 0x0F, 0xE0, 0x1C, 0xE0, 0x3C, 0x70, - 0x38, 0x78, 0x78, 0x38, 0xF0, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x59 'Y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3C, 0x70, 0x38, 0x38, 0x78, 0x3C, 0x70, 0x1C, 0xF0, - 0x1E, 0xE0, 0x0F, 0xC0, 0x07, 0xC0, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, - 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5A 'Z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x38, 0x00, 0x78, 0x00, 0xF0, - 0x00, 0xE0, 0x01, 0xE0, 0x03, 0xC0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x0F, 0x00, 0x1E, 0x00, - 0x3C, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5B '[' - { - 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, - 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, - 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xF0, 0x07, 0xF0 - }, - // 0x5C '\\' - { - 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x03, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x30, - 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5D ']' - { - 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, - 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, - 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0 - }, - // 0x5E '^' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x07, 0xE0, 0x06, 0x60, 0x0E, 0x70, - 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x38, 0x1C, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5F '_' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x60 '`' - { - 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x61 'a' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, - 0x1E, 0x78, 0x1C, 0x38, 0x00, 0x38, 0x07, 0xF8, 0x1F, 0xF8, 0x1C, 0x38, 0x3C, 0x38, 0x3C, 0x78, - 0x3C, 0xF8, 0x1F, 0xBE, 0x0F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x62 'b' - { - 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0xF0, 0x1D, 0xF8, - 0x1E, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x3C, - 0x1E, 0x38, 0x1D, 0xF8, 0x1C, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x63 'c' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF8, - 0x1E, 0x38, 0x1C, 0x3C, 0x1C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x1C, 0x1C, 0x1C, 0x3C, - 0x1E, 0x38, 0x0F, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x64 'd' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x07, 0xBC, 0x0F, 0xFC, - 0x1E, 0x7C, 0x1C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x1C, 0x3C, - 0x1E, 0x7C, 0x0F, 0xFC, 0x07, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x65 'e' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0xF0, - 0x1E, 0x38, 0x1C, 0x1C, 0x3C, 0x1C, 0x3F, 0xFC, 0x3F, 0xFC, 0x3C, 0x00, 0x3C, 0x00, 0x1C, 0x1C, - 0x1E, 0x38, 0x0F, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x66 'f' - { - 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x03, 0xFC, 0x03, 0x80, 0x07, 0x80, 0x3F, 0xFC, 0x3F, 0xFC, - 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, - 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x67 'g' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x9C, 0x0F, 0xDC, - 0x1E, 0x7C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, - 0x1E, 0x3C, 0x0F, 0xDC, 0x07, 0x9C, 0x00, 0x1C, 0x1C, 0x3C, 0x1E, 0x38, 0x0F, 0xF8, 0x03, 0xE0 - }, - // 0x68 'h' - { - 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0xF0, 0x1D, 0xF8, - 0x1E, 0x3C, 0x1E, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x69 'i' - { - 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6A 'j' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, - 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, - 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x3F, 0xC0, 0x1F, 0x00 - }, - // 0x6B 'k' - { - 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x3C, 0x1C, 0x38, - 0x1C, 0x70, 0x1C, 0xE0, 0x1D, 0xC0, 0x1F, 0xC0, 0x1F, 0xE0, 0x1E, 0xE0, 0x1C, 0x70, 0x1C, 0x78, - 0x1C, 0x38, 0x1C, 0x3C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6C 'l' - { - 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x0F, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6D 'm' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x38, 0x3F, 0xBC, - 0x3B, 0xDC, 0x39, 0xCC, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, - 0x39, 0xCE, 0x39, 0xCE, 0x39, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6E 'n' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xF0, 0x1D, 0xF8, - 0x1E, 0x3C, 0x1E, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6F 'o' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF8, - 0x1E, 0x38, 0x1C, 0x3C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x1C, 0x3C, - 0x1E, 0x38, 0x0F, 0xF0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x70 'p' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xF0, 0x1F, 0xF8, - 0x1E, 0x38, 0x1E, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, - 0x1E, 0x38, 0x1F, 0xF8, 0x1C, 0xF0, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00 - }, - // 0x71 'q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x9C, 0x0F, 0xFC, - 0x1E, 0x7C, 0x1C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x1C, 0x3C, - 0x1E, 0x7C, 0x1F, 0xFC, 0x07, 0xBC, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C - }, - // 0x72 'r' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x7C, 0x0E, 0xFC, - 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, - 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x73 's' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0F, 0xF0, - 0x1C, 0x38, 0x1C, 0x18, 0x1E, 0x00, 0x1F, 0xE0, 0x0F, 0xF8, 0x01, 0xFC, 0x00, 0x3C, 0x18, 0x1C, - 0x1C, 0x3C, 0x0F, 0xF8, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x74 't' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, - 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, - 0x07, 0x80, 0x03, 0xF8, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x75 'u' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, 0x1C, 0x3C, - 0x1E, 0x7C, 0x1F, 0xFC, 0x07, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x76 'v' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1E, 0x38, 0x1C, - 0x3C, 0x1C, 0x1C, 0x3C, 0x1C, 0x38, 0x1E, 0x38, 0x0E, 0x78, 0x0E, 0x70, 0x0F, 0x70, 0x07, 0xE0, - 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x77 'w' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0C, 0xE0, 0x1C, - 0x60, 0x1C, 0x63, 0x1C, 0x63, 0x9C, 0x77, 0x98, 0x77, 0x98, 0x76, 0xD8, 0x3E, 0xF8, 0x3C, 0xF8, - 0x3C, 0xF0, 0x3C, 0x70, 0x38, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x78 'x' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x1C, 0x1C, 0x38, - 0x0E, 0x38, 0x0E, 0x70, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x07, 0x70, 0x0E, 0x70, - 0x1E, 0x38, 0x1C, 0x3C, 0x38, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x79 'y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1E, 0x38, 0x1C, - 0x3C, 0x1C, 0x1C, 0x3C, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0xE0, - 0x03, 0xE0, 0x03, 0xE0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x07, 0x80, 0x1F, 0x00, 0x1E, 0x00 - }, - // 0x7A 'z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, - 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x01, 0xC0, 0x03, 0xC0, 0x07, 0x80, 0x07, 0x00, 0x0F, 0x00, - 0x1E, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x7B '{' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xF8, 0x03, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, - 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0x80, 0x1F, 0x00, 0x1F, 0x00, 0x07, 0x80, 0x03, 0x80, - 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x01, 0xF8, 0x00, 0xF8 - }, - // 0x7C '|' - { - 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0 - }, - // 0x7D '}' - { - 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x1F, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xE0, 0x00, 0xE0, 0x00, 0x78, 0x00, 0x78, 0x00, 0xE0, 0x01, 0xE0, - 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x1F, 0xC0, 0x1F, 0x80 - }, - // 0x7E '~' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x3F, 0x00, 0x31, 0xC4, 0x20, 0xFC, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, -}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h deleted file mode 100644 index da11bb19d099e..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x24.h +++ /dev/null @@ -1,779 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Font: LiberationMono-Bold.ttf -// Size: 24x24 pixels -// Characters: 0x20..0x7E (' '..'~') -// Each character: 72 bytes (24 rows × 3 bytes per row) -// Each row: 3 byte(s) for 24 pixels, MSB = leftmost pixel -// Indexing: glyph = rm690b0_font_24x24_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E -// -// Generated by ttf_to_rm690b0.py - -static const uint8_t rm690b0_font_24x24_data[95][72] = { - // 0x20 ' ' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x21 '!' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x22 '\"' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xE7, 0x00, 0x00, - 0xE7, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x23 '#' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x80, 0x00, 0x31, 0x80, 0x00, - 0x61, 0x80, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x63, 0x00, 0x00, 0x43, 0x00, 0x00, 0xC3, - 0x00, 0x00, 0xC2, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x86, 0x00, 0x01, 0x86, 0x00, - 0x01, 0x84, 0x00, 0x01, 0x8C, 0x00, 0x01, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x24 '$' - { - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xFF, 0x80, 0x01, - 0xCB, 0xC0, 0x03, 0xC9, 0xC0, 0x03, 0xC8, 0x00, 0x01, 0xC8, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x09, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, 0x03, 0x89, 0xC0, - 0x01, 0xCB, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x25 '%' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0x80, 0x07, 0xC1, 0x80, 0x0C, - 0xE3, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0x66, 0x00, 0x0C, 0xEC, 0x00, 0x07, 0xD8, 0x00, 0x07, 0x98, - 0x00, 0x00, 0x37, 0x80, 0x00, 0x6F, 0xC0, 0x00, 0xEC, 0xC0, 0x00, 0xCC, 0xC0, 0x01, 0x8C, 0xC0, - 0x03, 0x0C, 0xC0, 0x03, 0x0F, 0xC0, 0x06, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x26 '&' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFE, 0x00, 0x01, - 0xCE, 0x00, 0x01, 0x86, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xE1, - 0x80, 0x07, 0xF3, 0x80, 0x07, 0x73, 0x00, 0x0E, 0x3F, 0x00, 0x0E, 0x1F, 0x00, 0x0E, 0x0E, 0x00, - 0x07, 0x1F, 0x00, 0x07, 0xFF, 0xC0, 0x01, 0xF1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x27 '\'' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x28 '(' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00 - }, - // 0x29 ')' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00 - }, - // 0x2A '*' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x99, 0x00, 0x00, - 0xFF, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x67, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2B '+' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x03, 0xFF, - 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2C ',' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00 - }, - // 0x2D '-' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2E '.' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2F '/' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x30 '0' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xD9, - 0xC0, 0x03, 0xD9, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, - 0x00, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x31 '1' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x01, 0x9E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x32 '2' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x33 '3' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE7, 0x80, 0x01, 0xC3, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x3F, - 0x00, 0x00, 0x3F, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC1, 0xC0, - 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x34 '4' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC7, - 0x00, 0x01, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x35 '5' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDE, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, - 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x03, 0xC3, 0xC0, - 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x36 '6' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0x80, 0x00, - 0xE3, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xDF, 0x00, 0x03, 0xFF, - 0x80, 0x03, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x00, 0xE3, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x37 '7' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, - 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x38 '8' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xE3, 0x80, 0x00, 0x7F, - 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x39 '9' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x03, 0x80, 0x01, 0xC3, 0x80, - 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3A ':' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3B ';' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00 - }, - // 0x3C '<' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x01, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xE0, - 0x00, 0x03, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0x80, - 0x00, 0x01, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3D '=' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3E '>' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x01, 0xF0, 0x00, - 0x03, 0xC0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3F '?' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x40 '@' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x7F, 0x80, 0x00, 0xE1, 0x80, 0x01, - 0x80, 0xC0, 0x01, 0x9D, 0xC0, 0x03, 0x3F, 0x60, 0x03, 0x77, 0x60, 0x03, 0x63, 0x60, 0x02, 0x43, - 0x60, 0x02, 0xC2, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x60, 0x02, 0xC6, 0x40, 0x02, 0x6E, 0xC0, - 0x03, 0x7B, 0xC0, 0x03, 0x33, 0x80, 0x01, 0x80, 0x00, 0x01, 0xC1, 0x80, 0x00, 0xFF, 0x80, 0x00, - 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x41 'A' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0xEC, 0x00, 0x00, 0xEE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xC7, - 0x00, 0x03, 0x87, 0x00, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0x03, 0x80, 0x07, 0x03, 0x80, - 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0F, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x42 'B' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x01, - 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFF, - 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, - 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x43 'C' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xE3, 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, - 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x44 'D' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFF, 0x00, 0x01, - 0xC7, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xC7, 0x80, 0x01, 0xFF, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x45 'E' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, - 0x80, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x46 'F' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, - 0xC0, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x47 'G' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0x80, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, - 0x00, 0x03, 0x8F, 0xC0, 0x03, 0xCF, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x48 'H' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, - 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xFF, 0xC0, 0x01, 0xFF, - 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x49 'I' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4A 'J' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0x80, 0x00, - 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, - 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x01, 0xC7, 0x80, 0x03, 0xC7, 0x80, - 0x01, 0xE7, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4B 'K' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x83, 0xC0, 0x03, 0x87, 0x80, 0x03, - 0x8F, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x9E, 0x00, 0x03, 0xBC, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF8, - 0x00, 0x03, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xDE, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x8F, 0x00, - 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4C 'L' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, - 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, - 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4D 'M' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xC0, 0x03, 0xE3, 0xC0, 0x03, - 0xE3, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xF6, 0xC0, 0x03, 0xB6, 0xC0, 0x03, 0xBE, - 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0xBC, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x80, 0xC0, - 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x03, 0x80, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4E 'N' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE1, 0xC0, 0x01, 0xE1, 0xC0, 0x01, - 0xE1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF1, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xF9, 0xC0, 0x01, 0xD9, - 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xDD, 0xC0, 0x01, 0xCD, 0xC0, 0x01, 0xCF, 0xC0, 0x01, 0xCF, 0xC0, - 0x01, 0xC7, 0xC0, 0x01, 0xC7, 0xC0, 0x01, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4F 'O' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, - 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x50 'P' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xFF, 0x80, 0x01, - 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xFF, 0x80, 0x01, 0xFE, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, - 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x51 'Q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, - 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0x81, 0xC0, 0x03, 0x81, - 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xE0 - }, - // 0x52 'R' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x03, - 0x87, 0x80, 0x03, 0x83, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0xFF, - 0x00, 0x03, 0xFE, 0x00, 0x03, 0x9E, 0x00, 0x03, 0x8E, 0x00, 0x03, 0x8F, 0x00, 0x03, 0x87, 0x00, - 0x03, 0x87, 0x80, 0x03, 0x83, 0xC0, 0x03, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x53 'S' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, - 0xC3, 0x80, 0x03, 0xC3, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC0, 0x00, 0x01, 0xF8, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, - 0x03, 0xC3, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x54 'T' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x55 'U' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, - 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, - 0x01, 0xE7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x56 'V' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x01, 0xC0, 0x07, 0x03, 0xC0, 0x07, - 0x03, 0xC0, 0x07, 0x83, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xC7, - 0x00, 0x01, 0xCF, 0x00, 0x01, 0xCE, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x57 'W' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, - 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x07, 0x31, 0xC0, 0x07, 0x39, 0xC0, 0x07, 0x79, 0x80, 0x07, 0x7B, - 0x80, 0x07, 0x7F, 0x80, 0x07, 0xEF, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, 0x03, 0xCF, 0x00, - 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x58 'X' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0xC0, 0x07, 0x87, 0x80, 0x03, - 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xCE, 0x00, 0x03, 0xC7, 0x00, - 0x03, 0x87, 0x80, 0x07, 0x83, 0x80, 0x0F, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x59 'Y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xC0, 0x07, 0x03, 0x80, 0x03, - 0x87, 0x80, 0x03, 0xC7, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xEE, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5A 'Z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, - 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5B '[' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00 - }, - // 0x5C '\\' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5D ']' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00 - }, - // 0x5E '^' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x7E, 0x00, 0x00, 0x66, 0x00, 0x00, 0xE7, 0x00, 0x00, 0xC3, 0x00, 0x01, 0xC3, 0x80, 0x01, 0x81, - 0x80, 0x03, 0x81, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5F '_' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x60 '`' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x61 'a' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE7, 0x80, 0x01, 0xC3, 0x80, 0x00, 0x03, - 0x80, 0x00, 0x7F, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xC3, 0x80, 0x03, 0xC3, 0x80, 0x03, 0xC7, 0x80, - 0x03, 0xCF, 0x80, 0x01, 0xFB, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x62 'b' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xE3, 0xC0, - 0x01, 0xE3, 0x80, 0x01, 0xDF, 0x80, 0x01, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x63 'c' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC0, - 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x64 'd' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, - 0x03, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, - 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE7, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x65 'e' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xE3, 0x80, 0x01, 0xC1, 0xC0, 0x03, 0xC1, - 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC1, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x66 'f' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x38, 0x00, 0x00, - 0x78, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x67 'g' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFD, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0xC0, 0x00, 0xFD, 0xC0, 0x00, 0x79, 0xC0, 0x00, 0x01, 0xC0, 0x01, 0xC3, 0xC0, 0x01, - 0xE3, 0x80, 0x00, 0xFF, 0x80, 0x00, 0x3E, 0x00 - }, - // 0x68 'h' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x69 'i' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6A 'j' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x1E, 0x00, 0x03, 0xFC, 0x00, 0x01, 0xF0, 0x00 - }, - // 0x6B 'k' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0x80, 0x01, 0xC7, 0x00, 0x01, 0xCE, 0x00, 0x01, 0xDC, - 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xC7, 0x00, 0x01, 0xC7, 0x80, - 0x01, 0xC3, 0x80, 0x01, 0xC3, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6C 'l' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6D 'm' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x33, 0x80, 0x03, 0xFB, 0xC0, 0x03, 0xBD, 0xC0, 0x03, 0x9C, 0xC0, 0x03, 0x9C, - 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, - 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x03, 0x9C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6E 'n' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xDF, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, - 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6F 'o' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0xC1, - 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x70 'p' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xCF, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xE3, 0x80, 0x01, 0xE3, 0xC0, 0x01, 0xC1, - 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE3, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xCF, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, - 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00 - }, - // 0x71 'q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x79, 0xC0, 0x00, 0xFF, 0xC0, 0x01, 0xE7, 0xC0, 0x01, 0xC3, 0xC0, 0x03, 0xC3, - 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0 - }, - // 0x72 'r' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0xEF, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x73 's' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xC3, 0x80, 0x01, 0xC1, 0x80, 0x01, 0xE0, - 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0x81, 0xC0, - 0x01, 0xC3, 0xC0, 0x00, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x74 't' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x70, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x75 'u' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, - 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, 0xC0, - 0x01, 0xE7, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x71, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x76 'v' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xC3, - 0x80, 0x01, 0xE3, 0x80, 0x00, 0xE7, 0x80, 0x00, 0xE7, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x77 'w' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x06, 0x31, 0xC0, 0x06, 0x39, - 0xC0, 0x07, 0x79, 0x80, 0x07, 0x79, 0x80, 0x07, 0x6D, 0x80, 0x03, 0xEF, 0x80, 0x03, 0xCF, 0x80, - 0x03, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x78 'x' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x7E, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x77, 0x00, 0x00, 0xE7, 0x00, - 0x01, 0xE3, 0x80, 0x01, 0xC3, 0xC0, 0x03, 0x81, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x79 'y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x81, 0xE0, 0x03, 0x81, 0xC0, 0x03, 0xC1, 0xC0, 0x01, 0xC3, 0xC0, 0x01, 0xE3, - 0x80, 0x00, 0xE3, 0x80, 0x00, 0xE7, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x00 - }, - // 0x7A 'z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x7B '{' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x3C, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x78, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0x80 - }, - // 0x7C '|' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00 - }, - // 0x7D '}' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x1C, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xF8, 0x00 - }, - // 0x7E '~' - { - 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, 0xE0, 0x00, 0x03, 0xF0, 0x00, 0x03, 0x1C, - 0x40, 0x02, 0x0F, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, -}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h deleted file mode 100644 index 6d3181a97acac..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_24x32.h +++ /dev/null @@ -1,874 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Font: LiberationMono-Bold.ttf -// Size: 24x32 pixels -// Characters: 0x20..0x7E (' '..'~') -// Each character: 96 bytes (32 rows × 3 bytes per row) -// Each row: 3 byte(s) for 24 pixels, MSB = leftmost pixel -// Indexing: glyph = rm690b0_font_24x32_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E -// -// Generated by ttf_to_rm690b0.py - -static const uint8_t rm690b0_font_24x32_data[95][96] = { - // 0x20 ' ' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x21 '!' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x22 '\"' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, - 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC3, - 0x80, 0x03, 0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x23 '#' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x00, - 0x60, 0xC0, 0x00, 0xE0, 0xC0, 0x00, 0xE1, 0xC0, 0x00, 0xC1, 0x80, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x01, 0xC3, 0x80, 0x01, 0x83, 0x80, 0x01, 0x83, 0x00, 0x03, 0x83, 0x00, 0x03, 0x87, 0x00, - 0x1F, 0xFF, 0xE0, 0x1F, 0xFF, 0xE0, 0x03, 0x06, 0x00, 0x07, 0x06, 0x00, 0x07, 0x0E, 0x00, 0x06, - 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x24 '$' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x9B, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x11, 0xE0, 0x0F, 0x10, - 0x00, 0x0F, 0x90, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, - 0x00, 0x1F, 0xF0, 0x00, 0x11, 0xF0, 0x0E, 0x10, 0xF0, 0x1E, 0x10, 0xF0, 0x0F, 0x10, 0xF0, 0x0F, - 0x9B, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x25 '%' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x70, 0x1F, - 0xC0, 0xE0, 0x39, 0xC0, 0xE0, 0x38, 0xE1, 0xC0, 0x38, 0xE3, 0x80, 0x38, 0xE3, 0x00, 0x38, 0xE7, - 0x00, 0x38, 0xEE, 0x00, 0x1D, 0xCC, 0x00, 0x1F, 0xDC, 0x00, 0x0F, 0xBB, 0xE0, 0x00, 0x37, 0xF0, - 0x00, 0x77, 0x38, 0x00, 0xEE, 0x38, 0x01, 0xCE, 0x38, 0x01, 0xCE, 0x38, 0x03, 0x8E, 0x38, 0x07, - 0x0E, 0x38, 0x06, 0x07, 0x38, 0x0E, 0x07, 0xF0, 0x1C, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x26 '&' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01, - 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, 0x80, 0x03, 0x87, - 0x00, 0x03, 0xDF, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xE0, 0xE0, 0x0F, 0xF0, 0xE0, - 0x1E, 0x78, 0xE0, 0x1E, 0x39, 0xE0, 0x3C, 0x3F, 0xC0, 0x3C, 0x1F, 0xC0, 0x1E, 0x0F, 0x80, 0x1F, - 0x0F, 0xE8, 0x1F, 0xFF, 0xF8, 0x0F, 0xFD, 0xF8, 0x03, 0xF0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x27 '\'' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x28 '(' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, - 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00 - }, - // 0x29 ')' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF0, 0x00 - }, - // 0x2A '*' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x03, - 0x39, 0x80, 0x03, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xEE, - 0x00, 0x01, 0xEF, 0x00, 0x01, 0xC7, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2B '+' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, - 0x0F, 0xFF, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2C ',' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, - 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2D '-' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0x00, - 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 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 - }, - // 0x2E '.' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2F '/' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x07, - 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x30 '0' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x39, 0xE0, - 0x0F, 0x39, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, - 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x31 '1' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xBE, 0x00, 0x0E, 0x3E, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, - 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x3E, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x32 '2' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x03, - 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0xFC, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x33 '3' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0x87, 0xE0, 0x0F, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, - 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0xC0, - 0x00, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, - 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x34 '4' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, - 0x1F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x80, 0x00, 0xF7, 0x80, 0x00, 0xF7, - 0x80, 0x01, 0xE7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x80, 0x07, 0x87, 0x80, 0x0F, 0x07, 0x80, - 0x1E, 0x07, 0x80, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x07, 0x80, 0x00, - 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x35 '5' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, - 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, - 0x00, 0x07, 0xBE, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x87, 0xE0, - 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x36 '6' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x03, 0xE7, 0xC0, 0x07, 0xC3, 0xE0, 0x07, 0x81, 0xC0, 0x0F, 0x80, - 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x1F, 0x00, 0x0F, 0x7F, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xC3, 0xE0, - 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xE0, 0x03, - 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x37 '7' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x38 '8' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, - 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xC3, 0xC0, - 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC3, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x39 '9' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x03, - 0xFF, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, - 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, 0xFF, 0xE0, - 0x03, 0xFD, 0xE0, 0x00, 0xF9, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x07, 0x83, 0xC0, 0x07, - 0x87, 0xC0, 0x07, 0xFF, 0x80, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3A ':' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3B ';' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, - 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3C '<' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0xF0, 0x03, 0xFF, - 0xE0, 0x0F, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x0F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, - 0x01, 0xF0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3D '=' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, - 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3E '>' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xFC, 0x00, 0x07, 0xFF, - 0x80, 0x00, 0xFF, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x03, 0xF0, - 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x0F, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3F '?' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x1F, 0x01, 0xE0, 0x1F, 0x01, - 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3E, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x40 '@' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xC1, 0xC0, 0x03, - 0x80, 0xE0, 0x07, 0x00, 0x60, 0x06, 0x00, 0x70, 0x0C, 0x39, 0xB0, 0x0C, 0x7D, 0xB0, 0x1C, 0xE7, - 0xB0, 0x18, 0xC3, 0xB0, 0x19, 0xC3, 0x38, 0x19, 0x83, 0x18, 0x19, 0x83, 0x38, 0x1B, 0x87, 0x30, - 0x1B, 0x87, 0x30, 0x1B, 0x86, 0x30, 0x1B, 0x86, 0x30, 0x19, 0x8E, 0x30, 0x19, 0x9E, 0x60, 0x19, - 0xFB, 0xE0, 0x0C, 0xE3, 0x80, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0xC0, 0x03, 0x83, - 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x41 'A' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x01, 0xE7, - 0x00, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, - 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x1F, 0x01, 0xF0, 0x1F, - 0x00, 0xF0, 0x1E, 0x00, 0xF0, 0x3E, 0x00, 0xF8, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x42 'B' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, - 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, - 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, - 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x80, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, - 0xFF, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x43 'C' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, - 0xC0, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x80, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0xC3, 0xF0, 0x07, - 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x44 'D' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x0F, - 0xFF, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0x8F, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, - 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, - 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xE0, 0x0F, - 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x45 'E' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x0F, 0x80, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, - 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x46 'F' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, - 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, - 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, - 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, - 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x47 'G' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0x80, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, 0x1F, 0x1F, 0xF0, - 0x1F, 0x1F, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0xC1, 0xF0, 0x07, - 0xFF, 0xF0, 0x03, 0xFF, 0xE0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x48 'H' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xE0, 0x0F, - 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, - 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, - 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x49 'I' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x0F, - 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4A 'J' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, - 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, - 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x07, 0x07, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0xC0, 0x07, - 0xFF, 0x80, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4B 'K' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xF8, 0x0F, - 0x83, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0x87, 0xC0, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x9F, - 0x00, 0x0F, 0xBE, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFE, 0x00, 0x0F, 0xFE, 0x00, - 0x0F, 0xFF, 0x00, 0x0F, 0xDF, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, - 0x83, 0xE0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4C 'L' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, - 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, - 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4D 'M' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83, 0xF0, 0x0F, - 0x83, 0xF0, 0x0F, 0xC3, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xC7, 0xF0, 0x0F, 0xE7, 0xF0, 0x0E, 0xE7, - 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xEE, 0xF0, 0x0E, 0xFE, 0xF0, 0x0E, 0x7E, 0xF0, 0x0E, 0x7C, 0xF0, - 0x0E, 0x7C, 0xF0, 0x0E, 0x3C, 0xF0, 0x0E, 0x38, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, - 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x0E, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4E 'N' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC1, 0xE0, 0x0F, - 0xC1, 0xE0, 0x0F, 0xC1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xE1, 0xE0, 0x0F, 0xF1, - 0xE0, 0x0F, 0x71, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x79, 0xE0, 0x0F, 0x39, 0xE0, 0x0F, 0x3D, 0xE0, - 0x0F, 0x3D, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x1F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, 0x0F, 0xE0, 0x0F, - 0x0F, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x0F, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4F 'O' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, - 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, - 0xFF, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x50 'P' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x0F, - 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, - 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, - 0x0F, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x51 'Q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, - 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, - 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x0F, 0xC7, 0xE0, 0x07, - 0xFF, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00 - }, - // 0x52 'R' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, - 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, - 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x83, 0xF0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0x00, - 0x0F, 0xFF, 0x00, 0x0F, 0x8F, 0x80, 0x0F, 0x8F, 0x80, 0x0F, 0x87, 0xC0, 0x0F, 0x87, 0xC0, 0x0F, - 0x83, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x80, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x53 'S' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x03, - 0xFF, 0x80, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x0F, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, - 0x00, 0x07, 0xF0, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x81, 0xF0, 0x0F, - 0xFF, 0xF0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x54 'T' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x1F, - 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x55 'U' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, - 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, - 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0xC7, 0xE0, 0x07, - 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x56 'V' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1E, - 0x00, 0xF8, 0x1F, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, - 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xC7, 0x80, - 0x03, 0xE7, 0x80, 0x01, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x57 'W' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, - 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, 0x78, 0x1E, 0x00, 0x70, 0x1E, 0x00, 0xF0, 0x1E, 0x38, - 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x7C, 0xF0, 0x1E, 0x7C, 0xF0, 0x0E, 0x7C, 0xF0, 0x0E, 0xFE, 0xE0, - 0x0F, 0xEE, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xEF, 0xE0, 0x0F, 0xE7, 0xE0, 0x07, 0xC7, 0xE0, 0x07, - 0xC7, 0xC0, 0x07, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x58 'X' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, - 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, 0x03, 0xEF, 0x80, 0x01, 0xFF, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, - 0x00, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xEF, 0x80, 0x03, 0xC7, 0xC0, 0x07, 0xC3, 0xC0, 0x0F, - 0x83, 0xE0, 0x0F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x3E, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x59 'Y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF8, 0x1F, - 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, 0x03, 0xC7, - 0x80, 0x01, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5A 'Z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x07, - 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, - 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, - 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, - 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5B '[' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0x80 - }, - // 0x5C '\\' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, - 0x03, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5D ']' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00 - }, - // 0x5E '^' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xEE, 0x00, 0x01, 0xCF, 0x00, 0x03, 0xC7, 0x00, 0x03, 0x87, - 0x80, 0x03, 0x83, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x03, 0xC0, 0x0F, 0x01, 0xC0, 0x0E, 0x01, 0xE0, - 0x1E, 0x00, 0xE0, 0x1C, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5F '_' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x60 '`' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x61 'a' - { - 0x00, 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, 0x00, 0x03, 0xFF, 0x00, 0x07, 0xFF, - 0x80, 0x07, 0xC7, 0xC0, 0x07, 0x87, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x01, 0xFF, 0xC0, - 0x07, 0xFF, 0xC0, 0x0F, 0x83, 0xC0, 0x0F, 0x03, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, 0x07, 0xC0, 0x0F, - 0x8F, 0xC0, 0x0F, 0xFF, 0xF0, 0x07, 0xF9, 0xF0, 0x03, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x62 'b' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, - 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, - 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, - 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x63 'c' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, - 0xC0, 0x07, 0xC7, 0xC0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x64 'd' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x01, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, - 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, - 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x65 'e' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFF, 0x00, 0x03, 0xFF, - 0x80, 0x07, 0xC3, 0xC0, 0x0F, 0x81, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0xFF, 0xE0, - 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x81, 0xE0, 0x07, - 0xC3, 0xE0, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x66 'f' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, - 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, - 0xE0, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x67 'g' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x03, 0xFD, 0xE0, 0x07, 0xFF, - 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFD, 0xE0, 0x00, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, - 0xE0, 0x07, 0x83, 0xE0, 0x07, 0xC7, 0xC0, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00 - }, - // 0x68 'h' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, - 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x8F, 0x00, 0x0F, 0xBF, 0xC0, 0x0F, 0xFF, - 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, - 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x69 'i' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6A 'j' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x03, 0xFE, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xE0, 0x00 - }, - // 0x6B 'k' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, - 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x81, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0x87, - 0xC0, 0x07, 0x8F, 0x80, 0x07, 0x9F, 0x00, 0x07, 0xBE, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, - 0x07, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x07, 0x8F, 0x00, 0x07, 0x8F, 0x80, 0x07, 0x87, 0xC0, 0x07, - 0x87, 0xC0, 0x07, 0x83, 0xE0, 0x07, 0x81, 0xE0, 0x07, 0x81, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6C 'l' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6D 'm' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE1, 0xC0, 0x1D, 0xF3, 0xE0, 0x1F, 0xFF, - 0xF0, 0x1F, 0x7C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x3C, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, - 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, - 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x1E, 0x38, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6E 'n' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x0F, 0x3F, 0xC0, 0x0F, 0x7F, - 0xC0, 0x0F, 0xE3, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, - 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, - 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6F 'o' - { - 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, - 0xC0, 0x07, 0xC3, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, - 0x1F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x70 'p' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0xBF, 0x80, 0x0F, 0xFF, - 0xC0, 0x0F, 0xC7, 0xE0, 0x0F, 0xC3, 0xE0, 0x0F, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, - 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x0F, 0xFF, 0xC0, 0x0F, 0xBF, 0x80, 0x0F, 0x9F, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0F, 0x80, 0x00 - }, - // 0x71 'q' - { - 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, 0xF1, 0xE0, 0x03, 0xF9, 0xE0, 0x07, 0xFF, - 0xE0, 0x07, 0xC7, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x01, 0xE0, - 0x0F, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, - 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0 - }, - // 0x72 'r' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0xE0, 0x07, 0xCF, 0xE0, 0x03, 0xDF, - 0xE0, 0x03, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x03, 0xE0, 0x00, - 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, - 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x73 's' - { - 0x00, 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, 0x00, 0x03, 0xFF, 0x80, 0x07, 0xFF, - 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x81, 0xC0, 0x07, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFF, 0x00, - 0x03, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xE0, 0x0F, 0x01, 0xE0, 0x0F, - 0x83, 0xE0, 0x07, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x74 't' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0x07, 0xFF, - 0x80, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, - 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x01, - 0xF0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x75 'u' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, - 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, 0x0F, 0x03, 0xE0, - 0x0F, 0x03, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x0F, 0x83, 0xE0, 0x07, - 0xC7, 0xE0, 0x07, 0xFD, 0xE0, 0x03, 0xF9, 0xE0, 0x01, 0xE1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x76 'v' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x00, 0xF0, 0x1F, 0x01, - 0xF0, 0x0F, 0x01, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC7, 0xC0, - 0x03, 0xC7, 0x80, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x77 'w' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x78, 0x3C, 0x00, 0x78, 0x1C, 0x00, - 0x78, 0x1C, 0x00, 0x70, 0x1C, 0x38, 0x70, 0x1C, 0x3C, 0x70, 0x1E, 0x7C, 0x70, 0x1E, 0x7C, 0xF0, - 0x0E, 0x7C, 0xF0, 0x0E, 0xEE, 0xE0, 0x0E, 0xEE, 0xE0, 0x0E, 0xE7, 0xE0, 0x0F, 0xC7, 0xE0, 0x0F, - 0xC7, 0xE0, 0x07, 0xC7, 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x78 'x' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0xF0, 0x0F, 0x83, 0xE0, 0x07, 0x83, - 0xC0, 0x03, 0xC7, 0x80, 0x03, 0xEF, 0x80, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xEF, 0x00, 0x03, 0xC7, 0x80, 0x07, - 0xC7, 0xC0, 0x07, 0x83, 0xE0, 0x0F, 0x01, 0xE0, 0x1F, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x79 'y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0xF0, 0x1F, 0x01, 0xF0, 0x0F, 0x01, - 0xF0, 0x0F, 0x81, 0xE0, 0x0F, 0x83, 0xE0, 0x07, 0x83, 0xC0, 0x07, 0xC3, 0xC0, 0x03, 0xC7, 0xC0, - 0x03, 0xC7, 0x80, 0x01, 0xE7, 0x80, 0x01, 0xEF, 0x00, 0x01, 0xEF, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, - 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xC0, 0x00 - }, - // 0x7A 'z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x07, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x07, - 0xC0, 0x00, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x7B '{' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, - 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x07, 0xE0, 0x00, - 0x07, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0 - }, - // 0x7C '|' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00 - }, - // 0x7D '}' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x00, - 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x07, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF0, 0x00 - }, - // 0x7E '~' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x0F, 0xF8, 0x30, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, - 0x18, 0x3F, 0xF0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, -}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h deleted file mode 100644 index 91262bf63f2b2..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x32.h +++ /dev/null @@ -1,1064 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Font: LiberationMono-Bold.ttf -// Size: 32x32 pixels -// Characters: 0x20..0x7E (' '..'~') -// Each character: 128 bytes (32 rows × 4 bytes per row) -// Each row: 4 byte(s) for 32 pixels, MSB = leftmost pixel -// Indexing: glyph = rm690b0_font_32x32_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E -// -// Generated by ttf_to_rm690b0.py - -static const uint8_t rm690b0_font_32x32_data[95][128] = { - // 0x20 ' ' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x21 '!' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x22 '\"' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x38, 0x00, 0x00, 0x3C, 0x38, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x23 '#' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x06, 0x0C, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x0E, 0x0C, 0x00, 0x00, 0x0E, 0x1C, 0x00, - 0x00, 0x0C, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x38, 0x00, - 0x00, 0x18, 0x38, 0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x38, 0x30, 0x00, 0x00, 0x38, 0x70, 0x00, - 0x01, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x70, 0x60, 0x00, - 0x00, 0x70, 0xE0, 0x00, 0x00, 0x60, 0xE0, 0x00, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x60, 0xC0, 0x00, - 0x00, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x24 '$' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xF9, 0xBE, 0x00, - 0x00, 0xF1, 0x1E, 0x00, 0x00, 0xF1, 0x1E, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, - 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, - 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0x1F, 0x00, 0x00, 0xE1, 0x0F, 0x00, 0x01, 0xE1, 0x0F, 0x00, - 0x00, 0xF1, 0x0F, 0x00, 0x00, 0xF9, 0xBE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x25 '%' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x07, 0x00, 0x01, 0xFC, 0x0E, 0x00, 0x03, 0x9C, 0x0E, 0x00, 0x03, 0x8E, 0x1C, 0x00, - 0x03, 0x8E, 0x38, 0x00, 0x03, 0x8E, 0x30, 0x00, 0x03, 0x8E, 0x70, 0x00, 0x03, 0x8E, 0xE0, 0x00, - 0x01, 0xDC, 0xC0, 0x00, 0x01, 0xFD, 0xC0, 0x00, 0x00, 0xFB, 0xBE, 0x00, 0x00, 0x03, 0x7F, 0x00, - 0x00, 0x07, 0x73, 0x80, 0x00, 0x0E, 0xE3, 0x80, 0x00, 0x1C, 0xE3, 0x80, 0x00, 0x1C, 0xE3, 0x80, - 0x00, 0x38, 0xE3, 0x80, 0x00, 0x70, 0xE3, 0x80, 0x00, 0x60, 0x73, 0x80, 0x00, 0xE0, 0x7F, 0x00, - 0x01, 0xC0, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x26 '&' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3C, 0x78, 0x00, - 0x00, 0x38, 0x78, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x38, 0x70, 0x00, 0x00, 0x3D, 0xF0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7E, 0x0E, 0x00, 0x00, 0xFF, 0x0E, 0x00, - 0x01, 0xE7, 0x8E, 0x00, 0x01, 0xE3, 0x9E, 0x00, 0x03, 0xC3, 0xFC, 0x00, 0x03, 0xC1, 0xFC, 0x00, - 0x01, 0xE0, 0xF8, 0x00, 0x01, 0xF0, 0xFE, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xDF, 0x80, - 0x00, 0x3F, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x27 '\'' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x28 '(' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00 - }, - // 0x29 ')' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, - 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, - 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00 - }, - // 0x2A '*' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x33, 0x98, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x1E, 0xF0, 0x00, - 0x00, 0x1C, 0x70, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2B '+' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2C ',' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2D '-' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2E '.' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2F '/' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x30 '0' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0x7C, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF3, 0x9E, 0x00, - 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x31 '1' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, - 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xFB, 0xE0, 0x00, 0x00, 0xE3, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 - }, - // 0x32 '2' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7C, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x33 '3' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xF8, 0x7E, 0x00, - 0x00, 0xF0, 0x3E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x34 '4' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, - 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x78, 0x00, 0x00, 0x0F, 0x78, 0x00, 0x00, 0x1E, 0x78, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, 0xF0, 0x78, 0x00, - 0x01, 0xE0, 0x78, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x35 '5' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7B, 0xE0, 0x00, - 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xF8, 0x7E, 0x00, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x36 '6' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3E, 0x7C, 0x00, - 0x00, 0x7C, 0x3E, 0x00, 0x00, 0x78, 0x1C, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xF1, 0xF0, 0x00, 0x00, 0xF7, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFC, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x78, 0x1E, 0x00, - 0x00, 0x78, 0x3E, 0x00, 0x00, 0x3C, 0x3E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x37 '7' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xF8, 0x00, - 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x38 '8' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7C, 0x7E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7C, 0x00, - 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0x3C, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x3E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x39 '9' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7C, 0x7C, 0x00, - 0x00, 0xF8, 0x3C, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, - 0x00, 0x3F, 0xDE, 0x00, 0x00, 0x0F, 0x9E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3A ':' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3B ';' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3C '<' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0xFF, 0xF0, 0x00, - 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, - 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3D '=' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3E '>' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, - 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3F, 0x00, - 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0x00, - 0x00, 0xFE, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3F '?' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0x01, 0xF0, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xE0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x40 '@' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, - 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x38, 0x0E, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00, 0x60, 0x07, 0x00, - 0x00, 0xC3, 0x9B, 0x00, 0x00, 0xC7, 0xDB, 0x00, 0x01, 0xCE, 0x7B, 0x00, 0x01, 0x8C, 0x3B, 0x00, - 0x01, 0x9C, 0x33, 0x80, 0x01, 0x98, 0x31, 0x80, 0x01, 0x98, 0x33, 0x80, 0x01, 0xB8, 0x73, 0x00, - 0x01, 0xB8, 0x73, 0x00, 0x01, 0xB8, 0x63, 0x00, 0x01, 0xB8, 0x63, 0x00, 0x01, 0x98, 0xE3, 0x00, - 0x01, 0x99, 0xE6, 0x00, 0x01, 0x9F, 0xBE, 0x00, 0x00, 0xCE, 0x38, 0x00, 0x00, 0xC0, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0x00, 0x70, 0x0C, 0x00, 0x00, 0x38, 0x3C, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x41 'A' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1E, 0x70, 0x00, 0x00, 0x3C, 0x78, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x78, 0x3C, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x0F, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x03, 0xE0, 0x0F, 0x80, - 0x03, 0xE0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x42 'B' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, - 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x43 'C' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x7F, 0xFE, 0x00, - 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1C, 0x00, 0x01, 0xF0, 0x00, 0x00, - 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, - 0x01, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x0E, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x44 'D' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, - 0x00, 0xF8, 0xFE, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xF8, 0x7E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xF0, 0x00, - 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x45 'E' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 - }, - // 0x46 'F' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, - 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x47 'G' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x18, 0x00, 0x01, 0xF0, 0x00, 0x00, - 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF1, 0xFF, 0x00, 0x01, 0xF1, 0xFF, 0x00, 0x01, 0xF1, 0xFF, 0x00, - 0x01, 0xF1, 0xFF, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x48 'H' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x49 'I' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4A 'J' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFC, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x70, 0x7C, 0x00, 0x00, 0xF8, 0x7C, 0x00, - 0x00, 0xF8, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4B 'K' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x1F, 0x80, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x7C, 0x00, - 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xFB, 0xE0, 0x00, - 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, - 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFD, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x7C, 0x00, - 0x00, 0xF8, 0x7C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4C 'L' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, - 0x00, 0x7F, 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 - }, - // 0x4D 'M' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x7F, 0x00, - 0x00, 0xFC, 0x7F, 0x00, 0x00, 0xFE, 0x7F, 0x00, 0x00, 0xEE, 0x7F, 0x00, 0x00, 0xEE, 0xEF, 0x00, - 0x00, 0xEE, 0xEF, 0x00, 0x00, 0xEF, 0xEF, 0x00, 0x00, 0xE7, 0xEF, 0x00, 0x00, 0xE7, 0xCF, 0x00, - 0x00, 0xE7, 0xCF, 0x00, 0x00, 0xE3, 0xCF, 0x00, 0x00, 0xE3, 0x8F, 0x00, 0x00, 0xE0, 0x0F, 0x00, - 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, - 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4E 'N' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFC, 0x1E, 0x00, 0x00, 0xFC, 0x1E, 0x00, 0x00, 0xFC, 0x1E, 0x00, 0x00, 0xFE, 0x1E, 0x00, - 0x00, 0xFE, 0x1E, 0x00, 0x00, 0xFE, 0x1E, 0x00, 0x00, 0xFF, 0x1E, 0x00, 0x00, 0xF7, 0x1E, 0x00, - 0x00, 0xF7, 0x9E, 0x00, 0x00, 0xF7, 0x9E, 0x00, 0x00, 0xF3, 0x9E, 0x00, 0x00, 0xF3, 0xDE, 0x00, - 0x00, 0xF3, 0xDE, 0x00, 0x00, 0xF1, 0xFE, 0x00, 0x00, 0xF1, 0xFE, 0x00, 0x00, 0xF0, 0xFE, 0x00, - 0x00, 0xF0, 0xFE, 0x00, 0x00, 0xF0, 0xFE, 0x00, 0x00, 0xF0, 0x7E, 0x00, 0x00, 0xF0, 0x7E, 0x00, - 0x00, 0xF0, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4F 'O' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x50 'P' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, - 0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x51 'Q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0x00, - 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x52 'R' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF0, 0x00, - 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x7C, 0x00, - 0x00, 0xF8, 0x7C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x53 'S' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, - 0x00, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, - 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x01, 0xF0, 0x0F, 0x00, - 0x01, 0xF8, 0x1F, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x54 'T' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x55 'U' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x56 'V' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xE0, 0x0F, 0x80, 0x01, 0xE0, 0x0F, 0x80, 0x01, 0xF0, 0x0F, 0x00, 0x01, 0xF0, 0x1F, 0x00, - 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3E, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x3C, 0x00, 0x00, 0x3C, 0x7C, 0x00, 0x00, 0x3C, 0x78, 0x00, - 0x00, 0x3E, 0x78, 0x00, 0x00, 0x1E, 0xF8, 0x00, 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x57 'W' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xC0, 0x07, 0x80, 0x03, 0xC0, 0x07, 0x80, 0x03, 0xC0, 0x07, 0x80, 0x01, 0xC0, 0x07, 0x80, - 0x01, 0xE0, 0x07, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0xCF, 0x00, - 0x01, 0xE7, 0xCF, 0x00, 0x01, 0xE7, 0xCF, 0x00, 0x00, 0xE7, 0xCF, 0x00, 0x00, 0xEF, 0xEE, 0x00, - 0x00, 0xFE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0x7E, 0x00, - 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x7C, 0x3C, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x58 'X' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x3C, 0x00, - 0x00, 0x3C, 0x7C, 0x00, 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x3C, 0x7C, 0x00, - 0x00, 0x7C, 0x3C, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x01, 0xF0, 0x1F, 0x00, - 0x03, 0xE0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x59 'Y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xE0, 0x0F, 0x80, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x1E, 0xF8, 0x00, - 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5A 'Z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, - 0x01, 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 - }, - // 0x5B '[' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00, - 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00 - }, - // 0x5C '\\' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5D ']' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, - 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00 - }, - // 0x5E '^' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1E, 0xE0, 0x00, - 0x00, 0x1C, 0xF0, 0x00, 0x00, 0x3C, 0x70, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x38, 0x38, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x70, 0x3C, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0xE0, 0x1E, 0x00, - 0x01, 0xE0, 0x0E, 0x00, 0x01, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5F '_' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x80, - 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x60 '`' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x61 'a' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7C, 0x7C, 0x00, - 0x00, 0x78, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1F, 0xFC, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xF8, 0x3C, 0x00, 0x00, 0xF0, 0x3C, 0x00, 0x00, 0xF0, 0x7C, 0x00, - 0x00, 0xF0, 0x7C, 0x00, 0x00, 0xF8, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0x9F, 0x00, - 0x00, 0x3E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x62 'b' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xFB, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, - 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFB, 0xF8, 0x00, - 0x00, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x63 'c' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x7C, 0x7C, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x64 'd' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x3F, 0x9E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0xFC, 0x7E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0x9E, 0x00, - 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x65 'e' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0x3C, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x7C, 0x3E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x66 'f' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, - 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x67 'g' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0x1E, 0x00, 0x00, 0x3F, 0xDE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7C, 0x7E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xDE, 0x00, - 0x00, 0x0F, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x78, 0x3E, 0x00, - 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xE0, 0x00 - }, - // 0x68 'h' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0xF0, 0x00, 0x00, 0xFB, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFE, 0x3E, 0x00, - 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x69 'i' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 - }, - // 0x6A 'j' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x03, 0xE0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFE, 0x00, 0x00 - }, - // 0x6B 'k' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, - 0x00, 0x78, 0x1E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x78, 0xF8, 0x00, - 0x00, 0x79, 0xF0, 0x00, 0x00, 0x7B, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, - 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x78, 0xF0, 0x00, 0x00, 0x78, 0xF8, 0x00, - 0x00, 0x78, 0x7C, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x78, 0x3E, 0x00, 0x00, 0x78, 0x1E, 0x00, - 0x00, 0x78, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6C 'l' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, - 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 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 - }, - // 0x6D 'm' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xCE, 0x1C, 0x00, 0x01, 0xDF, 0x3E, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xF7, 0xCF, 0x00, - 0x01, 0xE3, 0xCF, 0x00, 0x01, 0xE3, 0xCF, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, - 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, - 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, 0x01, 0xE3, 0x8F, 0x00, - 0x01, 0xE3, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6E 'n' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF0, 0xF0, 0x00, 0x00, 0xF3, 0xFC, 0x00, 0x00, 0xF7, 0xFC, 0x00, 0x00, 0xFE, 0x3E, 0x00, - 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6F 'o' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7C, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x70 'p' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xFB, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, - 0x00, 0xFC, 0x3E, 0x00, 0x00, 0xF8, 0x1E, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, - 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFB, 0xF8, 0x00, - 0x00, 0xF9, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00 - }, - // 0x71 'q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x3F, 0x9E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7C, 0x7E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0x9E, 0x00, - 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00 - }, - // 0x72 'r' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x7E, 0x00, 0x00, 0x7C, 0xFE, 0x00, 0x00, 0x3D, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x73 's' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x78, 0x3C, 0x00, - 0x00, 0x78, 0x1C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, - 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x1E, 0x00, - 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x74 't' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, - 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xFC, 0x00, - 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x75 'u' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, - 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, - 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7F, 0xDE, 0x00, 0x00, 0x3F, 0x9E, 0x00, - 0x00, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x76 'v' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE0, 0x0F, 0x00, 0x01, 0xF0, 0x0F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x7C, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3C, 0x78, 0x00, 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x1E, 0xF0, 0x00, - 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x77 'w' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xC0, 0x07, 0x80, 0x03, 0xC0, 0x07, 0x80, 0x01, 0xC0, 0x07, 0x80, 0x01, 0xC0, 0x07, 0x00, - 0x01, 0xC3, 0x87, 0x00, 0x01, 0xC3, 0xC7, 0x00, 0x01, 0xE7, 0xC7, 0x00, 0x01, 0xE7, 0xCF, 0x00, - 0x00, 0xE7, 0xCF, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0x7E, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x78, 0x3C, 0x00, - 0x00, 0x78, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x78 'x' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x3C, 0x78, 0x00, - 0x00, 0x3E, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x78, 0x3E, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x01, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x79 'y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE0, 0x0F, 0x00, 0x01, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF8, 0x1E, 0x00, - 0x00, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x3C, 0x00, 0x00, 0x7C, 0x3C, 0x00, 0x00, 0x3C, 0x7C, 0x00, - 0x00, 0x3C, 0x78, 0x00, 0x00, 0x1E, 0x78, 0x00, 0x00, 0x1E, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00 - }, - // 0x7A 'z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x7B '{' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, - 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, - 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00 - }, - // 0x7C '|' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, - 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00 - }, - // 0x7D '}' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, - 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xFC, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, - 0x00, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x00, 0x00 - }, - // 0x7E '~' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFF, 0x83, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, - 0x01, 0x83, 0xFF, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, -}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h deleted file mode 100644 index 7b1e2892e7177..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_32x48.h +++ /dev/null @@ -1,1444 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Font: LiberationMono-Bold.ttf -// Size: 32x48 pixels -// Characters: 0x20..0x7E (' '..'~') -// Each character: 192 bytes (48 rows × 4 bytes per row) -// Each row: 4 byte(s) for 32 pixels, MSB = leftmost pixel -// Indexing: glyph = rm690b0_font_32x48_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7E -// -// Generated by ttf_to_rm690b0.py - -static const uint8_t rm690b0_font_32x48_data[95][192] = { - // 0x20 ' ' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x21 '!' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x22 '\"' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x3F, 0x00, - 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, - 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, - 0x01, 0xF8, 0x3E, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, - 0x00, 0xF0, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x23 '#' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x03, 0xC0, 0x00, 0x1E, 0x03, 0xC0, - 0x00, 0x1E, 0x03, 0x80, 0x00, 0x1C, 0x03, 0x80, 0x00, 0x1C, 0x07, 0x80, 0x00, 0x3C, 0x07, 0x80, - 0x00, 0x3C, 0x07, 0x80, 0x00, 0x3C, 0x07, 0x00, 0x00, 0x38, 0x07, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, - 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x70, 0x0E, 0x00, 0x00, 0x70, 0x1E, 0x00, - 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0xE0, 0x1C, 0x00, - 0x00, 0xE0, 0x3C, 0x00, 0x01, 0xE0, 0x3C, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xE0, - 0x3F, 0xFF, 0xFF, 0xE0, 0x03, 0xC0, 0x78, 0x00, 0x03, 0xC0, 0x78, 0x00, 0x03, 0xC0, 0x70, 0x00, - 0x03, 0x80, 0x70, 0x00, 0x03, 0x80, 0xF0, 0x00, 0x07, 0x80, 0xF0, 0x00, 0x07, 0x80, 0xF0, 0x00, - 0x07, 0x80, 0xE0, 0x00, 0x07, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x24 '$' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x03, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xF3, 0xBF, 0xC0, - 0x0F, 0xC3, 0x8F, 0xE0, 0x0F, 0xC3, 0x87, 0xE0, 0x0F, 0xC3, 0x87, 0x80, 0x0F, 0xC3, 0x80, 0x00, - 0x0F, 0xE3, 0x80, 0x00, 0x07, 0xFB, 0x80, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xF0, 0x00, - 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xE0, - 0x00, 0x03, 0x9F, 0xE0, 0x00, 0x03, 0x87, 0xE0, 0x00, 0x03, 0x87, 0xF0, 0x03, 0x83, 0x83, 0xF0, - 0x1F, 0x83, 0x83, 0xF0, 0x1F, 0x83, 0x83, 0xF0, 0x1F, 0xC3, 0x83, 0xF0, 0x0F, 0xE3, 0x87, 0xF0, - 0x0F, 0xF3, 0x9F, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x25 '%' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0xF0, 0x1F, 0xF0, 0x01, 0xE0, - 0x3F, 0xF8, 0x01, 0xE0, 0x3C, 0x7C, 0x03, 0xC0, 0x7C, 0x3C, 0x07, 0x80, 0x78, 0x3C, 0x07, 0x80, - 0x78, 0x3C, 0x0F, 0x00, 0x78, 0x3C, 0x1E, 0x00, 0x78, 0x3C, 0x3E, 0x00, 0x78, 0x3C, 0x3C, 0x00, - 0x78, 0x3C, 0x78, 0x00, 0x7C, 0x3C, 0xF8, 0x00, 0x3C, 0x7C, 0xF0, 0x00, 0x3F, 0xF9, 0xE0, 0x00, - 0x1F, 0xF3, 0xC0, 0x00, 0x07, 0xE3, 0xC0, 0x00, 0x00, 0x07, 0x8F, 0xC0, 0x00, 0x0F, 0x1F, 0xF0, - 0x00, 0x0F, 0x3F, 0xF8, 0x00, 0x1E, 0x7C, 0x78, 0x00, 0x3C, 0x78, 0x78, 0x00, 0x3C, 0x78, 0x7C, - 0x00, 0x78, 0xF8, 0x3C, 0x00, 0xF0, 0xF8, 0x3C, 0x00, 0xF0, 0xF8, 0x3C, 0x01, 0xE0, 0xF8, 0x3C, - 0x03, 0xC0, 0x78, 0x7C, 0x03, 0xC0, 0x78, 0x78, 0x07, 0x80, 0x7C, 0xF8, 0x0F, 0x00, 0x3F, 0xF0, - 0x1F, 0x00, 0x1F, 0xF0, 0x1E, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x26 '&' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xF8, 0x7E, 0x00, 0x01, 0xF0, 0x3E, 0x00, - 0x01, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x7E, 0x00, - 0x01, 0xF8, 0xFC, 0x00, 0x00, 0xFB, 0xF8, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xE0, 0x00, - 0x01, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x03, 0xC0, 0x07, 0xFE, 0x03, 0xE0, 0x0F, 0xFF, 0x03, 0xE0, - 0x1F, 0xDF, 0x87, 0xC0, 0x3F, 0x8F, 0x87, 0xC0, 0x3F, 0x0F, 0xC7, 0xC0, 0x3F, 0x07, 0xEF, 0x80, - 0x3E, 0x03, 0xFF, 0x80, 0x3E, 0x01, 0xFF, 0x80, 0x3E, 0x01, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, - 0x3F, 0x00, 0xFF, 0x80, 0x1F, 0xC1, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xF7, 0xFC, - 0x07, 0xFF, 0xC3, 0xFC, 0x00, 0xFF, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x27 '\'' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x28 '(' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, - 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, - 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00 - }, - // 0x29 ')' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, - 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, - 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, - 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00 - }, - // 0x2A '*' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x87, 0xC2, 0x00, - 0x01, 0xE7, 0xCF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x00, - 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3E, 0xF8, 0x00, - 0x00, 0x7E, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xF8, 0x7E, 0x00, 0x00, 0x38, 0x38, 0x00, - 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2B '+' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, - 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2C ',' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2D '-' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2E '.' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x2F '/' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, - 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, - 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, - 0x03, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, - 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x30 '0' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xF8, 0x3F, 0x80, - 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, - 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC7, 0xCF, 0xE0, - 0x0F, 0xC7, 0xCF, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, - 0x03, 0xF8, 0x7F, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x31 '1' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, - 0x0F, 0xFB, 0xF0, 0x00, 0x0F, 0xF3, 0xF0, 0x00, 0x0F, 0xC3, 0xF0, 0x00, 0x0F, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, - 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x32 '2' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, - 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, - 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, - 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, - 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x33 '3' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F, 0xFF, 0x00, - 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0x80, - 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, - 0x0F, 0xC0, 0x07, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, - 0x0F, 0xF8, 0x3F, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x34 '4' - { - 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, - 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x1F, 0xBF, 0x00, 0x00, 0x1F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, - 0x00, 0x7E, 0x3F, 0x00, 0x00, 0x7C, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, - 0x03, 0xF0, 0x3F, 0x00, 0x03, 0xE0, 0x3F, 0x00, 0x07, 0xE0, 0x3F, 0x00, 0x0F, 0xC0, 0x3F, 0x00, - 0x0F, 0x80, 0x3F, 0x00, 0x1F, 0x80, 0x3F, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, - 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0x00, - 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, - 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x35 '5' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, - 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xE0, 0x00, 0x00, - 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, - 0x07, 0xE3, 0xF0, 0x00, 0x07, 0xEF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, - 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, - 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, - 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, - 0x0F, 0xF8, 0x3F, 0xC0, 0x07, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, - 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x36 '6' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0xFC, 0x00, - 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFC, 0x3F, 0xC0, - 0x03, 0xF8, 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE1, 0xF8, 0x00, 0x0F, 0xCF, 0xFE, 0x00, 0x0F, 0xDF, 0xFF, 0x00, - 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x1F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, - 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x03, 0xF8, 0x1F, 0xC0, - 0x03, 0xFC, 0x3F, 0xC0, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0x00, - 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x37 '7' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x7E, 0x00, - 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x38 '8' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, - 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, - 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x80, - 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, - 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, - 0x0F, 0xF8, 0x3F, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x39 '9' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0xF8, 0x00, - 0x01, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xF8, 0x7F, 0x80, - 0x0F, 0xF0, 0x3F, 0x80, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, - 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, - 0x0F, 0xF0, 0x1F, 0xE0, 0x07, 0xF8, 0x7F, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, - 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xCF, 0xE0, 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x01, 0xE0, 0x1F, 0x80, 0x07, 0xE0, 0x3F, 0x80, - 0x07, 0xF0, 0x7F, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFC, 0x00, - 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3A ':' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3B ';' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3C '<' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x07, 0xE0, - 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0x00, - 0x00, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFC, 0x00, 0x00, - 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, - 0x1F, 0xFC, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFC, 0x00, - 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xE0, - 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3D '=' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, - 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, - 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3E '>' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, - 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xF0, 0x00, - 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x00, 0x7F, 0xE0, - 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x1F, 0xE0, - 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x7F, 0xFE, 0x00, - 0x03, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, - 0x1F, 0xC0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x3F '?' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0xFC, 0x00, - 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xF8, 0x3F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, - 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, - 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xF8, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x40 '@' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFC, 0x1F, 0x80, 0x01, 0xF0, 0x07, 0x80, - 0x01, 0xE0, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0xE0, 0x07, 0x80, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xE0, - 0x0F, 0x03, 0xC0, 0x70, 0x0E, 0x0F, 0xE7, 0x70, 0x0E, 0x1F, 0xEF, 0x70, 0x1E, 0x3E, 0x3E, 0x70, - 0x1C, 0x3C, 0x3E, 0x38, 0x1C, 0x78, 0x1E, 0x38, 0x1C, 0x78, 0x1E, 0x38, 0x1C, 0x70, 0x1E, 0x38, - 0x3C, 0xF0, 0x1C, 0x38, 0x38, 0xF0, 0x1C, 0x38, 0x38, 0xE0, 0x3C, 0x38, 0x38, 0xE0, 0x3C, 0x38, - 0x38, 0xE0, 0x3C, 0x38, 0x38, 0xE0, 0x38, 0x70, 0x38, 0xE0, 0x38, 0x70, 0x38, 0xE0, 0x78, 0x70, - 0x38, 0xE0, 0x78, 0x70, 0x38, 0xE0, 0xF8, 0xE0, 0x3C, 0xF0, 0xF8, 0xE0, 0x1C, 0xF1, 0xF9, 0xE0, - 0x1C, 0x7F, 0x9F, 0xC0, 0x1C, 0x3F, 0x1F, 0x80, 0x1E, 0x1E, 0x0F, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x07, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x0F, 0x80, - 0x01, 0xF0, 0x3F, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x41 'A' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7C, 0xFC, 0x00, 0x00, 0xFC, 0x7E, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x01, 0xF8, 0x7E, 0x00, 0x01, 0xF8, 0x3F, 0x00, - 0x01, 0xF8, 0x3F, 0x00, 0x03, 0xF8, 0x3F, 0x00, 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0x80, - 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x1F, 0xC0, 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0x80, 0x07, 0xF0, 0x3F, 0x80, 0x03, 0xF0, 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, - 0x7F, 0x00, 0x01, 0xF8, 0x7F, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x42 'B' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFE, 0x00, - 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, - 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x03, 0xF8, - 0x0F, 0xE0, 0x03, 0xF8, 0x0F, 0xE0, 0x03, 0xF8, 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x07, 0xF0, - 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, - 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x43 'C' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFC, 0x3F, 0xC0, - 0x07, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, - 0x1F, 0xC0, 0x06, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, - 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, - 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x03, 0x80, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x0F, 0xE0, - 0x07, 0xFC, 0x3F, 0xE0, 0x03, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x44 'D' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xF0, 0x00, - 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xE0, 0xFF, 0x80, - 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, - 0x0F, 0xE0, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, - 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x45 'E' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x80, - 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, - 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x46 'F' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, - 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, - 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x47 'G' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFC, 0x3F, 0x80, - 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0E, 0x00, - 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, - 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC1, 0xFF, 0xE0, - 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC1, 0xFF, 0xE0, 0x1F, 0xC0, 0x07, 0xE0, 0x1F, 0xE0, 0x07, 0xE0, - 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xF0, 0x07, 0xE0, 0x07, 0xF8, 0x07, 0xE0, - 0x03, 0xFC, 0x1F, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x48 'H' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x49 'I' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, - 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, - 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4A 'J' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, - 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x01, 0xC0, 0x3F, 0x80, - 0x1F, 0xE0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0x00, 0x0F, 0xF0, 0x7F, 0x00, - 0x07, 0xF8, 0xFF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFC, 0x00, - 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4B 'K' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x0F, 0xF0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xE0, 0x7F, 0x80, - 0x0F, 0xE0, 0x7F, 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x0F, 0xE1, 0xFE, 0x00, 0x0F, 0xE3, 0xFC, 0x00, - 0x0F, 0xE3, 0xF8, 0x00, 0x0F, 0xE7, 0xF0, 0x00, 0x0F, 0xEF, 0xF0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, - 0x0F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF8, 0x00, - 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFB, 0xFC, 0x00, 0x0F, 0xF9, 0xFE, 0x00, 0x0F, 0xF0, 0xFE, 0x00, - 0x0F, 0xE0, 0xFF, 0x00, 0x0F, 0xE0, 0x7F, 0x80, 0x0F, 0xE0, 0x7F, 0x80, 0x0F, 0xE0, 0x3F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, - 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4C 'L' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, - 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4D 'M' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x0F, 0xE0, 0x1F, 0xF0, 0x1F, 0xE0, - 0x1F, 0xF0, 0x1F, 0xE0, 0x1F, 0xF0, 0x1F, 0xE0, 0x1F, 0xF8, 0x3F, 0xE0, 0x1F, 0xF8, 0x3F, 0xE0, - 0x1F, 0xF8, 0x3F, 0xE0, 0x1F, 0xFC, 0x3F, 0xE0, 0x1F, 0x7C, 0x7F, 0xE0, 0x1F, 0x7C, 0x7F, 0xE0, - 0x1F, 0x3C, 0x7B, 0xE0, 0x1F, 0x3E, 0xFB, 0xE0, 0x1F, 0x3E, 0xFB, 0xE0, 0x1F, 0x3E, 0xFB, 0xE0, - 0x1F, 0x1E, 0xF3, 0xE0, 0x1F, 0x1F, 0xF3, 0xE0, 0x1F, 0x1F, 0xF3, 0xE0, 0x1F, 0x1F, 0xE3, 0xE0, - 0x1F, 0x0F, 0xE3, 0xE0, 0x1F, 0x0F, 0xE3, 0xE0, 0x1F, 0x0F, 0xE3, 0xE0, 0x1F, 0x0F, 0xC3, 0xE0, - 0x1F, 0x07, 0xC3, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, - 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, - 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4E 'N' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x07, 0xE0, 0x0F, 0xF8, 0x07, 0xE0, - 0x0F, 0xF8, 0x07, 0xE0, 0x0F, 0xF8, 0x07, 0xE0, 0x0F, 0xFC, 0x07, 0xE0, 0x0F, 0xFC, 0x07, 0xE0, - 0x0F, 0xFC, 0x07, 0xE0, 0x0F, 0xFE, 0x07, 0xE0, 0x0F, 0xFE, 0x07, 0xE0, 0x0F, 0xFF, 0x07, 0xE0, - 0x0F, 0xFF, 0x07, 0xE0, 0x0F, 0xDF, 0x07, 0xE0, 0x0F, 0xDF, 0x87, 0xE0, 0x0F, 0xCF, 0x87, 0xE0, - 0x0F, 0xCF, 0x87, 0xE0, 0x0F, 0xCF, 0xC7, 0xE0, 0x0F, 0xC7, 0xC7, 0xE0, 0x0F, 0xC7, 0xE7, 0xE0, - 0x0F, 0xC7, 0xE7, 0xE0, 0x0F, 0xC3, 0xE7, 0xE0, 0x0F, 0xC3, 0xF7, 0xE0, 0x0F, 0xC1, 0xF7, 0xE0, - 0x0F, 0xC1, 0xF7, 0xE0, 0x0F, 0xC1, 0xFF, 0xE0, 0x0F, 0xC0, 0xFF, 0xE0, 0x0F, 0xC0, 0xFF, 0xE0, - 0x0F, 0xC0, 0xFF, 0xE0, 0x0F, 0xC0, 0x7F, 0xE0, 0x0F, 0xC0, 0x7F, 0xE0, 0x0F, 0xC0, 0x3F, 0xE0, - 0x0F, 0xC0, 0x3F, 0xE0, 0x0F, 0xC0, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x4F 'O' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, - 0x0F, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, - 0x07, 0xF8, 0x7F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x50 'P' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, - 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xE0, 0x3F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x3F, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, - 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x51 'Q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, - 0x0F, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xF0, 0x1F, 0xC0, - 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xF0, - 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00 - }, - // 0x52 'R' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0x00, - 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x3F, 0xE0, - 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, - 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xE1, 0xFE, 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x0F, 0xE0, 0xFF, 0x00, - 0x0F, 0xE0, 0x7F, 0x00, 0x0F, 0xE0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, - 0x0F, 0xE0, 0x07, 0xF8, 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x53 'S' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0xFE, 0x00, - 0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xC0, 0x1F, 0xC0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, - 0x03, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xE0, - 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x07, 0xF0, - 0x07, 0x80, 0x03, 0xF0, 0x3F, 0x80, 0x03, 0xF0, 0x3F, 0xC0, 0x07, 0xF0, 0x1F, 0xE0, 0x07, 0xF0, - 0x1F, 0xF0, 0x1F, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x54 'T' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, - 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x55 'U' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, - 0x07, 0xF8, 0x7F, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x56 'V' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x03, 0xF8, - 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF0, 0x1F, 0x80, - 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x7F, 0x00, - 0x01, 0xFC, 0x7F, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFE, 0xFC, 0x00, - 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x57 'W' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, - 0x7E, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, - 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF0, 0x3F, 0x07, 0xC1, 0xF0, - 0x1F, 0x07, 0xC3, 0xF0, 0x1F, 0x8F, 0xC3, 0xF0, 0x1F, 0x8F, 0xE3, 0xF0, 0x1F, 0x8F, 0xE3, 0xF0, - 0x1F, 0x8F, 0xE3, 0xF0, 0x1F, 0x9F, 0xF3, 0xE0, 0x0F, 0x9F, 0xF3, 0xE0, 0x0F, 0x9F, 0xF3, 0xE0, - 0x0F, 0xBE, 0xF3, 0xE0, 0x0F, 0xBE, 0xFB, 0xE0, 0x0F, 0xBE, 0xFF, 0xE0, 0x0F, 0xFC, 0x7F, 0xC0, - 0x0F, 0xFC, 0x7F, 0xC0, 0x07, 0xFC, 0x7F, 0xC0, 0x07, 0xFC, 0x7F, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, - 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF8, 0x3F, 0x80, 0x03, 0xF0, 0x3F, 0x80, - 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x58 'X' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x1F, 0xC0, 0x07, 0xF0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x3F, 0x80, - 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xFC, 0x7F, 0x00, 0x01, 0xFC, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, - 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFE, 0xFE, 0x00, - 0x01, 0xFC, 0x7F, 0x00, 0x03, 0xF8, 0x7F, 0x00, 0x03, 0xF8, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, - 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x3F, 0x80, 0x03, 0xF8, 0x7F, 0x80, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x59 'Y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xF8, 0x3F, 0x00, - 0x01, 0xFC, 0x7F, 0x00, 0x00, 0xFC, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x7F, 0xFC, 0x00, - 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5A 'Z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, - 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xC0, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, - 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, - 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, - 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, - 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5B '[' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x00, - 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00 - }, - // 0x5C '\\' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, - 0x0F, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, - 0x03, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0xFC, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x7C, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x07, 0xC0, - 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5D ']' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, - 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF8, 0x00 - }, - // 0x5E '^' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, - 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7D, 0xF8, 0x00, 0x00, 0x7C, 0xF8, 0x00, - 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xF8, 0x7C, 0x00, 0x00, 0xF8, 0x7C, 0x00, 0x01, 0xF0, 0x3E, 0x00, - 0x01, 0xF0, 0x3E, 0x00, 0x03, 0xE0, 0x3F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x07, 0xE0, 0x1F, 0x80, - 0x07, 0xC0, 0x0F, 0x80, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0x80, 0x07, 0xC0, 0x0F, 0x80, 0x07, 0xC0, - 0x1F, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xE0, 0x3F, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x5F '_' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x60 '`' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x07, 0xE0, 0x00, - 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x61 'a' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, - 0x03, 0xF8, 0x7F, 0x00, 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, - 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0x80, - 0x0F, 0xE0, 0x3F, 0x80, 0x0F, 0xC0, 0x3F, 0x80, 0x0F, 0xC0, 0x3F, 0x80, 0x0F, 0xE0, 0x7F, 0x80, - 0x0F, 0xF1, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xCF, 0xF8, 0x07, 0xFF, 0x8F, 0xF8, - 0x03, 0xFF, 0x07, 0xF8, 0x00, 0xFC, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x62 'b' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE1, 0xF8, 0x00, 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xEF, 0xFF, 0x00, 0x0F, 0xEF, 0xFF, 0x80, - 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, - 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF8, 0x1F, 0xC0, - 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xEF, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0x00, - 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xE1, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x63 'c' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, - 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, - 0x07, 0xFC, 0x3F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFE, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x64 'd' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x3F, 0x0F, 0xC0, 0x00, 0xFF, 0x8F, 0xC0, 0x01, 0xFF, 0xCF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, - 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x7F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, - 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, - 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, - 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, 0x01, 0xFF, 0xCF, 0xC0, - 0x00, 0xFF, 0x8F, 0xC0, 0x00, 0x3E, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x65 'e' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, - 0x03, 0xF8, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x07, 0xC0, - 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, - 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x07, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, - 0x07, 0xFC, 0x3F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x66 'f' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, - 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xE0, - 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, - 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x67 'g' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3F, 0x07, 0xE0, 0x00, 0xFF, 0xC7, 0xE0, 0x01, 0xFF, 0xE7, 0xE0, 0x03, 0xFF, 0xF7, 0xE0, - 0x03, 0xFF, 0xFF, 0xE0, 0x07, 0xFC, 0x7F, 0xE0, 0x07, 0xF0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x1F, 0xE0, 0x07, 0xF0, 0x1F, 0xE0, - 0x07, 0xFC, 0x3F, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xEF, 0xE0, - 0x00, 0xFF, 0xCF, 0xE0, 0x00, 0x3F, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, - 0x00, 0x00, 0x0F, 0xE0, 0x01, 0xF0, 0x0F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xFC, 0x3F, 0x80, - 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00 - }, - // 0x68 'h' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0xFC, 0x00, 0x0F, 0xE3, 0xFF, 0x00, 0x0F, 0xE7, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0xC0, - 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, - 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x69 'i' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, - 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, - 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6A 'j' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, - 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, - 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x08, 0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, - 0x0F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00 - }, - // 0x6B 'k' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, - 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x3F, 0x80, - 0x07, 0xF0, 0x7F, 0x00, 0x07, 0xF0, 0xFE, 0x00, 0x07, 0xF1, 0xFC, 0x00, 0x07, 0xF3, 0xF8, 0x00, - 0x07, 0xF3, 0xF0, 0x00, 0x07, 0xF7, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF0, 0x00, - 0x07, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xF9, 0xFC, 0x00, - 0x07, 0xF0, 0xFE, 0x00, 0x07, 0xF0, 0xFE, 0x00, 0x07, 0xF0, 0x7F, 0x00, 0x07, 0xF0, 0x3F, 0x80, - 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, - 0x07, 0xF0, 0x0F, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6C 'l' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, - 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, - 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6D 'm' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1E, 0x07, 0x80, 0x1F, 0x7F, 0x1F, 0xC0, 0x1F, 0x7F, 0xBF, 0xE0, 0x1F, 0xFF, 0xBF, 0xE0, - 0x1F, 0xCF, 0xF3, 0xF0, 0x1F, 0x8F, 0xE3, 0xF0, 0x1F, 0x87, 0xE1, 0xF0, 0x1F, 0x87, 0xC1, 0xF0, - 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, - 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, - 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, - 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, - 0x1F, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6E 'n' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0xC0, 0xFC, 0x00, 0x0F, 0xE3, 0xFF, 0x00, 0x0F, 0xE7, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0xC0, - 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, - 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x6F 'o' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, - 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, - 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x1F, 0xC0, - 0x07, 0xF8, 0x3F, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x70 'p' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0xE0, 0xF8, 0x00, 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xE7, 0xFF, 0x00, 0x0F, 0xEF, 0xFF, 0x80, - 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x1F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, - 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, - 0x0F, 0xE0, 0x07, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, - 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xF8, 0x1F, 0xE0, - 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xEF, 0xFF, 0x80, 0x0F, 0xE7, 0xFF, 0x00, - 0x0F, 0xE3, 0xFE, 0x00, 0x0F, 0xE1, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, - 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00 - }, - // 0x71 'q' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3E, 0x0F, 0xC0, 0x00, 0xFF, 0x8F, 0xC0, 0x01, 0xFF, 0xCF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, - 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xF8, 0x7F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, - 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xC0, - 0x0F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, - 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, 0x03, 0xFF, 0xCF, 0xC0, - 0x00, 0xFF, 0x8F, 0xC0, 0x00, 0x7E, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, - 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0 - }, - // 0x72 'r' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xF0, 0x3F, 0xC0, 0x03, 0xF0, 0xFF, 0xC0, 0x03, 0xF9, 0xFF, 0xC0, 0x03, 0xFB, 0xFF, 0xC0, - 0x03, 0xFB, 0xFF, 0xC0, 0x01, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, - 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, - 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, - 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, - 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, - 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x73 's' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, - 0x03, 0xFF, 0xFF, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0x80, 0x07, 0xE0, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xFC, 0x00, - 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xC0, - 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, - 0x0F, 0xF0, 0x1F, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, - 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x74 't' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, - 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, - 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0x7F, 0x80, 0x80, 0x00, 0x7F, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x80, - 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x75 'u' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, - 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, - 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, - 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, - 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x3F, 0xC0, 0x0F, 0xF0, 0x3F, 0xC0, - 0x07, 0xF8, 0x7F, 0xC0, 0x07, 0xFF, 0xEF, 0xC0, 0x03, 0xFF, 0xEF, 0xC0, 0x03, 0xFF, 0xCF, 0xC0, - 0x01, 0xFF, 0x8F, 0xC0, 0x00, 0x7E, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x76 'v' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x1F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xC0, - 0x07, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF0, 0x3F, 0x80, - 0x03, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x7E, 0x00, 0x01, 0xFC, 0x7E, 0x00, - 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, - 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, - 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x77 'w' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x00, 0xF8, - 0x3E, 0x00, 0x00, 0xF8, 0x3E, 0x00, 0x01, 0xF8, 0x3E, 0x07, 0xC1, 0xF0, 0x1F, 0x07, 0xC1, 0xF0, - 0x1F, 0x0F, 0xC1, 0xF0, 0x1F, 0x0F, 0xE1, 0xF0, 0x1F, 0x0F, 0xE1, 0xF0, 0x1F, 0x1F, 0xE1, 0xF0, - 0x1F, 0x1F, 0xF3, 0xE0, 0x1F, 0x1F, 0xF3, 0xE0, 0x0F, 0x9E, 0xF3, 0xE0, 0x0F, 0xBE, 0xF3, 0xE0, - 0x0F, 0xBC, 0x7B, 0xE0, 0x0F, 0xBC, 0x7B, 0xE0, 0x0F, 0xFC, 0x7F, 0xC0, 0x0F, 0xF8, 0x7F, 0xC0, - 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF8, 0x3F, 0xC0, 0x07, 0xF0, 0x3F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, - 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xE0, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x78 'x' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0xC0, 0x07, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, - 0x03, 0xF8, 0x3F, 0x80, 0x01, 0xF8, 0x7F, 0x00, 0x01, 0xFC, 0x7E, 0x00, 0x00, 0xFE, 0xFE, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00, - 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x01, 0xFC, 0x7E, 0x00, 0x01, 0xF8, 0x7F, 0x00, - 0x03, 0xF8, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xE0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, - 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0x80, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x79 'y' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0x80, 0x03, 0xF8, 0x1F, 0x80, 0x03, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x07, 0xF0, - 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xE0, 0x0F, 0xC0, 0x07, 0xE0, 0x0F, 0xC0, - 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF0, 0x1F, 0x80, 0x03, 0xF8, 0x1F, 0x80, 0x01, 0xF8, 0x3F, 0x00, - 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x7E, 0x00, 0x00, 0xFC, 0x7E, 0x00, - 0x00, 0x7C, 0x7E, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x3E, 0xF8, 0x00, - 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, - 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F, 0xFF, 0x00, 0x00, - 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00 - }, - // 0x7A 'z' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, - 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFE, 0x00, - 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, - 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x7F, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, - 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, - 0x0F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - // 0x7B '{' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, - 0x00, 0x07, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x1F, 0xE0, 0x00, - 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, - 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, - 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, - 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x80 - }, - // 0x7C '|' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, - 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00 - }, - // 0x7D '}' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, - 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, - 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, - 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFE, 0x00, - 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, - 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, - 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x00, 0x00 - }, - // 0x7E '~' - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x30, - 0x1F, 0xFF, 0xE0, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1C, 0x0F, 0xFF, 0xF0, - 0x10, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, -}; diff --git a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h b/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h deleted file mode 100644 index aadea05bd5282..0000000000000 --- a/ports/espressif/common-hal/rm690b0/fonts/rm690b0_font_8x8.h +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -// Simple 8x8 ASCII font for characters 0x20..0x7F. -// Each character: 8 bytes, MSB = left pixel, LSB = right pixel, 1 bit per pixel. -// Indexing: glyph = rm690b0_font_8x8_data[codepoint - 0x20] for 0x20 <= codepoint <= 0x7F. -static const uint8_t rm690b0_font_8x8_data[96][8] = { - // 0x20 ' ' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - // 0x21 '!' - {0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, - // 0x22 '"' - {0x6C, 0x6C, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00}, - // 0x23 '#' - {0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00}, - // 0x24 '$' - {0x18, 0x3E, 0x58, 0x3C, 0x1A, 0x7C, 0x18, 0x00}, - // 0x25 '%' - {0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00}, - // 0x26 '&' - {0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00}, - // 0x27 ''' - {0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, - // 0x28 '(' - {0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00}, - // 0x29 ')' - {0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00}, - // 0x2A '*' - {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, - // 0x2B '+' - {0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, - // 0x2C ',' - {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00}, - // 0x2D '-' - {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, - // 0x2E '.' - {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, - // 0x2F '/' - {0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00}, - // 0x30 '0' - {0x7C, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0x7C, 0x00}, - // 0x31 '1' - {0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, - // 0x32 '2' - {0x7C, 0xC6, 0x0E, 0x1C, 0x70, 0xC0, 0xFE, 0x00}, - // 0x33 '3' - {0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00}, - // 0x34 '4' - {0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00}, - // 0x35 '5' - {0xFE, 0xC0, 0xFC, 0x06, 0x06, 0xC6, 0x7C, 0x00}, - // 0x36 '6' - {0x3C, 0x60, 0xC0, 0xFC, 0xC6, 0xC6, 0x7C, 0x00}, - // 0x37 '7' - {0xFE, 0xC6, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00}, - // 0x38 '8' - {0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0x00}, - // 0x39 '9' - {0x7C, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00}, - // 0x3A ':' - {0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00}, - // 0x3B ';' - {0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x00}, - // 0x3C '<' - {0x0E, 0x1C, 0x38, 0x70, 0x38, 0x1C, 0x0E, 0x00}, - // 0x3D '=' - {0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, - // 0x3E '>' - {0x70, 0x38, 0x1C, 0x0E, 0x1C, 0x38, 0x70, 0x00}, - // 0x3F '?' - {0x7C, 0xC6, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00}, - // 0x40 '@' - {0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x7C, 0x00}, - // 0x41 'A' - {0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00}, - // 0x42 'B' - {0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00}, - // 0x43 'C' - {0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00}, - // 0x44 'D' - {0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00}, - // 0x45 'E' - {0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00}, - // 0x46 'F' - {0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00}, - // 0x47 'G' - {0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00}, - // 0x48 'H' - {0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00}, - // 0x49 'I' - {0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, - // 0x4A 'J' - {0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0x78, 0x00}, - // 0x4B 'K' - {0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00}, - // 0x4C 'L' - {0xF0, 0x60, 0x60, 0x60, 0x60, 0x62, 0xFE, 0x00}, - // 0x4D 'M' - {0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00}, - // 0x4E 'N' - {0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00}, - // 0x4F 'O' - {0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, - // 0x50 'P' - {0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00}, - // 0x51 'Q' - {0x7C, 0xC6, 0xC6, 0xC6, 0xDE, 0xCC, 0x7A, 0x00}, - // 0x52 'R' - {0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00}, - // 0x53 'S' - {0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00}, - // 0x54 'T' - {0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x3C, 0x00}, - // 0x55 'U' - {0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, - // 0x56 'V' - {0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, - // 0x57 'W' - {0xC6, 0xC6, 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x00}, - // 0x58 'X' - {0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00}, - // 0x59 'Y' - {0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x00}, - // 0x5A 'Z' - {0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00}, - // 0x5B '[' - {0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00}, - // 0x5C '\' - {0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00}, - // 0x5D ']' - {0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00}, - // 0x5E '^' - {0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, - // 0x5F '_' - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, - // 0x60 '`' - {0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, - // 0x61 'a' - {0x00, 0x00, 0x7C, 0x06, 0x7E, 0xC6, 0x7E, 0x00}, - // 0x62 'b' - {0xE0, 0x60, 0x7C, 0x66, 0x66, 0x66, 0xDC, 0x00}, - // 0x63 'c' - {0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00}, - // 0x64 'd' - {0x1C, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, - // 0x65 'e' - {0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0x7C, 0x00}, - // 0x66 'f' - {0x1C, 0x36, 0x30, 0x7C, 0x30, 0x30, 0x78, 0x00}, - // 0x67 'g' - {0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8}, - // 0x68 'h' - {0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00}, - // 0x69 'i' - {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, - // 0x6A 'j' - {0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78}, - // 0x6B 'k' - {0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00}, - // 0x6C 'l' - {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, - // 0x6D 'm' - {0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xC6, 0x00}, - // 0x6E 'n' - {0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x00}, - // 0x6F 'o' - {0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, - // 0x70 'p' - {0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0}, - // 0x71 'q' - {0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E}, - // 0x72 'r' - {0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00}, - // 0x73 's' - {0x00, 0x00, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x00}, - // 0x74 't' - {0x30, 0x30, 0xFC, 0x30, 0x30, 0x36, 0x1C, 0x00}, - // 0x75 'u' - {0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00}, - // 0x76 'v' - {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00}, - // 0x77 'w' - {0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00}, - // 0x78 'x' - {0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00}, - // 0x79 'y' - {0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0xFC}, - // 0x7A 'z' - {0x00, 0x00, 0xFE, 0x8C, 0x18, 0x32, 0xFE, 0x00}, - // 0x7B '{' - {0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0x00}, - // 0x7C '|' - {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, - // 0x7D '}' - {0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0x00}, - // 0x7E '~' - {0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - // 0x7F (DEL / unused) - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index a7b34b44a6f9c..dfff62f495748 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -375,9 +375,6 @@ endif ifeq ($(CIRCUITPY_SHARPDISPLAY),1) SRC_PATTERNS += sharpdisplay/% endif -ifeq ($(CIRCUITPY_RM690B0),1) -SRC_PATTERNS += rm690b0/% -endif ifeq ($(CIRCUITPY_SOCKETPOOL),1) SRC_PATTERNS += socketpool/% endif @@ -577,7 +574,6 @@ SRC_COMMON_HAL_ALL = \ wifi/Radio.c \ wifi/ScannedNetworks.c \ wifi/__init__.c \ - rm690b0/RM690B0.c \ SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) @@ -636,7 +632,6 @@ $(filter $(SRC_PATTERNS), \ wifi/AuthMode.c \ wifi/Packet.c \ wifi/PowerManagement.c \ - rm690b0/__init__.c \ ) ifeq ($(CIRCUITPY_BLEIO_HCI),1) @@ -915,8 +910,8 @@ SRC_MOD += $(addprefix lib/AnimatedGIF/, \ $(BUILD)/lib/AnimatedGIF/gif.o: CFLAGS += -DCIRCUITPY endif -# tjpgd library is needed for both JPEGIO and RM690B0 JPEG support -ifneq ($(filter 1,$(CIRCUITPY_JPEGIO) $(CIRCUITPY_RM690B0)),) +# tjpgd library is needed for JPEGIO support. +ifneq ($(filter 1,$(CIRCUITPY_JPEGIO)),) SRC_MOD += lib/tjpgd/src/tjpgd.c $(BUILD)/lib/tjpgd/src/tjpgd.o: CFLAGS += -Wno-shadow -Wno-cast-align CFLAGS_MOD += -I$(TOP)/lib/tjpgd/src diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 4ab7d00e5e742..06eea7d3b01a5 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -257,8 +257,8 @@ CFLAGS += -DCIRCUITPY_EPAPERDISPLAY=$(CIRCUITPY_EPAPERDISPLAY) CIRCUITPY_I2CDISPLAYBUS ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_I2CDISPLAYBUS=$(CIRCUITPY_I2CDISPLAYBUS) -CIRCUITPY_RM690B0 ?= 0 -CFLAGS += -DCIRCUITPY_RM690B0=$(CIRCUITPY_RM690B0) +# CIRCUITPY_RM690B0 removed in Phase 4. +# Use qspibus + displayio for RM690B0 panels. ifeq ($(CIRCUITPY_DISPLAYIO),1) CIRCUITPY_PARALLELDISPLAYBUS ?= $(CIRCUITPY_FULL_BUILD) diff --git a/shared-bindings/rm690b0/RM690B0.c b/shared-bindings/rm690b0/RM690B0.c deleted file mode 100644 index 33e2950a4f115..0000000000000 --- a/shared-bindings/rm690b0/RM690B0.c +++ /dev/null @@ -1,513 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include - -#include "py/obj.h" -#include "py/runtime.h" - -#include "shared-bindings/rm690b0/RM690B0.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/busio/SPI.h" -#include "shared-bindings/time/__init__.h" -#include "py/objproperty.h" -#include "py/objstr.h" - -//| class RM690B0: -//| """RM690B0 driver for AMOLED displays -//| -//| This is a basic driver for the RM690B0 AMOLED display controller. -//| It provides low-level drawing primitives (pixels, lines, rectangles, circles, -//| blitting bitmaps) and a small built-in text API with several fixed fonts. -//| """ -//| -//| def __init__(self) -> None: -//| """Initialize the RM690B0 display driver -//| -//| Initializes the panel and internal framebuffers. Call `init_display()` -//| before performing any drawing operations. -//| """ -//| ... -//| - -static mp_obj_t rm690b0_rm690b0_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // For now, accept no arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - rm690b0_rm690b0_obj_t *self = mp_obj_malloc(rm690b0_rm690b0_obj_t, &rm690b0_rm690b0_type); - - common_hal_rm690b0_rm690b0_construct(self); - - return MP_OBJ_FROM_PTR(self); -} - -//| def deinit(self) -> None: -//| """Deinitialize the display driver -//| -//| Can be called as instance method or static method: -//| -//| Instance method:: -//| -//| d = rm690b0.RM690B0() -//| d.deinit() # Cleans up this specific instance -//| -//| Static method (REPL convenience):: -//| -//| import rm690b0 -//| # If display is stuck/initialized without a reference -//| rm690b0.RM690B0.deinit() # Cleans up any active instance -//| # Now you can create a new instance -//| d = rm690b0.RM690B0() -//| """ -//| ... -//| -static mp_obj_t rm690b0_rm690b0_deinit(size_t n_args, const mp_obj_t *args) { - if (n_args == 0) { - // Called as static method: RM690B0.deinit() - common_hal_rm690b0_rm690b0_deinit_all(); - } else { - // Called as instance method: d.deinit() - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - common_hal_rm690b0_rm690b0_deinit(self); - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_deinit_obj, 0, 1, rm690b0_rm690b0_deinit); - -//| def init_display(self) -> None: -//| """Initialize the display with default settings""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_init_display(mp_obj_t self_in) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_rm690b0_rm690b0_init_display(self); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_init_display_obj, rm690b0_rm690b0_init_display); - -//| # --- Built-in font and text API --- -//| -//| def set_font(self, font: int) -> None: -//| """Select one of the built-in fonts for subsequent text drawing. -//| -//| :param int font: Font identifier. Available fonts: -//| 0 = 8x8 monospace (smallest) -//| 1 = 16x16 monospace (Liberation Sans) -//| 2 = 16x24 monospace (Liberation Mono Bold) -//| 3 = 24x24 monospace -//| 4 = 24x32 monospace -//| 5 = 32x32 monospace -//| 6 = 32x48 monospace (largest) -//| -//| This affects `text()` only and does not interact with LVGL or Tiny TTF. -//| """ -//| ... -//| -static mp_obj_t rm690b0_rm690b0_set_font(mp_obj_t self_in, mp_obj_t font_obj) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_int_t font_id = mp_obj_get_int(font_obj); - common_hal_rm690b0_rm690b0_set_font(self, font_id); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_set_font_obj, rm690b0_rm690b0_set_font); - -//| def text(self, x: int, y: int, text: str, color: int = 0xFFFF, background: int | None = None) -> None: -//| """Draw a UTF-8 string using the currently selected built-in font. -//| -//| :param int x: Left coordinate (in pixels) -//| :param int y: Top coordinate (in pixels) -//| :param str text: Text to draw (UTF-8; unsupported glyphs may be replaced) -//| :param int color: Foreground RGB565 color (default: white) -//| :param int|None background: Optional background RGB565 color. If None, text is drawn transparent over existing pixels. -//| -//| This is a lightweight, non-LVGL text API intended for labels, debug info -//| and simple UIs. For full-featured text layout and TTF fonts, use `rm690b0_lvgl`. -//| """ -//| ... -//| -static mp_obj_t rm690b0_rm690b0_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_x, ARG_y, ARG_text, ARG_color, ARG_background }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_color, MP_ARG_INT, {.u_int = 0xFFFF} }, - { MP_QSTR_background, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_int_t x = args[ARG_x].u_int; - mp_int_t y = args[ARG_y].u_int; - - // Accept any object that can be converted to str - mp_obj_t text_obj = args[ARG_text].u_obj; - GET_STR_DATA_LEN(text_obj, text_data, text_len); - - uint16_t fg = (uint16_t)(args[ARG_color].u_int & 0xFFFF); - bool has_bg = args[ARG_background].u_obj != mp_const_none; - uint16_t bg = 0; - if (has_bg) { - bg = (uint16_t)(mp_obj_get_int(args[ARG_background].u_obj) & 0xFFFF); - } - - common_hal_rm690b0_rm690b0_text(self, x, y, - (const char *)text_data, (size_t)text_len, - fg, has_bg, bg); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_KW(rm690b0_rm690b0_text_obj, 1, rm690b0_rm690b0_text); - -static mp_obj_t rm690b0_rm690b0_fill_color(mp_obj_t self_in, mp_obj_t color_obj) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint16_t color = mp_obj_get_int(color_obj) & 0xFFFF; - common_hal_rm690b0_rm690b0_fill_color(self, color); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_fill_color_obj, rm690b0_rm690b0_fill_color); - -//| def pixel(self, x: int, y: int, color: int) -> None: -//| """Draw a single pixel""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_pixel(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t color = mp_obj_get_int(args[3]); - common_hal_rm690b0_rm690b0_pixel(self, x, y, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_pixel_obj, 4, 4, rm690b0_rm690b0_pixel); - -//| def fill_rect(self, x: int, y: int, width: int, height: int, color: int) -> None: -//| """Draw a filled rectangle""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_fill_rect(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t width = mp_obj_get_int(args[3]); - mp_int_t height = mp_obj_get_int(args[4]); - mp_int_t color = mp_obj_get_int(args[5]); - common_hal_rm690b0_rm690b0_fill_rect(self, x, y, width, height, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_fill_rect_obj, 6, 6, rm690b0_rm690b0_fill_rect); - -//| def hline(self, x: int, y: int, width: int, color: int) -> None: -//| """Draw a horizontal line""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_hline(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t width = mp_obj_get_int(args[3]); - mp_int_t color = mp_obj_get_int(args[4]); - common_hal_rm690b0_rm690b0_hline(self, x, y, width, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_hline_obj, 5, 5, rm690b0_rm690b0_hline); - -//| def vline(self, x: int, y: int, height: int, color: int) -> None: -//| """Draw a vertical line""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_vline(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t height = mp_obj_get_int(args[3]); - mp_int_t color = mp_obj_get_int(args[4]); - common_hal_rm690b0_rm690b0_vline(self, x, y, height, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_vline_obj, 5, 5, rm690b0_rm690b0_vline); - -//| def line(self, x0: int, y0: int, x1: int, y1: int, color: int) -> None: -//| """Draw a line""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_line(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x0 = mp_obj_get_int(args[1]); - mp_int_t y0 = mp_obj_get_int(args[2]); - mp_int_t x1 = mp_obj_get_int(args[3]); - mp_int_t y1 = mp_obj_get_int(args[4]); - mp_int_t color = mp_obj_get_int(args[5]); - common_hal_rm690b0_rm690b0_line(self, x0, y0, x1, y1, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_line_obj, 6, 6, rm690b0_rm690b0_line); - -//| def rect(self, x: int, y: int, width: int, height: int, color: int) -> None: -//| """Draw a rectangle outline""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_rect(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t width = mp_obj_get_int(args[3]); - mp_int_t height = mp_obj_get_int(args[4]); - mp_int_t color = mp_obj_get_int(args[5]); - common_hal_rm690b0_rm690b0_rect(self, x, y, width, height, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_rect_obj, 6, 6, rm690b0_rm690b0_rect); - -//| def circle(self, x: int, y: int, radius: int, color: int) -> None: -//| """Draw a circle outline""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_circle(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t radius = mp_obj_get_int(args[3]); - mp_int_t color = mp_obj_get_int(args[4]); - common_hal_rm690b0_rm690b0_circle(self, x, y, radius, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_circle_obj, 5, 5, rm690b0_rm690b0_circle); - -//| def fill_circle(self, x: int, y: int, radius: int, color: int) -> None: -//| """Draw a filled circle""" -//| ... -//| -static mp_obj_t rm690b0_rm690b0_fill_circle(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t radius = mp_obj_get_int(args[3]); - mp_int_t color = mp_obj_get_int(args[4]); - common_hal_rm690b0_rm690b0_fill_circle(self, x, y, radius, color); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_fill_circle_obj, 5, 5, rm690b0_rm690b0_fill_circle); - - - - -//| def blit_buffer(self, x: int, y: int, width: int, height: int, bitmap_data: bytearray) -> None: -//| """Draw a bitmap""" -//| ... -//| -//| def blit_bmp(self, x: int, y: int, bmp_data: readablebuffer) -> None: -//| """Draw a BMP image from memory. -//| -//| :param int x: X coordinate of the top-left corner -//| :param int y: Y coordinate of the top-left corner -//| :param readablebuffer bmp_data: BMP image data""" -//| ... -static mp_obj_t rm690b0_rm690b0_blit_bmp(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_obj_t bmp_data = args[3]; - common_hal_rm690b0_rm690b0_blit_bmp(self, x, y, bmp_data); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_bmp_obj, 4, 4, rm690b0_rm690b0_blit_bmp); - -//| def blit_jpeg(self, x: int, y: int, jpeg_data: readablebuffer) -> None: -//| """Draw a JPEG image from memory. -//| -//| :param int x: X coordinate of the top-left corner -//| :param int y: Y coordinate of the top-left corner -//| :param readablebuffer jpeg_data: JPEG image data""" -//| ... -static mp_obj_t rm690b0_rm690b0_blit_jpeg(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_obj_t jpeg_data = args[3]; - common_hal_rm690b0_rm690b0_blit_jpeg(self, x, y, jpeg_data); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_blit_jpeg_obj, 4, 4, rm690b0_rm690b0_blit_jpeg); - -//| def convert_bmp(self, src_data: readablebuffer, dest_bitmap: displayio.Bitmap) -> None: -//| """Convert a BMP file (internal buffer) to a displayio.Bitmap in RGB565 format (RGB/BGR swapped for display). -//| -//| :param readablebuffer src_data: The full BMP file data -//| :param displayio.Bitmap dest_bitmap: The destination bitmap (must be correct size)""" -//| ... -static mp_obj_t rm690b0_rm690b0_convert_bmp(size_t n_args, const mp_obj_t *args) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_obj_t src_data = args[1]; - mp_obj_t dest_bitmap = args[2]; - common_hal_rm690b0_rm690b0_convert_bmp(self, src_data, dest_bitmap); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rm690b0_rm690b0_convert_bmp_obj, 3, 3, rm690b0_rm690b0_convert_bmp); - - -static mp_obj_t rm690b0_rm690b0_blit_buffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_x, ARG_y, ARG_width, ARG_height, ARG_bitmap_data, ARG_dest_is_swapped }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_bitmap_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_dest_is_swapped, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - common_hal_rm690b0_rm690b0_blit_buffer(self, - args[ARG_x].u_int, - args[ARG_y].u_int, - args[ARG_width].u_int, - args[ARG_height].u_int, - args[ARG_bitmap_data].u_obj, - args[ARG_dest_is_swapped].u_bool - ); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(rm690b0_rm690b0_blit_buffer_obj, 1, rm690b0_rm690b0_blit_buffer); - -//| def swap_buffers(self, copy: bool = True) -> None: -//| """Swap the front and back framebuffers and display the result -//| -//| If double-buffering is enabled (two framebuffers allocated), this atomically -//| swaps the buffer pointers and then flushes the new front buffer to the display. -//| This provides tear-free rendering for animations and graphics. -//| -//| If double-buffering is not enabled (single framebuffer), this simply flushes -//| the current framebuffer to the display, equivalent to a refresh operation. -//| -//| :param bool copy: If True (default), copies front buffer to back buffer after swap. -//| This allows incremental drawing on top of existing content. -//| If False, back buffer is left unchanged (better performance for -//| full redraws like animations that clear the screen each frame). -//| """ -//| ... -//| -static mp_obj_t rm690b0_rm690b0_swap_buffers(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_copy }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_copy, MP_ARG_BOOL, {.u_bool = true} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - bool copy = args[ARG_copy].u_bool; - common_hal_rm690b0_rm690b0_swap_buffers(self, copy); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(rm690b0_rm690b0_swap_buffers_obj, 1, rm690b0_rm690b0_swap_buffers); - -//| rotation: int -//| """The rotation of the display as an int in degrees.""" -static mp_obj_t rm690b0_rm690b0_get_rotation_prop(mp_obj_t self_in) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_rm690b0_rm690b0_get_rotation(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_rotation_prop_obj, rm690b0_rm690b0_get_rotation_prop); - -static mp_obj_t rm690b0_rm690b0_set_rotation_prop(mp_obj_t self_in, mp_obj_t rotation_obj) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_int_t rotation = mp_obj_get_int(rotation_obj); - common_hal_rm690b0_rm690b0_set_rotation(self, rotation); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_set_rotation_prop_obj, rm690b0_rm690b0_set_rotation_prop); - -MP_PROPERTY_GETSET(rm690b0_rm690b0_rotation_obj, - (mp_obj_t)&rm690b0_rm690b0_get_rotation_prop_obj, - (mp_obj_t)&rm690b0_rm690b0_set_rotation_prop_obj); - - - - -//| brightness: float -//| """The brightness of the display, from 0.0 to 1.0""" -static mp_obj_t rm690b0_rm690b0_get_brightness_prop(mp_obj_t self_in) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_float(common_hal_rm690b0_rm690b0_get_brightness(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_brightness_prop_obj, rm690b0_rm690b0_get_brightness_prop); - -static mp_obj_t rm690b0_rm690b0_set_brightness_prop(mp_obj_t self_in, mp_obj_t brightness_obj) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_float_t brightness = mp_obj_get_float(brightness_obj); - common_hal_rm690b0_rm690b0_set_brightness(self, brightness); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(rm690b0_rm690b0_set_brightness_prop_obj, rm690b0_rm690b0_set_brightness_prop); - -MP_PROPERTY_GETSET(rm690b0_rm690b0_brightness_obj, - (mp_obj_t)&rm690b0_rm690b0_get_brightness_prop_obj, - (mp_obj_t)&rm690b0_rm690b0_set_brightness_prop_obj); - -//| width: int -//| """Gets the width of the display""" -static mp_obj_t rm690b0_rm690b0_get_width(mp_obj_t self_in) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(self->width); -} -MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_width_obj, rm690b0_rm690b0_get_width); - -MP_PROPERTY_GETTER(rm690b0_rm690b0_width_obj, - (mp_obj_t)&rm690b0_rm690b0_get_width_obj); - -//| height: int -//| """Gets the height of the display""" -static mp_obj_t rm690b0_rm690b0_get_height(mp_obj_t self_in) { - rm690b0_rm690b0_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(self->height); -} -MP_DEFINE_CONST_FUN_OBJ_1(rm690b0_rm690b0_get_height_obj, rm690b0_rm690b0_get_height); - -MP_PROPERTY_GETTER(rm690b0_rm690b0_height_obj, - (mp_obj_t)&rm690b0_rm690b0_get_height_obj); - -static const mp_rom_map_elem_t rm690b0_rm690b0_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rm690b0_rm690b0_deinit_obj) }, - - { MP_ROM_QSTR(MP_QSTR_init_display), MP_ROM_PTR(&rm690b0_rm690b0_init_display_obj) }, - { MP_ROM_QSTR(MP_QSTR_fill_color), MP_ROM_PTR(&rm690b0_rm690b0_fill_color_obj) }, - - { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&rm690b0_rm690b0_brightness_obj) }, - { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&rm690b0_rm690b0_pixel_obj) }, - { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&rm690b0_rm690b0_fill_rect_obj) }, - { MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&rm690b0_rm690b0_hline_obj) }, - { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&rm690b0_rm690b0_vline_obj) }, - { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&rm690b0_rm690b0_line_obj) }, - { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&rm690b0_rm690b0_rect_obj) }, - { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&rm690b0_rm690b0_circle_obj) }, - { MP_ROM_QSTR(MP_QSTR_fill_circle), MP_ROM_PTR(&rm690b0_rm690b0_fill_circle_obj) }, - - // Built-in text and font API - { MP_ROM_QSTR(MP_QSTR_set_font), MP_ROM_PTR(&rm690b0_rm690b0_set_font_obj) }, - { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&rm690b0_rm690b0_text_obj) }, - - { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&rm690b0_rm690b0_rotation_obj) }, - { MP_ROM_QSTR(MP_QSTR_blit_buffer), MP_ROM_PTR(&rm690b0_rm690b0_blit_buffer_obj) }, - { MP_ROM_QSTR(MP_QSTR_blit_bmp), MP_ROM_PTR(&rm690b0_rm690b0_blit_bmp_obj) }, - { MP_ROM_QSTR(MP_QSTR_blit_jpeg), MP_ROM_PTR(&rm690b0_rm690b0_blit_jpeg_obj) }, - { MP_ROM_QSTR(MP_QSTR_convert_bmp), MP_ROM_PTR(&rm690b0_rm690b0_convert_bmp_obj) }, - { MP_ROM_QSTR(MP_QSTR_swap_buffers), MP_ROM_PTR(&rm690b0_rm690b0_swap_buffers_obj) }, - - { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&rm690b0_rm690b0_width_obj) }, - { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&rm690b0_rm690b0_height_obj) }, -}; -static MP_DEFINE_CONST_DICT(rm690b0_rm690b0_locals_dict, rm690b0_rm690b0_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - rm690b0_rm690b0_type, - MP_QSTR_RM690B0, - MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, - make_new, rm690b0_rm690b0_make_new, - locals_dict, &rm690b0_rm690b0_locals_dict - ); diff --git a/shared-bindings/rm690b0/RM690B0.h b/shared-bindings/rm690b0/RM690B0.h deleted file mode 100644 index 6af661b085fae..0000000000000 --- a/shared-bindings/rm690b0/RM690B0.h +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include "py/obj.h" - -// Forward declaration for the rm690b0 object type -typedef struct { - mp_obj_base_t base; - bool initialized; - mp_int_t width; - mp_int_t height; - mp_int_t rotation; - uint8_t brightness_raw; - mp_int_t font_id; // Current font ID for text rendering - // Port-specific implementation data will be added by common-hal - void *impl; -} rm690b0_rm690b0_obj_t; - -extern const mp_obj_type_t rm690b0_rm690b0_type; - -// Common HAL function declarations -void common_hal_rm690b0_rm690b0_construct(rm690b0_rm690b0_obj_t *self); -void common_hal_rm690b0_rm690b0_deinit(rm690b0_rm690b0_obj_t *self); -void common_hal_rm690b0_rm690b0_init_display(rm690b0_rm690b0_obj_t *self); -void common_hal_rm690b0_rm690b0_fill_color(rm690b0_rm690b0_obj_t *self, uint16_t color); -void common_hal_rm690b0_rm690b0_set_brightness(rm690b0_rm690b0_obj_t *self, mp_float_t brightness); -mp_float_t common_hal_rm690b0_rm690b0_get_brightness(const rm690b0_rm690b0_obj_t *self); -void common_hal_rm690b0_rm690b0_pixel(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t color); -void common_hal_rm690b0_rm690b0_fill_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); -void common_hal_rm690b0_rm690b0_hline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t color); -void common_hal_rm690b0_rm690b0_vline(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t height, mp_int_t color); -void common_hal_rm690b0_rm690b0_line(rm690b0_rm690b0_obj_t *self, mp_int_t x0, mp_int_t y0, mp_int_t x1, mp_int_t y1, mp_int_t color); -void common_hal_rm690b0_rm690b0_rect(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_int_t color); -void common_hal_rm690b0_rm690b0_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); -void common_hal_rm690b0_rm690b0_fill_circle(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t radius, mp_int_t color); -void common_hal_rm690b0_rm690b0_set_rotation(rm690b0_rm690b0_obj_t *self, mp_int_t degrees); -mp_int_t common_hal_rm690b0_rm690b0_get_rotation(const rm690b0_rm690b0_obj_t *self); -void common_hal_rm690b0_rm690b0_blit_buffer(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_int_t width, mp_int_t height, mp_obj_t bitmap_data, bool dest_is_swapped); -void common_hal_rm690b0_rm690b0_blit_bmp(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t bmp_data); -void common_hal_rm690b0_rm690b0_blit_jpeg(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, mp_obj_t jpeg_data); -void common_hal_rm690b0_rm690b0_convert_bmp(rm690b0_rm690b0_obj_t *self, mp_obj_t src_data, mp_obj_t dest_bitmap); -void common_hal_rm690b0_rm690b0_swap_buffers(rm690b0_rm690b0_obj_t *self, bool copy); -void common_hal_rm690b0_rm690b0_deinit_all(void); -void common_hal_rm690b0_rm690b0_set_font(rm690b0_rm690b0_obj_t *self, mp_int_t font_id); -void common_hal_rm690b0_rm690b0_text(rm690b0_rm690b0_obj_t *self, mp_int_t x, mp_int_t y, - const char *text, size_t text_len, uint16_t fg, bool has_bg, uint16_t bg); diff --git a/shared-bindings/rm690b0/__init__.c b/shared-bindings/rm690b0/__init__.c deleted file mode 100644 index 0fa627804b848..0000000000000 --- a/shared-bindings/rm690b0/__init__.c +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include "py/obj.h" -#include "py/runtime.h" - -#include "shared-bindings/rm690b0/RM690B0.h" - -//| """RM690B0 AMOLED display driver -//| -//| This module provides direct control of the RM690B0 AMOLED display controller. -//| -//| **Font Constants** -//| -//| Built-in font size constants for use with ``set_font()``:: -//| -//| rm690b0.FONT_8x8 # 8×8 monospace (smallest, debug/logs) -//| rm690b0.FONT_16x16 # 16×16 monospace (standard UI) -//| rm690b0.FONT_16x24 # 16×24 monospace (readable UI) -//| rm690b0.FONT_24x24 # 24×24 monospace (headers) -//| rm690b0.FONT_24x32 # 24×32 monospace (large headers) -//| rm690b0.FONT_32x32 # 32×32 monospace (big displays) -//| rm690b0.FONT_32x48 # 32×48 monospace (huge displays) -//| -//| Example:: -//| -//| import rm690b0 -//| display = rm690b0.RM690B0() -//| display.init_display() -//| -//| # Use font constants instead of magic numbers -//| display.set_font(rm690b0.FONT_8x8) -//| display.text(10, 10, "Debug info", rm690b0.WHITE) -//| -//| display.set_font(rm690b0.FONT_24x24) -//| display.text(10, 50, "Header", rm690b0.CYAN) -//| -//| **Color Constants** -//| -//| RGB565 color constants are also provided (WHITE, BLACK, RED, GREEN, BLUE, etc.) -//| """ -//| - -static const mp_rom_map_elem_t rm690b0_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rm690b0) }, - { MP_ROM_QSTR(MP_QSTR_RM690B0), MP_ROM_PTR(&rm690b0_rm690b0_type) }, - - // RGB565 convenience constants - { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(0xFFFF) }, - { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(0x0000) }, - { MP_ROM_QSTR(MP_QSTR_DARK_GRAY), MP_ROM_INT(0x2104) }, - { MP_ROM_QSTR(MP_QSTR_GRAY), MP_ROM_INT(0x8410) }, - { MP_ROM_QSTR(MP_QSTR_LIGHT_GRAY), MP_ROM_INT(0xC618) }, - { MP_ROM_QSTR(MP_QSTR_BROWN), MP_ROM_INT(0x59E4) }, - { MP_ROM_QSTR(MP_QSTR_DARK_BROWN), MP_ROM_INT(0x30A0) }, - { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(0xFFE0) }, - { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(0x001F) }, - { MP_ROM_QSTR(MP_QSTR_ROYAL_BLUE), MP_ROM_INT(0x435C) }, - { MP_ROM_QSTR(MP_QSTR_SKY_BLUE), MP_ROM_INT(0x867D) }, - { MP_ROM_QSTR(MP_QSTR_DARK_BLUE), MP_ROM_INT(0x0010) }, - { MP_ROM_QSTR(MP_QSTR_LIGHT_BLUE), MP_ROM_INT(0x261F) }, - { MP_ROM_QSTR(MP_QSTR_LIGHT_VIOLET), MP_ROM_INT(0x8BFD) }, - { MP_ROM_QSTR(MP_QSTR_VIOLET), MP_ROM_INT(0x49F1) }, - { MP_ROM_QSTR(MP_QSTR_PURPLE), MP_ROM_INT(0x8010) }, - { MP_ROM_QSTR(MP_QSTR_PINK), MP_ROM_INT(0xF81F) }, - { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(0xBABA) }, - { MP_ROM_QSTR(MP_QSTR_OLIVE), MP_ROM_INT(0x8400) }, - { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(0x0400) }, - { MP_ROM_QSTR(MP_QSTR_DARK_GREEN), MP_ROM_INT(0x0200) }, - { MP_ROM_QSTR(MP_QSTR_LIME), MP_ROM_INT(0xAFE5) }, - { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(0x07FF) }, - { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(0xF800) }, - { MP_ROM_QSTR(MP_QSTR_ORANGE), MP_ROM_INT(0xFC60) }, - - // Font size constants - { MP_ROM_QSTR(MP_QSTR_FONT_8x8), MP_ROM_INT(0) }, - { MP_ROM_QSTR(MP_QSTR_FONT_16x16), MP_ROM_INT(1) }, - { MP_ROM_QSTR(MP_QSTR_FONT_16x24), MP_ROM_INT(2) }, - { MP_ROM_QSTR(MP_QSTR_FONT_24x24), MP_ROM_INT(3) }, - { MP_ROM_QSTR(MP_QSTR_FONT_24x32), MP_ROM_INT(4) }, - { MP_ROM_QSTR(MP_QSTR_FONT_32x32), MP_ROM_INT(5) }, - { MP_ROM_QSTR(MP_QSTR_FONT_32x48), MP_ROM_INT(6) }, -}; - -static MP_DEFINE_CONST_DICT(rm690b0_module_globals, rm690b0_module_globals_table); - -const mp_obj_module_t rm690b0_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&rm690b0_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR_rm690b0, rm690b0_module); From 1a438bddb67be31f239fea4b6da6876e6b563a89 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 6 Feb 2026 17:00:53 +0100 Subject: [PATCH 14/38] Phase 5: optimize qspibus displayio transfer path --- ports/espressif/common-hal/qspibus/QSPIBus.c | 148 +++++++++++++++++-- ports/espressif/common-hal/qspibus/QSPIBus.h | 6 + shared-module/busdisplay/BusDisplay.c | 24 +++ 3 files changed, 167 insertions(+), 11 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index a36f4cee6da7d..df99a6010f3a0 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -11,7 +11,9 @@ #include "py/runtime.h" #include "driver/gpio.h" +#include "esp_heap_caps.h" #include "soc/soc_caps.h" +#include #define QSPI_OPCODE_WRITE_CMD (0x02U) #define QSPI_OPCODE_WRITE_COLOR (0x32U) @@ -19,6 +21,9 @@ #define LCD_CMD_RAMWRC (0x3CU) #define LCD_CMD_DISPOFF (0x28U) #define LCD_CMD_SLPIN (0x10U) +#define QSPI_DMA_BUFFER_COUNT (2U) +#define QSPI_DMA_BUFFER_SIZE (16U * 1024U) +#define QSPI_COLOR_TIMEOUT_MS (1000U) #if defined(CIRCUITPY_LCD_POWER) #define CIRCUITPY_QSPIBUS_PANEL_POWER_PIN CIRCUITPY_LCD_POWER #elif defined(CIRCUITPY_RM690B0_POWER) @@ -33,6 +38,71 @@ #endif #endif +static void qspibus_release_dma_buffers(qspibus_qspibus_obj_t *self) { + for (size_t i = 0; i < QSPI_DMA_BUFFER_COUNT; i++) { + if (self->dma_buffer[i] != NULL) { + heap_caps_free(self->dma_buffer[i]); + self->dma_buffer[i] = NULL; + } + } + self->dma_buffer_size = 0; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->transfer_in_progress = false; +} + +static bool qspibus_allocate_dma_buffers(qspibus_qspibus_obj_t *self) { + const size_t candidates[] = { + QSPI_DMA_BUFFER_SIZE, + QSPI_DMA_BUFFER_SIZE / 2, + QSPI_DMA_BUFFER_SIZE / 4, + }; + + for (size_t c = 0; c < MP_ARRAY_SIZE(candidates); c++) { + size_t size = candidates[c]; + bool ok = true; + for (size_t i = 0; i < QSPI_DMA_BUFFER_COUNT; i++) { + self->dma_buffer[i] = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + if (self->dma_buffer[i] == NULL) { + ok = false; + break; + } + } + if (ok) { + self->dma_buffer_size = size; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->transfer_in_progress = false; + return true; + } + qspibus_release_dma_buffers(self); + } + return false; +} + +static bool qspibus_wait_one_transfer_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { + if (self->inflight_transfers == 0) { + self->transfer_in_progress = false; + return true; + } + + if (xSemaphoreTake(self->transfer_done_sem, timeout) != pdTRUE) { + return false; + } + self->inflight_transfers--; + self->transfer_in_progress = (self->inflight_transfers > 0); + return true; +} + +static bool qspibus_wait_all_transfers_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { + while (self->inflight_transfers > 0) { + if (!qspibus_wait_one_transfer_done(self, timeout)) { + return false; + } + } + return true; +} + static void qspibus_send_command_bytes( qspibus_qspibus_obj_t *self, uint8_t command, @@ -42,6 +112,11 @@ static void qspibus_send_command_bytes( if (!self->bus_initialized) { mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); } + if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { + if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI command timeout")); + } + } uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); @@ -60,17 +135,44 @@ static void qspibus_send_color_bytes( mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); } - uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)command << 8); - // Drop stale completion events if any. - while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + if (len == 0) { + qspibus_send_command_bytes(self, command, NULL, 0); + return; } - - esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, data, len); - if (err != ESP_OK) { - mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send color failed: %d"), err); + if (data == NULL || self->dma_buffer_size == 0) { + mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI DMA buffers unavailable")); } - if (xSemaphoreTake(self->transfer_done_sem, pdMS_TO_TICKS(1000)) != pdTRUE) { - mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); + + const uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)command << 8); + const uint8_t *cursor = data; + size_t remaining = len; + + while (remaining > 0) { + if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { + if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); + } + } + + size_t chunk = remaining; + if (chunk > self->dma_buffer_size) { + chunk = self->dma_buffer_size; + } + + uint8_t *buffer = self->dma_buffer[self->active_buffer]; + memcpy(buffer, cursor, chunk); + + esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, buffer, chunk); + if (err != ESP_OK) { + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send color failed: %d"), err); + } + + self->inflight_transfers++; + self->transfer_in_progress = true; + self->active_buffer = (self->active_buffer + 1) % QSPI_DMA_BUFFER_COUNT; + + cursor += chunk; + remaining -= chunk; } } @@ -83,6 +185,11 @@ static void qspibus_panel_sleep_best_effort(qspibus_qspibus_obj_t *self) { return; } + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; + } + // If a command is buffered, flush it first so the panel state machine // doesn't get a truncated transaction before sleep. if (self->has_pending_command) { @@ -140,13 +247,25 @@ void common_hal_qspibus_qspibus_construct( self->in_transaction = false; self->has_pending_command = false; self->pending_command = 0; + self->transfer_in_progress = false; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->dma_buffer_size = 0; + self->dma_buffer[0] = NULL; + self->dma_buffer[1] = NULL; self->transfer_done_sem = NULL; - self->transfer_done_sem = xSemaphoreCreateBinary(); + self->transfer_done_sem = xSemaphoreCreateCounting(QSPI_DMA_BUFFER_COUNT, 0); if (self->transfer_done_sem == NULL) { mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to create semaphore")); } + if (!qspibus_allocate_dma_buffers(self)) { + vSemaphoreDelete(self->transfer_done_sem); + self->transfer_done_sem = NULL; + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to allocate DMA buffers")); + } + const spi_bus_config_t bus_config = { .sclk_io_num = self->clock_pin, .data0_io_num = self->data0_pin, @@ -159,6 +278,7 @@ void common_hal_qspibus_qspibus_construct( esp_err_t err = spi_bus_initialize(self->host_id, &bus_config, SPI_DMA_CH_AUTO); if (err != ESP_OK) { + qspibus_release_dma_buffers(self); vSemaphoreDelete(self->transfer_done_sem); self->transfer_done_sem = NULL; mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SPI bus init failed: %d"), err); @@ -169,7 +289,7 @@ void common_hal_qspibus_qspibus_construct( .dc_gpio_num = -1, .spi_mode = 0, .pclk_hz = self->frequency, - .trans_queue_depth = 1, + .trans_queue_depth = QSPI_DMA_BUFFER_COUNT, .on_color_trans_done = qspibus_on_color_trans_done, .user_ctx = self, .lcd_cmd_bits = 32, @@ -182,6 +302,7 @@ void common_hal_qspibus_qspibus_construct( err = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)self->host_id, &io_config, &self->io_handle); if (err != ESP_OK) { spi_bus_free(self->host_id); + qspibus_release_dma_buffers(self); vSemaphoreDelete(self->transfer_done_sem); self->transfer_done_sem = NULL; mp_raise_OSError_msg_varg(MP_ERROR_TEXT("Panel IO init failed: %d"), err); @@ -221,6 +342,7 @@ void common_hal_qspibus_qspibus_construct( void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { if (!self->bus_initialized) { + qspibus_release_dma_buffers(self); return; } @@ -239,6 +361,8 @@ void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { self->transfer_done_sem = NULL; } + qspibus_release_dma_buffers(self); + reset_pin_number(self->clock_pin); reset_pin_number(self->data0_pin); reset_pin_number(self->data1_pin); @@ -256,6 +380,8 @@ void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { self->in_transaction = false; self->has_pending_command = false; self->pending_command = 0; + self->transfer_in_progress = false; + self->inflight_transfers = 0; } bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self) { diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.h b/ports/espressif/common-hal/qspibus/QSPIBus.h index ddca0809a781f..173c2be1eddd5 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.h +++ b/ports/espressif/common-hal/qspibus/QSPIBus.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -38,6 +39,11 @@ typedef struct { bool in_transaction; bool has_pending_command; uint8_t pending_command; + bool transfer_in_progress; + uint8_t active_buffer; + uint8_t inflight_transfers; + size_t dma_buffer_size; + uint8_t *dma_buffer[2]; // Signaled from ISR when panel IO transfer completes. SemaphoreHandle_t transfer_done_sem; diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index 39bceb7eba494..5fdd2436f2da3 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -258,6 +258,30 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are } #if CIRCUITPY_QSPIBUS + // QSPI panels benefit from larger sub-rectangle buffers because each chunk + // has non-trivial command/window overhead. Keep this path qspibus-specific + // to avoid increasing stack usage on other display buses. + if (mp_obj_is_type(self->bus.bus, &qspibus_qspibus_type) && + self->core.colorspace.depth == 16 && + !self->bus.data_as_commands && + !self->bus.SH1107_addressing && + buffer_size < 2048) { + buffer_size = 2048; // 8KB uint32_t buffer + rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width(&clipped); + if (rows_per_buffer == 0) { + rows_per_buffer = 1; + } + subrectangles = displayio_area_height(&clipped) / rows_per_buffer; + if (displayio_area_height(&clipped) % rows_per_buffer != 0) { + subrectangles++; + } + pixels_per_buffer = rows_per_buffer * displayio_area_width(&clipped); + buffer_size = pixels_per_buffer / pixels_per_word; + if (pixels_per_buffer % pixels_per_word) { + buffer_size += 1; + } + } + // RM690B0 over qspibus is unstable with single-row bursts. Keep chunks at // two rows minimum when possible. if (mp_obj_is_type(self->bus.bus, &qspibus_qspibus_type) && From d5774f655c99dfdb6ca7a515d511d8ec41d810c6 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Fri, 6 Feb 2026 17:12:19 +0100 Subject: [PATCH 15/38] Phase 6: add final v2.0 changelog docs --- CHANGES.md | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.rst | 6 + 2 files changed, 343 insertions(+) create mode 100644 CHANGES.md diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000000000..6645887435c93 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,337 @@ +# CircuitPython RM690B0 Driver - Changes for v2.0 + +## Version + +- Release: `2.0.0` +- Release date: `2026-02-06` +- Type: `BREAKING CHANGES` +- Board scope: `waveshare_esp32_s3_amoled_241` +- Last updated: `2026-02-06` + +## 1. Executive Summary + +Version `2.0.0` replaces the standalone `rm690b0` module with the standard CircuitPython display stack: + +- `qspibus` for QSPI panel transport +- `displayio` and `busdisplay` for scene and refresh lifecycle +- RM690B0 panel init sequence integrated with `BusDisplay` +- `sdioio` instead of custom `sdcardio` implementation + +This change aligns the board with CircuitPython upstream architecture expectations and makes display code compatible with standard ecosystem libraries. + +Important: +- Existing applications that use `import rm690b0` must migrate. +- Existing applications that use legacy `sdcardio` APIs on this board must migrate to `sdioio`. + +Quick migration example: + +```python +# OLD (v1.x) +import rm690b0 +rm690b0.init_display() +rm690b0.fill_color(rm690b0.RED) +rm690b0.swap_buffers() + +# NEW (v2.0) +import board +import displayio +import qspibus +from adafruit_rm690b0 import RM690B0 + +displayio.release_displays() +bus = qspibus.QSPIBus( + clock=board.LCD_CLK, + data0=board.LCD_D0, + data1=board.LCD_D1, + data2=board.LCD_D2, + data3=board.LCD_D3, + cs=board.LCD_CS, + reset=board.LCD_RESET, + frequency=40_000_000, +) +panel = RM690B0(bus, width=600, height=450) +display = displayio.Display(panel, width=600, height=450) +``` + +## 2. Breaking Changes + +### 2.1 Standalone `rm690b0` module removed + +The old standalone API was removed from firmware build and bindings. + +Removed behavior: +- `import rm690b0` +- imperative drawing calls from `rm690b0.*` +- standalone framebuffer and swap model + +Required replacement: +- `displayio` scene graph (`Group`, `TileGrid`, `Bitmap`, `Palette`) +- `qspibus.QSPIBus` transport +- RM690B0 panel class using `BusDisplay` + +### 2.2 Custom `sdcardio` path removed + +Legacy board-specific SD path was removed. + +Required replacement: +- `sdioio.SDCard(...)` +- `storage.VfsFat` + `storage.mount` + +Example: + +```python +import board +import sdioio + +sd = sdioio.SDCard( + clock=board.SD_CLK, + command=board.SD_MOSI, + data=[board.SD_MISO], + frequency=20_000_000, +) +``` + +### 2.3 API comparison + +| Legacy v1.x API | v2.0 replacement | +|---|---| +| `rm690b0.init_display()` | `qspibus.QSPIBus(...)` + panel init + `displayio.Display(...)` | +| `rm690b0.fill_color(color)` | Full-screen `Bitmap` + single-color `Palette` | +| `rm690b0.fill_rect(...)` | Rect bitmap/tile in `displayio.Group` | +| `rm690b0.line(...)` | `vectorio` or bitmap draw helper | +| `rm690b0.circle(...)` | `vectorio.Circle` | +| `rm690b0.text(...)` | `adafruit_display_text.label` or `terminalio` | +| `rm690b0.blit_bmp(...)` | `adafruit_imageload` + displayio | +| `rm690b0.blit_jpeg(...)` | `jpegio` path (future integration for accelerated flow) | +| `rm690b0.swap_buffers()` | `display.refresh()` or auto-refresh | +| custom `sdcardio` usage | `sdioio.SDCard(...)` | + +## 3. New Features + +### 3.1 `qspibus` module + +New module added as QSPI display transport analog to `fourwire`. + +Main points: +- explicit command/data path used by `busdisplay` +- stable pin ownership lifecycle for display stack +- context manager support +- deinit support with panel sleep handling for safer reruns + +Location: +- `shared-bindings/qspibus/` +- `shared-module/qspibus/` +- `ports/espressif/common-hal/qspibus/` + +### 3.2 RM690B0 displayio panel integration + +RM690B0 panel is now initialized and refreshed through `BusDisplay`. + +Main points: +- panel init sequence migrated to displayio flow +- geometry offsets supported (`colstart`, `rowstart`) +- tested color rendering path on real hardware +- integrated cleanup sequence for reruns + +### 3.3 Standard displayio compatibility + +Applications can now use regular displayio ecosystem primitives and libraries. + +Examples: +- `displayio.Bitmap`, `displayio.Palette`, `displayio.Group` +- `adafruit_display_text` +- `vectorio` +- `adafruit_imageload` + +### 3.4 Backward-compatible board aliases + +Canonical aliases are now generic `LCD_*` names. Compatibility aliases are still exposed for existing scripts. + +Examples: +- canonical: `LCD_CLK`, `LCD_D0`, `LCD_D1`, `LCD_D2`, `LCD_D3`, `LCD_CS`, `LCD_RESET` +- compatibility: `QSPI_CLK`, `QSPI_D0`, `QSPI_D1`, `QSPI_D2`, `QSPI_D3`, `QSPI_CS`, `AMOLED_RESET` + +## 4. Removed Code + +### 4.1 Core components removed + +| Component | Approx lines removed | Reason | +|---|---:|---| +| `shared-bindings/rm690b0/*` | 656 | Standalone module removed | +| `ports/espressif/common-hal/rm690b0/RM690B0.c` and `.h` | 3788 | Replaced by displayio panel path | +| `ports/espressif/common-hal/rm690b0/fonts/*.h` (7 files) | 5449 | Built-in standalone font pack removed | +| custom board `sdcardio` path | ~501 | Replaced by standard `sdioio` | + +Totals: +- conservative template baseline previously tracked: `~4963` lines +- full audit (including font headers): `9893` lines removed + +Audit reference: +- `../ws-esp32-s3-amoled-241/docs/CODE_REMOVAL_AUDIT.md` + +## 5. Retained Code + +The following components were intentionally kept: + +| Component | Approx lines | Location | Purpose | +|---|---:|---|---| +| `esp_lcd_rm690b0.c` | 342 | `ports/espressif/common-hal/rm690b0/` | Vendor RM690B0 init commands | +| `esp_lcd_rm690b0.h` | 109 | `ports/espressif/common-hal/rm690b0/` | Panel definitions | +| `esp_jpeg.c` | 295 | `ports/espressif/common-hal/rm690b0/esp_jpeg/` | JPEG decode path for future integration | +| `esp_jpeg.h` | 72 | `ports/espressif/common-hal/rm690b0/esp_jpeg/` | JPEG API definitions | + +Rationale: +- Vendor init command source remains required for panel bring-up. +- JPEG path is retained for planned `jpegio` integration work. + +## 6. Configuration Changes + +### 6.1 Board config (`mpconfigboard.mk`) + +Active settings in `ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk`: + +```makefile +CIRCUITPY_QSPIBUS = 1 +CIRCUITPY_SDIOIO = 1 + +# Disabled legacy path +CIRCUITPY_SDCARDIO = 0 +CIRCUITPY_SDCARDIO_ESPRESSIF = 0 +``` + +### 6.2 Build graph cleanup + +Build graph references for standalone `rm690b0` module were removed from make config where applicable. + +Impact: +- standalone module symbols are no longer present in the built firmware +- display pipeline now resolves through `qspibus` + `displayio` + +### 6.3 Pin naming updates + +Board pin API normalized to generic LCD naming while preserving compatibility aliases. + +Examples: +- old naming style: `RM690B0_QSPI_*` +- current naming style: `LCD_*` + +## 7. Architecture Changes + +### 7.1 Old architecture + +```text +Application + -> rm690b0 standalone module + -> board-specific draw and swap path + -> RM690B0 hardware +``` + +### 7.2 New architecture + +```text +Application + -> displayio scene graph + -> BusDisplay RM690B0 panel driver + -> qspibus transport + -> RM690B0 hardware +``` + +### 7.3 Benefits + +- standardized API model for CircuitPython users +- better upstream maintainability +- easier reuse of ecosystem display libraries +- clear separation of concerns between scene, panel, and transport +- future optimization path without changing user-level API + +## 8. Performance Impact + +### 8.1 Summary + +`v2.0` prioritizes correctness and upstream-compatible architecture. Full-screen refresh is slower than historical standalone path, but integration stability and API compatibility are achieved. + +### 8.2 Measured metrics + +Measured on Waveshare ESP32-S3 AMOLED 2.41 with current test scripts: + +| Operation | Legacy v1.x (historical) | v2.0 baseline | v2.0 optimized in Phase 5 | Notes | +|---|---:|---:|---:|---| +| Full screen fill (600x450) | ~25 ms (historical standalone estimate) | 360.499 ms | 341.250 ms | still above `<100 ms` target | +| Partial update (100x100) | n/a | 62.584 ms | 52.916 ms | improved after qspibus transfer updates | +| Multi-element scene | n/a | 59.700 ms | 51.500 ms | improved after batching/tuning | + +Additional Phase 1 SD metrics: +- write throughput: around `180 KB/s` +- read throughput (`readinto`): up to `~1.13 MB/s` at 40 MHz + +### 8.3 Optimization plan for v2.1 + +Planned focus areas: +- deeper refresh batching and dirty-region behavior tuning +- panel/bus refresh path profiling under scene-heavy workloads +- optional pipeline improvements for high-frequency full-screen refresh use cases +- incremental validation against stability constraints (no reboot/deinit regressions) + +## 9. Migration Guide + +Migration details are documented in: +- `../ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md` + +What it includes: +- old-to-new API mapping +- init sequence migration examples +- common pitfalls and compatibility notes +- cleanup best practices for reliable rerun behavior + +## 10. Testing + +Hardware validation used the phase test suite in: +- `../ws-esp32-s3-amoled-241/examples/tests/` + +Core tests: +- `test_phase1_sdioio.py` +- `test_phase2_qspibus.py` +- `test_phase3_displayio.py` +- `test_phase4_integration.py` + +Optional benchmark: +- `benchmark_phase5_displayio.py` + +Observed status in this cycle: +- Phase 1: pass +- Phase 2: pass +- Phase 3: pass (display colors and rectangle visible) +- Phase 4: pass (full stack integration) + +Testing guide: +- `../ws-esp32-s3-amoled-241/docs/TESTING_GUIDE.md` + +## 11. Known Issues + +1. Full-screen displayio refresh is slower than standalone historical path. +2. JPEG acceleration path is retained but not fully integrated with a finalized `jpegio` workflow. +3. Legacy built-in font bundle from standalone module is removed; applications should use `terminalio` or external font assets. +4. For robust reruns, cleanup order matters (`screen black` -> `displayio.release_displays()` -> `qspibus.deinit()`). + +## 12. Credits + +- Original board and RM690B0 integration work: project author and contributors +- Refactor toward upstream displayio architecture: project maintainer workstream +- CircuitPython architecture feedback and direction: `@tannewt` +- Hardware validation and regression checks: Waveshare ESP32-S3 AMOLED 2.41 test runs + +## References + +- `../ws-esp32-s3-amoled-241/docs/IMPLEMENTATION_PLAN.md` +- `../ws-esp32-s3-amoled-241/docs/IMPLEMENTATION_PLAN_SUMMARY.md` +- `../ws-esp32-s3-amoled-241/docs/TECHNICAL_NOTES.md` +- `../ws-esp32-s3-amoled-241/docs/CODE_REMOVAL_AUDIT.md` +- `../ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md` +- `../ws-esp32-s3-amoled-241/docs/TESTING_GUIDE.md` + +## Support + +For issue reporting and debugging context, include: +- board model and firmware build date +- full serial log from test run +- phase script name and whether display output matched expected behavior diff --git a/README.rst b/README.rst index d7e549bd817d8..faef0197aa093 100644 --- a/README.rst +++ b/README.rst @@ -48,6 +48,12 @@ New API (v2.0+):: For migration details, see: ``/home/pps/Downloads/__ai__/repos/ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md``. +For v2.0 release notes, see: +``CHANGES.md``. + +For hardware test procedure (Phase 1-4), see: +``/home/pps/Downloads/__ai__/repos/ws-esp32-s3-amoled-241/docs/TESTING_GUIDE.md``. + **CircuitPython** is a *beginner friendly*, open source version of Python for tiny, inexpensive computers called microcontrollers. Microcontrollers are the brains of many electronics including a wide variety of development boards used to build hobby projects and prototypes. CircuitPython in From 0650ab1ad1fad5bbee904a9f81f226dc23d271b8 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 16:54:08 +0100 Subject: [PATCH 16/38] Update: QSPBus API --- ports/espressif/common-hal/qspibus/QSPIBus.c | 101 ++++++++++++++++++- ports/espressif/common-hal/qspibus/QSPIBus.h | 1 + shared-bindings/qspibus/QSPIBus.c | 93 ++++++++++++++++- shared-bindings/qspibus/QSPIBus.h | 13 +++ 4 files changed, 203 insertions(+), 5 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index df99a6010f3a0..4485b648c6545 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -143,7 +143,8 @@ static void qspibus_send_color_bytes( mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI DMA buffers unavailable")); } - const uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)command << 8); + // RAMWR must transition to RAMWRC for continued payload chunks. + uint8_t chunk_command = command; const uint8_t *cursor = data; size_t remaining = len; @@ -162,6 +163,7 @@ static void qspibus_send_color_bytes( uint8_t *buffer = self->dma_buffer[self->active_buffer]; memcpy(buffer, cursor, chunk); + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)chunk_command << 8); esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, buffer, chunk); if (err != ESP_OK) { mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send color failed: %d"), err); @@ -171,9 +173,19 @@ static void qspibus_send_color_bytes( self->transfer_in_progress = true; self->active_buffer = (self->active_buffer + 1) % QSPI_DMA_BUFFER_COUNT; + if (chunk_command == LCD_CMD_RAMWR) { + chunk_command = LCD_CMD_RAMWRC; + } + cursor += chunk; remaining -= chunk; } + + // Keep Python/API semantics predictable: color transfer call returns only + // after queued DMA chunks have completed. + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); + } } static bool qspibus_is_color_payload_command(uint8_t command) { @@ -229,6 +241,7 @@ void common_hal_qspibus_qspibus_construct( const mcu_pin_obj_t *data2, const mcu_pin_obj_t *data3, const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *dcx, const mcu_pin_obj_t *reset, uint32_t frequency) { @@ -240,6 +253,7 @@ void common_hal_qspibus_qspibus_construct( self->data2_pin = data2->number; self->data3_pin = data3->number; self->cs_pin = cs->number; + self->dcx_pin = (dcx != NULL) ? dcx->number : -1; self->reset_pin = (reset != NULL) ? reset->number : -1; self->power_pin = -1; self->frequency = frequency; @@ -314,6 +328,11 @@ void common_hal_qspibus_qspibus_construct( claim_pin(data2); claim_pin(data3); claim_pin(cs); + if (dcx != NULL) { + claim_pin(dcx); + gpio_set_direction((gpio_num_t)self->dcx_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->dcx_pin, 1); + } #ifdef CIRCUITPY_QSPIBUS_PANEL_POWER_PIN const mcu_pin_obj_t *power = CIRCUITPY_QSPIBUS_PANEL_POWER_PIN; @@ -369,6 +388,9 @@ void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { reset_pin_number(self->data2_pin); reset_pin_number(self->data3_pin); reset_pin_number(self->cs_pin); + if (self->dcx_pin >= 0) { + reset_pin_number(self->dcx_pin); + } if (self->power_pin >= 0) { reset_pin_number(self->power_pin); } @@ -396,6 +418,83 @@ void common_hal_qspibus_qspibus_send_command( qspibus_send_command_bytes(self, command, data, len); } +void common_hal_qspibus_qspibus_send_command_data( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + if (!self->bus_initialized) { + mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); + } + + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } + + if (data == NULL || len == 0) { + qspibus_send_command_bytes(self, command, NULL, 0); + return; + } + + if (qspibus_is_color_payload_command(command)) { + qspibus_send_color_bytes(self, command, data, len); + } else { + qspibus_send_command_bytes(self, command, data, len); + } +} + +void common_hal_qspibus_qspibus_write_command( + qspibus_qspibus_obj_t *self, + uint8_t command) { + if (!self->bus_initialized) { + mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); + } + + // If caller stages command-only operations repeatedly, flush the previous + // pending command as no-data before replacing it. + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + } + + self->pending_command = command; + self->has_pending_command = true; +} + +void common_hal_qspibus_qspibus_write_data( + qspibus_qspibus_obj_t *self, + const uint8_t *data, + size_t len) { + if (!self->bus_initialized) { + mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); + } + if (len == 0) { + return; + } + if (data == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("data buffer is null")); + } + if (!self->has_pending_command) { + mp_raise_ValueError(MP_ERROR_TEXT("No pending command")); + } + + if (qspibus_is_color_payload_command(self->pending_command)) { + qspibus_send_color_bytes(self, self->pending_command, data, len); + } else { + qspibus_send_command_bytes(self, self->pending_command, data, len); + } + self->has_pending_command = false; +} + bool common_hal_qspibus_qspibus_reset(mp_obj_t obj) { qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); if (!self->bus_initialized || self->reset_pin < 0) { diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.h b/ports/espressif/common-hal/qspibus/QSPIBus.h index 173c2be1eddd5..ba525a0e6edc9 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.h +++ b/ports/espressif/common-hal/qspibus/QSPIBus.h @@ -31,6 +31,7 @@ typedef struct { int8_t data2_pin; int8_t data3_pin; int8_t cs_pin; + int8_t dcx_pin; // -1 when optional DCX line is not provided. int8_t reset_pin; // -1 when reset line is not provided. int8_t power_pin; // -1 when board has no explicit display power pin. diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c index 8778dae23cf5f..493b93f4ee8d8 100644 --- a/shared-bindings/qspibus/QSPIBus.c +++ b/shared-bindings/qspibus/QSPIBus.c @@ -9,9 +9,16 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" +#include "py/binary.h" #include "py/obj.h" #include "py/runtime.h" +static void check_for_deinit(qspibus_qspibus_obj_t *self) { + if (common_hal_qspibus_qspibus_deinited(self)) { + raise_deinited_error(); + } +} + //| class QSPIBus: //| """QSPI bus for quad-SPI displays.""" //| @@ -24,6 +31,7 @@ //| data2: microcontroller.Pin, //| data3: microcontroller.Pin, //| cs: microcontroller.Pin, +//| dcx: Optional[microcontroller.Pin] = None, //| reset: Optional[microcontroller.Pin] = None, //| frequency: int = 80_000_000, //| ) -> None: @@ -35,6 +43,9 @@ //| :param ~microcontroller.Pin data2: QSPI data line 2 //| :param ~microcontroller.Pin data3: QSPI data line 3 //| :param ~microcontroller.Pin cs: Chip select pin +//| :param ~microcontroller.Pin dcx: Optional data/command select pin. +//| Reserved for future hardware paths. Current ESP32-S3 implementation +//| uses encoded QSPI command words and does not require explicit DCX. //| :param ~microcontroller.Pin reset: Optional reset pin //| :param int frequency: Bus frequency in Hz (1-80MHz) //| """ @@ -43,7 +54,7 @@ static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_clock, ARG_data0, ARG_data1, ARG_data2, ARG_data3, ARG_cs, ARG_reset, ARG_frequency }; + enum { ARG_clock, ARG_data0, ARG_data1, ARG_data2, ARG_data3, ARG_cs, ARG_dcx, ARG_reset, ARG_frequency }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_data0, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, @@ -51,6 +62,7 @@ static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_arg { MP_QSTR_data2, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_data3, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_dcx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 80000000} }, }; @@ -64,12 +76,13 @@ static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_arg const mcu_pin_obj_t *data2 = validate_obj_is_free_pin(args[ARG_data2].u_obj, MP_QSTR_data2); const mcu_pin_obj_t *data3 = validate_obj_is_free_pin(args[ARG_data3].u_obj, MP_QSTR_data3); const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + const mcu_pin_obj_t *dcx = validate_obj_is_free_pin_or_none(args[ARG_dcx].u_obj, MP_QSTR_dcx); const mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset); uint32_t frequency = (uint32_t)mp_arg_validate_int_range(args[ARG_frequency].u_int, 1, 80000000, MP_QSTR_frequency); qspibus_qspibus_obj_t *self = mp_obj_malloc(qspibus_qspibus_obj_t, &qspibus_qspibus_type); - common_hal_qspibus_qspibus_construct(self, clock, data0, data1, data2, data3, cs, reset, frequency); + common_hal_qspibus_qspibus_construct(self, clock, data0, data1, data2, data3, cs, dcx, reset, frequency); return MP_OBJ_FROM_PTR(self); } @@ -85,6 +98,77 @@ static mp_obj_t qspibus_qspibus_deinit(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(qspibus_qspibus_deinit_obj, qspibus_qspibus_deinit); +//| def send(self, command: int, data: ReadableBuffer = b"") -> None: +//| """Send command with optional payload bytes. +//| +//| This mirrors FourWire-style convenience API: +//| - command byte is sent first +//| - optional payload bytes follow +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_command, ARG_data }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_command, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + + uint8_t command = (uint8_t)mp_arg_validate_int_range(args[ARG_command].u_int, 0, 255, MP_QSTR_command); + + const uint8_t *data = NULL; + size_t len = 0; + mp_buffer_info_t data_bufinfo; + if (args[ARG_data].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ); + data = (const uint8_t *)data_bufinfo.buf; + len = data_bufinfo.len; + } + + common_hal_qspibus_qspibus_send_command_data(self, command, data, len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(qspibus_qspibus_send_obj, 1, qspibus_qspibus_send); + +//| def write_command(self, command: int) -> None: +//| """Stage a command byte for subsequent :py:meth:`write_data`. +//| +//| If a previously staged command had no data, it is sent as +//| a command-only transaction before staging the new one. +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_write_command(mp_obj_t self_in, mp_obj_t command_obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + uint8_t command = (uint8_t)mp_arg_validate_int_range(mp_obj_get_int(command_obj), 0, 255, MP_QSTR_command); + common_hal_qspibus_qspibus_write_command(self, command); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(qspibus_qspibus_write_command_obj, qspibus_qspibus_write_command); + +//| def write_data(self, data: ReadableBuffer) -> None: +//| """Send payload bytes for the most recently staged command.""" +//| ... +//| +static mp_obj_t qspibus_qspibus_write_data(mp_obj_t self_in, mp_obj_t data_obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ); + common_hal_qspibus_qspibus_write_data(self, (const uint8_t *)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(qspibus_qspibus_write_data_obj, qspibus_qspibus_write_data); + //| def __enter__(self) -> QSPIBus: //| """No-op context manager entry.""" //| ... @@ -105,10 +189,11 @@ static mp_obj_t qspibus_qspibus___exit__(size_t n_args, const mp_obj_t *args) { } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qspibus_qspibus___exit___obj, 4, 4, qspibus_qspibus___exit__); -// send() intentionally remains C-only for display drivers. - static const mp_rom_map_elem_t qspibus_qspibus_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&qspibus_qspibus_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&qspibus_qspibus_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_command), MP_ROM_PTR(&qspibus_qspibus_write_command_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_data), MP_ROM_PTR(&qspibus_qspibus_write_data_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&qspibus_qspibus___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&qspibus_qspibus___exit___obj) }, }; diff --git a/shared-bindings/qspibus/QSPIBus.h b/shared-bindings/qspibus/QSPIBus.h index 608e81d1311b2..93a0a258a0d13 100644 --- a/shared-bindings/qspibus/QSPIBus.h +++ b/shared-bindings/qspibus/QSPIBus.h @@ -24,6 +24,7 @@ void common_hal_qspibus_qspibus_construct( const mcu_pin_obj_t *data2, const mcu_pin_obj_t *data3, const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *dcx, const mcu_pin_obj_t *reset, uint32_t frequency); @@ -35,6 +36,18 @@ void common_hal_qspibus_qspibus_send_command( uint8_t command, const uint8_t *data, size_t len); +void common_hal_qspibus_qspibus_send_command_data( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len); +void common_hal_qspibus_qspibus_write_command( + qspibus_qspibus_obj_t *self, + uint8_t command); +void common_hal_qspibus_qspibus_write_data( + qspibus_qspibus_obj_t *self, + const uint8_t *data, + size_t len); bool common_hal_qspibus_qspibus_reset(mp_obj_t obj); bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj); From d2680d5c9dc361ff4ce8995a9892aaeb7545fb51 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 17:27:58 +0100 Subject: [PATCH 17/38] Cleanup --- CHANGES.md | 337 ----------------- README.rst | 44 --- locale/circuitpython.pot | 295 +++------------ ports/espressif/Makefile | 6 - .../mpconfigboard.mk | 7 - ports/espressif/common-hal/qspibus/QSPIBus.c | 8 +- .../common-hal/rm690b0/esp_jpeg/esp_jpeg.c | 295 --------------- .../common-hal/rm690b0/esp_jpeg/esp_jpeg.h | 72 ---- .../common-hal/rm690b0/esp_lcd_rm690b0.c | 342 ------------------ .../common-hal/rm690b0/esp_lcd_rm690b0.h | 109 ------ py/circuitpy_defns.mk | 12 - py/circuitpy_mpconfig.h | 5 - py/circuitpy_mpconfig.mk | 8 - 13 files changed, 55 insertions(+), 1485 deletions(-) delete mode 100644 CHANGES.md delete mode 100644 ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c delete mode 100644 ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.h delete mode 100644 ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c delete mode 100644 ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h diff --git a/CHANGES.md b/CHANGES.md deleted file mode 100644 index 6645887435c93..0000000000000 --- a/CHANGES.md +++ /dev/null @@ -1,337 +0,0 @@ -# CircuitPython RM690B0 Driver - Changes for v2.0 - -## Version - -- Release: `2.0.0` -- Release date: `2026-02-06` -- Type: `BREAKING CHANGES` -- Board scope: `waveshare_esp32_s3_amoled_241` -- Last updated: `2026-02-06` - -## 1. Executive Summary - -Version `2.0.0` replaces the standalone `rm690b0` module with the standard CircuitPython display stack: - -- `qspibus` for QSPI panel transport -- `displayio` and `busdisplay` for scene and refresh lifecycle -- RM690B0 panel init sequence integrated with `BusDisplay` -- `sdioio` instead of custom `sdcardio` implementation - -This change aligns the board with CircuitPython upstream architecture expectations and makes display code compatible with standard ecosystem libraries. - -Important: -- Existing applications that use `import rm690b0` must migrate. -- Existing applications that use legacy `sdcardio` APIs on this board must migrate to `sdioio`. - -Quick migration example: - -```python -# OLD (v1.x) -import rm690b0 -rm690b0.init_display() -rm690b0.fill_color(rm690b0.RED) -rm690b0.swap_buffers() - -# NEW (v2.0) -import board -import displayio -import qspibus -from adafruit_rm690b0 import RM690B0 - -displayio.release_displays() -bus = qspibus.QSPIBus( - clock=board.LCD_CLK, - data0=board.LCD_D0, - data1=board.LCD_D1, - data2=board.LCD_D2, - data3=board.LCD_D3, - cs=board.LCD_CS, - reset=board.LCD_RESET, - frequency=40_000_000, -) -panel = RM690B0(bus, width=600, height=450) -display = displayio.Display(panel, width=600, height=450) -``` - -## 2. Breaking Changes - -### 2.1 Standalone `rm690b0` module removed - -The old standalone API was removed from firmware build and bindings. - -Removed behavior: -- `import rm690b0` -- imperative drawing calls from `rm690b0.*` -- standalone framebuffer and swap model - -Required replacement: -- `displayio` scene graph (`Group`, `TileGrid`, `Bitmap`, `Palette`) -- `qspibus.QSPIBus` transport -- RM690B0 panel class using `BusDisplay` - -### 2.2 Custom `sdcardio` path removed - -Legacy board-specific SD path was removed. - -Required replacement: -- `sdioio.SDCard(...)` -- `storage.VfsFat` + `storage.mount` - -Example: - -```python -import board -import sdioio - -sd = sdioio.SDCard( - clock=board.SD_CLK, - command=board.SD_MOSI, - data=[board.SD_MISO], - frequency=20_000_000, -) -``` - -### 2.3 API comparison - -| Legacy v1.x API | v2.0 replacement | -|---|---| -| `rm690b0.init_display()` | `qspibus.QSPIBus(...)` + panel init + `displayio.Display(...)` | -| `rm690b0.fill_color(color)` | Full-screen `Bitmap` + single-color `Palette` | -| `rm690b0.fill_rect(...)` | Rect bitmap/tile in `displayio.Group` | -| `rm690b0.line(...)` | `vectorio` or bitmap draw helper | -| `rm690b0.circle(...)` | `vectorio.Circle` | -| `rm690b0.text(...)` | `adafruit_display_text.label` or `terminalio` | -| `rm690b0.blit_bmp(...)` | `adafruit_imageload` + displayio | -| `rm690b0.blit_jpeg(...)` | `jpegio` path (future integration for accelerated flow) | -| `rm690b0.swap_buffers()` | `display.refresh()` or auto-refresh | -| custom `sdcardio` usage | `sdioio.SDCard(...)` | - -## 3. New Features - -### 3.1 `qspibus` module - -New module added as QSPI display transport analog to `fourwire`. - -Main points: -- explicit command/data path used by `busdisplay` -- stable pin ownership lifecycle for display stack -- context manager support -- deinit support with panel sleep handling for safer reruns - -Location: -- `shared-bindings/qspibus/` -- `shared-module/qspibus/` -- `ports/espressif/common-hal/qspibus/` - -### 3.2 RM690B0 displayio panel integration - -RM690B0 panel is now initialized and refreshed through `BusDisplay`. - -Main points: -- panel init sequence migrated to displayio flow -- geometry offsets supported (`colstart`, `rowstart`) -- tested color rendering path on real hardware -- integrated cleanup sequence for reruns - -### 3.3 Standard displayio compatibility - -Applications can now use regular displayio ecosystem primitives and libraries. - -Examples: -- `displayio.Bitmap`, `displayio.Palette`, `displayio.Group` -- `adafruit_display_text` -- `vectorio` -- `adafruit_imageload` - -### 3.4 Backward-compatible board aliases - -Canonical aliases are now generic `LCD_*` names. Compatibility aliases are still exposed for existing scripts. - -Examples: -- canonical: `LCD_CLK`, `LCD_D0`, `LCD_D1`, `LCD_D2`, `LCD_D3`, `LCD_CS`, `LCD_RESET` -- compatibility: `QSPI_CLK`, `QSPI_D0`, `QSPI_D1`, `QSPI_D2`, `QSPI_D3`, `QSPI_CS`, `AMOLED_RESET` - -## 4. Removed Code - -### 4.1 Core components removed - -| Component | Approx lines removed | Reason | -|---|---:|---| -| `shared-bindings/rm690b0/*` | 656 | Standalone module removed | -| `ports/espressif/common-hal/rm690b0/RM690B0.c` and `.h` | 3788 | Replaced by displayio panel path | -| `ports/espressif/common-hal/rm690b0/fonts/*.h` (7 files) | 5449 | Built-in standalone font pack removed | -| custom board `sdcardio` path | ~501 | Replaced by standard `sdioio` | - -Totals: -- conservative template baseline previously tracked: `~4963` lines -- full audit (including font headers): `9893` lines removed - -Audit reference: -- `../ws-esp32-s3-amoled-241/docs/CODE_REMOVAL_AUDIT.md` - -## 5. Retained Code - -The following components were intentionally kept: - -| Component | Approx lines | Location | Purpose | -|---|---:|---|---| -| `esp_lcd_rm690b0.c` | 342 | `ports/espressif/common-hal/rm690b0/` | Vendor RM690B0 init commands | -| `esp_lcd_rm690b0.h` | 109 | `ports/espressif/common-hal/rm690b0/` | Panel definitions | -| `esp_jpeg.c` | 295 | `ports/espressif/common-hal/rm690b0/esp_jpeg/` | JPEG decode path for future integration | -| `esp_jpeg.h` | 72 | `ports/espressif/common-hal/rm690b0/esp_jpeg/` | JPEG API definitions | - -Rationale: -- Vendor init command source remains required for panel bring-up. -- JPEG path is retained for planned `jpegio` integration work. - -## 6. Configuration Changes - -### 6.1 Board config (`mpconfigboard.mk`) - -Active settings in `ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk`: - -```makefile -CIRCUITPY_QSPIBUS = 1 -CIRCUITPY_SDIOIO = 1 - -# Disabled legacy path -CIRCUITPY_SDCARDIO = 0 -CIRCUITPY_SDCARDIO_ESPRESSIF = 0 -``` - -### 6.2 Build graph cleanup - -Build graph references for standalone `rm690b0` module were removed from make config where applicable. - -Impact: -- standalone module symbols are no longer present in the built firmware -- display pipeline now resolves through `qspibus` + `displayio` - -### 6.3 Pin naming updates - -Board pin API normalized to generic LCD naming while preserving compatibility aliases. - -Examples: -- old naming style: `RM690B0_QSPI_*` -- current naming style: `LCD_*` - -## 7. Architecture Changes - -### 7.1 Old architecture - -```text -Application - -> rm690b0 standalone module - -> board-specific draw and swap path - -> RM690B0 hardware -``` - -### 7.2 New architecture - -```text -Application - -> displayio scene graph - -> BusDisplay RM690B0 panel driver - -> qspibus transport - -> RM690B0 hardware -``` - -### 7.3 Benefits - -- standardized API model for CircuitPython users -- better upstream maintainability -- easier reuse of ecosystem display libraries -- clear separation of concerns between scene, panel, and transport -- future optimization path without changing user-level API - -## 8. Performance Impact - -### 8.1 Summary - -`v2.0` prioritizes correctness and upstream-compatible architecture. Full-screen refresh is slower than historical standalone path, but integration stability and API compatibility are achieved. - -### 8.2 Measured metrics - -Measured on Waveshare ESP32-S3 AMOLED 2.41 with current test scripts: - -| Operation | Legacy v1.x (historical) | v2.0 baseline | v2.0 optimized in Phase 5 | Notes | -|---|---:|---:|---:|---| -| Full screen fill (600x450) | ~25 ms (historical standalone estimate) | 360.499 ms | 341.250 ms | still above `<100 ms` target | -| Partial update (100x100) | n/a | 62.584 ms | 52.916 ms | improved after qspibus transfer updates | -| Multi-element scene | n/a | 59.700 ms | 51.500 ms | improved after batching/tuning | - -Additional Phase 1 SD metrics: -- write throughput: around `180 KB/s` -- read throughput (`readinto`): up to `~1.13 MB/s` at 40 MHz - -### 8.3 Optimization plan for v2.1 - -Planned focus areas: -- deeper refresh batching and dirty-region behavior tuning -- panel/bus refresh path profiling under scene-heavy workloads -- optional pipeline improvements for high-frequency full-screen refresh use cases -- incremental validation against stability constraints (no reboot/deinit regressions) - -## 9. Migration Guide - -Migration details are documented in: -- `../ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md` - -What it includes: -- old-to-new API mapping -- init sequence migration examples -- common pitfalls and compatibility notes -- cleanup best practices for reliable rerun behavior - -## 10. Testing - -Hardware validation used the phase test suite in: -- `../ws-esp32-s3-amoled-241/examples/tests/` - -Core tests: -- `test_phase1_sdioio.py` -- `test_phase2_qspibus.py` -- `test_phase3_displayio.py` -- `test_phase4_integration.py` - -Optional benchmark: -- `benchmark_phase5_displayio.py` - -Observed status in this cycle: -- Phase 1: pass -- Phase 2: pass -- Phase 3: pass (display colors and rectangle visible) -- Phase 4: pass (full stack integration) - -Testing guide: -- `../ws-esp32-s3-amoled-241/docs/TESTING_GUIDE.md` - -## 11. Known Issues - -1. Full-screen displayio refresh is slower than standalone historical path. -2. JPEG acceleration path is retained but not fully integrated with a finalized `jpegio` workflow. -3. Legacy built-in font bundle from standalone module is removed; applications should use `terminalio` or external font assets. -4. For robust reruns, cleanup order matters (`screen black` -> `displayio.release_displays()` -> `qspibus.deinit()`). - -## 12. Credits - -- Original board and RM690B0 integration work: project author and contributors -- Refactor toward upstream displayio architecture: project maintainer workstream -- CircuitPython architecture feedback and direction: `@tannewt` -- Hardware validation and regression checks: Waveshare ESP32-S3 AMOLED 2.41 test runs - -## References - -- `../ws-esp32-s3-amoled-241/docs/IMPLEMENTATION_PLAN.md` -- `../ws-esp32-s3-amoled-241/docs/IMPLEMENTATION_PLAN_SUMMARY.md` -- `../ws-esp32-s3-amoled-241/docs/TECHNICAL_NOTES.md` -- `../ws-esp32-s3-amoled-241/docs/CODE_REMOVAL_AUDIT.md` -- `../ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md` -- `../ws-esp32-s3-amoled-241/docs/TESTING_GUIDE.md` - -## Support - -For issue reporting and debugging context, include: -- board model and firmware build date -- full serial log from test run -- phase script name and whether display output matched expected behavior diff --git a/README.rst b/README.rst index faef0197aa093..80aa1b2aee282 100644 --- a/README.rst +++ b/README.rst @@ -10,50 +10,6 @@ CircuitPython `Branding <#branding>`__ \| `Differences from Micropython <#differences-from-micropython>`__ \| `Project Structure <#project-structure>`__ -Breaking Changes (v2.0) ------------------------ - -The standalone ``rm690b0`` module was removed in favor of ``displayio + qspibus`` integration. - -Migration is required for all code that used ``import rm690b0``. - -Old API (no longer available):: - - import rm690b0 - rm690b0.init_display() - rm690b0.fill_color(rm690b0.RED) - rm690b0.swap_buffers() - -New API (v2.0+):: - - import board - import displayio - import qspibus - from adafruit_rm690b0 import RM690B0 - - displayio.release_displays() - bus = qspibus.QSPIBus( - clock=board.LCD_CLK, - data0=board.LCD_D0, - data1=board.LCD_D1, - data2=board.LCD_D2, - data3=board.LCD_D3, - cs=board.LCD_CS, - reset=board.LCD_RESET, - frequency=40_000_000, - ) - panel = RM690B0(bus, width=600, height=450) - display = displayio.Display(panel, width=600, height=450) - -For migration details, see: -``/home/pps/Downloads/__ai__/repos/ws-esp32-s3-amoled-241/docs/MIGRATION_GUIDE.md``. - -For v2.0 release notes, see: -``CHANGES.md``. - -For hardware test procedure (Phase 1-4), see: -``/home/pps/Downloads/__ai__/repos/ws-esp32-s3-amoled-241/docs/TESTING_GUIDE.md``. - **CircuitPython** is a *beginner friendly*, open source version of Python for tiny, inexpensive computers called microcontrollers. Microcontrollers are the brains of many electronics including a wide variety of development boards used to build hobby projects and prototypes. CircuitPython in diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 0ebd949afdd85..7e29d380a4532 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -631,19 +631,14 @@ msgid "" "disable.\n" msgstr "" -#: shared-bindings/rm690b0/__init__.c -#, c-format -msgid "BMP conversion failed (%s)" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "BMP data too small" -msgstr "" - #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "Begin transaction first" +msgstr "" + #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -653,14 +648,6 @@ msgstr "" msgid "Bit clock and word select must be sequential GPIO pins" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Bitmap data too small for width * height" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Bitmap dimensions too large (max ~32767x32767 on 32-bit systems)" -msgstr "" - #: shared-bindings/bitmaptools/__init__.c msgid "Bitmap size and bits per value must match" msgstr "" @@ -674,10 +661,6 @@ msgstr "" msgid "Both RX and TX required for flow control" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Brightness must be between 0.0 and 1.0" -msgstr "" - #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" @@ -705,15 +688,10 @@ msgstr "" #: ports/cxd56/common-hal/sdioio/SDCard.c #: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -#: shared-module/sdcardio/SDCard.c #, c-format msgid "Buffer must be a multiple of %d bytes" msgstr "" -#: ports/espressif/common-hal/sdcardio/SDCard.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "" - #: shared-bindings/_bleio/PacketBuffer.c #, c-format msgid "Buffer too short by %d bytes" @@ -726,6 +704,10 @@ msgstr "" msgid "Buffer too small" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "Bus in display transaction" +msgstr "" + #: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c #: ports/nordic/common-hal/paralleldisplaybus/ParallelBus.c @@ -859,10 +841,6 @@ msgstr "" msgid "Clock unit in use" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Compressed BMP not supported" -msgstr "" - #: shared-bindings/_bleio/Connection.c msgid "" "Connection has been disconnected and can no longer be used. Create a new " @@ -914,10 +892,6 @@ msgstr "" msgid "DAC already in use" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "DMA transfer timed out - hardware requires reset" -msgstr "" - #: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c #: ports/nordic/common-hal/paralleldisplaybus/ParallelBus.c msgid "Data 0 pin must be byte aligned" @@ -953,24 +927,11 @@ msgstr "" msgid "Device in use" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Display initialization failed: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Display initialization failed: Out of memory" -msgstr "" - #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Display must have a 16 bit colorspace." msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Display not initialized. Call init_display() first" -msgstr "" - #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -1045,12 +1006,12 @@ msgstr "" msgid "Failed to allocate %q buffer" msgstr "" -#: ports/espressif/common-hal/wifi/__init__.c -msgid "Failed to allocate Wifi memory" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "Failed to allocate DMA buffers" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Failed to allocate memory for circle" +#: ports/espressif/common-hal/wifi/__init__.c +msgid "Failed to allocate Wifi memory" msgstr "" #: ports/espressif/common-hal/wifi/ScannedNetworks.c @@ -1061,11 +1022,6 @@ msgstr "" msgid "Failed to buffer the sample" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to clear display: %s" -msgstr "" - #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" @@ -1075,14 +1031,6 @@ msgstr "" msgid "Failed to connect: timeout" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Failed to create DMA semaphore" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Failed to create RM690B0 panel" -msgstr "" - #: ports/espressif/common-hal/audioio/AudioOut.c msgid "Failed to create continuous channels: invalid arg" msgstr "" @@ -1099,68 +1047,18 @@ msgstr "" msgid "Failed to create continuous channels: not found" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Failed to create panel I/O" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw BMP: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw JPEG: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw bitmap: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw circle: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw fill_circle: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw fill_rect: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to draw pixel: %s" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "Failed to create semaphore" msgstr "" #: ports/espressif/common-hal/audioio/AudioOut.c msgid "Failed to enable continuous" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to initialize SPI bus: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to latch brightness: %s" -msgstr "" - #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to refresh display: %s (0x%x)" -msgstr "" - #: ports/espressif/common-hal/audioio/AudioOut.c msgid "Failed to register continuous events callback" msgstr "" @@ -1170,11 +1068,6 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to select brightness page: %s" -msgstr "" - #: ports/analog/common-hal/busio/SPI.c msgid "Failed to set SPI Clock Mode" msgstr "" @@ -1187,11 +1080,6 @@ msgstr "" msgid "Failed to start async audio" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "Failed to write brightness: %s" -msgstr "" - #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "" @@ -1427,32 +1315,10 @@ msgstr "" msgid "Invalid BLE parameter" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Invalid BMP data offset" -msgstr "" - -#: shared-bindings/rm690b0/__init__.c -#, c-format -msgid "Invalid BMP format (%s)" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Invalid BMP header" -msgstr "" - #: shared-bindings/wifi/Radio.c msgid "Invalid BSSID" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Invalid JPEG data" -msgstr "" - -#: shared-bindings/rm690b0/__init__.c -#, c-format -msgid "Invalid JPEG format (%s)" -msgstr "" - #: shared-bindings/wifi/Radio.c msgid "Invalid MAC address" msgstr "" @@ -1479,10 +1345,6 @@ msgstr "" msgid "Invalid data_pins[%d]" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Invalid display handle" -msgstr "" - #: shared-module/msgpack/__init__.c msgid "Invalid format" msgstr "" @@ -1518,19 +1380,6 @@ msgstr "" msgid "Invalid unicode escape" msgstr "" -#: shared-bindings/rm690b0/__init__.c -#, c-format -msgid "JPEG conversion failed (%s)" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "JPEG decode failed" -msgstr "" - -#: shared-bindings/rm690b0/__init__.c -msgid "JPEG support not compiled in" -msgstr "" - #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" msgstr "" @@ -1744,10 +1593,6 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/espressif/common-hal/sdcardio/SDCard.c -msgid "No memory for SD card structure" -msgstr "" - #: shared-bindings/wifi/Radio.c msgid "No network with that ssid" msgstr "" @@ -1756,6 +1601,10 @@ msgstr "" msgid "No out in program" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "No pending command" +msgstr "" + #: ports/atmel-samd/common-hal/busio/I2C.c #: ports/espressif/common-hal/busio/I2C.c #: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nordic/common-hal/busio/I2C.c @@ -1833,10 +1682,6 @@ msgstr "" msgid "Ok" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Only 16-bit and 24-bit BMP supported" -msgstr "" - #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c #, c-format @@ -1944,6 +1789,11 @@ msgstr "" msgid "Packet buffers for an SPI transfer must have the same length." msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +#, c-format +msgid "Panel IO init failed: %d" +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -2049,6 +1899,32 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "QSPI DMA buffers unavailable" +msgstr "" + +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "QSPI bus deinitialized" +msgstr "" + +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "QSPI color timeout" +msgstr "" + +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "QSPI command timeout" +msgstr "" + +#: ports/espressif/common-hal/qspibus/QSPIBus.c +#, c-format +msgid "QSPI send color failed: %d" +msgstr "" + +#: ports/espressif/common-hal/qspibus/QSPIBus.c +#, c-format +msgid "QSPI send failed: %d" +msgstr "" + #: ports/raspberrypi/common-hal/countio/Counter.c msgid "RISE_AND_FALL not available on this chip" msgstr "" @@ -2147,28 +2023,10 @@ msgstr "" msgid "Right format but not supported" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Rotation must be 0, 90, 180, or 270" -msgstr "" - #: main.c msgid "Running in safe mode! Not running saved code.\n" msgstr "" -#: shared-module/sdcardio/SDCard.c -msgid "SD card CSD format not supported" -msgstr "" - -#: ports/espressif/common-hal/sdcardio/SDCard.c -#, c-format -msgid "SD card init failed: %d" -msgstr "" - -#: ports/espressif/common-hal/sdcardio/SDCard.c -#, c-format -msgid "SD host init failed: %d" -msgstr "" - #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "SDCard init" msgstr "" @@ -2184,19 +2042,11 @@ msgstr "" msgid "SDIO Init Error %x" msgstr "" -#: ports/espressif/common-hal/sdcardio/SDCard.c -msgid "SPI bus already deinitialized" -msgstr "" - -#: ports/espressif/common-hal/sdcardio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #, c-format msgid "SPI bus init failed: %d" msgstr "" -#: ports/espressif/common-hal/sdcardio/SDCard.c -msgid "SPI bus must have MOSI, MISO, and CLK pins" -msgstr "" - #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" msgstr "" @@ -2580,10 +2430,6 @@ msgstr "" msgid "Unsupported hash algorithm" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "Unsupported rotation" -msgstr "" - #: ports/espressif/common-hal/socketpool/Socket.c #: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" @@ -3056,10 +2902,6 @@ msgstr "" msgid "can't send non-None value to a just-started generator" msgstr "" -#: shared-module/sdcardio/SDCard.c -msgid "can't set 512 block size" -msgstr "" - #: py/objexcept.c py/objnamedtuple.c msgid "can't set attribute" msgstr "" @@ -3210,14 +3052,14 @@ msgstr "" msgid "could not invert Vandermonde matrix" msgstr "" -#: shared-module/sdcardio/SDCard.c -msgid "couldn't determine SD card version" -msgstr "" - #: extmod/ulab/code/numpy/numerical.c msgid "cross is defined for 1D arrays of length 3" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c +msgid "data buffer is null" +msgstr "" + #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be iterable" msgstr "" @@ -3375,15 +3217,6 @@ msgstr "" msgid "file write is not available" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -#, c-format -msgid "fill_color failed: %s" -msgstr "" - -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "fill_color: unable to allocate DMA buffer" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3948,10 +3781,6 @@ msgstr "" msgid "nested index must be int" msgstr "" -#: ports/espressif/common-hal/sdcardio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "no SD card" -msgstr "" - #: py/vm.c msgid "no active exception to reraise" msgstr "" @@ -3972,10 +3801,6 @@ msgstr "" msgid "no module named '%q'" msgstr "" -#: shared-module/sdcardio/SDCard.c -msgid "no response from SD card" -msgstr "" - #: ports/espressif/common-hal/espcamera/Camera.c py/objobject.c py/runtime.c msgid "no such attribute" msgstr "" @@ -4287,10 +4112,6 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: ports/espressif/common-hal/rm690b0/RM690B0.c -msgid "radius must be non-negative" -msgstr "" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" @@ -4485,14 +4306,6 @@ msgstr "" msgid "timeout waiting for index pulse" msgstr "" -#: shared-module/sdcardio/SDCard.c -msgid "timeout waiting for v1 card" -msgstr "" - -#: shared-module/sdcardio/SDCard.c -msgid "timeout waiting for v2 card" -msgstr "" - #: ports/stm/common-hal/pwmio/PWMOut.c msgid "timer re-init" msgstr "" diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 5d2a9cb3eda61..dec6f045a3bbf 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -503,12 +503,6 @@ SRC_ESPNOW := \ SRC_C += $(SRC_ESPNOW) endif -ifneq ($(CIRCUITPY_SDCARDIO_ESPRESSIF),0) -INC += -isystem esp-idf/components/sdmmc/include -INC += -isystem esp-idf/components/esp_driver_sdmmc/include -INC += -isystem esp-idf/components/esp_driver_sdspi/include -endif - ifneq ($(CIRCUITPY_ESPULP),0) SRC_ULP := \ $(wildcard common-hal/espulp/*.c) \ diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index ffd216538b830..700881459bb42 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -40,8 +40,6 @@ CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_BITMAPTOOLS = 1 CIRCUITPY_JPEGIO = 1 CIRCUITPY_FRAMEBUFFERIO = 1 -# RM690B0 standalone module removed in Phase 4. -# Display path is now: qspibus + displayio + user-space panel driver. # Enable ESP-NOW for peer-to-peer wireless communication CIRCUITPY_ESPNOW = 1 @@ -75,11 +73,6 @@ CIRCUITPY_USB_MIDI = 1 # Storage configuration CIRCUITPY_STORAGE = 1 CIRCUITPY_NVM = 1 -# Use existing sdioio instead of custom sdcardio -# CIRCUITPY_SDCARDIO = 1 # REMOVED - using sdioio -# CIRCUITPY_SDCARDIO_ESPRESSIF = 1 # REMOVED -CIRCUITPY_SDCARDIO = 0 -CIRCUITPY_SDCARDIO_ESPRESSIF = 0 CIRCUITPY_SDIOIO = 1 # Enable touch support diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 4485b648c6545..72b77d5f8145f 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -26,16 +26,10 @@ #define QSPI_COLOR_TIMEOUT_MS (1000U) #if defined(CIRCUITPY_LCD_POWER) #define CIRCUITPY_QSPIBUS_PANEL_POWER_PIN CIRCUITPY_LCD_POWER -#elif defined(CIRCUITPY_RM690B0_POWER) -#define CIRCUITPY_QSPIBUS_PANEL_POWER_PIN CIRCUITPY_RM690B0_POWER #endif #ifndef CIRCUITPY_LCD_POWER_ON_LEVEL - #if defined(CIRCUITPY_RM690B0_POWER_ON_LEVEL) - #define CIRCUITPY_LCD_POWER_ON_LEVEL CIRCUITPY_RM690B0_POWER_ON_LEVEL - #else - #define CIRCUITPY_LCD_POWER_ON_LEVEL (1) - #endif +#define CIRCUITPY_LCD_POWER_ON_LEVEL (1) #endif static void qspibus_release_dma_buffers(qspibus_qspibus_obj_t *self) { diff --git a/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c b/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c deleted file mode 100644 index 7d48113dc8381..0000000000000 --- a/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.c +++ /dev/null @@ -1,295 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT -// -// Minimal esp_jpeg implementation backed by TJpgDec. - -#include "esp_jpeg.h" - -#include -#include - -#include "tjpgd.h" - -#if defined(ESP_PLATFORM) -#include "esp_heap_caps.h" -#endif - -// TJpgDec work buffer size (heap allocated) -#define ESP_JPEG_TJPGD_WORK_BUFFER_SIZE 4096 - -// Maximum pixels per decoded block for on_block callback mode. -// This determines the stack usage of esp_jpeg_output(): -// Stack usage = ESP_JPEG_MAX_BLOCK_PIXELS * sizeof(uint16_t) = 512 bytes -// Ensure sufficient stack space when using on_block callback in deeply nested contexts. -#define ESP_JPEG_MAX_BLOCK_PIXELS 256 - -typedef struct { - uint8_t *rgb565_buffer; - uint32_t width; - const uint8_t *jpg_data; - size_t jpg_size; - size_t jpg_offset; - bool swap_bytes; - intptr_t user_data; - esp_err_t (*on_block)(intptr_t, - uint32_t, uint32_t, - uint32_t, uint32_t, - const uint16_t *); - esp_err_t last_error; -} esp_jpeg_tjpgd_ctx_t; - -static void *esp_jpeg_alloc(size_t size) { -#if defined(ESP_PLATFORM) - void *ptr = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!ptr) { - ptr = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - } - return ptr; -#else - return malloc(size); -#endif -} - -static void esp_jpeg_free(void *ptr) { -#if defined(ESP_PLATFORM) - heap_caps_free(ptr); -#else - free(ptr); -#endif -} - -/** - * @brief Calculate RGB565 buffer size with overflow protection. - * - * @param width Image width in pixels - * @param height Image height in pixels - * @param out_size Output: buffer size in bytes (only valid if function returns true) - * @return true if calculation succeeded, false if overflow detected - */ -static bool esp_jpeg_calc_rgb565_size(uint32_t width, uint32_t height, size_t *out_size) { - // Check for overflow: width * height must fit in size_t - if (width != 0 && height > SIZE_MAX / width) { - return false; - } - size_t pixel_count = (size_t)width * height; - - // Check for overflow when multiplying by 2 (bytes per pixel) - if (pixel_count > SIZE_MAX / 2) { - return false; - } - - *out_size = pixel_count * 2; - return true; -} - -static size_t esp_jpeg_input(JDEC *jd, uint8_t *buff, size_t ndata) { - esp_jpeg_tjpgd_ctx_t *ctx = (esp_jpeg_tjpgd_ctx_t *)jd->device; - - if (!buff) { - size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; - size_t bytes_to_skip = ndata; - if (bytes_to_skip > bytes_available) { - bytes_to_skip = bytes_available; - } - ctx->jpg_offset += bytes_to_skip; - return bytes_to_skip; - } - - size_t bytes_to_read = ndata; - size_t bytes_available = ctx->jpg_size - ctx->jpg_offset; - if (bytes_to_read > bytes_available) { - bytes_to_read = bytes_available; - } - - if (bytes_to_read > 0) { - memcpy(buff, ctx->jpg_data + ctx->jpg_offset, bytes_to_read); - ctx->jpg_offset += bytes_to_read; - } - - return bytes_to_read; -} - -static int esp_jpeg_output(JDEC *jd, void *bitmap, JRECT *rect) { - esp_jpeg_tjpgd_ctx_t *ctx = (esp_jpeg_tjpgd_ctx_t *)jd->device; - - if (ctx->rgb565_buffer != NULL) { - uint8_t *src = (uint8_t *)bitmap; - for (int y = rect->top; y <= rect->bottom; y++) { - uint32_t row_base = (uint32_t)y * ctx->width; - for (int x = rect->left; x <= rect->right; x++) { - uint16_t rgb565 = ((uint16_t)src[0] << 8) | src[1]; - src += 2; - uint32_t offset = (row_base + x) * 2; - if (ctx->swap_bytes) { - ctx->rgb565_buffer[offset] = (rgb565 >> 8) & 0xFF; - ctx->rgb565_buffer[offset + 1] = rgb565 & 0xFF; - } else { - ctx->rgb565_buffer[offset] = rgb565 & 0xFF; - ctx->rgb565_buffer[offset + 1] = (rgb565 >> 8) & 0xFF; - } - } - } - } else if (ctx->on_block != NULL) { - uint32_t width = (uint32_t)rect->right - (uint32_t)rect->left + 1; - uint32_t height = (uint32_t)rect->bottom - (uint32_t)rect->top + 1; - - // Validate dimensions individually to prevent overflow in multiplication. - // Since ESP_JPEG_MAX_BLOCK_PIXELS is 256, if either dimension exceeds it, - // the total would exceed the limit anyway. - if (width == 0 || height == 0 || - width > ESP_JPEG_MAX_BLOCK_PIXELS || height > ESP_JPEG_MAX_BLOCK_PIXELS) { - ctx->last_error = ESP_ERR_INVALID_SIZE; - return 0; - } - - uint32_t total = width * height; // Safe: max is 256 * 256 = 65536 - if (total > ESP_JPEG_MAX_BLOCK_PIXELS) { - ctx->last_error = ESP_ERR_INVALID_SIZE; - return 0; - } - - // Stack-allocated buffer for pixel conversion (512 bytes). - // See ESP_JPEG_MAX_BLOCK_PIXELS definition for stack usage notes. - uint16_t block_pixels[ESP_JPEG_MAX_BLOCK_PIXELS]; - const uint8_t *block_src = (const uint8_t *)bitmap; - for (uint32_t i = 0; i < total; i++) { - uint16_t rgb565 = ((uint16_t)block_src[0] << 8) | block_src[1]; - block_src += 2; - if (ctx->swap_bytes) { - rgb565 = (uint16_t)((rgb565 << 8) | (rgb565 >> 8)); - } - block_pixels[i] = rgb565; - } - - esp_err_t cb = ctx->on_block(ctx->user_data, - (uint32_t)rect->top, - (uint32_t)rect->left, - (uint32_t)rect->bottom, - (uint32_t)rect->right, - block_pixels); - if (cb != ESP_OK) { - ctx->last_error = cb; - return 0; - } - } else { - return 0; - } - - return 1; -} - -static esp_err_t esp_jpeg_prepare_decoder(const esp_jpeg_image_cfg_t *cfg, JDEC *out_dec, esp_jpeg_tjpgd_ctx_t *ctx, void **work_buffer) { - if (cfg == NULL || cfg->indata == NULL || cfg->indata_size == 0) { - return ESP_ERR_INVALID_ARG; - } - - if (cfg->out_scale != JPEG_IMAGE_SCALE_0) { - return ESP_ERR_NOT_SUPPORTED; - } - - void *work = esp_jpeg_alloc(ESP_JPEG_TJPGD_WORK_BUFFER_SIZE); - if (!work) { - return ESP_ERR_NO_MEM; - } - - ctx->rgb565_buffer = NULL; - ctx->width = 0; - ctx->jpg_data = cfg->indata; - ctx->jpg_size = cfg->indata_size; - ctx->jpg_offset = 0; - ctx->swap_bytes = cfg->flags.swap_color_bytes; - ctx->user_data = cfg->user_data; - ctx->on_block = cfg->on_block; - ctx->last_error = ESP_OK; - - JRESULT res = jd_prepare(out_dec, esp_jpeg_input, work, ESP_JPEG_TJPGD_WORK_BUFFER_SIZE, ctx); - if (res != JDR_OK) { - esp_jpeg_free(work); - return ESP_ERR_INVALID_ARG; - } - - if (out_dec->width == 0 || out_dec->height == 0) { - esp_jpeg_free(work); - return ESP_ERR_INVALID_ARG; - } - - *work_buffer = work; - return ESP_OK; -} - -esp_err_t esp_jpeg_get_image_info(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out) { - if (out == NULL) { - return ESP_ERR_INVALID_ARG; - } - - JDEC jdec; - esp_jpeg_tjpgd_ctx_t ctx; - void *work = NULL; - - esp_err_t err = esp_jpeg_prepare_decoder(cfg, &jdec, &ctx, &work); - if (err != ESP_OK) { - return err; - } - - out->width = jdec.width; - out->height = jdec.height; - out->outbuf = NULL; - - // Calculate buffer size with overflow protection - if (!esp_jpeg_calc_rgb565_size(jdec.width, jdec.height, &out->outbuf_size)) { - esp_jpeg_free(work); - return ESP_ERR_INVALID_SIZE; - } - - esp_jpeg_free(work); - return ESP_OK; -} - -esp_err_t esp_jpeg_decode(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out) { - if (cfg == NULL || (cfg->outbuf == NULL && cfg->on_block == NULL)) { - return ESP_ERR_INVALID_ARG; - } - if (cfg->out_format != JPEG_IMAGE_FORMAT_RGB565) { - return ESP_ERR_NOT_SUPPORTED; - } - - JDEC jdec; - esp_jpeg_tjpgd_ctx_t ctx; - void *work = NULL; - - esp_err_t err = esp_jpeg_prepare_decoder(cfg, &jdec, &ctx, &work); - if (err != ESP_OK) { - return err; - } - - // Calculate required buffer size with overflow protection - size_t required_size; - if (!esp_jpeg_calc_rgb565_size(jdec.width, jdec.height, &required_size)) { - esp_jpeg_free(work); - return ESP_ERR_INVALID_SIZE; - } - if (cfg->outbuf != NULL && cfg->outbuf_size < required_size) { - esp_jpeg_free(work); - return ESP_ERR_NO_MEM; - } - - ctx.rgb565_buffer = cfg->outbuf; - ctx.width = jdec.width; - - JRESULT res = jd_decomp(&jdec, esp_jpeg_output, 0); - esp_jpeg_free(work); - - if (res != JDR_OK) { - return (ctx.last_error != ESP_OK) ? ctx.last_error : ESP_FAIL; - } - - if (out) { - out->width = jdec.width; - out->height = jdec.height; - out->outbuf = cfg->outbuf; - out->outbuf_size = (cfg->outbuf != NULL) ? required_size : 0; - } - - return ESP_OK; -} diff --git a/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.h b/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.h deleted file mode 100644 index 98ba5195f1079..0000000000000 --- a/ports/espressif/common-hal/rm690b0/esp_jpeg/esp_jpeg.h +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT -// -// Minimal esp_jpeg interface used by the RM690B0 driver. -// Provides a drop-in replacement for the ESP-IDF component by wrapping TJpgDec. - -#pragma once - -#include -#include -#include - -#if defined(ESP_PLATFORM) -#include "esp_err.h" -#else -typedef int32_t esp_err_t; -#define ESP_OK 0 -#define ESP_FAIL -1 -#define ESP_ERR_INVALID_ARG 0x102 -#define ESP_ERR_NO_MEM 0x103 -#define ESP_ERR_NOT_SUPPORTED 0x105 -#define ESP_ERR_INVALID_SIZE 0x10B -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - JPEG_IMAGE_FORMAT_RGB565 = 0, - JPEG_IMAGE_FORMAT_RGB888 = 1, - JPEG_IMAGE_FORMAT_GRAYSCALE = 2, -} esp_jpeg_image_format_t; - -typedef enum { - JPEG_IMAGE_SCALE_0 = 0, -} esp_jpeg_image_scale_t; - -typedef struct { - bool swap_color_bytes : 1; - bool use_scaler : 1; -} esp_jpeg_flags_t; - -typedef struct { - const uint8_t *indata; - size_t indata_size; - uint8_t *outbuf; - size_t outbuf_size; - esp_jpeg_image_format_t out_format; - esp_jpeg_image_scale_t out_scale; - esp_jpeg_flags_t flags; - intptr_t user_data; - esp_err_t (*on_block)(intptr_t ctx, - uint32_t top, uint32_t left, - uint32_t bottom, uint32_t right, - const uint16_t *pixels); -} esp_jpeg_image_cfg_t; - -typedef struct { - uint32_t width; - uint32_t height; - uint8_t *outbuf; - size_t outbuf_size; -} esp_jpeg_image_output_t; - -esp_err_t esp_jpeg_get_image_info(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out); -esp_err_t esp_jpeg_decode(const esp_jpeg_image_cfg_t *cfg, esp_jpeg_image_output_t *out); - -#ifdef __cplusplus -} -#endif diff --git a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c deleted file mode 100644 index 4aed54a261801..0000000000000 --- a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.c +++ /dev/null @@ -1,342 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/gpio.h" -#include "esp_check.h" -#include "esp-idf/components/esp_lcd/interface/esp_lcd_panel_interface.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_vendor.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_ops.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_commands.h" -#include "esp_log.h" - -#include "esp_lcd_rm690b0.h" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x03ULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const char *TAG = "rm690b0"; - -static esp_err_t panel_rm690b0_del(esp_lcd_panel_t *panel); -static esp_err_t panel_rm690b0_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_rm690b0_init(esp_lcd_panel_t *panel); -static esp_err_t panel_rm690b0_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); -static esp_err_t panel_rm690b0_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); -static esp_err_t panel_rm690b0_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_rm690b0_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); -static esp_err_t panel_rm690b0_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_rm690b0_disp_on_off(esp_lcd_panel_t *panel, bool off); - -typedef struct { - esp_lcd_panel_t base; - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - int x_gap; - int y_gap; - uint8_t fb_bits_per_pixel; - uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register - const rm690b0_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - struct { - unsigned int use_qspi_interface : 1; - unsigned int reset_level : 1; - } flags; -} rm690b0_panel_t; - -esp_err_t esp_lcd_new_panel_rm690b0(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel) { - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - - esp_err_t ret = ESP_OK; - rm690b0_panel_t *rm690b0 = NULL; - rm690b0 = calloc(1, sizeof(rm690b0_panel_t)); - ESP_GOTO_ON_FALSE(rm690b0, ESP_ERR_NO_MEM, err, TAG, "no mem for rm690b0 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) { - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, - }; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - switch (panel_dev_config->rgb_ele_order) { - case LCD_RGB_ELEMENT_ORDER_RGB: - rm690b0->madctl_val = 0; - break; - case LCD_RGB_ELEMENT_ORDER_BGR: - rm690b0->madctl_val |= LCD_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order"); - break; - } - - uint8_t fb_bits_per_pixel = 0; - switch (panel_dev_config->bits_per_pixel) { - case 16: // RGB565 - rm690b0->colmod_val = 0x55; - fb_bits_per_pixel = 16; - break; - case 18: // RGB666 - rm690b0->colmod_val = 0x66; - // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel - fb_bits_per_pixel = 24; - break; - case 24: // RGB888 - rm690b0->colmod_val = 0x77; - fb_bits_per_pixel = 24; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - rm690b0->io = io; - rm690b0->reset_gpio_num = panel_dev_config->reset_gpio_num; - rm690b0->fb_bits_per_pixel = fb_bits_per_pixel; - rm690b0_vendor_config_t *vendor_config = (rm690b0_vendor_config_t *)panel_dev_config->vendor_config; - if (vendor_config) { - rm690b0->init_cmds = vendor_config->init_cmds; - rm690b0->init_cmds_size = vendor_config->init_cmds_size; - rm690b0->flags.use_qspi_interface = vendor_config->flags.use_qspi_interface; - } - rm690b0->flags.reset_level = panel_dev_config->flags.reset_active_high; - rm690b0->base.del = panel_rm690b0_del; - rm690b0->base.reset = panel_rm690b0_reset; - rm690b0->base.init = panel_rm690b0_init; - rm690b0->base.draw_bitmap = panel_rm690b0_draw_bitmap; - rm690b0->base.invert_color = panel_rm690b0_invert_color; - rm690b0->base.set_gap = panel_rm690b0_set_gap; - rm690b0->base.mirror = panel_rm690b0_mirror; - rm690b0->base.swap_xy = panel_rm690b0_swap_xy; - rm690b0->base.disp_on_off = panel_rm690b0_disp_on_off; - *ret_panel = &(rm690b0->base); - ESP_LOGD(TAG, "new rm690b0 panel @%p", rm690b0); - - return ESP_OK; - -err: - if (rm690b0) { - if (panel_dev_config->reset_gpio_num >= 0) { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(rm690b0); - } - return ret; -} - -static esp_err_t tx_param(rm690b0_panel_t *rm690b0, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size) { - if (rm690b0->flags.use_qspi_interface) { - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - } - return esp_lcd_panel_io_tx_param(io, lcd_cmd, param, param_size); -} - -static esp_err_t tx_color(rm690b0_panel_t *rm690b0, esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size) { - if (rm690b0->flags.use_qspi_interface) { - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_COLOR << 24; - } - return esp_lcd_panel_io_tx_color(io, lcd_cmd, param, param_size); -} - -static esp_err_t panel_rm690b0_del(esp_lcd_panel_t *panel) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - - if (rm690b0->reset_gpio_num >= 0) { - gpio_reset_pin(rm690b0->reset_gpio_num); - } - ESP_LOGD(TAG, "del rm690b0 panel @%p", rm690b0); - free(rm690b0); - return ESP_OK; -} - -static esp_err_t panel_rm690b0_reset(esp_lcd_panel_t *panel) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - esp_lcd_panel_io_handle_t io = rm690b0->io; - - // Perform hardware reset - if (rm690b0->reset_gpio_num >= 0) { - gpio_set_level(rm690b0->reset_gpio_num, rm690b0->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(rm690b0->reset_gpio_num, !rm690b0->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(150)); - } else { // Perform software reset - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(80)); - } - - return ESP_OK; -} - -static const rm690b0_lcd_init_cmd_t vendor_specific_init_default[] = { -// {cmd, { data }, data_size, delay_ms} - {0xFE, (uint8_t []) {0x20}, 1, 0}, - {0x26, (uint8_t []) {0x0A}, 1, 0}, - {0x24, (uint8_t []) {0x80}, 1, 0}, - {0xFE, (uint8_t []) {0x00}, 1, 0}, - {0x3A, (uint8_t []) {0x55}, 1, 0}, - {0xC2, (uint8_t []) {0x00}, 1, 10}, - {0x35, (uint8_t []) {0x00}, 0, 0}, - {0x51, (uint8_t []) {0x00}, 1, 10}, - {0x11, (uint8_t []) {0x00}, 0, 80}, - {0x2A, (uint8_t []) {0x00, 0x10, 0x01, 0xD1}, 4, 0}, - {0x2B, (uint8_t []) {0x00, 0x00, 0x02, 0x57}, 4, 0}, - {0x29, (uint8_t []) {0x00}, 0, 10}, - {0x51, (uint8_t []) {0xFF}, 1, 0}, - {0x51, (uint8_t []) {0xFF}, 1, 0}, -}; - -static esp_err_t panel_rm690b0_init(esp_lcd_panel_t *panel) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - esp_lcd_panel_io_handle_t io = rm690b0->io; - const rm690b0_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - bool is_cmd_overwritten = false; - - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_MADCTL, (uint8_t[]) { - rm690b0->madctl_val, - }, 1), TAG, "send command failed"); - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_COLMOD, (uint8_t[]) { - rm690b0->colmod_val, - }, 1), TAG, "send command failed"); - - // vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - if (rm690b0->init_cmds) { - init_cmds = rm690b0->init_cmds; - init_cmds_size = rm690b0->init_cmds_size; - } else { - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(rm690b0_lcd_init_cmd_t); - } - - for (int i = 0; i < init_cmds_size; i++) { - // Check if the command has been used or conflicts with the internal - switch (init_cmds[i].cmd) { - case LCD_CMD_MADCTL: - is_cmd_overwritten = true; - rm690b0->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - case LCD_CMD_COLMOD: - is_cmd_overwritten = true; - rm690b0->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - default: - is_cmd_overwritten = false; - break; - } - - if (is_cmd_overwritten) { - ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd); - } - - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, - "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - } - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_rm690b0_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); - esp_lcd_panel_io_handle_t io = rm690b0->io; - - x_start += rm690b0->x_gap; - x_end += rm690b0->x_gap; - y_start += rm690b0->y_gap; - y_end += rm690b0->y_gap; - - // define an area of frame memory where MCU can access - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_CASET, (uint8_t[]) { - (x_start >> 8) & 0xFF, - x_start & 0xFF, - ((x_end - 1) >> 8) & 0xFF, - (x_end - 1) & 0xFF, - }, 4), TAG, "send command failed"); - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_RASET, (uint8_t[]) { - (y_start >> 8) & 0xFF, - y_start & 0xFF, - ((y_end - 1) >> 8) & 0xFF, - (y_end - 1) & 0xFF, - }, 4), TAG, "send command failed"); - // transfer frame buffer - size_t len = (x_end - x_start) * (y_end - y_start) * rm690b0->fb_bits_per_pixel / 8; - tx_color(rm690b0, io, LCD_CMD_RAMWR, color_data, len); - - return ESP_OK; -} - -static esp_err_t panel_rm690b0_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - esp_lcd_panel_io_handle_t io = rm690b0->io; - int command = 0; - if (invert_color_data) { - command = LCD_CMD_INVON; - } else { - command = LCD_CMD_INVOFF; - } - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_rm690b0_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - esp_lcd_panel_io_handle_t io = rm690b0->io; - - if (mirror_y) { - ESP_LOGE(TAG, "mirror_y is not supported by this panel"); - return ESP_ERR_NOT_SUPPORTED; - } - - if (mirror_x) { - rm690b0->madctl_val |= BIT(6); - } else { - rm690b0->madctl_val &= ~BIT(6); - } - - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, LCD_CMD_MADCTL, (uint8_t[]) { - rm690b0->madctl_val - }, 1), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_rm690b0_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) { - ESP_LOGE(TAG, "swap_xy is not supported by this panel"); - return ESP_ERR_NOT_SUPPORTED; -} - -static esp_err_t panel_rm690b0_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - rm690b0->x_gap = x_gap; - rm690b0->y_gap = y_gap; - return ESP_OK; -} - -static esp_err_t panel_rm690b0_disp_on_off(esp_lcd_panel_t *panel, bool on_off) { - rm690b0_panel_t *rm690b0 = __containerof(panel, rm690b0_panel_t, base); - esp_lcd_panel_io_handle_t io = rm690b0->io; - int command = 0; - - if (on_off) { - command = LCD_CMD_DISPON; - } else { - command = LCD_CMD_DISPOFF; - } - ESP_RETURN_ON_ERROR(tx_param(rm690b0, io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} diff --git a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h b/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h deleted file mode 100644 index f331f19970ce1..0000000000000 --- a/ports/espressif/common-hal/rm690b0/esp_lcd_rm690b0.h +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include - -#include "driver/spi_master.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_vendor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct { - int cmd; /* Date: Sat, 7 Feb 2026 17:41:00 +0100 Subject: [PATCH 18/38] Cleanup --- locale/circuitpython.pot | 29 ++ shared-bindings/sdcardio/SDCard.c | 189 ++++++++++ shared-bindings/sdcardio/SDCard.h | 25 ++ shared-bindings/sdcardio/__init__.c | 29 ++ shared-bindings/sdcardio/__init__.h | 7 + shared-module/sdcardio/SDCard.c | 523 ++++++++++++++++++++++++++++ shared-module/sdcardio/SDCard.h | 28 ++ shared-module/sdcardio/__init__.c | 127 +++++++ shared-module/sdcardio/__init__.h | 10 + 9 files changed, 967 insertions(+) create mode 100644 shared-bindings/sdcardio/SDCard.c create mode 100644 shared-bindings/sdcardio/SDCard.h create mode 100644 shared-bindings/sdcardio/__init__.c create mode 100644 shared-bindings/sdcardio/__init__.h create mode 100644 shared-module/sdcardio/SDCard.c create mode 100644 shared-module/sdcardio/SDCard.h create mode 100644 shared-module/sdcardio/__init__.c create mode 100644 shared-module/sdcardio/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 7e29d380a4532..e9a997fce4a52 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -688,6 +688,7 @@ msgstr "" #: ports/cxd56/common-hal/sdioio/SDCard.c #: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c +#: shared-module/sdcardio/SDCard.c #, c-format msgid "Buffer must be a multiple of %d bytes" msgstr "" @@ -2027,6 +2028,10 @@ msgstr "" msgid "Running in safe mode! Not running saved code.\n" msgstr "" +#: shared-module/sdcardio/SDCard.c +msgid "SD card CSD format not supported" +msgstr "" + #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "SDCard init" msgstr "" @@ -2902,6 +2907,10 @@ msgstr "" msgid "can't send non-None value to a just-started generator" msgstr "" +#: shared-module/sdcardio/SDCard.c +msgid "can't set 512 block size" +msgstr "" + #: py/objexcept.c py/objnamedtuple.c msgid "can't set attribute" msgstr "" @@ -3052,6 +3061,10 @@ msgstr "" msgid "could not invert Vandermonde matrix" msgstr "" +#: shared-module/sdcardio/SDCard.c +msgid "couldn't determine SD card version" +msgstr "" + #: extmod/ulab/code/numpy/numerical.c msgid "cross is defined for 1D arrays of length 3" msgstr "" @@ -3781,6 +3794,10 @@ msgstr "" msgid "nested index must be int" msgstr "" +#: shared-module/sdcardio/SDCard.c +msgid "no SD card" +msgstr "" + #: py/vm.c msgid "no active exception to reraise" msgstr "" @@ -3801,6 +3818,10 @@ msgstr "" msgid "no module named '%q'" msgstr "" +#: shared-module/sdcardio/SDCard.c +msgid "no response from SD card" +msgstr "" + #: ports/espressif/common-hal/espcamera/Camera.c py/objobject.c py/runtime.c msgid "no such attribute" msgstr "" @@ -4306,6 +4327,14 @@ msgstr "" msgid "timeout waiting for index pulse" msgstr "" +#: shared-module/sdcardio/SDCard.c +msgid "timeout waiting for v1 card" +msgstr "" + +#: shared-module/sdcardio/SDCard.c +msgid "timeout waiting for v2 card" +msgstr "" + #: ports/stm/common-hal/pwmio/PWMOut.c msgid "timer re-init" msgstr "" diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c new file mode 100644 index 0000000000000..d7978261cab9d --- /dev/null +++ b/shared-bindings/sdcardio/SDCard.c @@ -0,0 +1,189 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/objarray.h" + +#include "shared-bindings/sdcardio/SDCard.h" +#include "shared-module/sdcardio/SDCard.h" +#include "common-hal/busio/SPI.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/flash.h" + +//| class SDCard: +//| """SD Card Block Interface +//| +//| Controls an SD card over SPI. This built-in module has higher read +//| performance than the library adafruit_sdcard, but it is only compatible with +//| `busio.SPI`, not `bitbangio.SPI`. Usually an SDCard object is used +//| with ``storage.VfsFat`` to allow file I/O to an SD card.""" +//| +//| def __init__( +//| self, bus: busio.SPI, cs: microcontroller.Pin, baudrate: int = 8000000 +//| ) -> None: +//| """Construct an SPI SD Card object with the given properties +//| +//| :param busio.SPI spi: The SPI bus +//| :param microcontroller.Pin cs: The chip select connected to the card +//| :param int baudrate: The SPI data rate to use after card setup +//| +//| Note that during detection and configuration, a hard-coded low baudrate is used. +//| Data transfers use the specified baurate (rounded down to one that is supported by +//| the microcontroller) +//| +//| .. important:: +//| If the same SPI bus is shared with other peripherals, it is important that +//| the SD card be initialized before accessing any other peripheral on the bus. +//| Failure to do so can prevent the SD card from being recognized until it is +//| powered off or re-inserted. +//| +//| Example usage: +//| +//| .. code-block:: python +//| +//| import os +//| +//| import board +//| import sdcardio +//| import storage +//| +//| sd = sdcardio.SDCard(board.SPI(), board.SD_CS) +//| vfs = storage.VfsFat(sd) +//| storage.mount(vfs, '/sd') +//| os.listdir('/sd')""" +//| + +static mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_spi, ARG_cs, ARG_baudrate, NUM_ARGS }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = mp_const_none } }, + { MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = mp_const_none } }, + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 8000000} }, + }; + MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_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); + + busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj, MP_QSTR_spi); + const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + + sdcardio_sdcard_obj_t *self = mp_obj_malloc(sdcardio_sdcard_obj_t, &sdcardio_SDCard_type); + + common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int); + + return self; +} + + +//| def count(self) -> int: +//| """Returns the total number of sectors +//| +//| Due to technical limitations, this is a function and not a property. +//| +//| :return: The number of 512-byte blocks, as a number""" +//| +static mp_obj_t sdcardio_sdcard_count(mp_obj_t self_in) { + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + return mp_obj_new_int_from_ull(common_hal_sdcardio_sdcard_get_blockcount(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count); + +//| def deinit(self) -> None: +//| """Disable permanently. +//| +//| :return: None""" +//| +static mp_obj_t sdcardio_sdcard_deinit(mp_obj_t self_in) { + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + common_hal_sdcardio_sdcard_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit); + + +//| def readblocks(self, start_block: int, buf: WriteableBuffer) -> None: +//| """Read one or more blocks from the card +//| +//| :param int start_block: The block to start reading from +//| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512. +//| +//| :return: None""" +//| + +static mp_obj_t _sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { + uint32_t start_block = mp_obj_get_int(start_block_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + int result = common_hal_sdcardio_sdcard_readblocks(self, start_block, &bufinfo); + if (result < 0) { + mp_raise_OSError(-result); + } + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, _sdcardio_sdcard_readblocks); + +//| def sync(self) -> None: +//| """Ensure all blocks written are actually committed to the SD card +//| +//| :return: None""" +//| ... +//| +static mp_obj_t sdcardio_sdcard_sync(mp_obj_t self_in) { + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + int result = common_hal_sdcardio_sdcard_sync(self); + if (result < 0) { + mp_raise_OSError(-result); + } + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_sync_obj, sdcardio_sdcard_sync); + + +//| def writeblocks(self, start_block: int, buf: ReadableBuffer) -> None: +//| """Write one or more blocks to the card +//| +//| :param int start_block: The block to start writing from +//| :param ~circuitpython_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512. +//| +//| :return: None""" +//| +//| + +static mp_obj_t _sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { + uint32_t start_block = mp_obj_get_int(start_block_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + int result = common_hal_sdcardio_sdcard_writeblocks(self, start_block, &bufinfo); + if (result < 0) { + mp_raise_OSError(-result); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, _sdcardio_sdcard_writeblocks); + +static const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdcardio_sdcard_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&sdcardio_sdcard_sync_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdcardio_sdcard_writeblocks_obj) }, +}; +static MP_DEFINE_CONST_DICT(sdcardio_sdcard_locals_dict, sdcardio_sdcard_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + sdcardio_SDCard_type, + MP_QSTR_SDCard, + MP_TYPE_FLAG_NONE, + make_new, sdcardio_sdcard_make_new, + locals_dict, &sdcardio_sdcard_locals_dict + ); + diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h new file mode 100644 index 0000000000000..ac27b47aa4d21 --- /dev/null +++ b/shared-bindings/sdcardio/SDCard.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/sdcardio/SDCard.h" + +extern const mp_obj_type_t sdcardio_SDCard_type; + +void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate); +void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self); +void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self); +int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self); +int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); +int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self); +int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); + +// Used by native vfs blockdev. +mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); +mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); +bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value); diff --git a/shared-bindings/sdcardio/__init__.c b/shared-bindings/sdcardio/__init__.c new file mode 100644 index 0000000000000..7fb230189788f --- /dev/null +++ b/shared-bindings/sdcardio/__init__.c @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/sdcardio/SDCard.h" + +//| """Interface to an SD card via the SPI bus""" + +static const mp_rom_map_elem_t sdcardio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdcardio) }, + { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdcardio_SDCard_type) }, +}; + +static MP_DEFINE_CONST_DICT(sdcardio_module_globals, sdcardio_module_globals_table); + +const mp_obj_module_t sdcardio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&sdcardio_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_sdcardio, sdcardio_module); diff --git a/shared-bindings/sdcardio/__init__.h b/shared-bindings/sdcardio/__init__.h new file mode 100644 index 0000000000000..c9069db9fd7d5 --- /dev/null +++ b/shared-bindings/sdcardio/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c new file mode 100644 index 0000000000000..38ae387880afa --- /dev/null +++ b/shared-module/sdcardio/SDCard.c @@ -0,0 +1,523 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// This implementation largely follows the structure of adafruit_sdcard.py + +#include "extmod/vfs.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/sdcardio/SDCard.h" +#include "shared-bindings/time/__init__.h" +#include "shared-bindings/util.h" +#include "shared-module/sdcardio/SDCard.h" + +#include "py/mperrno.h" + +#if 0 +#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print,##__VA_ARGS__)) +#else +#define DEBUG_PRINT(...) ((void)0) +#endif + +#define CMD_TIMEOUT (200) + +#define R1_IDLE_STATE (1 << 0) +#define R1_ILLEGAL_COMMAND (1 << 2) + +#define TOKEN_CMD25 (0xFC) +#define TOKEN_STOP_TRAN (0xFD) +#define TOKEN_DATA (0xFE) + +static void common_hal_sdcardio_check_for_deinit(sdcardio_sdcard_obj_t *self) { + if (!self->bus) { + raise_deinited_error(); + } +} + +static bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) { + common_hal_sdcardio_check_for_deinit(self); + + if (!common_hal_busio_spi_try_lock(self->bus)) { + return false; + } + common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8); + common_hal_digitalio_digitalinout_set_value(&self->cs, false); + return true; +} + +static void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) { + if (!lock_and_configure_bus(self)) { + mp_raise_OSError(EAGAIN); + } +} + +static void clock_card(sdcardio_sdcard_obj_t *self, int bytes) { + uint8_t buf[] = {0xff}; + common_hal_digitalio_digitalinout_set_value(&self->cs, true); + for (int i = 0; i < bytes; i++) { + common_hal_busio_spi_write(self->bus, buf, 1); + } +} + +static void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) { + clock_card(self, 1); + common_hal_busio_spi_unlock(self->bus); +} + +static uint8_t CRC7(const uint8_t *data, uint8_t n) { + uint8_t crc = 0; + for (uint8_t i = 0; i < n; i++) { + uint8_t d = data[i]; + for (uint8_t j = 0; j < 8; j++) { + crc <<= 1; + if ((d & 0x80) ^ (crc & 0x80)) { + crc ^= 0x09; + } + d <<= 1; + } + } + return (crc << 1) | 1; +} + +#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms +static int wait_for_ready(sdcardio_sdcard_obj_t *self) { + uint64_t deadline = common_hal_time_monotonic_ns() + READY_TIMEOUT_NS; + while (common_hal_time_monotonic_ns() < deadline) { + uint8_t b; + common_hal_busio_spi_read(self->bus, &b, 1, 0xff); + if (b == 0xff) { + return 0; + } + } + return -ETIMEDOUT; +} + +// Note: this is never called while "in cmd25" (in fact, it's only used by `exit_cmd25`) +static bool cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { + uint8_t cmdbuf[2] = {cmd, 0xff}; + + assert(!self->in_cmd25); + + common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); + + // Wait for the response (response[7] == response) + for (int i = 0; i < CMD_TIMEOUT; i++) { + common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); + if (cmdbuf[0] == response) { + return 0; + } + } + return -EIO; +} + + +static int exit_cmd25(sdcardio_sdcard_obj_t *self) { + if (self->in_cmd25) { + DEBUG_PRINT("exit cmd25\n"); + self->in_cmd25 = false; + return cmd_nodata(self, TOKEN_STOP_TRAN, 0); + } + return 0; +} + +// In Python API, defaults are response=None, data_block=True, wait=True +static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf, size_t response_len, bool data_block, bool wait) { + int r = exit_cmd25(self); + if (r < 0) { + return r; + } + + DEBUG_PRINT("cmd % 3d [%02x] arg=% 11d [%08x] len=%d%s%s\n", cmd, cmd, arg, arg, response_len, data_block ? " data" : "", wait ? " wait" : ""); + uint8_t cmdbuf[6]; + cmdbuf[0] = cmd | 0x40; + cmdbuf[1] = (arg >> 24) & 0xff; + cmdbuf[2] = (arg >> 16) & 0xff; + cmdbuf[3] = (arg >> 8) & 0xff; + cmdbuf[4] = arg & 0xff; + cmdbuf[5] = CRC7(cmdbuf, 5); + + if (wait) { + r = wait_for_ready(self); + if (r < 0) { + return r; + } + } + + common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); + + // Wait for the response (response[7] == 0) + bool response_received = false; + for (int i = 0; i < CMD_TIMEOUT; i++) { + common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); + if ((cmdbuf[0] & 0x80) == 0) { + response_received = true; + break; + } + } + + if (!response_received) { + return -EIO; + } + + if (response_buf) { + + if (data_block) { + cmdbuf[1] = 0xff; + do { + // Wait for the start block byte + common_hal_busio_spi_read(self->bus, cmdbuf + 1, 1, 0xff); + } while (cmdbuf[1] != 0xfe); + } + + common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff); + + if (data_block) { + // Read and discard the CRC-CCITT checksum + common_hal_busio_spi_read(self->bus, cmdbuf + 1, 2, 0xff); + } + + } + + return cmdbuf[0]; +} + +static int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *response_buf, size_t response_len, bool data_block, bool wait) { + return cmd(self, cmd_, block * self->cdv, response_buf, response_len, true, true); +} + +static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) { + for (int i = 0; i < CMD_TIMEOUT; i++) { + if (cmd(self, 41, 0, NULL, 0, true, true) == 0) { + return NULL; + } + } + return MP_ERROR_TEXT("timeout waiting for v1 card"); +} + +static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) { + for (int i = 0; i < CMD_TIMEOUT; i++) { + uint8_t ocr[4]; + common_hal_time_delay_ms(50); + cmd(self, 58, 0, ocr, sizeof(ocr), false, true); + cmd(self, 55, 0, NULL, 0, true, true); + if (cmd(self, 41, 0x40000000, NULL, 0, true, true) == 0) { + cmd(self, 58, 0, ocr, sizeof(ocr), false, true); + if ((ocr[0] & 0x40) != 0) { + self->cdv = 1; + } + return NULL; + } + } + return MP_ERROR_TEXT("timeout waiting for v2 card"); +} + +static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) { + clock_card(self, 10); + + common_hal_digitalio_digitalinout_set_value(&self->cs, false); + + assert(!self->in_cmd25); + self->in_cmd25 = false; // should be false already + + // CMD0: init card: should return _R1_IDLE_STATE (allow 5 attempts) + { + bool reached_idle_state = false; + for (int i = 0; i < 5; i++) { + // do not call cmd with wait=true, because that will return + // prematurely if the idle state is not reached. we can't depend on + // this when the card is not yet in SPI mode + (void)wait_for_ready(self); + if (cmd(self, 0, 0, NULL, 0, true, false) == R1_IDLE_STATE) { + reached_idle_state = true; + break; + } + } + if (!reached_idle_state) { + return MP_ERROR_TEXT("no SD card"); + } + } + + // CMD8: determine card version + { + uint8_t rb7[4]; + int response = cmd(self, 8, 0x1AA, rb7, sizeof(rb7), false, true); + if (response == R1_IDLE_STATE) { + mp_rom_error_text_t result = init_card_v2(self); + if (result != NULL) { + return result; + } + } else if (response == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { + mp_rom_error_text_t result = init_card_v1(self); + if (result != NULL) { + return result; + } + } else { + DEBUG_PRINT("Reading card version, response=0x%02x\n", response); + return MP_ERROR_TEXT("couldn't determine SD card version"); + } + } + + // CMD9: get number of sectors + { + uint8_t csd[16]; + int response = cmd(self, 9, 0, csd, sizeof(csd), true, true); + if (response != 0) { + return MP_ERROR_TEXT("no response from SD card"); + } + int csd_version = (csd[0] & 0xC0) >> 6; + if (csd_version >= 2) { + return MP_ERROR_TEXT("SD card CSD format not supported"); + } + + if (csd_version == 1) { + self->sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024; + } else { + uint32_t block_length = 1 << (csd[5] & 0xF); + uint32_t c_size = ((csd[6] & 0x3) << 10) | (csd[7] << 2) | ((csd[8] & 0xC) >> 6); + uint32_t mult = 1 << (((csd[9] & 0x3) << 1 | (csd[10] & 0x80) >> 7) + 2); + self->sectors = block_length / 512 * mult * (c_size + 1); + } + } + + // CMD16: set block length to 512 bytes + { + int response = cmd(self, 16, 512, NULL, 0, true, true); + if (response != 0) { + return MP_ERROR_TEXT("can't set 512 block size"); + } + } + + return NULL; +} + +mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { + self->bus = bus; + common_hal_digitalio_digitalinout_construct(&self->cs, cs); + common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL); + + self->cdv = 512; + self->sectors = 0; + self->baudrate = 250000; + + lock_bus_or_throw(self); + mp_rom_error_text_t result = init_card(self); + extraclock_and_unlock_bus(self); + + if (result != NULL) { + common_hal_digitalio_digitalinout_deinit(&self->cs); + return result; + } + + self->baudrate = baudrate; + return NULL; +} + + +void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { + mp_rom_error_text_t result = sdcardio_sdcard_construct(self, bus, cs, baudrate); + if (result != NULL) { + mp_raise_OSError_msg(result); + } +} + +void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) { + if (!self->bus) { + return; + } + common_hal_sdcardio_sdcard_sync(self); + self->bus = 0; + common_hal_digitalio_digitalinout_deinit(&self->cs); +} + +int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { + common_hal_sdcardio_check_for_deinit(self); + return self->sectors; +} + +static int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) { + uint8_t aux[2] = {0, 0}; + while (aux[0] != 0xfe) { + common_hal_busio_spi_read(self->bus, aux, 1, 0xff); + } + + common_hal_busio_spi_read(self->bus, buf, size, 0xff); + + // Read checksum and throw it away + common_hal_busio_spi_read(self->bus, aux, sizeof(aux), 0xff); + return 0; +} + +mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) { + // deinit check is in lock_and_configure_bus() + sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (!lock_and_configure_bus(self)) { + return MP_EAGAIN; + } + int r = 0; + size_t buflen = 512 * nblocks; + if (nblocks == 1) { + // Use CMD17 to read a single block + r = block_cmd(self, 17, start_block, buf, buflen, true, true); + } else { + // Use CMD18 to read multiple blocks + r = block_cmd(self, 18, start_block, NULL, 0, true, true); + uint8_t *ptr = buf; + while (nblocks-- && r >= 0) { + r = readinto(self, ptr, 512); + if (r != 0) { + break; + } + ptr += 512; + } + + // End the multi-block read + r = cmd(self, 12, 0, NULL, 0, true, false); + + // Return first status 0 or last before card ready (0xff) + while (r != 0) { + uint8_t single_byte; + common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff); + if (single_byte & 0x80) { + break; + } + r = single_byte; + } + } + extraclock_and_unlock_bus(self); + return r; +} + +int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { + if (buf->len % 512 != 0) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); + } + + return sdcardio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); +} + +static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) { + wait_for_ready(self); + + uint8_t cmd[2]; + cmd[0] = token; + + common_hal_busio_spi_write(self->bus, cmd, 1); + common_hal_busio_spi_write(self->bus, buf, size); + + cmd[0] = cmd[1] = 0xff; + common_hal_busio_spi_write(self->bus, cmd, 2); + + // Check the response + // This differs from the traditional adafruit_sdcard handling, + // but adafruit_sdcard also ignored the return value of SDCard._write(!) + // so nobody noticed + // + // + // Response is as follows: + // x x x 0 STAT 1 + // 7 6 5 4 3..1 0 + // with STATUS 010 indicating "data accepted", and other status bit + // combinations indicating failure. + // In practice, I was seeing cmd[0] as 0xe5, indicating success + for (int i = 0; i < CMD_TIMEOUT; i++) { + common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); + DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]); + if ((cmd[0] & 0b00010001) == 0b00000001) { + if ((cmd[0] & 0x1f) != 0x5) { + return -EIO; + } else { + break; + } + } + } + + // Wait for the write to finish + do { + common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); + } while (cmd[0] == 0); + + // Success + return 0; +} + +mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) { + // deinit check is in lock_and_configure_bus() + sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (!lock_and_configure_bus(self)) { + return MP_EAGAIN; + } + + if (!self->in_cmd25 || start_block != self->next_block) { + DEBUG_PRINT("entering CMD25 at %d\n", (int)start_block); + // Use CMD25 to write multiple block + int r = block_cmd(self, 25, start_block, NULL, 0, true, true); + if (r < 0) { + extraclock_and_unlock_bus(self); + return r; + } + self->in_cmd25 = true; + } + + self->next_block = start_block; + + uint8_t *ptr = buf; + while (nblocks--) { + int r = _write(self, TOKEN_CMD25, ptr, 512); + if (r < 0) { + self->in_cmd25 = false; + extraclock_and_unlock_bus(self); + return r; + } + self->next_block++; + ptr += 512; + } + + extraclock_and_unlock_bus(self); + return 0; +} + +int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { + // deinit check is in lock_and_configure_bus() + lock_and_configure_bus(self); + int r = exit_cmd25(self); + extraclock_and_unlock_bus(self); + return r; +} + +int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { + // deinit check is in lock_and_configure_bus() + if (buf->len % 512 != 0) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); + } + lock_and_configure_bus(self); + int r = sdcardio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); + extraclock_and_unlock_bus(self); + return r; +} + +bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { + sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + common_hal_sdcardio_sdcard_sync(self); + break; // TODO properly + case MP_BLOCKDEV_IOCTL_SYNC: + common_hal_sdcardio_sdcard_sync(self); + break; + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = common_hal_sdcardio_sdcard_get_blockcount(self); + break; + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; + break; + default: + return false; + } + return true; +} + diff --git a/shared-module/sdcardio/SDCard.h b/shared-module/sdcardio/SDCard.h new file mode 100644 index 0000000000000..f9cd64b812532 --- /dev/null +++ b/shared-module/sdcardio/SDCard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/objarray.h" + +#include "common-hal/busio/SPI.h" +#include "common-hal/digitalio/DigitalInOut.h" + +typedef struct { + mp_obj_base_t base; + busio_spi_obj_t *bus; + digitalio_digitalinout_obj_t cs; + int cdv; + int baudrate; + uint32_t sectors; + uint32_t next_block; + bool in_cmd25; +} sdcardio_sdcard_obj_t; + +mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate); diff --git a/shared-module/sdcardio/__init__.c b/shared-module/sdcardio/__init__.c new file mode 100644 index 0000000000000..29c890c6870c1 --- /dev/null +++ b/shared-module/sdcardio/__init__.c @@ -0,0 +1,127 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "shared-module/sdcardio/__init__.h" + +#include "extmod/vfs_fat.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/sdcardio/SDCard.h" + +#include "supervisor/filesystem.h" + +#ifdef DEFAULT_SD_CARD_DETECT +static digitalio_digitalinout_obj_t sd_card_detect_pin; +static sdcardio_sdcard_obj_t sdcard; + +static mp_vfs_mount_t _sdcard_vfs; +fs_user_mount_t _sdcard_usermount; + +static bool _init_error = false; +static bool _mounted = false; + +#ifdef DEFAULT_SD_MOSI +static busio_spi_obj_t busio_spi_obj; +#else +#include "shared-bindings/board/__init__.h" +#endif +#endif + +void sdcardio_init(void) { + #ifdef DEFAULT_SD_CARD_DETECT + sd_card_detect_pin.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT); + common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP); + common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin); + #endif +} + +void automount_sd_card(void) { + #ifdef DEFAULT_SD_CARD_DETECT + if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) { + // No card. + _init_error = false; + if (_mounted) { + // Unmount the card. + mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table); + if (cur == &_sdcard_vfs) { + MP_STATE_VM(vfs_mount_table) = cur->next; + } else { + while (cur->next != &_sdcard_vfs && cur != NULL) { + cur = cur->next; + } + if (cur != NULL) { + cur->next = _sdcard_vfs.next; + } + } + _sdcard_vfs.next = NULL; + + #ifdef DEFAULT_SD_MOSI + common_hal_busio_spi_deinit(&busio_spi_obj); + #endif + _mounted = false; + } + return; + } else if (_init_error || _mounted) { + // We've already tried and failed to init the card. Don't try again. + return; + } + + busio_spi_obj_t *spi_obj; + #ifndef DEFAULT_SD_MOSI + spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0)); + #else + spi_obj = &busio_spi_obj; + spi_obj->base.type = &busio_spi_type; + common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false); + common_hal_busio_spi_never_reset(spi_obj); + #endif + sdcard.base.type = &sdcardio_SDCard_type; + mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000); + if (error != NULL) { + // Failed to communicate with the card. + _mounted = false; + _init_error = true; + #ifdef DEFAULT_SD_MOSI + common_hal_busio_spi_deinit(spi_obj); + #endif + return; + } + common_hal_digitalio_digitalinout_never_reset(&sdcard.cs); + + fs_user_mount_t *vfs = &_sdcard_usermount; + vfs->base.type = &mp_fat_vfs_type; + vfs->fatfs.drv = vfs; + + // Initialise underlying block device + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE + mp_vfs_blockdev_init(&vfs->blockdev, &sdcard); + + // mount the block device so the VFS methods can be used + FRESULT res = f_mount(&vfs->fatfs); + if (res != FR_OK) { + _mounted = false; + _init_error = true; + common_hal_sdcardio_sdcard_deinit(&sdcard); + #ifdef DEFAULT_SD_MOSI + common_hal_busio_spi_deinit(spi_obj); + #endif + return; + } + + filesystem_set_concurrent_write_protection(vfs, true); + filesystem_set_writable_by_usb(vfs, false); + + mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; + sdcard_vfs->str = "/sd"; + sdcard_vfs->len = 3; + sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); + sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); + MP_STATE_VM(vfs_mount_table) = sdcard_vfs; + _mounted = true; + #endif // DEFAULT_SD_CARD_DETECT +} diff --git a/shared-module/sdcardio/__init__.h b/shared-module/sdcardio/__init__.h new file mode 100644 index 0000000000000..59b4cf892f29b --- /dev/null +++ b/shared-module/sdcardio/__init__.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +void sdcardio_init(void); +void automount_sd_card(void); From 5a5eec64d126a13e85920fbb0fd545b524566353 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 17:44:23 +0100 Subject: [PATCH 19/38] Cleanup --- shared-bindings/sdcardio/SDCard.c | 1 - shared-module/sdcardio/SDCard.c | 1 - 2 files changed, 2 deletions(-) diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c index d7978261cab9d..e6d8453eae108 100644 --- a/shared-bindings/sdcardio/SDCard.c +++ b/shared-bindings/sdcardio/SDCard.c @@ -186,4 +186,3 @@ MP_DEFINE_CONST_OBJ_TYPE( make_new, sdcardio_sdcard_make_new, locals_dict, &sdcardio_sdcard_locals_dict ); - diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c index 38ae387880afa..bd3ea62d141e5 100644 --- a/shared-module/sdcardio/SDCard.c +++ b/shared-module/sdcardio/SDCard.c @@ -520,4 +520,3 @@ bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *o } return true; } - From 0621d5e72fb1ce5f783e95d178c26b0cef90303a Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 18:25:01 +0100 Subject: [PATCH 20/38] More cleanup --- ports/espressif/Makefile | 6 +- .../waveshare_esp32_s3_amoled_241/board.c | 2 +- .../mpconfigboard.h | 2 +- .../mpconfigboard.mk | 65 ++----------------- .../waveshare_esp32_s3_amoled_241/pins.c | 11 +--- .../waveshare_esp32_s3_amoled_241/sdkconfig | 2 +- py/circuitpy_defns.mk | 6 +- shared-module/busdisplay/BusDisplay.c | 2 - 8 files changed, 16 insertions(+), 80 deletions(-) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index dec6f045a3bbf..0c3f279cf24e1 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -722,6 +722,9 @@ endif ifneq ($(CIRCUITPY_PARALLELDISPLAYBUS),0) ESP_IDF_COMPONENTS_LINK += esp_lcd endif +ifneq ($(CIRCUITPY_QSPIBUS),0) + ESP_IDF_COMPONENTS_LINK += esp_lcd +endif ifneq ($(CIRCUITPY_USB_DEVICE),0) ESP_IDF_COMPONENTS_LINK += usb endif @@ -729,9 +732,6 @@ ifneq ($(CIRCUITPY_SDIOIO),0) ESP_IDF_COMPONENTS_LINK += sdmmc esp_driver_sdmmc endif -# Add any board-specific extra components -ESP_IDF_COMPONENTS_LINK += $(ESP_IDF_EXTRA_COMPONENTS) - ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a) MBEDTLS_COMPONENTS_LINK = crypto tls x509 diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c index e1b896210d8a3..10ef3d7274c48 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha // // SPDX-License-Identifier: MIT diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h index 7844a6eb5f486..6eca189f96869 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha // // SPDX-License-Identifier: MIT diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk index 700881459bb42..0546d90693390 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +# SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha # # SPDX-License-Identifier: MIT @@ -11,9 +11,7 @@ USB_PID = 0x82CE USB_MANUFACTURER = "Waveshare" USB_PRODUCT = "ESP32-S3-Touch-AMOLED-2.41" -# ESP32-S3 chip configuration IDF_TARGET = esp32s3 -CHIP_VARIANT = ESP32S3 # Flash configuration - 16MB QSPI Flash CIRCUITPY_ESP_FLASH_SIZE = 16MB @@ -25,68 +23,17 @@ CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m -# Add extra ESP-IDF components needed for board bring-up and display stack -ESP_IDF_EXTRA_COMPONENTS += driver freertos esp_lcd sdmmc esp_driver_sdmmc esp_driver_sdspi - -# Build optimization OPTIMIZATION_FLAGS = -Os -# Enable features for this board -CIRCUITPY_DISPLAYIO = 1 # QSPI bus for RM690B0 AMOLED display CIRCUITPY_QSPIBUS = 1 -CIRCUITPY_PARALLELDISPLAY = 0 -CIRCUITPY_RGBMATRIX = 0 -CIRCUITPY_BITMAPTOOLS = 1 -CIRCUITPY_JPEGIO = 1 -CIRCUITPY_FRAMEBUFFERIO = 1 - -# Enable ESP-NOW for peer-to-peer wireless communication -CIRCUITPY_ESPNOW = 1 +CIRCUITPY_PARALLELDISPLAYBUS = 0 -# Disable camera support (not present on this board) +# No camera on this board CIRCUITPY_ESPCAMERA = 0 -# Enable I2C for touch, RTC, and IMU -CIRCUITPY_BITBANGIO = 1 -CIRCUITPY_I2C = 1 - -# Enable SPI support -CIRCUITPY_SPI = 1 - -# Enable ADC for battery monitoring -CIRCUITPY_ANALOGIO = 1 - -# Enable WiFi and networking -CIRCUITPY_WIFI = 1 -CIRCUITPY_SOCKETPOOL = 1 -CIRCUITPY_SSL = 1 -CIRCUITPY_HASHLIB = 1 -CIRCUITPY_WEB_WORKFLOW = 1 - -# Enable USB features -CIRCUITPY_USB = 1 -CIRCUITPY_USB_CDC = 1 -CIRCUITPY_USB_HID = 1 -CIRCUITPY_USB_MIDI = 1 - -# Storage configuration -CIRCUITPY_STORAGE = 1 -CIRCUITPY_NVM = 1 -CIRCUITPY_SDIOIO = 1 - -# Enable touch support +# Capacitive touch not available; board uses I2C touch controller CIRCUITPY_TOUCHIO = 0 -CIRCUITPY_TOUCHSCREEN = 1 -# Enable RTC support -CIRCUITPY_RTC = 1 - -# Enable JSON support for configuration -CIRCUITPY_JSON = 1 - -# Enable other useful modules -CIRCUITPY_RANDOM = 1 -CIRCUITPY_STRUCT = 1 -CIRCUITPY_ULAB = 1 -CIRCUITPY_ZLIB = 1 +# SD card via SDMMC interface +CIRCUITPY_SDIOIO = 1 diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c index 8f24f8b067cd9..ab9c9b7ba389c 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025 Przemyslaw Patrick Socha +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha // // SPDX-License-Identifier: MIT @@ -61,15 +61,6 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO21) }, - // Backward-compatible aliases used by existing tests/scripts. - { MP_ROM_QSTR(MP_QSTR_QSPI_CS), MP_ROM_PTR(&pin_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_QSPI_CLK), MP_ROM_PTR(&pin_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_QSPI_D0), MP_ROM_PTR(&pin_GPIO11) }, - { MP_ROM_QSTR(MP_QSTR_QSPI_D1), MP_ROM_PTR(&pin_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_QSPI_D2), MP_ROM_PTR(&pin_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_QSPI_D3), MP_ROM_PTR(&pin_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_AMOLED_RESET), MP_ROM_PTR(&pin_GPIO21) }, - // Display Aliases { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_ROM_PTR(&pin_GPIO10) }, diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig index d41ee3bcebd58..3ef898aed3e46 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig @@ -26,7 +26,7 @@ CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-16MB.csv" # Networking CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-amoled" -# Disable USB-Serial/JTAG to free up I2C pins +# Disable USB-Serial/JTAG console - CircuitPython uses TinyUSB (USB OTG) for REPL CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=n # Enable .app_desc structure diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 12bcd35d48da4..f344486809c87 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -771,6 +771,8 @@ SRC_SHARED_MODULE_ALL = \ rgbmatrix/RGBMatrix.c \ rgbmatrix/__init__.c \ rotaryio/IncrementalEncoder.c \ + sdcardio/SDCard.c \ + sdcardio/__init__.c \ sharpdisplay/SharpMemoryFramebuffer.c \ sharpdisplay/__init__.c \ socket/__init__.c \ @@ -898,11 +900,9 @@ SRC_MOD += $(addprefix lib/AnimatedGIF/, \ $(BUILD)/lib/AnimatedGIF/gif.o: CFLAGS += -DCIRCUITPY endif -# tjpgd library is needed for JPEGIO support. -ifneq ($(filter 1,$(CIRCUITPY_JPEGIO)),) +ifeq ($(CIRCUITPY_JPEGIO),1) SRC_MOD += lib/tjpgd/src/tjpgd.c $(BUILD)/lib/tjpgd/src/tjpgd.o: CFLAGS += -Wno-shadow -Wno-cast-align -CFLAGS_MOD += -I$(TOP)/lib/tjpgd/src endif ifeq ($(CIRCUITPY_HASHLIB_MBEDTLS_ONLY),1) diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index 5fdd2436f2da3..d4d2c7a92d286 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -282,8 +282,6 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are } } - // RM690B0 over qspibus is unstable with single-row bursts. Keep chunks at - // two rows minimum when possible. if (mp_obj_is_type(self->bus.bus, &qspibus_qspibus_type) && self->core.colorspace.depth == 16 && !self->bus.data_as_commands && From 5946dd2411e1a8166cd9e4de932672e06e3fcf6e Mon Sep 17 00:00:00 2001 From: ppsx Date: Sat, 7 Feb 2026 21:53:41 +0100 Subject: [PATCH 21/38] Update ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c index ab9c9b7ba389c..9808630a21442 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -89,8 +89,6 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, // Available { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, // Available { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, // Available - { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, // Available - { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, // Available { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // Available { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, // Available { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, // Available From cb91159a087255fabff1c46fc1a3294fd784e591 Mon Sep 17 00:00:00 2001 From: ppsx Date: Sat, 7 Feb 2026 21:54:41 +0100 Subject: [PATCH 22/38] Update shared-bindings/qspibus/QSPIBus.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- shared-bindings/qspibus/QSPIBus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c index 493b93f4ee8d8..8f3d818ece953 100644 --- a/shared-bindings/qspibus/QSPIBus.c +++ b/shared-bindings/qspibus/QSPIBus.c @@ -111,7 +111,7 @@ static mp_obj_t qspibus_qspibus_send(size_t n_args, const mp_obj_t *pos_args, mp enum { ARG_command, ARG_data }; static const mp_arg_t allowed_args[] = { { MP_QSTR_command, MP_ARG_INT | MP_ARG_REQUIRED }, - { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; From d5723aee2c9acb494de14c9d7f5e72cd0a1a97ad Mon Sep 17 00:00:00 2001 From: ppsx Date: Sat, 7 Feb 2026 21:55:14 +0100 Subject: [PATCH 23/38] Update ports/espressif/common-hal/qspibus/QSPIBus.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- ports/espressif/common-hal/qspibus/QSPIBus.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 72b77d5f8145f..275d9a929e513 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -276,10 +276,10 @@ void common_hal_qspibus_qspibus_construct( const spi_bus_config_t bus_config = { .sclk_io_num = self->clock_pin, - .data0_io_num = self->data0_pin, - .data1_io_num = self->data1_pin, - .data2_io_num = self->data2_pin, - .data3_io_num = self->data3_pin, + .mosi_io_num = self->data0_pin, + .miso_io_num = self->data1_pin, + .quadwp_io_num = self->data2_pin, + .quadhd_io_num = self->data3_pin, .max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE, .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS, }; From 52c441715356fda6d4b5672bdf49c4ee4408b8ec Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 21:57:26 +0100 Subject: [PATCH 24/38] Update shared-bindings/qspibus/QSPIBus.c --- shared-bindings/qspibus/QSPIBus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c index 8f3d818ece953..446d311126e08 100644 --- a/shared-bindings/qspibus/QSPIBus.c +++ b/shared-bindings/qspibus/QSPIBus.c @@ -178,7 +178,12 @@ static mp_obj_t qspibus_qspibus___enter__(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(qspibus_qspibus___enter___obj, qspibus_qspibus___enter__); -//| def __exit__(self) -> None: +//| def __exit__( +//| self, +//| exc_type: type[BaseException] | None, +//| exc_value: BaseException | None, +//| traceback: TracebackType | None, +//| ) -> None: //| """Deinitialize on context manager exit.""" //| ... //| From cfc6d1bc3958340f3724d6f2588fea61ec7cb2df Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 22:11:56 +0100 Subject: [PATCH 25/38] Renamed CIRCUITPY_ESP32_CAMERA -> CIRCUITPY_CAMERA --- .../boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h index 6eca189f96869..765d1f1fa095b 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -38,4 +38,4 @@ #define DEFAULT_UART_BUS_TX (&pin_GPIO43) // Disable unnecessary modules to save space -#define CIRCUITPY_ESP32_CAMERA (0) +#define CIRCUITPY_CAMERA (0) From 1c28d4980d2d447b227908f0e78147440ec0f7e3 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 23:00:58 +0100 Subject: [PATCH 26/38] Fixed Copilot findings --- .../waveshare_esp32_s3_amoled_241/mpconfigboard.h | 12 ++++++------ .../boards/waveshare_esp32_s3_amoled_241/pins.c | 11 +++++------ py/circuitpy_mpconfig.h | 7 +++++++ shared-bindings/qspibus/QSPIBus.c | 4 +++- shared-module/busdisplay/BusDisplay.c | 4 ++-- shared-module/displayio/__init__.c | 9 +++++++++ shared-module/displayio/__init__.h | 6 ++++++ 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h index 765d1f1fa095b..b4d4df961bf41 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -17,6 +17,10 @@ #define CIRCUITPY_BOARD_I2C (0) #define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}} +// QSPI display refresh buffer: 2048 uint32_t words = 8KB on stack. +// ESP32-S3 main task stack is 24KB; verified safe with this board. +#define CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE (2048) + // AMOLED Display (displayio + qspibus path) #define CIRCUITPY_BOARD_DISPLAY (0) #define CIRCUITPY_LCD_CS (&pin_GPIO9) @@ -29,13 +33,9 @@ #define CIRCUITPY_LCD_POWER (&pin_GPIO16) #define CIRCUITPY_LCD_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low -// SPI bus for SD Card -#define CIRCUITPY_BOARD_SPI (1) -#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO4, .mosi = &pin_GPIO5, .miso = &pin_GPIO6}} +// No default SPI bus — SD card uses SDIO, display uses QSPI. +#define CIRCUITPY_BOARD_SPI (0) // Default UART bus #define DEFAULT_UART_BUS_RX (&pin_GPIO44) #define DEFAULT_UART_BUS_TX (&pin_GPIO43) - -// Disable unnecessary modules to save space -#define CIRCUITPY_CAMERA (0) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c index 9808630a21442..2ea4d02fd6648 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -70,12 +70,11 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_DISPLAY_D3), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY_RST), MP_ROM_PTR(&pin_GPIO21) }, - // SD Card (SPI) - { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO5) }, - { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO4) }, - { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_spi_obj) }, + // SD Card (SDIO / SDMMC) + { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D3), MP_ROM_PTR(&pin_GPIO2) }, // ================================================================= // GENERAL PURPOSE I/O (IOxx - Espressif Convention) diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 2754d57b01c9b..2f34fd1b4e53b 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -388,6 +388,13 @@ typedef long mp_off_t; #define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (128) #endif +// QSPI display buffer size in uint32_t words for _refresh_area() VLA. +// Allocated on stack; boards should verify sufficient stack headroom. +// Default 512 words = 2KB. Override per-board for larger buffers. +#ifndef CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE +#define CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE (512) +#endif + #else #define CIRCUITPY_DISPLAY_LIMIT (0) #define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (0) diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c index 446d311126e08..fdcc93af950a6 100644 --- a/shared-bindings/qspibus/QSPIBus.c +++ b/shared-bindings/qspibus/QSPIBus.c @@ -8,6 +8,7 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" +#include "shared-module/displayio/__init__.h" #include "py/binary.h" #include "py/obj.h" @@ -81,7 +82,8 @@ static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_arg uint32_t frequency = (uint32_t)mp_arg_validate_int_range(args[ARG_frequency].u_int, 1, 80000000, MP_QSTR_frequency); - qspibus_qspibus_obj_t *self = mp_obj_malloc(qspibus_qspibus_obj_t, &qspibus_qspibus_type); + qspibus_qspibus_obj_t *self = &allocate_display_bus_or_raise()->qspi_bus; + self->base.type = &qspibus_qspibus_type; common_hal_qspibus_qspibus_construct(self, clock, data0, data1, data2, data3, cs, dcx, reset, frequency); return MP_OBJ_FROM_PTR(self); diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index d4d2c7a92d286..56e81c82dcc3c 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -265,8 +265,8 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are self->core.colorspace.depth == 16 && !self->bus.data_as_commands && !self->bus.SH1107_addressing && - buffer_size < 2048) { - buffer_size = 2048; // 8KB uint32_t buffer + buffer_size < CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE) { + buffer_size = CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE; rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width(&clipped); if (rows_per_buffer == 0) { rows_per_buffer = 1; diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index f3444241b3cca..a52f33cae60dd 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -179,6 +179,10 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) { } else if (bus_type == &picodvi_framebuffer_type) { common_hal_picodvi_framebuffer_deinit(&display_buses[i].picodvi); #endif + #if CIRCUITPY_QSPIBUS + } else if (bus_type == &qspibus_qspibus_type) { + common_hal_qspibus_qspibus_deinit(&display_buses[i].qspi_bus); + #endif } display_buses[i].bus_base.type = &mp_type_NoneType; } @@ -329,6 +333,11 @@ void reset_displays(void) { // Set to None, gets deinit'd up by display_base display_buses[i].bus_base.type = &mp_type_NoneType; #endif + #if CIRCUITPY_QSPIBUS + } else if (display_bus_type == &qspibus_qspibus_type) { + // QSPIBus is self-contained (no heap sub-objects to inline). + // It persists across soft reloads in the display_buses pool. + #endif } else { // Not an active display bus. continue; diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h index 29b8c64c97240..bc06cf239e06f 100644 --- a/shared-module/displayio/__init__.h +++ b/shared-module/displayio/__init__.h @@ -38,6 +38,9 @@ #if CIRCUITPY_DOTCLOCKFRAMEBUFFER #include "common-hal/dotclockframebuffer/DotClockFramebuffer.h" #endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif // Port unique frame buffers. #if CIRCUITPY_VIDEOCORE #include "bindings/videocore/Framebuffer.h" @@ -81,6 +84,9 @@ typedef struct { #if CIRCUITPY_AURORA_EPAPER aurora_epaper_framebuffer_obj_t aurora_epaper; #endif + #if CIRCUITPY_QSPIBUS + qspibus_qspibus_obj_t qspi_bus; + #endif }; } primary_display_bus_t; From 2d11d9d3dd24323e9298a0a91d793b7389cb520a Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 23:17:40 +0100 Subject: [PATCH 27/38] Fixed 3/4 of Copilot suggestions --- ports/espressif/common-hal/qspibus/QSPIBus.c | 8 +++++++- ports/espressif/mpconfigport.mk | 1 - shared-module/busdisplay/BusDisplay.c | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 275d9a929e513..8e2610e1e19df 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -145,6 +145,8 @@ static void qspibus_send_color_bytes( while (remaining > 0) { if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); } } @@ -160,6 +162,8 @@ static void qspibus_send_color_bytes( uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)chunk_command << 8); esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, buffer, chunk); if (err != ESP_OK) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send color failed: %d"), err); } @@ -178,6 +182,8 @@ static void qspibus_send_color_bytes( // Keep Python/API semantics predictable: color transfer call returns only // after queued DMA chunks have completed. if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); } } @@ -504,7 +510,7 @@ bool common_hal_qspibus_qspibus_reset(mp_obj_t obj) { bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj) { qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); - return self->bus_initialized && !self->in_transaction; + return self->bus_initialized && !self->in_transaction && !self->transfer_in_progress; } bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj) { diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 3515bb3d6a69c..42bf3418f9639 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -78,7 +78,6 @@ CIRCUITPY_MEMORYMAP ?= 1 CIRCUITPY_RCLCPY ?= 0 CIRCUITPY_NVM ?= 1 CIRCUITPY_PARALLELDISPLAYBUS ?= 1 -CIRCUITPY_QSPIBUS ?= 1 CIRCUITPY_PS2IO ?= 1 CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_ROTARYIO ?= 1 diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index 56e81c82dcc3c..e980067248ba7 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -286,7 +286,8 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are self->core.colorspace.depth == 16 && !self->bus.data_as_commands && displayio_area_height(&clipped) > 1 && - rows_per_buffer < 2) { + rows_per_buffer < 2 && + (2 * displayio_area_width(&clipped) + pixels_per_word - 1) / pixels_per_word <= CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE) { rows_per_buffer = 2; subrectangles = displayio_area_height(&clipped) / rows_per_buffer; if (displayio_area_height(&clipped) % rows_per_buffer != 0) { From 14afb73e3686642d2b494d5a81ae2239eb0d474c Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 23:36:18 +0100 Subject: [PATCH 28/38] Fix in QSPIBus.c --- ports/espressif/common-hal/qspibus/QSPIBus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 8e2610e1e19df..725fe91d12981 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -108,6 +108,8 @@ static void qspibus_send_command_bytes( } if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI command timeout")); } } @@ -115,6 +117,8 @@ static void qspibus_send_command_bytes( uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); if (err != ESP_OK) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send failed: %d"), err); } } @@ -510,7 +514,7 @@ bool common_hal_qspibus_qspibus_reset(mp_obj_t obj) { bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj) { qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); - return self->bus_initialized && !self->in_transaction && !self->transfer_in_progress; + return self->bus_initialized && !self->in_transaction && !self->transfer_in_progress && !self->has_pending_command; } bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj) { From 5c4e9f4d80e67f2f63b86736ad87b8816104d130 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sat, 7 Feb 2026 23:51:55 +0100 Subject: [PATCH 29/38] Fix in pins.c --- ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c index 2ea4d02fd6648..437488e3f2b52 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -14,10 +14,13 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { // ONBOARD PERIPHERALS - Functional Names // ================================================================= - // Boot/Control/Battery + // Boot/Control/Battery/Display Power + // NOTE: GPIO16 is shared between battery control circuitry and LCD power + // (see CIRCUITPY_QSPIBUS_PANEL_POWER_PIN in mpconfigboard.h). { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_LCD_POWER), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO17) }, // I2C Bus (shared by Touch, RTC, IMU, IO Expander) From 0a96f3c252a6cdb7a04651eff8c325bbdafc5594 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 8 Feb 2026 00:11:48 +0100 Subject: [PATCH 30/38] More fixes --- ports/espressif/common-hal/qspibus/QSPIBus.c | 13 +++++++------ shared-bindings/qspibus/QSPIBus.c | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 725fe91d12981..7b9d02f187bab 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -6,6 +6,7 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" #include "py/gc.h" #include "py/runtime.h" @@ -104,7 +105,7 @@ static void qspibus_send_command_bytes( size_t len) { if (!self->bus_initialized) { - mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + raise_deinited_error(); } if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { @@ -130,7 +131,7 @@ static void qspibus_send_color_bytes( size_t len) { if (!self->bus_initialized) { - mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + raise_deinited_error(); } if (len == 0) { @@ -428,7 +429,7 @@ void common_hal_qspibus_qspibus_send_command_data( const uint8_t *data, size_t len) { if (!self->bus_initialized) { - mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + raise_deinited_error(); } if (self->in_transaction) { mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); @@ -455,7 +456,7 @@ void common_hal_qspibus_qspibus_write_command( qspibus_qspibus_obj_t *self, uint8_t command) { if (!self->bus_initialized) { - mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + raise_deinited_error(); } if (self->in_transaction) { mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); @@ -476,7 +477,7 @@ void common_hal_qspibus_qspibus_write_data( const uint8_t *data, size_t len) { if (!self->bus_initialized) { - mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + raise_deinited_error(); } if (self->in_transaction) { mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); @@ -537,7 +538,7 @@ void common_hal_qspibus_qspibus_send( qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); (void)chip_select; if (!self->bus_initialized) { - mp_raise_ValueError(MP_ERROR_TEXT("QSPI bus deinitialized")); + raise_deinited_error(); } if (!self->in_transaction) { mp_raise_RuntimeError(MP_ERROR_TEXT("Begin transaction first")); diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c index fdcc93af950a6..b41e47a7dc736 100644 --- a/shared-bindings/qspibus/QSPIBus.c +++ b/shared-bindings/qspibus/QSPIBus.c @@ -133,6 +133,10 @@ static mp_obj_t qspibus_qspibus_send(size_t n_args, const mp_obj_t *pos_args, mp len = data_bufinfo.len; } + // Wait for display bus to be available (mirrors FourWire.send() behavior). + while (!common_hal_qspibus_qspibus_bus_free(MP_OBJ_FROM_PTR(self))) { + RUN_BACKGROUND_TASKS; + } common_hal_qspibus_qspibus_send_command_data(self, command, data, len); return mp_const_none; } From a754bd1dbcf7fae896b5c95395c8ddf378327909 Mon Sep 17 00:00:00 2001 From: ppsx Date: Sun, 8 Feb 2026 00:23:50 +0100 Subject: [PATCH 31/38] Update locale/circuitpython.pot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- locale/circuitpython.pot | 4 ---- 1 file changed, 4 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index e9a997fce4a52..9cad9b5974205 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1904,10 +1904,6 @@ msgstr "" msgid "QSPI DMA buffers unavailable" msgstr "" -#: ports/espressif/common-hal/qspibus/QSPIBus.c -msgid "QSPI bus deinitialized" -msgstr "" - #: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "QSPI color timeout" msgstr "" From 3f5ffcc54f9ad90e64caa6ff81dfd30c151435d8 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 8 Feb 2026 00:29:40 +0100 Subject: [PATCH 32/38] Another fix in QSPIBus.c --- ports/espressif/common-hal/qspibus/QSPIBus.c | 29 ++++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 7b9d02f187bab..b93ba20cfdf3a 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -75,6 +75,17 @@ static bool qspibus_allocate_dma_buffers(qspibus_qspibus_obj_t *self) { return false; } +// Reset transfer bookkeeping after timeout/error. Drains any stale semaphore +// tokens that late ISR completions may have posted after the timeout expired. +static void qspibus_reset_transfer_state(qspibus_qspibus_obj_t *self) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; + if (self->transfer_done_sem != NULL) { + while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + } + } +} + static bool qspibus_wait_one_transfer_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { if (self->inflight_transfers == 0) { self->transfer_in_progress = false; @@ -109,8 +120,7 @@ static void qspibus_send_command_bytes( } if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { - self->inflight_transfers = 0; - self->transfer_in_progress = false; + qspibus_reset_transfer_state(self); mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI command timeout")); } } @@ -118,8 +128,7 @@ static void qspibus_send_command_bytes( uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); if (err != ESP_OK) { - self->inflight_transfers = 0; - self->transfer_in_progress = false; + qspibus_reset_transfer_state(self); mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send failed: %d"), err); } } @@ -150,8 +159,7 @@ static void qspibus_send_color_bytes( while (remaining > 0) { if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { - self->inflight_transfers = 0; - self->transfer_in_progress = false; + qspibus_reset_transfer_state(self); mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); } } @@ -167,8 +175,7 @@ static void qspibus_send_color_bytes( uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)chunk_command << 8); esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, buffer, chunk); if (err != ESP_OK) { - self->inflight_transfers = 0; - self->transfer_in_progress = false; + qspibus_reset_transfer_state(self); mp_raise_OSError_msg_varg(MP_ERROR_TEXT("QSPI send color failed: %d"), err); } @@ -187,8 +194,7 @@ static void qspibus_send_color_bytes( // Keep Python/API semantics predictable: color transfer call returns only // after queued DMA chunks have completed. if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { - self->inflight_transfers = 0; - self->transfer_in_progress = false; + qspibus_reset_transfer_state(self); mp_raise_OSError_msg(MP_ERROR_TEXT("QSPI color timeout")); } } @@ -203,8 +209,7 @@ static void qspibus_panel_sleep_best_effort(qspibus_qspibus_obj_t *self) { } if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { - self->inflight_transfers = 0; - self->transfer_in_progress = false; + qspibus_reset_transfer_state(self); } // If a command is buffered, flush it first so the panel state machine From 948393672a3d9bdb6cfcf99a152eecb474555e60 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 8 Feb 2026 00:43:25 +0100 Subject: [PATCH 33/38] Almost there... --- ports/espressif/common-hal/qspibus/QSPIBus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index b93ba20cfdf3a..21bf50734acc4 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -296,7 +296,7 @@ void common_hal_qspibus_qspibus_construct( .miso_io_num = self->data1_pin, .quadwp_io_num = self->data2_pin, .quadhd_io_num = self->data3_pin, - .max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE, + .max_transfer_sz = self->dma_buffer_size, .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS, }; From 3a9305abd88b704fe5975bcddf9c58bc0ab2d9fe Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 8 Feb 2026 01:01:22 +0100 Subject: [PATCH 34/38] Fixes: QSPI --- ports/espressif/common-hal/qspibus/QSPIBus.c | 3 +++ shared-bindings/qspibus/QSPIBus.c | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 21bf50734acc4..95f9a60a3c453 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -237,6 +237,9 @@ static bool IRAM_ATTR qspibus_on_color_trans_done( (void)event_data; qspibus_qspibus_obj_t *self = (qspibus_qspibus_obj_t *)user_ctx; + if (self->transfer_done_sem == NULL) { + return false; + } BaseType_t x_higher_priority_task_woken = pdFALSE; xSemaphoreGiveFromISR(self->transfer_done_sem, &x_higher_priority_task_woken); diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c index b41e47a7dc736..18419bf6c559c 100644 --- a/shared-bindings/qspibus/QSPIBus.c +++ b/shared-bindings/qspibus/QSPIBus.c @@ -133,11 +133,14 @@ static mp_obj_t qspibus_qspibus_send(size_t n_args, const mp_obj_t *pos_args, mp len = data_bufinfo.len; } - // Wait for display bus to be available (mirrors FourWire.send() behavior). - while (!common_hal_qspibus_qspibus_bus_free(MP_OBJ_FROM_PTR(self))) { + // Wait for display bus to be available, then acquire transaction. + // Mirrors FourWire.send() pattern: begin_transaction → send → end_transaction. + while (!common_hal_qspibus_qspibus_begin_transaction(MP_OBJ_FROM_PTR(self))) { RUN_BACKGROUND_TASKS; } - common_hal_qspibus_qspibus_send_command_data(self, command, data, len); + common_hal_qspibus_qspibus_send(MP_OBJ_FROM_PTR(self), DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, &command, 1); + common_hal_qspibus_qspibus_send(MP_OBJ_FROM_PTR(self), DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, data, len); + common_hal_qspibus_qspibus_end_transaction(MP_OBJ_FROM_PTR(self)); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(qspibus_qspibus_send_obj, 1, qspibus_qspibus_send); From f8a01a5dc3f1ad0be71986b04c0e714031182595 Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 8 Feb 2026 01:04:58 +0100 Subject: [PATCH 35/38] Removed dead code --- ports/espressif/common-hal/qspibus/QSPIBus.c | 32 ++------------------ shared-bindings/qspibus/QSPIBus.h | 5 --- 2 files changed, 3 insertions(+), 34 deletions(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 95f9a60a3c453..17da67ae5b060 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -389,8 +389,10 @@ void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { spi_bus_free(self->host_id); if (self->transfer_done_sem != NULL) { - vSemaphoreDelete(self->transfer_done_sem); + // Set NULL before delete so late ISR callbacks (if any) see NULL and skip. + SemaphoreHandle_t sem = self->transfer_done_sem; self->transfer_done_sem = NULL; + vSemaphoreDelete(sem); } qspibus_release_dma_buffers(self); @@ -431,34 +433,6 @@ void common_hal_qspibus_qspibus_send_command( qspibus_send_command_bytes(self, command, data, len); } -void common_hal_qspibus_qspibus_send_command_data( - qspibus_qspibus_obj_t *self, - uint8_t command, - const uint8_t *data, - size_t len) { - if (!self->bus_initialized) { - raise_deinited_error(); - } - if (self->in_transaction) { - mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); - } - - if (self->has_pending_command) { - qspibus_send_command_bytes(self, self->pending_command, NULL, 0); - self->has_pending_command = false; - } - - if (data == NULL || len == 0) { - qspibus_send_command_bytes(self, command, NULL, 0); - return; - } - - if (qspibus_is_color_payload_command(command)) { - qspibus_send_color_bytes(self, command, data, len); - } else { - qspibus_send_command_bytes(self, command, data, len); - } -} void common_hal_qspibus_qspibus_write_command( qspibus_qspibus_obj_t *self, diff --git a/shared-bindings/qspibus/QSPIBus.h b/shared-bindings/qspibus/QSPIBus.h index 93a0a258a0d13..1055ee7c6a5f5 100644 --- a/shared-bindings/qspibus/QSPIBus.h +++ b/shared-bindings/qspibus/QSPIBus.h @@ -36,11 +36,6 @@ void common_hal_qspibus_qspibus_send_command( uint8_t command, const uint8_t *data, size_t len); -void common_hal_qspibus_qspibus_send_command_data( - qspibus_qspibus_obj_t *self, - uint8_t command, - const uint8_t *data, - size_t len); void common_hal_qspibus_qspibus_write_command( qspibus_qspibus_obj_t *self, uint8_t command); From bcbf2cd2990569cb986ffd0381446b642fba945d Mon Sep 17 00:00:00 2001 From: ppsx Date: Sun, 8 Feb 2026 14:31:04 +0100 Subject: [PATCH 36/38] Update ports/espressif/common-hal/qspibus/QSPIBus.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- ports/espressif/common-hal/qspibus/QSPIBus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index 17da67ae5b060..b434b61b6d5a8 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -468,7 +468,7 @@ void common_hal_qspibus_qspibus_write_data( return; } if (data == NULL) { - mp_raise_ValueError(MP_ERROR_TEXT("data buffer is null")); + mp_raise_ValueError(MP_ERROR_TEXT("Data buffer is null")); } if (!self->has_pending_command) { mp_raise_ValueError(MP_ERROR_TEXT("No pending command")); From 964c30be22f8e2c9f12a306b895e87c7a7d6537b Mon Sep 17 00:00:00 2001 From: "P. Patrick Socha" Date: Sun, 8 Feb 2026 14:34:11 +0100 Subject: [PATCH 37/38] Fix in QSPIBus.c --- ports/espressif/common-hal/qspibus/QSPIBus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c index b434b61b6d5a8..7182869b6b600 100644 --- a/ports/espressif/common-hal/qspibus/QSPIBus.c +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -465,6 +465,10 @@ void common_hal_qspibus_qspibus_write_data( mp_raise_RuntimeError(MP_ERROR_TEXT("Bus in display transaction")); } if (len == 0) { + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } return; } if (data == NULL) { From 53a390d79aae1b14b0618ef96ae79c111c1ed6a2 Mon Sep 17 00:00:00 2001 From: ppsx Date: Sun, 8 Feb 2026 14:48:46 +0100 Subject: [PATCH 38/38] Update locale/circuitpython.pot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- locale/circuitpython.pot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 9cad9b5974205..a1d0f649d9ffe 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -3066,7 +3066,7 @@ msgid "cross is defined for 1D arrays of length 3" msgstr "" #: ports/espressif/common-hal/qspibus/QSPIBus.c -msgid "data buffer is null" +msgid "Data buffer is null" msgstr "" #: extmod/ulab/code/scipy/optimize/optimize.c