From 73b0a7eaa5d2eaf390bc8e6c002dbe33ac6d5e5c Mon Sep 17 00:00:00 2001 From: zhouli <1932489836@qq.com> Date: Thu, 9 Apr 2026 19:24:33 +0800 Subject: [PATCH] feat(demo): update lua module and board --- .gitlab/ci/astyle-rules.yml | 29 +- .gitlab/ci/build.yml | 33 +- .gitlab/ci/build_apps.py | 53 - application/basic_demo/CMakeLists.txt | 9 - .../esp32_S3_DevKitC_1/board_devices.yaml | 53 + .../boards/esp32_S3_DevKitC_1/board_info.yaml | 5 + .../esp32_S3_DevKitC_1/board_peripherals.yaml | 27 + .../sdkconfig.defaults.board | 9 + .../boards/esp32_S3_DevKitC_1/setup_device.c | 14 + .../boards/esp_SensairHalo/board_devices.yaml | 143 ++ .../boards/esp_SensairHalo/board_info.yaml | 5 + .../esp_SensairHalo/board_peripherals.yaml | 51 + .../esp_SensairHalo/sdkconfig.defaults.board | 20 + .../boards/esp_SensairHalo/setup_device.c | 131 + .../esp_SensairShuttle/board_devices.yaml | 87 + .../boards/esp_SensairShuttle/board_info.yaml | 5 + .../esp_SensairShuttle/board_peripherals.yaml | 63 + .../sdkconfig.defaults.board | 16 + .../boards/esp_SensairShuttle/setup_device.c | 85 + .../esp_vocat_board_v1_2/board_devices.yaml | 153 ++ .../esp_vocat_board_v1_2/board_info.yaml | 5 + .../board_peripherals.yaml | 94 + .../sdkconfig.defaults.board | 10 + .../esp_vocat_board_v1_2/setup_device.c | 233 ++ .../basic_demo/fatfs_image/lua/audio_demo.lua | 66 + .../fatfs_image/lua/audio_play_test_wav.lua | 30 + .../fatfs_image/lua/button_demo.lua | 58 + .../fatfs_image/lua/button_play_test_wav.lua | 66 + .../fatfs_image/lua/camera_capture_demo.lua | 69 + .../fatfs_image/lua/coroutine_demo.lua | 47 + .../fatfs_image/lua/display_demo.lua | 142 ++ .../basic_demo/fatfs_image/lua/gc_demo.lua | 33 + .../fatfs_image/lua/gc_userdata_demo.lua | 39 + .../fatfs_image/lua/lcd_touch_demo.lua | 53 + .../fatfs_image/lua/lcd_touch_paint.lua | 217 ++ .../fatfs_image/lua/led_strip_demo.lua | 40 + .../fatfs_image/lua/random_demo_stress.lua | 184 ++ application/basic_demo/fatfs_image/test.wav | Bin 0 -> 102340 bytes application/basic_demo/main/CMakeLists.txt | 47 +- application/basic_demo/main/app_clawgent.c | 13 +- .../basic_demo/main/basic_demo_lua_modules.c | 55 + application/basic_demo/main/idf_component.yml | 115 +- application/basic_demo/main/main.c | 2 + application/basic_demo/partitions.csv | 8 - application/basic_demo/partitions_16MB.csv | 7 + application/basic_demo/partitions_4MB.csv | 6 + application/basic_demo/partitions_8MB.csv | 7 + application/basic_demo/partitions_8mb.csv | 8 - application/basic_demo/sdkconfig.defaults | 9 +- .../cap_lua/src/cap_lua_async.c | 29 +- .../cap_lua/src/cap_lua_runtime.c | 4 + .../cap_lua/src/cmd_cap_lua.c | 80 +- .../lua_modules/esp_painter/CMakeLists.txt | 16 + components/lua_modules/esp_painter/Kconfig | 49 + .../lua_modules/esp_painter/esp_painter.c | 622 +++++ .../esp_painter/font/basic_font_12.c | 212 ++ .../esp_painter/font/basic_font_16.c | 212 ++ .../esp_painter/font/basic_font_20.c | 402 ++++ .../esp_painter/font/basic_font_24.c | 402 ++++ .../esp_painter/font/basic_font_28.c | 497 ++++ .../esp_painter/font/basic_font_32.c | 497 ++++ .../esp_painter/font/basic_font_36.c | 782 ++++++ .../esp_painter/font/basic_font_40.c | 877 +++++++ .../esp_painter/font/basic_font_44.c | 972 ++++++++ .../esp_painter/font/basic_font_48.c | 972 ++++++++ .../esp_painter/include/esp_painter.h | 83 + .../esp_painter/include/esp_painter_font.h | 65 + .../lua_module_audio/CMakeLists.txt | 10 + .../lua_module_audio/idf_component.yml | 3 + .../include/lua_module_audio.h | 11 + .../lua_module_audio/lua_module_audio.c | 743 ++++++ .../skills/lua_module_audio.md | 28 + .../lua_module_audio/skills/skills_list.json | 13 + .../lua_module_board_manager/CMakeLists.txt | 9 + .../include/lua_module_board_manager.h | 12 + .../lua_module_board_manager.c | 464 ++++ .../skills/lua_module_board_manager.md | 30 + .../skills/skills_list.json | 13 + .../lua_module_button/CMakeLists.txt | 8 + .../lua_module_button/idf_component.yml | 3 + .../include/lua_module_button.h | 11 + .../lua_module_button/lua_module_button.c | 498 ++++ .../skills/lua_module_button.md | 26 + .../lua_module_button/skills/skills_list.json | 13 + .../lua_module_camera/CMakeLists.txt | 12 + .../lua_module_camera/idf_component.yml | 4 + .../include/lua_module_camera.h | 20 + .../skills/lua_module_camera.md | 25 + .../lua_module_camera/skills/skills_list.json | 13 + .../lua_module_camera/src/lua_module_camera.c | 209 ++ .../src/lua_module_camera_service.c | 672 ++++++ .../src/lua_module_camera_service.h | 42 + .../lua_module_display/CMakeLists.txt | 12 + .../lua_module_display/idf_component.yml | 3 + .../lua_module_display/include/display_hal.h | 136 ++ .../include/lua_module_display.h | 23 + .../skills/lua_module_display.md | 433 ++++ .../skills/skills_list.json | 13 + .../lua_module_display/src/display_hal.c | 2142 +++++++++++++++++ .../src/lua_module_display.c | 1288 ++++++++++ .../lua_module_esp_heap/CMakeLists.txt | 10 + .../include/lua_module_esp_heap.h | 18 + .../lua_module_esp_heap/lua_module_esp_heap.c | 191 ++ .../skills/lua_module_esp_heap.md | 22 + .../skills/skills_list.json | 13 + .../lua_module_lcd_touch/CMakeLists.txt | 9 + .../include/lua_module_lcd_touch.h | 20 + .../skills/lua_module_lcd_touch.md | 23 + .../skills/skills_list.json | 13 + .../src/lua_module_lcd_touch.c | 290 +++ .../lua_module_led_strip/CMakeLists.txt | 1 - .../lua_module_led_strip/idf_component.yml | 3 + 112 files changed, 16786 insertions(+), 196 deletions(-) create mode 100644 application/basic_demo/boards/esp32_S3_DevKitC_1/board_devices.yaml create mode 100644 application/basic_demo/boards/esp32_S3_DevKitC_1/board_info.yaml create mode 100644 application/basic_demo/boards/esp32_S3_DevKitC_1/board_peripherals.yaml create mode 100644 application/basic_demo/boards/esp32_S3_DevKitC_1/sdkconfig.defaults.board create mode 100644 application/basic_demo/boards/esp32_S3_DevKitC_1/setup_device.c create mode 100644 application/basic_demo/boards/esp_SensairHalo/board_devices.yaml create mode 100644 application/basic_demo/boards/esp_SensairHalo/board_info.yaml create mode 100644 application/basic_demo/boards/esp_SensairHalo/board_peripherals.yaml create mode 100644 application/basic_demo/boards/esp_SensairHalo/sdkconfig.defaults.board create mode 100644 application/basic_demo/boards/esp_SensairHalo/setup_device.c create mode 100644 application/basic_demo/boards/esp_SensairShuttle/board_devices.yaml create mode 100644 application/basic_demo/boards/esp_SensairShuttle/board_info.yaml create mode 100644 application/basic_demo/boards/esp_SensairShuttle/board_peripherals.yaml create mode 100644 application/basic_demo/boards/esp_SensairShuttle/sdkconfig.defaults.board create mode 100644 application/basic_demo/boards/esp_SensairShuttle/setup_device.c create mode 100644 application/basic_demo/boards/esp_vocat_board_v1_2/board_devices.yaml create mode 100644 application/basic_demo/boards/esp_vocat_board_v1_2/board_info.yaml create mode 100644 application/basic_demo/boards/esp_vocat_board_v1_2/board_peripherals.yaml create mode 100644 application/basic_demo/boards/esp_vocat_board_v1_2/sdkconfig.defaults.board create mode 100644 application/basic_demo/boards/esp_vocat_board_v1_2/setup_device.c create mode 100644 application/basic_demo/fatfs_image/lua/audio_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/audio_play_test_wav.lua create mode 100644 application/basic_demo/fatfs_image/lua/button_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/button_play_test_wav.lua create mode 100644 application/basic_demo/fatfs_image/lua/camera_capture_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/coroutine_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/display_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/gc_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/gc_userdata_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/lcd_touch_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/lcd_touch_paint.lua create mode 100644 application/basic_demo/fatfs_image/lua/led_strip_demo.lua create mode 100644 application/basic_demo/fatfs_image/lua/random_demo_stress.lua create mode 100644 application/basic_demo/fatfs_image/test.wav delete mode 100644 application/basic_demo/partitions.csv create mode 100644 application/basic_demo/partitions_16MB.csv create mode 100644 application/basic_demo/partitions_4MB.csv create mode 100644 application/basic_demo/partitions_8MB.csv delete mode 100644 application/basic_demo/partitions_8mb.csv create mode 100644 components/lua_modules/esp_painter/CMakeLists.txt create mode 100644 components/lua_modules/esp_painter/Kconfig create mode 100644 components/lua_modules/esp_painter/esp_painter.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_12.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_16.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_20.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_24.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_28.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_32.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_36.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_40.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_44.c create mode 100644 components/lua_modules/esp_painter/font/basic_font_48.c create mode 100644 components/lua_modules/esp_painter/include/esp_painter.h create mode 100644 components/lua_modules/esp_painter/include/esp_painter_font.h create mode 100644 components/lua_modules/lua_module_audio/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_audio/idf_component.yml create mode 100644 components/lua_modules/lua_module_audio/include/lua_module_audio.h create mode 100644 components/lua_modules/lua_module_audio/lua_module_audio.c create mode 100644 components/lua_modules/lua_module_audio/skills/lua_module_audio.md create mode 100644 components/lua_modules/lua_module_audio/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_board_manager/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_board_manager/include/lua_module_board_manager.h create mode 100644 components/lua_modules/lua_module_board_manager/lua_module_board_manager.c create mode 100644 components/lua_modules/lua_module_board_manager/skills/lua_module_board_manager.md create mode 100644 components/lua_modules/lua_module_board_manager/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_button/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_button/idf_component.yml create mode 100644 components/lua_modules/lua_module_button/include/lua_module_button.h create mode 100644 components/lua_modules/lua_module_button/lua_module_button.c create mode 100644 components/lua_modules/lua_module_button/skills/lua_module_button.md create mode 100644 components/lua_modules/lua_module_button/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_camera/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_camera/idf_component.yml create mode 100644 components/lua_modules/lua_module_camera/include/lua_module_camera.h create mode 100644 components/lua_modules/lua_module_camera/skills/lua_module_camera.md create mode 100644 components/lua_modules/lua_module_camera/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_camera/src/lua_module_camera.c create mode 100644 components/lua_modules/lua_module_camera/src/lua_module_camera_service.c create mode 100644 components/lua_modules/lua_module_camera/src/lua_module_camera_service.h create mode 100644 components/lua_modules/lua_module_display/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_display/idf_component.yml create mode 100644 components/lua_modules/lua_module_display/include/display_hal.h create mode 100644 components/lua_modules/lua_module_display/include/lua_module_display.h create mode 100644 components/lua_modules/lua_module_display/skills/lua_module_display.md create mode 100644 components/lua_modules/lua_module_display/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_display/src/display_hal.c create mode 100644 components/lua_modules/lua_module_display/src/lua_module_display.c create mode 100644 components/lua_modules/lua_module_esp_heap/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_esp_heap/include/lua_module_esp_heap.h create mode 100644 components/lua_modules/lua_module_esp_heap/lua_module_esp_heap.c create mode 100644 components/lua_modules/lua_module_esp_heap/skills/lua_module_esp_heap.md create mode 100644 components/lua_modules/lua_module_esp_heap/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_lcd_touch/CMakeLists.txt create mode 100644 components/lua_modules/lua_module_lcd_touch/include/lua_module_lcd_touch.h create mode 100644 components/lua_modules/lua_module_lcd_touch/skills/lua_module_lcd_touch.md create mode 100644 components/lua_modules/lua_module_lcd_touch/skills/skills_list.json create mode 100644 components/lua_modules/lua_module_lcd_touch/src/lua_module_lcd_touch.c create mode 100644 components/lua_modules/lua_module_led_strip/idf_component.yml diff --git a/.gitlab/ci/astyle-rules.yml b/.gitlab/ci/astyle-rules.yml index 8a29d0a..c4a6faf 100644 --- a/.gitlab/ci/astyle-rules.yml +++ b/.gitlab/ci/astyle-rules.yml @@ -22,34 +22,7 @@ not_formatted_permanent: # - Upstream source code we don't want to modify # - Generated files check: false - include: - - "components/audio/dac_audio/test/wave_1ch_16bits.c" - - "components/audio/dac_audio/test/wave_1ch_8bits.c" - - "components/audio/dac_audio/test/wave_2ch_16bits.c" - - "components/audio/dac_audio/test/wave_2ch_8bits.c" - - "components/audio/pwm_audio/test/wave_1ch_16bits.c" - - "components/audio/pwm_audio/test/wave_1ch_8bits.c" - - "components/audio/pwm_audio/test/wave_2ch_16bits.c" - - "components/audio/pwm_audio/test/wave_2ch_8bits.c" - - "components/bluetooth/ble_profiles/esp/ble_ota/proto-c/" - - "components/bluetooth/ble_profiles/esp/ble_ota/python/" - - "components/display/touch_panel/calibration/basic_painter/fonts/" - - "components/usb/usb_stream/test_apps/main/wave_1ch_16bits.c" - - "components/utilities/xz/" - - "docs/_static/esp32s2_adc_range_to_3300.patch" - - "docs/_static/esp32s2_adc_range_to_3300_v531.patch" - - "docs/_static/esp32s3_adc_range_to_3300.patch" - - "docs/_static/esp32s3_adc_range_to_3300_v531.patch" - - "docs/doxygen-known-warnings.txt" - - "docs/sphinx-known-warnings.txt" - - "examples/usb/device/usb_webcam/eyes_show/" - - "examples/ai/esp_dl/self_learning_classification/main/ui" - - "examples/usb/host/usb_camera_lcd_display/components/esp_painter/font/" - - "examples/usb/host/usb_camera_mic_spk/main/wave_1ch_16bits.c" - - "examples/robot/ragtime_panther/follower/main/ui/" - - "components/sensors/gas/bme690/bme69x.c" - - "components/sensors/gas/bme690/bme69x.h" - - "components/sensors/gas/bme690/bme69x_defs.h" + docs: # Docs directory contains some .inc files, which are not C include files diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 7b02f15..689aa82 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -38,15 +38,16 @@ # By configuring this macro, you can append the compiled configuration file. # For example, using "sdkconf.etc=default" specifies the default sdkconfig file. EXAMPLE_CONFIG: "=" + EXAMPLE_TARGET: "" EXAMPLE_APPEND_ARGS: "" EXAMPLE_BOARD: "default" BUILD_RECURSIVE: "1" script: - - pip install idf_build_apps + - pip install idf_build_apps esp-bmgr-assist - | python .gitlab/ci/build_apps.py ${EXAMPLE_DIR} \ --config ${EXAMPLE_CONFIG} \ - -t all \ + -t ${EXAMPLE_TARGET} \ -r ${BUILD_RECURSIVE} \ -vv \ --board ${EXAMPLE_BOARD} \ @@ -62,25 +63,25 @@ .build_idf_active_release_version: parallel: matrix: # EOL date - - IMAGE: espressif/idf:release-v5.5 # 2028-01-21 - -# ESP-IDF 6.0 is currently in pre-release stage. - -.build_idf_active_release_version_with_pre_release: - parallel: - matrix: - - IMAGE: espressif/idf:release-v5.2 - - IMAGE: espressif/idf:release-v5.3 - - IMAGE: espressif/idf:release-v5.4 - - IMAGE: espressif/idf:release-v5.5 - - IMAGE: espressif/idf:release-v6.0 - build_application_basic_demo: extends: - .build_examples_template - .rules:build:application_basic_demo - - .build_idf_active_release_version + parallel: + matrix: + - IMAGE: espressif/idf:release-v5.5 + EXAMPLE_BOARD: esp_SensairHalo + EXAMPLE_TARGET: esp32c5 + - IMAGE: espressif/idf:release-v5.5 + EXAMPLE_BOARD: esp_SensairShuttle + EXAMPLE_TARGET: esp32c5 + - IMAGE: espressif/idf:release-v5.5 + EXAMPLE_BOARD: esp_vocat_board_v1_2 + EXAMPLE_TARGET: esp32s3 + - IMAGE: espressif/idf:release-v5.5 + EXAMPLE_BOARD: esp32_S3_DevKitC_1 + EXAMPLE_TARGET: esp32s3 variables: EXAMPLE_DIR: application/basic_demo diff --git a/.gitlab/ci/build_apps.py b/.gitlab/ci/build_apps.py index e11964e..4ee3a85 100644 --- a/.gitlab/ci/build_apps.py +++ b/.gitlab/ci/build_apps.py @@ -134,50 +134,6 @@ class CustomApp(CMakeApp): shutil.rmtree(proj_path / 'components' / 'gen_bmgr_codes', ignore_errors=True) (proj_path / 'board_manager.defaults').unlink(missing_ok=True) - def _download_bmgr_component(self) -> bool: - """ - Extract the esp_board_manager dependency from the manifest file and download it. - Returns True if successful, False otherwise. - """ - if not all([yaml, download_project_dependencies, ManifestManager, ProjectRequirements]): - logger.warning('idf-component-manager is not available, cannot download board manager component') - return False - - proj = Path(self.work_dir).absolute() - managed_path = proj / 'managed_components' - lock_path = proj / 'dependencies.lock' - - bmgr_dep = self._find_bmgr_dependency() - if not bmgr_dep: - logger.warning( - 'esp_board_manager dependency not found in project manifests under %s/main or %s/components/*', - proj, - proj, - ) - return False - - manifest_path, bmgr_key, bmgr_value = bmgr_dep - - managed_path.mkdir(parents=True, exist_ok=True) - - try: - with tempfile.TemporaryDirectory() as temp_dir: - temp_manifest = Path(temp_dir) / 'idf_component.yml' - with open(temp_manifest, 'w', encoding='utf-8') as f: - yaml.dump({'dependencies': {bmgr_key: bmgr_value}}, f) - - manifest = ManifestManager(str(temp_dir), 'temp').load() - download_project_dependencies( - ProjectRequirements([manifest]), - str(lock_path), - str(managed_path), - ) - logger.info('Successfully downloaded esp_board_manager component from %s to %s', manifest_path, managed_path) - return True - except Exception as e: - logger.error('Error downloading esp_board_manager component: %s', e) - return False - def _pre_hook(self, board_name: str) -> None: logger.info( "Pre build hook for app '%s' at '%s' for target '%s', board '%s'", @@ -194,17 +150,8 @@ class CustomApp(CMakeApp): logger.warning('IDF_PATH is not set; skip board manager config generation.') return - # Download board manager component if needed - bmgr_path = Path(self.work_dir).absolute() / 'managed_components' / 'espressif__esp_board_manager' - if not bmgr_path.exists(): - logger.info('Board manager component not found, downloading...') - if not self._download_bmgr_component(): - logger.error('Failed to download board manager component, cannot generate config') - return - # Set environment variable for IDF_EXTRA_ACTIONS_PATH env = os.environ.copy() - env['IDF_EXTRA_ACTIONS_PATH'] = str(bmgr_path) subprocess.run( [ diff --git a/application/basic_demo/CMakeLists.txt b/application/basic_demo/CMakeLists.txt index 7ea5fab..dd1bf86 100644 --- a/application/basic_demo/CMakeLists.txt +++ b/application/basic_demo/CMakeLists.txt @@ -1,14 +1,5 @@ cmake_minimum_required(VERSION 3.16) -set(EXTRA_COMPONENT_DIRS - "../../components/claw_modules" - "../../components/lua_modules" - "../../components/claw_capabilities" - ) -if(NOT DEFINED IDF_TARGET) - set(IDF_TARGET "esp32s3" CACHE STRING "ESP-IDF target") -endif() - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(basic_demo) diff --git a/application/basic_demo/boards/esp32_S3_DevKitC_1/board_devices.yaml b/application/basic_demo/boards/esp32_S3_DevKitC_1/board_devices.yaml new file mode 100644 index 0000000..594490e --- /dev/null +++ b/application/basic_demo/boards/esp32_S3_DevKitC_1/board_devices.yaml @@ -0,0 +1,53 @@ +version: 1.0.0 +# Devices Configuration +devices: + + - name: led_strip + chip: ws2812 + type: custom + version: default + init_skip: true + dependencies: + espressif/led_strip: + version: "^3.0" + public: true + config: + max_leds: 1 # Number of LEDs in the strip + peripherals: + - name: rmt_tx # RMT TX peripheral used by the LED strip + + # Example GPIO Button device configuration + - name: gpio_button_0 # The name of the device, must be unique + type: button # The type of the device + sub_type: gpio # Button sub type: "gpio", "adc_single", or "adc_multi" + config: + # GPIO Configuration + active_level: 0 # [TO_BE_CONFIRMED] Active level (0-low, 1-high) when button is pressed + enable_power_save: false # Enable power save mode (default: false) + disable_pull: false # Disable internal pull-up/pull-down (default: false) + + # Button Timing Configuration + long_press_time: 2000 # Long press time in milliseconds (default: 2000) + short_press_time: 100 # Short press time in milliseconds (default: 100) + + # Event Configuration (NEW - Easy button features) + events_cfg: + press_down: true # Enable press down event (default: true) + press_up: true # Enable press up event (default: true) + single_click: true # Enable single click event (default: true) + double_click: true # Enable double click event (default: true) + multi_click: false # Enable multi click event (default: false) + click_counts: [] # Multi click counts configuration (default: []) + # eg: Set to [3, 4] means enable multi_click event with 3 and 4 counts + long_press_start: true # Enable long press start event (default: true) + long_press_start_time: [] # Long press start time configuration in ms (default: []) + # eg: Set to [3000, 4000] means enable long_press_start event with 3 and 4 seconds + long_press_hold: false # Enable long press hold event (default: false) + long_press_up: true # Enable long press up event (default: true) + long_press_up_time: [] # Long press up time configuration in ms (default: []) + press_repeat: false # Enable press repeat event (default: false) + press_repeat_done: false # Enable press repeat done event (default: false) + press_end: false # Enable press end event (default: false) + + peripherals: + - name: gpio_button # [TO_BE_CONFIRMED] GPIO peripheral name diff --git a/application/basic_demo/boards/esp32_S3_DevKitC_1/board_info.yaml b/application/basic_demo/boards/esp32_S3_DevKitC_1/board_info.yaml new file mode 100644 index 0000000..2d9ce06 --- /dev/null +++ b/application/basic_demo/boards/esp32_S3_DevKitC_1/board_info.yaml @@ -0,0 +1,5 @@ +board: esp32_S3_DevKitC_1 +chip: esp32s3 +version: 1.3.0 +description: "ESP32-S3-DevKitC-1 Development Board" +manufacturer: "ESPRESSIF" diff --git a/application/basic_demo/boards/esp32_S3_DevKitC_1/board_peripherals.yaml b/application/basic_demo/boards/esp32_S3_DevKitC_1/board_peripherals.yaml new file mode 100644 index 0000000..855ff8a --- /dev/null +++ b/application/basic_demo/boards/esp32_S3_DevKitC_1/board_peripherals.yaml @@ -0,0 +1,27 @@ +version: 1.0.0 +# Peripherals Configuration +peripherals: + - name: gpio_button + type: gpio + config: + pin: 0 + mode: GPIO_MODE_INPUT + default_level: 1 + + - name: rmt_tx + type: rmt + role: tx + config: + gpio_num: 38 + clk_src: RMT_CLK_SRC_DEFAULT + resolution_hz: 10000000 + mem_block_symbols: 64 + trans_queue_depth: 4 + intr_priority: 1 + flags: + invert_out: false + with_dma: true # RMT peripheral can connect to DMA channel in esp32s3 + io_loop_back: false + io_od_mode: false + allow_pd: false + init_level: false diff --git a/application/basic_demo/boards/esp32_S3_DevKitC_1/sdkconfig.defaults.board b/application/basic_demo/boards/esp32_S3_DevKitC_1/sdkconfig.defaults.board new file mode 100644 index 0000000..98269c9 --- /dev/null +++ b/application/basic_demo/boards/esp32_S3_DevKitC_1/sdkconfig.defaults.board @@ -0,0 +1,9 @@ + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_120M=y +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_8MB.csv" +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_120M=y diff --git a/application/basic_demo/boards/esp32_S3_DevKitC_1/setup_device.c b/application/basic_demo/boards/esp32_S3_DevKitC_1/setup_device.c new file mode 100644 index 0000000..a1be78d --- /dev/null +++ b/application/basic_demo/boards/esp32_S3_DevKitC_1/setup_device.c @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_log.h" +#include "esp_check.h" +#include "esp_board_manager_includes.h" +#include "gen_board_device_custom.h" +#include "periph_rmt.h" +#include "led_strip.h" +#include "led_strip_rmt.h" +#include "led_strip_types.h" diff --git a/application/basic_demo/boards/esp_SensairHalo/board_devices.yaml b/application/basic_demo/boards/esp_SensairHalo/board_devices.yaml new file mode 100644 index 0000000..80b635c --- /dev/null +++ b/application/basic_demo/boards/esp_SensairHalo/board_devices.yaml @@ -0,0 +1,143 @@ +version: 1.0.0 +# Devices Configuration +devices: + - name: display_lcd + type: display_lcd + version: default + sub_type: parlio + chip: ili9341 + dependencies: + espressif/esp_lcd_ili9341: "*" + config: + mirror_x: false + mirror_y: true + swap_xy: true + x_max: 284 # [TO_BE_CONFIRMED] Horizontal resolution + y_max: 240 # [TO_BE_CONFIRMED] Vertical resolution + need_reset: true # Whether to reset the LCD panel during initialization (default: true) + # dev_display_lcd_parlio_sub_config_t fields for Parlio communication + io_parl_config: + dc_gpio_num: 7 # [IO] GPIO used for D/C line + clk_gpio_num: 1 # [IO] GPIO used for CLK line + cs_gpio_num: 6 # [IO] GPIO used for CS line + # GPIOs used for data lines (ESP_PARLIO_LCD_WIDTH_MAX == 8); 1-line SPI uses index 0 only, rest -1 + data_gpio_nums: [0, -1, -1, -1, -1, -1, -1, -1] # [IO] GPIOs used for data lines + data_width: 1 # Number of data lines, 1 (SPI) or 8 (I80) + pclk_hz: 40000000 # [TO_BE_CONFIRMED] Frequency of pixel clock + clk_src: PARLIO_CLK_SRC_DEFAULT # Clock source for the Parlio peripheral (parlio_clock_source_t) + max_transfer_bytes: 136320 # Maximum transfer size; determines internal DMA link length + dma_burst_size: 32 # DMA burst size, in bytes + trans_queue_depth: 10 # Transaction queue size; larger queue, higher throughput + lcd_cmd_bits: 8 # [TO_BE_CONFIRMED] Bit-width of LCD command + lcd_param_bits: 8 # [TO_BE_CONFIRMED] Bit-width of LCD parameter + dc_levels: + dc_cmd_level: 0 # [TO_BE_CONFIRMED] Level of DC line in CMD phase + dc_data_level: 1 # [TO_BE_CONFIRMED] Level of DC line in DATA phase + flags: + # If set, high CS selects device; otherwise CS is low-active + cs_active_high: false + lcd_panel_config: + reset_gpio_num: -1 + rgb_ele_order: LCD_RGB_ELEMENT_ORDER_RGB # [TO_BE_CONFIRMED] RGB element order (default: RGB) + # Valid values: + # - LCD_RGB_ELEMENT_ORDER_RGB + # - LCD_RGB_ELEMENT_ORDER_BGR + data_endian: LCD_RGB_DATA_ENDIAN_LITTLE # [TO_BE_CONFIRMED] Data endianness (default: LITTLE) + # Valid values: + # - LCD_RGB_DATA_ENDIAN_BIG + # - LCD_RGB_DATA_ENDIAN_LITTLE + bits_per_pixel: 16 # [TO_BE_CONFIRMED] Bits per pixel (default: 16) + flags: + reset_active_high: true # Reset pin active level (default: false) + vendor_config: "" + + + # Touch Panel Configuration + - name: lcd_touch + chip: cst816s + type: lcd_touch_i2c + version: default + dependencies: + espressif/esp_lcd_touch_cst816s: "*" + config: + # esp_lcd_panel_io_i2c_config_t fields for touch communication + io_i2c_config: + dev_addr: 0x15 # CST816S I2C address (different from default 0x5A) + peripherals: + - name: i2c_master # I2C peripheral for touch communication + + # esp_lcd_touch_config_t fields for touch configuration + touch_config: + x_max: 284 # Maximum X coordinate (BSP_LCD_H_RES) + y_max: 240 # Maximum Y coordinate (BSP_LCD_V_RES) + int_gpio_num: -1 # Interrupt GPIO (BSP_LCD_TOUCH_INT) + flags: + swap_xy: true # Swap X and Y coordinates (default: false) + mirror_x: false # Mirror X coordinates (default: false) + mirror_y: true # Mirror Y coordinates (default: false) + + - name: touch_button + chip: bs8112 + type: custom + version: default + dependencies: + touch_ic_bs8112a3: + version: "^0.1" + peripherals: + - name: i2c_master # I2C peripheral for touch communication + config: + irq_pin: 4 + + - name: camera + type: camera + sub_type: spi + config: + spi_config: + intf: ESP_CAM_CTLR_SPI_CAM_INTF_SPI + # SPI CAM data I/O mode (SPI interface only supports 1-bit): ESP_CAM_CTLR_SPI_CAM_IO_MODE_1BIT / _2BIT + io_mode: ESP_CAM_CTLR_SPI_CAM_IO_MODE_1BIT + spi_port: 1 # [TO_BE_CONFIRMED] SPI port + spi_cs_pin: 27 # [IO] SPI CS pin + spi_sclk_pin: 25 # [IO] SPI SCLK pin + spi_data0_io_pin: 23 # [IO] SPI data0 I/O pin + spi_data1_io_pin: -1 # [IO] SPI data1 I/O pin + reset_pin: -1 # [IO] SPI interface camera sensor reset pin + pwdn_pin: -1 # [IO] SPI interface camera sensor power down pin + xclk_source: ESP_CAM_SENSOR_XCLK_LEDC + xclk_freq: 24000000 # [TO_BE_CONFIRMED] XCLK frequency in Hz (default: 20MHz) + xclk_pin: 24 # [IO] XCLK pin + xclk_ledc_cfg: + timer: 0 # [TO_BE_CONFIRMED] The timer source of channel + clk_cfg: LEDC_AUTO_CLK # [TO_BE_CONFIRMED] LEDC source clock from ledc_clk_cfg_t + channel: 0 # [TO_BE_CONFIRMED] LEDC channel used for XCLK + peripherals: + - name: i2c_master # Must match a periph_i2c name; provides SCCB i2c_handle to esp_video + frequency: 100000 # SCCB I2C frequency (Hz) + + - name: audio_adc + chip: internal + type: audio_codec + config: + adc_enabled: true + dac_enabled: false + adc_local_cfg: + channel_list: [4] # required + sample_rate_hz: 16000 + max_store_buf_size: 1024 + conv_frame_size: 256 + unit_id: ADC_UNIT_1 + atten: ADC_ATTEN_DB_0 + + - name: audio_dac + chip: internal + type: audio_codec + version: default + config: + dac_enabled: true + peripherals: + - name: i2s_audio_out + tx_aux_out_io: 10 + tx_aux_out_invert: true + - name: gpio_pa_control + gain: 6 + active_level: 1 diff --git a/application/basic_demo/boards/esp_SensairHalo/board_info.yaml b/application/basic_demo/boards/esp_SensairHalo/board_info.yaml new file mode 100644 index 0000000..4fc033d --- /dev/null +++ b/application/basic_demo/boards/esp_SensairHalo/board_info.yaml @@ -0,0 +1,5 @@ +board: esp_SensairHalo +chip: esp32c5 +version: 1.3.0 +description: "ESP-SensairHalo Development Board" +manufacturer: "ESPRESSIF" diff --git a/application/basic_demo/boards/esp_SensairHalo/board_peripherals.yaml b/application/basic_demo/boards/esp_SensairHalo/board_peripherals.yaml new file mode 100644 index 0000000..db549a4 --- /dev/null +++ b/application/basic_demo/boards/esp_SensairHalo/board_peripherals.yaml @@ -0,0 +1,51 @@ +version: 1.0.0 +# Peripherals Configuration +peripherals: + - name: i2c_master + type: i2c + role: master + config: + port: 0 + pins: + sda: 2 + scl: 3 + + - name: i2s_audio_out + type: i2s + role: master + format: pdm-out + config: + sample_rate_hz: 16000 + clk_src: I2S_CLK_SRC_DEFAULT + mclk_multiple: 256 + up_sample_fp: 960 + up_sample_fs: 441 + bclk_div: 8 + data_bit_width: 16 + slot_bit_width: I2S_SLOT_BIT_WIDTH_AUTO + slot_mode: I2S_SLOT_MODE_MONO + slot_mask: I2S_PDM_SLOT_LEFT + data_fmt: "I2S_PDM_DATA_FMT_PCM" + sd_prescale: 0 + sd_scale: I2S_PDM_SIG_SCALING_MUL_4 + hp_scale: I2S_PDM_SIG_SCALING_MUL_4 + lp_scale: I2S_PDM_SIG_SCALING_MUL_4 + sinc_scale: I2S_PDM_SIG_SCALING_MUL_4 + line_mode: I2S_PDM_TX_ONE_LINE_CODEC + hp_en: false + hp_cut_off_freq_hz: 35.5 + sd_dither: 0 + sd_dither2: 1 + pins: + doubt: 9 # [IO] Data output pin + invert_flags: + clk_inv: false + + # PA CONTROL + - name: gpio_pa_control + type: gpio + role: io + config: + pin: 8 # GPIO pin number + mode: GPIO_MODE_OUTPUT + default_level: 1 diff --git a/application/basic_demo/boards/esp_SensairHalo/sdkconfig.defaults.board b/application/basic_demo/boards/esp_SensairHalo/sdkconfig.defaults.board new file mode 100644 index 0000000..d9f4f61 --- /dev/null +++ b/application/basic_demo/boards/esp_SensairHalo/sdkconfig.defaults.board @@ -0,0 +1,20 @@ + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_16MB.csv" +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y + +CONFIG_CODEC_DUMMY_SUPPORT=y +CONFIG_CODEC_DATA_ADC_SUPPORT=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_SECONDARY_NONE=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART_NUM=-1 + +CONFIG_CAMERA_BF3901=y +CONFIG_CAMERA_BF3901_SPI_RGB565_240X320_15FPS=y +CONFIG_CAMERA_BF3901_SPI_YUV422_240X320_15FPS=n diff --git a/application/basic_demo/boards/esp_SensairHalo/setup_device.c b/application/basic_demo/boards/esp_SensairHalo/setup_device.c new file mode 100644 index 0000000..ca70341 --- /dev/null +++ b/application/basic_demo/boards/esp_SensairHalo/setup_device.c @@ -0,0 +1,131 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_board_device.h" +#include "esp_codec_dev.h" +#include "periph_i2c.h" +#include "periph_gpio.h" +#include "gen_board_device_custom.h" +#include "dev_audio_codec.h" +#include "touch_ic_bs8112a3.h" +#include "dev_custom.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_ili9341.h" +#include "esp_lcd_touch_cst816s.h" +#include "esp_log.h" +#include "esp_check.h" + +static const char *TAG = "SETUP_DEVICE"; + +static const ili9341_lcd_init_cmd_t s_vendor_init_cmds[] = { + {0x11, NULL, 0, 120}, + {0x3A, (uint8_t []){0x05}, 1, 0}, + {0xB2, (uint8_t []){0x0C, 0x0C, 0x00, 0x33, 0x33}, 5, 0}, + {0xB7, (uint8_t []){0x05}, 1, 0}, + {0xBB, (uint8_t []){0x21}, 1, 0}, + {0xC0, (uint8_t []){0x2C}, 1, 0}, + {0xC2, (uint8_t []){0x01}, 1, 0}, + {0xC3, (uint8_t []){0x15}, 1, 0}, + {0xC6, (uint8_t []){0x0F}, 1, 0}, + {0xD0, (uint8_t []){0xA7}, 1, 0}, + {0xD0, (uint8_t []){0xA4, 0xA1}, 2, 0}, + {0xD6, (uint8_t []){0xA1}, 1, 0}, + {0xE0, (uint8_t []){0xF0, 0x05, 0x0E, 0x08, 0x0A, 0x17, 0x39, 0x54, + 0x4E, 0x37, 0x12, 0x12, 0x31, 0x37}, 14, 0}, + {0xE1, (uint8_t []){0xF0, 0x10, 0x14, 0x0D, 0x0B, 0x05, 0x39, 0x44, + 0x4D, 0x38, 0x14, 0x14, 0x2E, 0x35}, 14, 0}, + {0xE4, (uint8_t []){0x23, 0x00, 0x00}, 3, 0}, + {0x21, NULL, 0, 0}, + {0x29, NULL, 0, 0}, + {0x2C, NULL, 0, 0}, +}; + +static const ili9341_vendor_config_t vendor_config = { + .init_cmds = s_vendor_init_cmds, + .init_cmds_size = sizeof(s_vendor_init_cmds) / sizeof(s_vendor_init_cmds[0]), +}; + +esp_err_t lcd_panel_factory_entry_t(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_lcd_panel_dev_config_t panel_dev_cfg = {0}; + memcpy(&panel_dev_cfg, panel_dev_config, sizeof(esp_lcd_panel_dev_config_t)); + + panel_dev_cfg.vendor_config = (void *)&vendor_config; + int ret = esp_lcd_new_panel_ili9341(io, &panel_dev_cfg, ret_panel); + if (ret != ESP_OK) { + ESP_LOGE("lcd_panel_factory_entry_t", "New ili9341 panel failed"); + return ret; + } + esp_lcd_panel_set_gap(*ret_panel, 36, 0); + return ESP_OK; +} + +esp_err_t lcd_touch_factory_entry_t(esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *touch_dev_config, esp_lcd_touch_handle_t *ret_touch) +{ + esp_lcd_touch_config_t touch_cfg = {0}; + memcpy(&touch_cfg, touch_dev_config, sizeof(esp_lcd_touch_config_t)); + if (touch_cfg.int_gpio_num != GPIO_NUM_NC) { + ESP_LOGW("lcd_touch_factory_entry_t", "Touch interrupt supported!"); + touch_cfg.interrupt_callback = NULL; + } + esp_err_t ret = esp_lcd_touch_new_i2c_cst816s(io, &touch_cfg, ret_touch); + if (ret != ESP_OK) { + ESP_LOGE("lcd_touch_factory_entry_t", "Failed to create gt911 touch driver: %s", esp_err_to_name(ret)); + return ret; + } + return ESP_OK; +} + +static int touch_button_init(void *config, int cfg_size, void **device_handle) +{ + esp_err_t ret = ESP_OK; + dev_custom_touch_button_config_t *touch_button_cfg = (dev_custom_touch_button_config_t *)config; + ESP_LOGI(TAG, "Initializing %s device", touch_button_cfg->name); + + ESP_RETURN_ON_FALSE(strcmp(touch_button_cfg->chip, "bs8112") == 0, ESP_ERR_INVALID_ARG, + TAG, "Unsupported chip: %s", touch_button_cfg->chip); + + // Try to get existing I2C bus handle first + i2c_master_bus_handle_t i2c_bus_handle = NULL; + esp_board_periph_ref_handle(touch_button_cfg->peripheral_name, (void**)&i2c_bus_handle); + ESP_RETURN_ON_FALSE(i2c_bus_handle != NULL, ESP_ERR_INVALID_STATE, TAG, "Failed to get I2C bus handle"); + + // Use default chip configuration + bs8112a3_chip_config_t default_chip_cfg = TOUCH_IC_BS8112A3_DEFAULT_CHIP_CONFIG(); + default_chip_cfg.lsc_mode = BS8112A3_LSC_MODE_NORMAL; + default_chip_cfg.irq_oms = BS8112A3_IRQ_OMS_LEVEL_HOLD; + default_chip_cfg.k12_mode = BS8112A3_K12_MODE_IRQ; + + touch_ic_bs8112a3_config_t bs8112_cfg = { + .i2c_bus_handle = i2c_bus_handle, + .device_address = BS8112A3_I2C_ADDR, + .scl_speed_hz = 400000, + .irq_pin = touch_button_cfg->irq_pin, + .chip_config = &default_chip_cfg, + }; + + touch_ic_bs8112a3_handle_t touch_handle = NULL; + ret = touch_ic_bs8112a3_create(&bs8112_cfg, &touch_handle); + ESP_RETURN_ON_ERROR(ret, TAG, "Failed to create BS8112A3 touch IC instance"); + + // Store handle in device_handle + *device_handle = (void *)touch_handle; + return ESP_OK; +} + +static int touch_button_deinit(void *device_handle) +{ + if (!device_handle) { + return ESP_OK; + } + + touch_ic_bs8112a3_handle_t touch_handle = (touch_ic_bs8112a3_handle_t)device_handle; + esp_err_t ret = touch_ic_bs8112a3_delete(touch_handle); + + return ret; +} + +CUSTOM_DEVICE_IMPLEMENT(touch_button, touch_button_init, touch_button_deinit); diff --git a/application/basic_demo/boards/esp_SensairShuttle/board_devices.yaml b/application/basic_demo/boards/esp_SensairShuttle/board_devices.yaml new file mode 100644 index 0000000..a723284 --- /dev/null +++ b/application/basic_demo/boards/esp_SensairShuttle/board_devices.yaml @@ -0,0 +1,87 @@ +version: 1.0.0 +# Devices Configuration +devices: + + - name: display_lcd + chip: ili9341 + type: display_lcd + sub_type: spi + version: default + dependencies: + espressif/esp_lcd_ili9341: "*" + config: + mirror_x: true + mirror_y: false + swap_xy: true + x_max: 284 + y_max: 240 + # esp_lcd_panel_io_spi_config_t fields + io_spi_config: + cs_gpio_num: 25 # GPIO14 - LCD_CS (BSP_LCD_CS) + dc_gpio_num: 26 # GPIO45 - LCD_DC (BSP_LCD_DC) + spi_mode: 3 # Traditional SPI mode (0~3) + pclk_hz: 20000000 # Frequency of pixel clock + flags: + sio_mode: true # Single line mode + peripherals: + - name: spi_display # SPI peripheral for LCD communication + + lcd_panel_config: + reset_gpio_num: -1 + data_endian: "LCD_RGB_DATA_ENDIAN_LITTLE" # LCD_RGB_DATA_ENDIAN_LITTLE + flags: + reset_active_high: true + # ST77916 specific configuration + vendor_config: NULL + + # Touch Panel Configuration + - name: lcd_touch + chip: cst816s + type: lcd_touch_i2c + version: default + dependencies: + espressif/esp_lcd_touch_cst816s: "*" + config: + # esp_lcd_panel_io_i2c_config_t fields for touch communication + io_i2c_config: + dev_addr: 0x15 # CST816S I2C address (different from default 0x5A) + peripherals: + - name: i2c_master # I2C peripheral for touch communication + + # esp_lcd_touch_config_t fields for touch configuration + touch_config: + x_max: 240 # Maximum X coordinate (BSP_LCD_H_RES) + y_max: 284 # Maximum Y coordinate (BSP_LCD_V_RES) + int_gpio_num: -1 # Interrupt GPIO (BSP_LCD_TOUCH_INT) + flags: + swap_xy: true # Swap X and Y coordinates (default: false) + mirror_x: true # Mirror X coordinates (default: false) + mirror_y: true # Mirror Y coordinates (default: false) + + - name: audio_dac + chip: internal + type: audio_codec + version: default + config: + dac_enabled: true + peripherals: + - name: i2s_audio_out + tx_aux_out_io: 8 + tx_aux_out_invert: true + - name: gpio_pa_control + gain: 6 + active_level: 1 + + - name: audio_adc + chip: internal + type: audio_codec + config: + adc_enabled: true + dac_enabled: false + adc_local_cfg: + channel_list: [5] # required + sample_rate_hz: 16000 + max_store_buf_size: 1024 + conv_frame_size: 256 + unit_id: ADC_UNIT_1 + atten: ADC_ATTEN_DB_0 diff --git a/application/basic_demo/boards/esp_SensairShuttle/board_info.yaml b/application/basic_demo/boards/esp_SensairShuttle/board_info.yaml new file mode 100644 index 0000000..65afd5d --- /dev/null +++ b/application/basic_demo/boards/esp_SensairShuttle/board_info.yaml @@ -0,0 +1,5 @@ +board: esp_SensairShuttle +chip: esp32c5 +version: 1.3.0 +description: "ESP-SensairShuttle Development Board" +manufacturer: "ESPRESSIF" diff --git a/application/basic_demo/boards/esp_SensairShuttle/board_peripherals.yaml b/application/basic_demo/boards/esp_SensairShuttle/board_peripherals.yaml new file mode 100644 index 0000000..e8c8172 --- /dev/null +++ b/application/basic_demo/boards/esp_SensairShuttle/board_peripherals.yaml @@ -0,0 +1,63 @@ +version: 1.0.0 +# Peripherals Configuration +peripherals: + - name: i2c_master + type: i2c + role: master + config: + port: 0 + pins: + sda: 2 + scl: 3 + + # LCD SPI Configuration for ST77916 QSPI + - name: spi_display + type: spi + role: master + config: + # spi_bus_config_t fields + spi_bus_config: + spi_port: SPI2_HOST # 0: SPI1_HOST, 1: SPI2_HOST, 2: SPI3_HOST + data0_io_num: 23 # MOSI_IO_NUM + sclk_io_num: 24 # SPI Clock signal + max_transfer_sz: 3600 # Maximum transfer size in bytes + + - name: i2s_audio_out + type: i2s + role: master + format: pdm-out + config: + sample_rate_hz: 16000 + clk_src: I2S_CLK_SRC_DEFAULT + mclk_multiple: 256 + up_sample_fp: 960 + up_sample_fs: 441 + bclk_div: 8 + data_bit_width: 16 + slot_bit_width: I2S_SLOT_BIT_WIDTH_AUTO + slot_mode: I2S_SLOT_MODE_MONO + slot_mask: I2S_PDM_SLOT_LEFT + data_fmt: "I2S_PDM_DATA_FMT_PCM" + sd_prescale: 0 + sd_scale: I2S_PDM_SIG_SCALING_MUL_4 + hp_scale: I2S_PDM_SIG_SCALING_MUL_4 + lp_scale: I2S_PDM_SIG_SCALING_MUL_4 + sinc_scale: I2S_PDM_SIG_SCALING_MUL_4 + line_mode: I2S_PDM_TX_ONE_LINE_CODEC + hp_en: false + hp_cut_off_freq_hz: 35.5 + sd_dither: 0 + sd_dither2: 1 + pins: + doubt: 7 # [IO] Data output pin + invert_flags: + clk_inv: false + + # PA CONTROL + - name: gpio_pa_control + type: gpio + role: io + config: + pin: 1 # GPIO pin number + mode: GPIO_MODE_OUTPUT + default_level: 1 diff --git a/application/basic_demo/boards/esp_SensairShuttle/sdkconfig.defaults.board b/application/basic_demo/boards/esp_SensairShuttle/sdkconfig.defaults.board new file mode 100644 index 0000000..d7d9cda --- /dev/null +++ b/application/basic_demo/boards/esp_SensairShuttle/sdkconfig.defaults.board @@ -0,0 +1,16 @@ + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_16MB.csv" +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y + +CONFIG_CODEC_DUMMY_SUPPORT=y +CONFIG_CODEC_DATA_ADC_SUPPORT=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_SECONDARY_NONE=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART_NUM=-1 diff --git a/application/basic_demo/boards/esp_SensairShuttle/setup_device.c b/application/basic_demo/boards/esp_SensairShuttle/setup_device.c new file mode 100644 index 0000000..d6acfea --- /dev/null +++ b/application/basic_demo/boards/esp_SensairShuttle/setup_device.c @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_board_manager_includes.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_ili9341.h" +#include "esp_lcd_touch_cst816s.h" +#include "esp_log.h" +#include "esp_check.h" + +static const char *TAG = "SETUP_DEVICE"; + +static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { + {0x11, NULL, 0, 120}, // Sleep Out + {0x36, (uint8_t []){0x00}, 1, 0}, // Memory Data Access Control + {0x3A, (uint8_t []){0x05}, 1, 0}, // Interface Pixel Format (16-bit) + {0xB2, (uint8_t []){0x0C, 0x0C, 0x00, 0x33, 0x33}, 5, 0}, // Porch Setting + {0xB7, (uint8_t []){0x05}, 1, 0}, // Gate Control + {0xBB, (uint8_t []){0x21}, 1, 0}, // VCOM Setting + {0xC0, (uint8_t []){0x2C}, 1, 0}, // LCM Control + {0xC2, (uint8_t []){0x01}, 1, 0}, // VDV and VRH Command Enable + {0xC3, (uint8_t []){0x15}, 1, 0}, // VRH Set + {0xC6, (uint8_t []){0x0F}, 1, 0}, // Frame Rate Control + {0xD0, (uint8_t []){0xA7}, 1, 0}, // Power Control 1 + {0xD0, (uint8_t []){0xA4, 0xA1}, 2, 0}, // Power Control 1 + {0xD6, (uint8_t []){0xA1}, 1, 0}, // Gate output GND in sleep mode + { + 0xE0, (uint8_t []) + { + 0xF0, 0x05, 0x0E, 0x08, 0x0A, 0x17, 0x39, 0x54, + 0x4E, 0x37, 0x12, 0x12, 0x31, 0x37 + }, 14, 0 + }, // Positive Gamma Control + { + 0xE1, (uint8_t []) + { + 0xF0, 0x10, 0x14, 0x0D, 0x0B, 0x05, 0x39, 0x44, + 0x4D, 0x38, 0x14, 0x14, 0x2E, 0x35 + }, 14, 0 + }, // Negative Gamma Control + {0xE4, (uint8_t []){0x23, 0x00, 0x00}, 3, 0}, // Gate position control + {0x21, NULL, 0, 0}, // Display Inversion On + {0x29, NULL, 0, 0}, // Display On + {0x2C, NULL, 0, 0}, // Memory Write +}; + +// define st77916_vendor_config_t +static const ili9341_vendor_config_t vendor_config = { + .init_cmds = vendor_specific_init, + .init_cmds_size = sizeof(vendor_specific_init) / sizeof(vendor_specific_init[0]), +}; + +esp_err_t lcd_panel_factory_entry_t(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_lcd_panel_dev_config_t panel_dev_cfg = {0}; + memcpy(&panel_dev_cfg, panel_dev_config, sizeof(esp_lcd_panel_dev_config_t)); + + panel_dev_cfg.vendor_config = (void *)&vendor_config; + int ret = esp_lcd_new_panel_ili9341(io, &panel_dev_cfg, ret_panel); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "New ili9341 panel failed"); + return ret; + } + // esp_lcd_panel_set_gap(*ret_panel, 36, 0); + return ESP_OK; +} + +esp_err_t lcd_touch_factory_entry_t(esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *touch_dev_config, esp_lcd_touch_handle_t *ret_touch) +{ + esp_lcd_touch_config_t touch_cfg = {0}; + memcpy(&touch_cfg, touch_dev_config, sizeof(esp_lcd_touch_config_t)); + if (touch_cfg.int_gpio_num != GPIO_NUM_NC) { + ESP_LOGW(TAG, "Touch interrupt supported!"); + touch_cfg.interrupt_callback = NULL; + } + esp_err_t ret = esp_lcd_touch_new_i2c_cst816s(io, &touch_cfg, ret_touch); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create gt911 touch driver: %s", esp_err_to_name(ret)); + return ret; + } + return ESP_OK; +} diff --git a/application/basic_demo/boards/esp_vocat_board_v1_2/board_devices.yaml b/application/basic_demo/boards/esp_vocat_board_v1_2/board_devices.yaml new file mode 100644 index 0000000..db81ca4 --- /dev/null +++ b/application/basic_demo/boards/esp_vocat_board_v1_2/board_devices.yaml @@ -0,0 +1,153 @@ +# Devices Configuration for EchoEar Core Board V1.0 +devices: + # Audio Power Control after Audio init + - name: audio_power + type: gpio_ctrl + version: default + config: + active_level: 1 + default_level: 0 + peripherals: + - name: gpio_power_audio + + # LCD and SDCard Power Control before LCD init + - name: lcd_sdcard_power + type: power_ctrl + sub_type: gpio + peripherals: + - name: gpio_power_lcd_sdcard + active_level: 0 + + - name: lcd_brightness + type: ledc_ctrl + version: default + config: + default_percent: 100 # 0-100, default 0 percent + peripherals: + - name: ledc_backlight # LEDC peripheral for GPIO 44 + + - name: audio_dac + chip: es8311 + type: audio_codec + version: default + config: + adc_enabled: false + dac_enabled: true + dac_max_channel: 1 + # DAC channel mask, 1-enable, 0-disable, layout: left,right + dac_channel_mask: "1" # Left, Right enable + mclk_enabled: true + + # Power amplifier configuration + peripherals: + - name: gpio_pa_control + gain: 6 # dB + active_level: 1 # 0-low, 1-high + + # I2S interface configuration + - name: i2s_audio_out + # I2C interface configuration + - name: i2c_master + address: 0x30 + frequency: 400000 # Hz + + # Audio ADC Configuration (ES7210) + - name: audio_adc + chip: es7210 + type: audio_codec + version: default + config: + adc_enabled: true + adc_max_channel: 4 + # The channel mask, 1-enable, 0-disable + # e.g."0111", bit0: Mic0 enable, bit1: Mic1 enable, bit2: Mic2 enable, bit3: Mic3 enable, bit4: Mic4 disable + adc_channel_mask: "0111" # Mic0, Mic1, Mic2 enable + adc_channel_labels: ['NA', 'RE', 'FR', 'FL'] # MSB ~ LSB + adc_init_gain: 0 # dB + + # I2S interface configuration + peripherals: + # I2S interface configuration + - name: i2s_audio_in + # I2C interface configuration + - name: i2c_master + address: 0x80 + frequency: 400000 # Hz + + - name: fs_sdcard + type: fs_fat + sub_type: sdmmc + power_ctrl_device: lcd_sdcard_power + version: default + config: + vfs_config: + format_if_mount_failed: true + sub_config: + bus_width: 1 # 1, 4, or 8 for slot 0; 1 or 4 for slot 1 + slot_flags: "SDMMC_SLOT_FLAG_INTERNAL_PULLUP" # SDMMC_SLOT_FLAG_INTERNAL_PULLUP, SDMMC_SLOT_FLAG_WP_ACTIVE_HIGH, SDMMC_SLOT_FLAG_UHS1 + pins: + clk: 16 # GPIO_NUM_16 + cmd: 38 # GPIO_NUM_38 + d0: 17 # GPIO_NUM_17 + + # LCD Display Configuration + - name: display_lcd + chip: st77916 + type: display_lcd + sub_type: spi + power_ctrl_device: lcd_sdcard_power + version: default + dependencies: + espressif/esp_lcd_st77916: "*" + config: + x_max: 360 + y_max: 360 + need_reset: false + # esp_lcd_panel_io_spi_config_t fields + io_spi_config: + cs_gpio_num: 14 # GPIO14 - LCD_CS (BSP_LCD_CS) + dc_gpio_num: 45 # GPIO45 - LCD_DC (BSP_LCD_DC) + spi_mode: 0 # Traditional SPI mode (0~3) + lcd_cmd_bits: 32 # Bit-width of LCD command + flags: + quad_mode: true # Quad mode (4 data lines) - ST77916 uses quad mode + + lcd_panel_config: + reset_gpio_num: 47 + flags: + reset_active_high: true # Reset pin active level (default: false) + # ST77916 specific configuration + vendor_config: NULL + + peripherals: + - name: spi_display # SPI peripheral for LCD communication + + # Touch Panel Configuration + - name: lcd_touch + chip: cst816s + type: lcd_touch_i2c + version: default + dependencies: + espressif/esp_lcd_touch_cst816s: "*" + config: + # esp_lcd_panel_io_i2c_config_t fields for touch communication + io_i2c_config: + dev_addr: 0x15 # CST816S I2C address (different from default 0x5A) + peripherals: + - name: i2c_master # I2C peripheral for touch communication + + # esp_lcd_touch_config_t fields for touch configuration + touch_config: + x_max: 360 # Maximum X coordinate (BSP_LCD_H_RES) + y_max: 360 # Maximum Y coordinate (BSP_LCD_V_RES) + int_gpio_num: 10 # Interrupt GPIO (BSP_LCD_TOUCH_INT) + + # LED GREEN + - name: led_green + type: gpio_ctrl + version: default + config: + active_level: 0 + default_level: 1 + peripherals: + - name: gpio_led_g diff --git a/application/basic_demo/boards/esp_vocat_board_v1_2/board_info.yaml b/application/basic_demo/boards/esp_vocat_board_v1_2/board_info.yaml new file mode 100644 index 0000000..256abc8 --- /dev/null +++ b/application/basic_demo/boards/esp_vocat_board_v1_2/board_info.yaml @@ -0,0 +1,5 @@ +board: esp_vocat_board_v1_2 +chip: esp32s3 +version: 1.2.0 +description: "ESP VoCat Board V1.2 AI Pet Companion Development Board" +manufacturer: "ESPRESSIF" diff --git a/application/basic_demo/boards/esp_vocat_board_v1_2/board_peripherals.yaml b/application/basic_demo/boards/esp_vocat_board_v1_2/board_peripherals.yaml new file mode 100644 index 0000000..fffe109 --- /dev/null +++ b/application/basic_demo/boards/esp_vocat_board_v1_2/board_peripherals.yaml @@ -0,0 +1,94 @@ +peripherals: + # I2C Configuration + - name: i2c_master + type: i2c + role: master + config: + port: 0 + pins: + sda: 2 # GPIO2 - I2C SDA + scl: 1 # GPIO1 - I2C SCL + + # I2S Audio Configuration + - name: i2s_audio_out + type: i2s + role: master + format: std-out # std-out, std-in + config: &i2s_config + port: 0 + # Clock configuration + sample_rate_hz: 16000 # Sample rate in Hz + mclk_multiple: 256 # Multiple of MCLK to sample rate (256 or 384 for 24-bit) + # Slot configuration + data_bit_width: 16 # Data bit width (valid data bits per sample) + slot_bit_width: I2S_SLOT_BIT_WIDTH_AUTO # Total bits per slot (I2S_SLOT_BIT_WIDTH_AUTO or specific value) + slot_mode: I2S_SLOT_MODE_MONO # I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO + slot_mask: I2S_STD_SLOT_BOTH # I2S_STD_SLOT_LEFT, I2S_STD_SLOT_RIGHT, or I2S_STD_SLOT_BOTH slots + ws_width: 16 # WS signal width in BCLK ticks + + # GPIO configuration + pins: + mclk: 42 # GPIO42 - I2S_MCLK (BSP_I2S_MCLK) + bclk: 40 # GPIO40 - I2S_SCLK (BSP_I2S_SCLK) + ws: 39 # GPIO39 - I2S_LCLK (BSP_I2S_LCLK) + doubt: 41 # GPIO41 - I2S_DOUT (BSP_I2S_DOUT) + din: 3 # GPIO3 - I2S_DSIN (BSP_I2S_DSIN) + + - name: i2s_audio_in + type: i2s + role: master + format: std-in + config: *i2s_config + + # LCD SPI Configuration for ST77916 QSPI + - name: spi_display + type: spi + role: master + config: + # spi_bus_config_t fields + spi_bus_config: + spi_port: SPI2_HOST # 0: SPI1_HOST, 1: SPI2_HOST, 2: SPI3_HOST + data0_io_num: 46 # MOSI_IO_NUM + data1_io_num: 13 # MISO_IO_NUM + data2_io_num: 11 # QUADWP_IO_NUM + data3_io_num: 12 # QUADHD_IO_NUM + sclk_io_num: 18 # SPI Clock signal + max_transfer_sz: 14400 # Maximum transfer size in bytes : width * 2 * 20 + + - name: ledc_backlight + type: ledc + role: none + config: + gpio_num: 44 # GPIO44 - LED control pin + freq_hz: 2000 # PWM frequency 2kHz + duty: 100 # Initial duty cycle (0%) + duty_resolution: LEDC_TIMER_10_BIT # 10-bit duty resolution + + ## CHIP POWER_ON_OFF LCD and SD card power control + - name: gpio_power_lcd_sdcard + type: gpio + config: + pin: 9 # GPIO9 - LCD_RST (CHIP POWER_ON_OFF) + mode: GPIO_MODE_OUTPUT + default_level: 1 + + - name: gpio_power_audio + type: gpio + config: + pin: 48 # GPIO48 - POWER_AUDIO + mode: GPIO_MODE_OUTPUT + default_level: 1 + + - name: gpio_pa_control + type: gpio + config: + pin: 15 # GPIO15 - AMP Control + mode: GPIO_MODE_OUTPUT + default_level: 0 + + - name: gpio_led_g + type: gpio + config: + pin: 43 # GPIO43 - LED GREEN + mode: GPIO_MODE_OUTPUT + default_level: 1 diff --git a/application/basic_demo/boards/esp_vocat_board_v1_2/sdkconfig.defaults.board b/application/basic_demo/boards/esp_vocat_board_v1_2/sdkconfig.defaults.board new file mode 100644 index 0000000..364fd4c --- /dev/null +++ b/application/basic_demo/boards/esp_vocat_board_v1_2/sdkconfig.defaults.board @@ -0,0 +1,10 @@ +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_16MB.csv" +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y + +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y diff --git a/application/basic_demo/boards/esp_vocat_board_v1_2/setup_device.c b/application/basic_demo/boards/esp_vocat_board_v1_2/setup_device.c new file mode 100644 index 0000000..33bace3 --- /dev/null +++ b/application/basic_demo/boards/esp_vocat_board_v1_2/setup_device.c @@ -0,0 +1,233 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_board_device.h" +#include "esp_lcd_st77916.h" +#include "esp_lcd_touch_cst816s.h" +#include "esp_log.h" + +static const st77916_lcd_init_cmd_t vendor_specific_init_default[] = { + {0xF0, (uint8_t[]) {0x28}, 1, 0}, + {0xF2, (uint8_t[]) {0x28}, 1, 0}, + {0x73, (uint8_t[]) {0xF0}, 1, 0}, + {0x7C, (uint8_t[]) {0xD1}, 1, 0}, + {0x83, (uint8_t[]) {0xE0}, 1, 0}, + {0x84, (uint8_t[]) {0x61}, 1, 0}, + {0xF2, (uint8_t[]) {0x82}, 1, 0}, + {0xF0, (uint8_t[]) {0x00}, 1, 0}, + {0xF0, (uint8_t[]) {0x01}, 1, 0}, + {0xF1, (uint8_t[]) {0x01}, 1, 0}, + {0xB0, (uint8_t[]) {0x56}, 1, 0}, + {0xB1, (uint8_t[]) {0x4D}, 1, 0}, + {0xB2, (uint8_t[]) {0x24}, 1, 0}, + {0xB4, (uint8_t[]) {0x87}, 1, 0}, + {0xB5, (uint8_t[]) {0x44}, 1, 0}, + {0xB6, (uint8_t[]) {0x8B}, 1, 0}, + {0xB7, (uint8_t[]) {0x40}, 1, 0}, + {0xB8, (uint8_t[]) {0x86}, 1, 0}, + {0xBA, (uint8_t[]) {0x00}, 1, 0}, + {0xBB, (uint8_t[]) {0x08}, 1, 0}, + {0xBC, (uint8_t[]) {0x08}, 1, 0}, + {0xBD, (uint8_t[]) {0x00}, 1, 0}, + {0xC0, (uint8_t[]) {0x80}, 1, 0}, + {0xC1, (uint8_t[]) {0x10}, 1, 0}, + {0xC2, (uint8_t[]) {0x37}, 1, 0}, + {0xC3, (uint8_t[]) {0x80}, 1, 0}, + {0xC4, (uint8_t[]) {0x10}, 1, 0}, + {0xC5, (uint8_t[]) {0x37}, 1, 0}, + {0xC6, (uint8_t[]) {0xA9}, 1, 0}, + {0xC7, (uint8_t[]) {0x41}, 1, 0}, + {0xC8, (uint8_t[]) {0x01}, 1, 0}, + {0xC9, (uint8_t[]) {0xA9}, 1, 0}, + {0xCA, (uint8_t[]) {0x41}, 1, 0}, + {0xCB, (uint8_t[]) {0x01}, 1, 0}, + {0xD0, (uint8_t[]) {0x91}, 1, 0}, + {0xD1, (uint8_t[]) {0x68}, 1, 0}, + {0xD2, (uint8_t[]) {0x68}, 1, 0}, + {0xF5, (uint8_t[]) {0x00, 0xA5}, 2, 0}, + {0xDD, (uint8_t[]) {0x4F}, 1, 0}, + {0xDE, (uint8_t[]) {0x4F}, 1, 0}, + {0xF1, (uint8_t[]) {0x10}, 1, 0}, + {0xF0, (uint8_t[]) {0x00}, 1, 0}, + {0xF0, (uint8_t[]) {0x02}, 1, 0}, + {0xE0, (uint8_t[]) {0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, + {0xE1, (uint8_t[]) {0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, + {0xF0, (uint8_t[]) {0x10}, 1, 0}, + {0xF3, (uint8_t[]) {0x10}, 1, 0}, + {0xE0, (uint8_t[]) {0x07}, 1, 0}, + {0xE1, (uint8_t[]) {0x00}, 1, 0}, + {0xE2, (uint8_t[]) {0x00}, 1, 0}, + {0xE3, (uint8_t[]) {0x00}, 1, 0}, + {0xE4, (uint8_t[]) {0xE0}, 1, 0}, + {0xE5, (uint8_t[]) {0x06}, 1, 0}, + {0xE6, (uint8_t[]) {0x21}, 1, 0}, + {0xE7, (uint8_t[]) {0x01}, 1, 0}, + {0xE8, (uint8_t[]) {0x05}, 1, 0}, + {0xE9, (uint8_t[]) {0x02}, 1, 0}, + {0xEA, (uint8_t[]) {0xDA}, 1, 0}, + {0xEB, (uint8_t[]) {0x00}, 1, 0}, + {0xEC, (uint8_t[]) {0x00}, 1, 0}, + {0xED, (uint8_t[]) {0x0F}, 1, 0}, + {0xEE, (uint8_t[]) {0x00}, 1, 0}, + {0xEF, (uint8_t[]) {0x00}, 1, 0}, + {0xF8, (uint8_t[]) {0x00}, 1, 0}, + {0xF9, (uint8_t[]) {0x00}, 1, 0}, + {0xFA, (uint8_t[]) {0x00}, 1, 0}, + {0xFB, (uint8_t[]) {0x00}, 1, 0}, + {0xFC, (uint8_t[]) {0x00}, 1, 0}, + {0xFD, (uint8_t[]) {0x00}, 1, 0}, + {0xFE, (uint8_t[]) {0x00}, 1, 0}, + {0xFF, (uint8_t[]) {0x00}, 1, 0}, + {0x60, (uint8_t[]) {0x40}, 1, 0}, + {0x61, (uint8_t[]) {0x04}, 1, 0}, + {0x62, (uint8_t[]) {0x00}, 1, 0}, + {0x63, (uint8_t[]) {0x42}, 1, 0}, + {0x64, (uint8_t[]) {0xD9}, 1, 0}, + {0x65, (uint8_t[]) {0x00}, 1, 0}, + {0x66, (uint8_t[]) {0x00}, 1, 0}, + {0x67, (uint8_t[]) {0x00}, 1, 0}, + {0x68, (uint8_t[]) {0x00}, 1, 0}, + {0x69, (uint8_t[]) {0x00}, 1, 0}, + {0x6A, (uint8_t[]) {0x00}, 1, 0}, + {0x6B, (uint8_t[]) {0x00}, 1, 0}, + {0x70, (uint8_t[]) {0x40}, 1, 0}, + {0x71, (uint8_t[]) {0x03}, 1, 0}, + {0x72, (uint8_t[]) {0x00}, 1, 0}, + {0x73, (uint8_t[]) {0x42}, 1, 0}, + {0x74, (uint8_t[]) {0xD8}, 1, 0}, + {0x75, (uint8_t[]) {0x00}, 1, 0}, + {0x76, (uint8_t[]) {0x00}, 1, 0}, + {0x77, (uint8_t[]) {0x00}, 1, 0}, + {0x78, (uint8_t[]) {0x00}, 1, 0}, + {0x79, (uint8_t[]) {0x00}, 1, 0}, + {0x7A, (uint8_t[]) {0x00}, 1, 0}, + {0x7B, (uint8_t[]) {0x00}, 1, 0}, + {0x80, (uint8_t[]) {0x48}, 1, 0}, + {0x81, (uint8_t[]) {0x00}, 1, 0}, + {0x82, (uint8_t[]) {0x06}, 1, 0}, + {0x83, (uint8_t[]) {0x02}, 1, 0}, + {0x84, (uint8_t[]) {0xD6}, 1, 0}, + {0x85, (uint8_t[]) {0x04}, 1, 0}, + {0x86, (uint8_t[]) {0x00}, 1, 0}, + {0x87, (uint8_t[]) {0x00}, 1, 0}, + {0x88, (uint8_t[]) {0x48}, 1, 0}, + {0x89, (uint8_t[]) {0x00}, 1, 0}, + {0x8A, (uint8_t[]) {0x08}, 1, 0}, + {0x8B, (uint8_t[]) {0x02}, 1, 0}, + {0x8C, (uint8_t[]) {0xD8}, 1, 0}, + {0x8D, (uint8_t[]) {0x04}, 1, 0}, + {0x8E, (uint8_t[]) {0x00}, 1, 0}, + {0x8F, (uint8_t[]) {0x00}, 1, 0}, + {0x90, (uint8_t[]) {0x48}, 1, 0}, + {0x91, (uint8_t[]) {0x00}, 1, 0}, + {0x92, (uint8_t[]) {0x0A}, 1, 0}, + {0x93, (uint8_t[]) {0x02}, 1, 0}, + {0x94, (uint8_t[]) {0xDA}, 1, 0}, + {0x95, (uint8_t[]) {0x04}, 1, 0}, + {0x96, (uint8_t[]) {0x00}, 1, 0}, + {0x97, (uint8_t[]) {0x00}, 1, 0}, + {0x98, (uint8_t[]) {0x48}, 1, 0}, + {0x99, (uint8_t[]) {0x00}, 1, 0}, + {0x9A, (uint8_t[]) {0x0C}, 1, 0}, + {0x9B, (uint8_t[]) {0x02}, 1, 0}, + {0x9C, (uint8_t[]) {0xDC}, 1, 0}, + {0x9D, (uint8_t[]) {0x04}, 1, 0}, + {0x9E, (uint8_t[]) {0x00}, 1, 0}, + {0x9F, (uint8_t[]) {0x00}, 1, 0}, + {0xA0, (uint8_t[]) {0x48}, 1, 0}, + {0xA1, (uint8_t[]) {0x00}, 1, 0}, + {0xA2, (uint8_t[]) {0x05}, 1, 0}, + {0xA3, (uint8_t[]) {0x02}, 1, 0}, + {0xA4, (uint8_t[]) {0xD5}, 1, 0}, + {0xA5, (uint8_t[]) {0x04}, 1, 0}, + {0xA6, (uint8_t[]) {0x00}, 1, 0}, + {0xA7, (uint8_t[]) {0x00}, 1, 0}, + {0xA8, (uint8_t[]) {0x48}, 1, 0}, + {0xA9, (uint8_t[]) {0x00}, 1, 0}, + {0xAA, (uint8_t[]) {0x07}, 1, 0}, + {0xAB, (uint8_t[]) {0x02}, 1, 0}, + {0xAC, (uint8_t[]) {0xD7}, 1, 0}, + {0xAD, (uint8_t[]) {0x04}, 1, 0}, + {0xAE, (uint8_t[]) {0x00}, 1, 0}, + {0xAF, (uint8_t[]) {0x00}, 1, 0}, + {0xB0, (uint8_t[]) {0x48}, 1, 0}, + {0xB1, (uint8_t[]) {0x00}, 1, 0}, + {0xB2, (uint8_t[]) {0x09}, 1, 0}, + {0xB3, (uint8_t[]) {0x02}, 1, 0}, + {0xB4, (uint8_t[]) {0xD9}, 1, 0}, + {0xB5, (uint8_t[]) {0x04}, 1, 0}, + {0xB6, (uint8_t[]) {0x00}, 1, 0}, + {0xB7, (uint8_t[]) {0x00}, 1, 0}, + {0xB8, (uint8_t[]) {0x48}, 1, 0}, + {0xB9, (uint8_t[]) {0x00}, 1, 0}, + {0xBA, (uint8_t[]) {0x0B}, 1, 0}, + {0xBB, (uint8_t[]) {0x02}, 1, 0}, + {0xBC, (uint8_t[]) {0xDB}, 1, 0}, + {0xBD, (uint8_t[]) {0x04}, 1, 0}, + {0xBE, (uint8_t[]) {0x00}, 1, 0}, + {0xBF, (uint8_t[]) {0x00}, 1, 0}, + {0xC0, (uint8_t[]) {0x10}, 1, 0}, + {0xC1, (uint8_t[]) {0x47}, 1, 0}, + {0xC2, (uint8_t[]) {0x56}, 1, 0}, + {0xC3, (uint8_t[]) {0x65}, 1, 0}, + {0xC4, (uint8_t[]) {0x74}, 1, 0}, + {0xC5, (uint8_t[]) {0x88}, 1, 0}, + {0xC6, (uint8_t[]) {0x99}, 1, 0}, + {0xC7, (uint8_t[]) {0x01}, 1, 0}, + {0xC8, (uint8_t[]) {0xBB}, 1, 0}, + {0xC9, (uint8_t[]) {0xAA}, 1, 0}, + {0xD0, (uint8_t[]) {0x10}, 1, 0}, + {0xD1, (uint8_t[]) {0x47}, 1, 0}, + {0xD2, (uint8_t[]) {0x56}, 1, 0}, + {0xD3, (uint8_t[]) {0x65}, 1, 0}, + {0xD4, (uint8_t[]) {0x74}, 1, 0}, + {0xD5, (uint8_t[]) {0x88}, 1, 0}, + {0xD6, (uint8_t[]) {0x99}, 1, 0}, + {0xD7, (uint8_t[]) {0x01}, 1, 0}, + {0xD8, (uint8_t[]) {0xBB}, 1, 0}, + {0xD9, (uint8_t[]) {0xAA}, 1, 0}, + {0xF3, (uint8_t[]) {0x01}, 1, 0}, + {0xF0, (uint8_t[]) {0x00}, 1, 0}, + {0x21, (uint8_t[]) {}, 0, 0}, + {0x11, (uint8_t[]) {}, 0, 0}, + {0x00, (uint8_t[]) {}, 0, 120}, +}; + +// define st77916_vendor_config_t +static const st77916_vendor_config_t vendor_config = { + .init_cmds = vendor_specific_init_default, + .init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(vendor_specific_init_default[0]), + .flags = { + .use_qspi_interface = 1, // QSPI + } +}; + +esp_err_t lcd_panel_factory_entry_t(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_lcd_panel_dev_config_t panel_dev_cfg = {0}; + memcpy(&panel_dev_cfg, panel_dev_config, sizeof(esp_lcd_panel_dev_config_t)); + + panel_dev_cfg.vendor_config = (void *)&vendor_config; + int ret = esp_lcd_new_panel_st77916(io, &panel_dev_cfg, ret_panel); + if (ret != ESP_OK) { + ESP_LOGE("lcd_panel_factory_entry_t", "New ST77916 panel failed"); + return ret; + } + return ESP_OK; +} + +esp_err_t lcd_touch_factory_entry_t(esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *touch_dev_config, esp_lcd_touch_handle_t *ret_touch) +{ + esp_lcd_touch_config_t touch_cfg = {0}; + memcpy(&touch_cfg, touch_dev_config, sizeof(esp_lcd_touch_config_t)); + esp_err_t ret = esp_lcd_touch_new_i2c_cst816s(io, &touch_cfg, ret_touch); + if (ret != ESP_OK) { + ESP_LOGE("lcd_touch_factory_entry_t", "Failed to create CST816S touch driver: %s", esp_err_to_name(ret)); + return ret; + } + return ESP_OK; +} diff --git a/application/basic_demo/fatfs_image/lua/audio_demo.lua b/application/basic_demo/fatfs_image/lua/audio_demo.lua new file mode 100644 index 0000000..3756d0f --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/audio_demo.lua @@ -0,0 +1,66 @@ +local audio = require("audio") +local bm = require("board_manager") +local delay = require("delay") + +local REC_PATH = "/fatfs/data/rec.wav" +local input_codec, input_rate, input_channels, input_bits, input_gain = + bm.get_audio_codec_input_params("audio_adc") +if not input_codec then + print("[audio_demo] ERROR: get_audio_codec_input_params(audio_adc) failed: " .. tostring(input_rate)) + return +end + +local output_codec, output_rate, output_channels, output_bits = + bm.get_audio_codec_output_params("audio_dac") +if not output_codec then + print("[audio_demo] ERROR: get_audio_codec_output_params(audio_dac) failed: " .. tostring(output_rate)) + return +end + +local input, in_err = audio.new_input(input_codec, input_rate, input_channels, input_bits) +if not input then + print("[audio_demo] ERROR: new_input failed: " .. tostring(in_err)) + return +end + +local output, out_err = audio.new_output(output_codec, output_rate, output_channels, output_bits) +if not output then + print("[audio_demo] ERROR: new_output failed: " .. tostring(out_err)) + audio.close(input) + return +end + +print(string.format("[audio_demo] input=%dHz/%dch/%dbit output=%dHz/%dch/%dbit", + input_rate, input_channels, input_bits, + output_rate, output_channels, output_bits)) + +local function close_all() + pcall(audio.close, output) + pcall(audio.close, input) +end + +local ok, err = xpcall(function() + -- ── 1. volume ──────────────────────────────────────────────────────────── + print("[audio_demo] setting volume to 100...") + audio.set_volume(output, 100) + local vol = audio.get_volume(output) + print("[audio_demo] current volume: " .. tostring(vol)) + + -- ── 2. record ──────────────────────────────────────────────────────────── + print("[audio_demo] recording 3 seconds to " .. REC_PATH .. " ...") + local info = audio.record_wav(input, REC_PATH, 3000) + print(string.format("[audio_demo] recorded path=%s bytes=%d duration=%d ms", + info.path, info.bytes, info.duration_ms)) + + delay.delay_ms(200) + + -- ── 3. play back the recording ─────────────────────────────────────────── + print("[audio_demo] playing back " .. REC_PATH .. " ...") + audio.play_wav(output, REC_PATH) + print("[audio_demo] playback done") +end, debug.traceback) + +close_all() +if not ok then + error(err) +end diff --git a/application/basic_demo/fatfs_image/lua/audio_play_test_wav.lua b/application/basic_demo/fatfs_image/lua/audio_play_test_wav.lua new file mode 100644 index 0000000..cddc17d --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/audio_play_test_wav.lua @@ -0,0 +1,30 @@ +local audio = require("audio") +local bm = require("board_manager") + +local TEST_WAV_PATH = "/fatfs/data/test.wav" + +local output_codec, output_rate, output_channels, output_bits = + bm.get_audio_codec_output_params("audio_dac") +if not output_codec then + print("[audio_play_test_wav] ERROR: get_audio_codec_output_params(audio_dac) failed: " .. tostring(output_rate)) + return +end + +local output, out_err = audio.new_output(output_codec, output_rate, output_channels, output_bits) +if not output then + print("[audio_play_test_wav] ERROR: new_output failed: " .. tostring(out_err)) + return +end + +local ok, err = xpcall(function() + print(string.format("[audio_play_test_wav] output=%dHz/%dch/%dbit", + output_rate, output_channels, output_bits)) + print("[audio_play_test_wav] playing " .. TEST_WAV_PATH .. " ...") + audio.play_wav(output, TEST_WAV_PATH) +end, debug.traceback) + +pcall(audio.close, output) +if not ok then + error(err) +end +print("[audio_play_test_wav] done") diff --git a/application/basic_demo/fatfs_image/lua/button_demo.lua b/application/basic_demo/fatfs_image/lua/button_demo.lua new file mode 100644 index 0000000..c5e8551 --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/button_demo.lua @@ -0,0 +1,58 @@ +local bm = require("board_manager") +local btn = require("button") +local delay = require("delay") + +local cfg_pin = 0 + +local handle, herr = btn.new(cfg_pin, 0) +if not handle then + print("[button_demo] ERROR: button.new failed: " .. tostring(herr)) + return +end +print("[button_demo] button handle created on gpio " .. tostring(cfg_pin)) + +-- Read initial button state +local level, lerr = btn.get_key_level(handle) +if level == nil then + print("[button_demo] ERROR: get_key_level: " .. tostring(lerr)) +else + print("[button_demo] initial key level: " .. tostring(level)) +end + +-- Register callbacks for the events we care about +btn.on(handle, "press_down", function(info) + print("[button_demo] press_down (pressed_time=" .. tostring(info.pressed_time_ms) .. "ms)") +end) + +btn.on(handle, "press_up", function(info) + print("[button_demo] press_up (pressed_time=" .. tostring(info.pressed_time_ms) .. "ms)") +end) + +btn.on(handle, "single_click", function(info) + print("[button_demo] single_click") +end) + +btn.on(handle, "double_click", function(info) + print("[button_demo] double_click") +end) + +btn.on(handle, "long_press_start", function(info) + print("[button_demo] long_press_start (pressed_time=" .. tostring(info.pressed_time_ms) .. "ms)") +end) + +btn.on(handle, "long_press_up", function(info) + print("[button_demo] long_press_up (pressed_time=" .. tostring(info.pressed_time_ms) .. "ms)") +end) + +print("[button_demo] listening for 30 seconds, press the button...") + +-- Poll for events; dispatch() invokes the callbacks registered above +for _ = 1, 3000 do + btn.dispatch() + delay.delay_ms(10) +end + +-- Clean up callbacks +btn.off(handle) +btn.close(handle) +print("[button_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/button_play_test_wav.lua b/application/basic_demo/fatfs_image/lua/button_play_test_wav.lua new file mode 100644 index 0000000..4055127 --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/button_play_test_wav.lua @@ -0,0 +1,66 @@ +local audio = require("audio") +local bm = require("board_manager") +local btn = require("button") +local delay = require("delay") + +local BUTTON_GPIO_NUM = 28 +local TEST_WAV_PATH = "/fatfs/data/test.wav" +local POLL_INTERVAL_MS = 10 +local RUN_TIME_MS = 60000 + +local output_codec, output_rate, output_channels, output_bits = + bm.get_audio_codec_output_params("audio_dac") +if not output_codec then + print("[button_play_test_wav] ERROR: get_audio_codec_output_params(audio_dac) failed: " .. tostring(output_rate)) + return +end + +local output, out_err = audio.new_output(output_codec, output_rate, output_channels, output_bits) +if not output then + print("[button_play_test_wav] ERROR: new_output failed: " .. tostring(out_err)) + return +end + +local handle, herr = btn.new(BUTTON_GPIO_NUM, 0) +if not handle then + print("[button_play_test_wav] ERROR: button.new failed: " .. tostring(herr)) + audio.close(output) + return +end + +local is_playing = false + +btn.on(handle, "single_click", function() + if is_playing then + print("[button_play_test_wav] playback already in progress") + return + end + + is_playing = true + print("[button_play_test_wav] playing " .. TEST_WAV_PATH .. " ...") + audio.play_wav(output, TEST_WAV_PATH) + print("[button_play_test_wav] playback done") + is_playing = false +end) + +print(string.format("[button_play_test_wav] button gpio=%d output=%dHz/%dch/%dbit", + BUTTON_GPIO_NUM, output_rate, output_channels, output_bits)) +print("[button_play_test_wav] press the button once to play test.wav") +print("[button_play_test_wav] running for " .. tostring(RUN_TIME_MS) .. " ms") + +local ok, err = xpcall(function() + for _ = 1, math.floor(RUN_TIME_MS / POLL_INTERVAL_MS) do + btn.dispatch() + delay.delay_ms(POLL_INTERVAL_MS) + end +end, debug.traceback) + +pcall(btn.off, handle) +pcall(btn.close, handle) +pcall(audio.close, output) + +if not ok then + error(err) +end + +print("[button_play_test_wav] done") diff --git a/application/basic_demo/fatfs_image/lua/camera_capture_demo.lua b/application/basic_demo/fatfs_image/lua/camera_capture_demo.lua new file mode 100644 index 0000000..63cddec --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/camera_capture_demo.lua @@ -0,0 +1,69 @@ +local board_manager = require("board_manager") +local camera = require("camera") + +local SAVE_PATH = "/fatfs/data/capture_demo.jpg" +local CAPTURE_TIMEOUT_MS = 3000 + +local function close_camera() + local ok, err = pcall(camera.close) + if not ok then + print("[camera_capture_demo] WARN: close failed: " .. tostring(err)) + end +end + +local camera_paths, path_err = board_manager.get_camera_paths() +if not camera_paths then + print("[camera_capture_demo] ERROR: get_camera_paths failed: " .. tostring(path_err)) + return +end + +print("[camera_capture_demo] camera dev_path: " .. tostring(camera_paths.dev_path)) +if camera_paths.meta_path then + print("[camera_capture_demo] camera meta_path: " .. tostring(camera_paths.meta_path)) +end + +local opened, open_err = pcall(camera.open, camera_paths.dev_path) +if not opened then + print("[camera_capture_demo] ERROR: " .. tostring(open_err)) + return +end + +local info_ok, info_or_err = pcall(camera.info) +if not info_ok then + print("[camera_capture_demo] ERROR: " .. tostring(info_or_err)) + close_camera() + return +end + +print(string.format( + "[camera_capture_demo] stream: %dx%d format=%s", + info_or_err.width, + info_or_err.height, + tostring(info_or_err.pixel_format) +)) + +print(string.format( + "[camera_capture_demo] capturing to %s (timeout=%d ms) ...", + SAVE_PATH, + CAPTURE_TIMEOUT_MS +)) + +local capture_ok, result_or_err = pcall(camera.capture, SAVE_PATH, CAPTURE_TIMEOUT_MS) +if not capture_ok then + print("[camera_capture_demo] ERROR: " .. tostring(result_or_err)) + close_camera() + return +end + +print(string.format( + "[camera_capture_demo] saved: path=%s bytes=%d frame=%dx%d format=%s timestamp_us=%d", + result_or_err.path, + result_or_err.bytes, + result_or_err.width, + result_or_err.height, + tostring(result_or_err.pixel_format), + result_or_err.timestamp_us +)) + +close_camera() +print("[camera_capture_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/coroutine_demo.lua b/application/basic_demo/fatfs_image/lua/coroutine_demo.lua new file mode 100644 index 0000000..ec0464f --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/coroutine_demo.lua @@ -0,0 +1,47 @@ +local delay = require("delay") + +print("[coroutine_demo] start") + +local co = coroutine.create(function(name) + print("[coroutine_demo] worker enter: " .. tostring(name)) + + for step = 1, 3 do + print(string.format("[coroutine_demo] worker step=%d before yield", step)) + coroutine.yield("yield@" .. tostring(step)) + print(string.format("[coroutine_demo] worker step=%d after resume", step)) + delay.delay_ms(100) + end + + return "done:" .. tostring(name) +end) + +print("[coroutine_demo] initial status: " .. coroutine.status(co)) + +local ok, value = coroutine.resume(co, "demo-task") +print(string.format("[coroutine_demo] resume #1 ok=%s value=%s status=%s", + tostring(ok), tostring(value), coroutine.status(co))) + +ok, value = coroutine.resume(co) +print(string.format("[coroutine_demo] resume #2 ok=%s value=%s status=%s", + tostring(ok), tostring(value), coroutine.status(co))) + +ok, value = coroutine.resume(co) +print(string.format("[coroutine_demo] resume #3 ok=%s value=%s status=%s", + tostring(ok), tostring(value), coroutine.status(co))) + +ok, value = coroutine.resume(co) +print(string.format("[coroutine_demo] resume #4 ok=%s value=%s status=%s", + tostring(ok), tostring(value), coroutine.status(co))) + +local wrapped = coroutine.wrap(function() + for i = 1, 2 do + coroutine.yield("wrap@" .. tostring(i)) + end + return "wrap-done" +end) + +print("[coroutine_demo] wrap call #1: " .. tostring(wrapped())) +print("[coroutine_demo] wrap call #2: " .. tostring(wrapped())) +print("[coroutine_demo] wrap call #3: " .. tostring(wrapped())) + +print("[coroutine_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/display_demo.lua b/application/basic_demo/fatfs_image/lua/display_demo.lua new file mode 100644 index 0000000..786b8da --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/display_demo.lua @@ -0,0 +1,142 @@ +local bm = require("board_manager") +local display = require("display") +local delay = require("delay") + +local function rgb(r, g, b) + return { r = r, g = g, b = b } +end + +local function clear_with(color) + display.clear(color.r, color.g, color.b) +end + +local function centered_text(y, text, color, font_size) + local w = display.width() + local tw, th = display.measure_text(text, { font_size = font_size }) + local x = math.floor((w - tw) / 2) + display.draw_text(x, y, text, { + r = color.r, + g = color.g, + b = color.b, + font_size = font_size, + }) + return th +end + +local function wait_frame(ms) + display.present() + delay.delay_ms(ms) +end + +local panel_handle, io_handle, width, height = bm.get_display_lcd_params("display_lcd") +if not panel_handle then + print("[display_demo] ERROR: get_display_lcd_params(display_lcd) failed: " .. tostring(io_handle)) + return +end + +local ok, err = pcall(display.create_screen, panel_handle, io_handle, width, height) +if not ok then + print("[display_demo] ERROR: create_screen failed: " .. tostring(err)) + return +end + +local screen_created = true + +local function cleanup() + if screen_created then + pcall(display.end_frame) + pcall(display.destroy_screen) + screen_created = false + end +end + +width = display.width() +height = display.height() + +if width <= 0 or height <= 0 then + print("[display_demo] ERROR: invalid display size after create_screen") + cleanup() + return +end + +print(string.format("[display_demo] screen ready: %dx%d", width, height)) +print("[display_demo] created from board_manager handle + config") + +local bg = rgb(12, 18, 28) +local fg = rgb(245, 244, 238) +local accent = rgb(255, 160, 60) +local cyan = rgb(72, 208, 235) +local green = rgb(88, 210, 124) +local red = rgb(235, 90, 90) + +local run_ok, run_err = xpcall(function() + display.begin_frame({ clear = true, r = bg.r, g = bg.g, b = bg.b }) + + local title_h = centered_text(16, "Lua Display Demo", fg, 24) + centered_text(16 + title_h + 6, "basic primitives + frame API", accent, 16) + + display.draw_rect(12, 12, width - 24, height - 24, 80, 120, 160) + display.draw_line(20, 72, width - 20, 72, 40, 70, 95) + + display.fill_rect(20, 92, 56, 36, cyan.r, cyan.g, cyan.b) + display.draw_rect(20, 92, 56, 36, fg.r, fg.g, fg.b) + display.fill_circle(110, 110, 18, accent.r, accent.g, accent.b) + display.draw_circle(110, 110, 24, fg.r, fg.g, fg.b) + display.draw_line(142, 92, 196, 128, red.r, red.g, red.b) + display.draw_triangle(212, 90, 252, 126, 220, 136, green.r, green.g, green.b) + display.fill_triangle(262, 92, 298, 126, 278, 138, 110, 130, 250) + + display.draw_round_rect(18, 148, 92, 50, 10, 255, 205, 90) + display.fill_round_rect(122, 148, 92, 50, 12, 64, 104, 255) + display.draw_ellipse(244, 172, 34, 18, 250, 120, 140) + display.fill_ellipse(292, 172, 20, 12, 80, 200, 150) + + display.draw_arc(56, 218, 18, -90, 210, 255, 180, 70) + display.fill_arc(122, 218, 10, 24, -45, 225, 88, 210, 124) + + display.draw_text_aligned(18, height - 42, width - 36, 20, + string.format("%dx%d frame_active=%s", width, height, tostring(display.frame_active())), + { + r = 210, + g = 220, + b = 228, + font_size = 16, + align = "center", + valign = "middle", + }) + wait_frame(1200) + display.end_frame() + + display.begin_frame({ clear = true, r = 8, g = 10, b = 14 }) + for i = 0, 5 do + local y = 20 + i * 34 + local rr = 40 + i * 30 + local gg = 120 + i * 18 + local bb = 220 - i * 22 + display.fill_rect(18, y, width - 36, 22, rr, gg, bb) + display.draw_text_aligned(24, y, width - 48, 22, + string.format("row %d rgb(%d,%d,%d)", i + 1, rr, gg, bb), + { + r = 255, + g = 255, + b = 255, + font_size = 16, + align = "center", + valign = "middle", + }) + end + wait_frame(1200) + display.end_frame() + + display.begin_frame({ clear = true, r = 0, g = 0, b = 0 }) + centered_text(math.floor(height / 2) - 10, "display_demo done", fg, 20) + display.present() + display.end_frame() +end, debug.traceback) + +cleanup() +if not run_ok then + error(run_err) +end + +print("[display_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/gc_demo.lua b/application/basic_demo/fatfs_image/lua/gc_demo.lua new file mode 100644 index 0000000..4da00aa --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/gc_demo.lua @@ -0,0 +1,33 @@ +local function kb() + return collectgarbage("count") +end + +local function print_kb(label) + print(string.format("[gc_demo] %s: %.2f KB", label, kb())) +end + +print("[gc_demo] start") +print_kb("initial") + +local blocks = {} +for i = 1, 400 do + local t = {} + for j = 1, 64 do + t[j] = string.format("block=%d item=%d", i, j) + end + blocks[i] = t +end + +print_kb("after allocation") + +blocks = nil +print_kb("after release refs") + +local step_done = collectgarbage("step", 64) +print(string.format("[gc_demo] step result: %s", tostring(step_done))) +print_kb("after one step") + +collectgarbage("collect") +print_kb("after full collect") + +print("[gc_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/gc_userdata_demo.lua b/application/basic_demo/fatfs_image/lua/gc_userdata_demo.lua new file mode 100644 index 0000000..bf68614 --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/gc_userdata_demo.lua @@ -0,0 +1,39 @@ +local btn = require("button") + +local gpio_num = (args and args.gpio_num) or 0 +local rounds = (args and args.rounds) or 12 + +print(string.format( + "[gc_userdata_demo] start gpio=%d rounds=%d", + gpio_num, + rounds +)) + +local function make_and_drop_button(index) + local handle, err = btn.new(gpio_num, 0) + if not handle then + error(string.format("button.new failed at round %d: %s", index, tostring(err))) + end + + print(string.format("[gc_userdata_demo] round=%d created handle=%s", index, tostring(handle))) + + -- Drop the only Lua reference on purpose. The userdata __gc should release + -- the native button handle so repeated creation does not exhaust BTN_MAX_HANDLES. + handle = nil + collectgarbage("collect") + collectgarbage("collect") +end + +for i = 1, rounds do + make_and_drop_button(i) +end + +local final_handle, final_err = btn.new(gpio_num, 0) +if not final_handle then + error("[gc_userdata_demo] final create failed after GC cycling: " .. tostring(final_err)) +end + +print("[gc_userdata_demo] final create succeeded after repeated GC") +btn.close(final_handle) +collectgarbage("collect") +print("[gc_userdata_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/lcd_touch_demo.lua b/application/basic_demo/fatfs_image/lua/lcd_touch_demo.lua new file mode 100644 index 0000000..e10343b --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/lcd_touch_demo.lua @@ -0,0 +1,53 @@ +local bm = require("board_manager") +local touch = require("lcd_touch") +local delay = require("delay") + +local touch_handle, err = bm.get_lcd_touch_handle("lcd_touch") +if not touch_handle then + print("[lcd_touch_demo] ERROR: get_lcd_touch_handle(lcd_touch) failed: " .. tostring(err)) + return +end + +local ok, info = pcall(touch.sync, touch_handle) +if not ok then + print("[lcd_touch_demo] ERROR: sync failed: " .. tostring(info)) + return +end + +print("[lcd_touch_demo] listening for touch events for 30 seconds...") +print("[lcd_touch_demo] touch the LCD to see press / move / release events") + +local last_pressed = info.pressed +local last_x = info.x or 0 +local last_y = info.y or 0 + +for _ = 1, 600 do + ok, info = pcall(touch.poll, touch_handle) + if not ok then + print("[lcd_touch_demo] ERROR: poll failed: " .. tostring(info)) + return + end + + if info.just_pressed then + print(string.format("[lcd_touch_demo] press x=%d y=%d", info.x, info.y)) + elseif info.pressed and info.moved then + print(string.format( + "[lcd_touch_demo] move x=%d y=%d dx=%d dy=%d held=%.0fms", + info.x, info.y, info.dx, info.dy, info.held_ms)) + elseif info.just_released then + print(string.format( + "[lcd_touch_demo] release x=%d y=%d held=%.0fms", + info.x, info.y, info.held_ms)) + elseif info.pressed and (not last_pressed or info.x ~= last_x or info.y ~= last_y) then + print(string.format( + "[lcd_touch_demo] hold x=%d y=%d held=%.0fms", + info.x, info.y, info.held_ms)) + end + + last_pressed = info.pressed + last_x = info.x + last_y = info.y + delay.delay_ms(50) +end + +print("[lcd_touch_demo] done") diff --git a/application/basic_demo/fatfs_image/lua/lcd_touch_paint.lua b/application/basic_demo/fatfs_image/lua/lcd_touch_paint.lua new file mode 100644 index 0000000..a20f04d --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/lcd_touch_paint.lua @@ -0,0 +1,217 @@ +local bm = require("board_manager") +local display = require("display") +local lcd_touch = require("lcd_touch") +local delay = require("delay") + +local panel_handle, io_handle, width, height = bm.get_display_lcd_params("display_lcd") +if not panel_handle then + print("[lcd_touch_paint] ERROR: get_display_lcd_params(display_lcd) failed: " .. tostring(io_handle)) + return +end + +local ok, err = pcall(display.create_screen, panel_handle, io_handle, width, height) +if not ok then + print("[lcd_touch_paint] ERROR: create_screen failed: " .. tostring(err)) + return +end + +local screen_created = true + +local function cleanup() + if screen_created then + pcall(display.end_frame) + pcall(display.destroy_screen) + screen_created = false + end +end + +width = display.width() +height = display.height() + +if width <= 0 or height <= 0 then + print("[lcd_touch_paint] ERROR: invalid display size after create_screen") + cleanup() + return +end + +local BG_R, BG_G, BG_B = 250, 246, 238 +local INK_R, INK_G, INK_B = 24, 74, 126 +local ACCENT_R, ACCENT_G, ACCENT_B = 210, 88, 52 +local TEXT_R, TEXT_G, TEXT_B = 32, 36, 42 + +local CLEAR_W = 74 +local CLEAR_H = 32 +local CLEAR_X = math.floor((width - CLEAR_W) / 2) +local CLEAR_Y = 8 +local BRUSH_R = 4 +local POLL_INTERVAL_MS = 10 +local FLUSH_INTERVAL_MS = 16 +local RUN_TIME_MS = 50000 + +local dirty_x0 = nil +local dirty_y0 = nil +local dirty_x1 = nil +local dirty_y1 = nil +local dirty_age_ms = 0 + +local function draw_ui() + display.fill_rect(CLEAR_X, CLEAR_Y, CLEAR_W, CLEAR_H, ACCENT_R, ACCENT_G, ACCENT_B) + display.draw_rect(CLEAR_X, CLEAR_Y, CLEAR_W, CLEAR_H, 120, 30, 12) + display.draw_text_aligned(CLEAR_X, CLEAR_Y, CLEAR_W, CLEAR_H, "CLEAR", { + r = 255, + g = 255, + b = 255, + font_size = 16, + align = "center", + valign = "middle", + }) + display.draw_text(10, 10, "LCD Touch Paint", { + r = TEXT_R, + g = TEXT_G, + b = TEXT_B, + font_size = 20, + }) + display.draw_text(10, 34, "draw with finger, tap CLEAR to wipe", { + r = 90, + g = 96, + b = 104, + font_size = 12, + }) + display.present() +end + +local function inside_clear_button(x, y) + return x >= CLEAR_X and x < (CLEAR_X + CLEAR_W) and y >= CLEAR_Y and y < (CLEAR_Y + CLEAR_H) +end + +local function stamp_brush(x, y) + display.fill_circle(x, y, BRUSH_R, INK_R, INK_G, INK_B) +end + +local function mark_dirty(x, y, w, h) + if w <= 0 or h <= 0 then + return + end + + local x0 = math.max(0, x) + local y0 = math.max(0, y) + local x1 = math.min(width, x + w) + local y1 = math.min(height, y + h) + if x1 <= x0 or y1 <= y0 then + return + end + + if dirty_x0 == nil then + dirty_x0 = x0 + dirty_y0 = y0 + dirty_x1 = x1 + dirty_y1 = y1 + else + dirty_x0 = math.min(dirty_x0, x0) + dirty_y0 = math.min(dirty_y0, y0) + dirty_x1 = math.max(dirty_x1, x1) + dirty_y1 = math.max(dirty_y1, y1) + end +end + +local function mark_brush_dirty(x, y) + mark_dirty(x - BRUSH_R - 1, y - BRUSH_R - 1, BRUSH_R * 2 + 3, BRUSH_R * 2 + 3) +end + +local function draw_segment(x0, y0, x1, y1) + display.draw_line(x0, y0, x1, y1, INK_R, INK_G, INK_B) + stamp_brush(x1, y1) + local min_x = math.min(x0, x1) - BRUSH_R - 1 + local min_y = math.min(y0, y1) - BRUSH_R - 1 + local max_x = math.max(x0, x1) + BRUSH_R + 1 + local max_y = math.max(y0, y1) + BRUSH_R + 1 + mark_dirty(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1) +end + +local function flush_dirty(force) + if dirty_x0 == nil then + dirty_age_ms = 0 + return + end + if not force and dirty_age_ms < FLUSH_INTERVAL_MS then + return + end + + display.present_rect(dirty_x0, dirty_y0, dirty_x1 - dirty_x0, dirty_y1 - dirty_y0) + dirty_x0 = nil + dirty_y0 = nil + dirty_x1 = nil + dirty_y1 = nil + dirty_age_ms = 0 +end + +display.begin_frame({ clear = true, r = BG_R, g = BG_G, b = BG_B }) + +local touch_handle, touch_err = bm.get_lcd_touch_handle("lcd_touch") +if not touch_handle then + print("[lcd_touch_paint] ERROR: get_lcd_touch_handle(lcd_touch) failed: " .. tostring(touch_err)) + cleanup() + return +end + +local synced, info = pcall(lcd_touch.sync, touch_handle) +if not synced then + print("[lcd_touch_paint] ERROR: lcd_touch.sync failed: " .. tostring(info)) + cleanup() + return +end + +display.clear(BG_R, BG_G, BG_B) +draw_ui() + +print("[lcd_touch_paint] ready") +print("[lcd_touch_paint] drag on the LCD to paint, tap CLEAR to wipe, running for 60 seconds") + +local drawing = false +local last_x = 0 +local last_y = 0 + +for _ = 1, math.floor(RUN_TIME_MS / POLL_INTERVAL_MS) do + local polled + polled, info = pcall(lcd_touch.poll, touch_handle) + if not polled then + print("[lcd_touch_paint] ERROR: lcd_touch.poll failed: " .. tostring(info)) + break + end + + if info.just_pressed then + if inside_clear_button(info.x, info.y) then + display.clear(BG_R, BG_G, BG_B) + draw_ui() + drawing = false + dirty_x0 = nil + dirty_y0 = nil + dirty_x1 = nil + dirty_y1 = nil + dirty_age_ms = 0 + else + drawing = true + last_x = info.x + last_y = info.y + stamp_brush(info.x, info.y) + mark_brush_dirty(info.x, info.y) + end + elseif info.pressed and drawing then + if not inside_clear_button(info.x, info.y) then + draw_segment(last_x, last_y, info.x, info.y) + last_x = info.x + last_y = info.y + end + elseif info.just_released then + flush_dirty(true) + drawing = false + end + + dirty_age_ms = dirty_age_ms + POLL_INTERVAL_MS + flush_dirty(false) + delay.delay_ms(POLL_INTERVAL_MS) +end + +flush_dirty(true) +cleanup() +print("[lcd_touch_paint] done") diff --git a/application/basic_demo/fatfs_image/lua/led_strip_demo.lua b/application/basic_demo/fatfs_image/lua/led_strip_demo.lua new file mode 100644 index 0000000..f886d20 --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/led_strip_demo.lua @@ -0,0 +1,40 @@ +local ls = require("led_strip") +local delay = require("delay") + +-- Update these values to match the LED strip wiring on the target board. +local LED_GPIO_NUM = 26 +local LED_COUNT = 16 + +-- Create the strip handle and drive all pixels together. +print("[led] creating led strip on gpio " .. tostring(LED_GPIO_NUM)) +local strip, serr = ls.new(LED_GPIO_NUM, LED_COUNT) +if not strip then + print("[led] ERROR: failed to create led strip: " .. tostring(serr)) + return +end +print("[led] led strip created") + +-- Clear first so the demo always starts from a known LED state. +strip:clear() +print("[led] strip cleared") + +local function fill_all(r, g, b) + for index = 0, LED_COUNT - 1 do + strip:set_pixel(index, r, g, b) + end +end + +-- Flash solid red twice. +for i = 1, 2 do + print("[led] flash " .. i .. ": on") + fill_all(255, 0, 0) + strip:refresh() + delay.delay_ms(300) + + print("[led] flash " .. i .. ": off") + strip:clear() + strip:refresh() + delay.delay_ms(300) +end + +print("[led] done") diff --git a/application/basic_demo/fatfs_image/lua/random_demo_stress.lua b/application/basic_demo/fatfs_image/lua/random_demo_stress.lua new file mode 100644 index 0000000..bcf8ace --- /dev/null +++ b/application/basic_demo/fatfs_image/lua/random_demo_stress.lua @@ -0,0 +1,184 @@ +local delay = require("delay") +local esp_heap = require("esp_heap") + +local LUA_ROOT = "/fatfs/data/lua" +local caps = esp_heap.caps() + +local iterations = (args and args.iterations) or 20 +local pause_ms = (args and args.pause_ms) or 200 +local gc_each_round = (args and args.gc_each_round) ~= false +local include_interactive = (args and args.include_interactive) == true +local summary = { + ok = 0, + failed = 0, + failures = {}, +} + +local demos = { + "hello.lua", + "coroutine_demo.lua", + "gc_demo.lua", + "led_strip_demo.lua", + "display_demo.lua", + "audio_play_test_wav.lua", + "audio_demo.lua", + "camera_capture_demo.lua", +} + +if include_interactive then + demos[#demos + 1] = "button_demo.lua" + demos[#demos + 1] = "button_play_test_wav.lua" + demos[#demos + 1] = "lcd_touch_demo.lua" + demos[#demos + 1] = "lcd_touch_paint.lua" +end + +local function info(c) + return esp_heap.get_info(c) +end + +local function print_heap_snapshot(tag) + local default_info = info(caps.DEFAULT) + local internal_info = info(caps.INTERNAL) + local spiram_info = info(caps.SPIRAM) + + print(string.format( + "[random_demo_stress] heap %s default free=%d min=%d largest=%d | internal free=%d min=%d | spiram free=%d min=%d", + tag, + default_info.free_size, + default_info.minimum_free_size, + default_info.largest_free_block, + internal_info.free_size, + internal_info.minimum_free_size, + spiram_info.free_size, + spiram_info.minimum_free_size + )) +end + +local function print_task_watermarks(tag) + local tasks = esp_heap.get_task_watermarks() + + if tasks._warning then + print("[random_demo_stress] task watermark note: " .. tostring(tasks._warning)) + end + + table.sort(tasks, function(a, b) + if a.stack_high_water_mark_bytes == b.stack_high_water_mark_bytes then + return a.name < b.name + end + return a.stack_high_water_mark_bytes < b.stack_high_water_mark_bytes + end) + + print("[random_demo_stress] task watermarks " .. tag) + for i = 1, math.min(#tasks, 6) do + local task = tasks[i] + print(string.format( + "[random_demo_stress] #%d %s state=%s stack_hwm=%dB prio=%d", + i, + tostring(task.name), + tostring(task.state), + tonumber(task.stack_high_water_mark_bytes) or -1, + tonumber(task.current_priority) or -1 + )) + end +end + +local function run_demo(name) + local path = LUA_ROOT .. "/" .. name + local original_print = print + local saw_error_output = false + local result_ok = false + local result_reason = nil + + local function wrapped_print(...) + local parts = {} + for i = 1, select("#", ...) do + parts[i] = tostring(select(i, ...)) + end + local line = table.concat(parts, "\t") + if string.find(line, "ERROR:", 1, true) then + saw_error_output = true + end + original_print(...) + end + + print(string.format("[random_demo_stress] running %s", name)) + print = wrapped_print + local ok, err = xpcall(function() + dofile(path) + end, debug.traceback) + print = original_print + + if ok and not saw_error_output then + print(string.format("[random_demo_stress] result %s ok", name)) + result_ok = true + elseif ok then + print(string.format("[random_demo_stress] result %s failed: demo printed ERROR output", name)) + result_reason = "demo printed ERROR output" + else + print(string.format("[random_demo_stress] result %s failed: %s", name, tostring(err))) + result_reason = tostring(err) + end + + return result_ok, result_reason +end + +math.randomseed((os.time() % 2147483647) + math.floor(collectgarbage("count"))) + +print(string.format( + "[random_demo_stress] start iterations=%d pause_ms=%d gc_each_round=%s include_interactive=%s", + iterations, + pause_ms, + tostring(gc_each_round), + tostring(include_interactive) +)) + +print_heap_snapshot("initial") +print_task_watermarks("initial") + +for i = 1, iterations do + local index = math.random(1, #demos) + local name = demos[index] + + print(string.format("[random_demo_stress] round %d/%d pick=%s", i, iterations, name)) + print_heap_snapshot("before") + local ok, reason = run_demo(name) + if ok then + summary.ok = summary.ok + 1 + else + summary.failed = summary.failed + 1 + summary.failures[#summary.failures + 1] = { + round = i, + name = name, + reason = reason or "unknown failure", + } + end + + if gc_each_round then + collectgarbage("collect") + end + + print_heap_snapshot("after") + print_task_watermarks("after round " .. tostring(i)) + if pause_ms > 0 then + delay.delay_ms(pause_ms) + end +end + +print_heap_snapshot("final") +print_task_watermarks("final") +print(string.format( + "[random_demo_stress] summary total=%d ok=%d failed=%d", + iterations, + summary.ok, + summary.failed +)) +for i = 1, #summary.failures do + local item = summary.failures[i] + print(string.format( + "[random_demo_stress] summary failure round=%d demo=%s reason=%s", + item.round, + item.name, + tostring(item.reason) + )) +end +print("[random_demo_stress] done") diff --git a/application/basic_demo/fatfs_image/test.wav b/application/basic_demo/fatfs_image/test.wav new file mode 100644 index 0000000000000000000000000000000000000000..8148f8bf610ebe798c47769b33999e435369605a GIT binary patch literal 102340 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 A^8f$< literal 0 HcmV?d00001 diff --git a/application/basic_demo/main/CMakeLists.txt b/application/basic_demo/main/CMakeLists.txt index 680f154..27d640a 100644 --- a/application/basic_demo/main/CMakeLists.txt +++ b/application/basic_demo/main/CMakeLists.txt @@ -1,51 +1,8 @@ idf_component_register( - SRCS - "app_clawgent.c" - "main.c" - "basic_demo_cli.c" - "basic_demo_lua_modules.c" - "basic_demo_settings.c" - "basic_demo_wifi.c" - "config_http_server.c" + SRC_DIRS + "." INCLUDE_DIRS "." - REQUIRES - cap_cli - cap_files - cap_im_feishu - cap_im_qq - cap_im_tg - cap_im_wechat - cap_llm_inspect - cap_lua - cap_mcp_client - cap_mcp_server - cap_router_mgr - cap_session_mng - cap_scheduler - cap_skill - cap_time - cap_web_search - claw_event_router - claw_cap - claw_core - claw_memory - claw_skill - console - driver - esp_event - esp_http_server - esp_netif - esp_wifi - fatfs - json - nvs_flash - wear_levelling - lua_module_delay - lua_module_event_publisher - lua_module_gpio - lua_module_led_strip - lua_module_storage EMBED_TXTFILES "web/index.html" "web/styles.css" diff --git a/application/basic_demo/main/app_clawgent.c b/application/basic_demo/main/app_clawgent.c index 4346133..a10dc6b 100644 --- a/application/basic_demo/main/app_clawgent.c +++ b/application/basic_demo/main/app_clawgent.c @@ -224,16 +224,9 @@ static esp_err_t init_capabilities(const basic_demo_settings_t *settings) TAG, "Failed to register WeChat cap"); ESP_RETURN_ON_ERROR(cap_files_register_group(), TAG, "Failed to register files cap"); - // ESP_RETURN_ON_ERROR(basic_demo_lua_modules_register(), - // TAG, - // "Failed to register app Lua modules"); - // ESP_RETURN_ON_ERROR(cap_lua_register_group(), TAG, "Failed to register Lua cap"); - // ESP_RETURN_ON_ERROR(cap_mcp_client_register_group(), - // TAG, - // "Failed to register MCP client cap"); - // ESP_RETURN_ON_ERROR(cap_mcp_server_register_group(), - // TAG, - // "Failed to register MCP server cap"); + ESP_RETURN_ON_ERROR(basic_demo_lua_modules_register(), + TAG, + "Failed to register app Lua modules"); ESP_RETURN_ON_ERROR(cap_scheduler_register_group(), TAG, "Failed to register scheduler cap"); diff --git a/application/basic_demo/main/basic_demo_lua_modules.c b/application/basic_demo/main/basic_demo_lua_modules.c index b4498ab..5c65a7f 100644 --- a/application/basic_demo/main/basic_demo_lua_modules.c +++ b/application/basic_demo/main/basic_demo_lua_modules.c @@ -10,6 +10,20 @@ #include "lua_module_gpio.h" #include "lua_module_led_strip.h" #include "lua_module_storage.h" +#include "lua_module_button.h" +#include "lua_module_esp_heap.h" +#include "lua_module_board_manager.h" + +#if defined(CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT) +#include "lua_module_audio.h" +#endif +#include "lua_module_display.h" +#if defined(CONFIG_ESP_BOARD_DEV_LCD_TOUCH_I2C_SUPPORT) +#include "lua_module_lcd_touch.h" +#endif +#if defined(CONFIG_ESP_BOARD_DEV_CAMERA_SUPPORT) +#include "lua_module_camera.h" +#endif esp_err_t basic_demo_lua_modules_register(void) { @@ -35,5 +49,46 @@ esp_err_t basic_demo_lua_modules_register(void) return err; } +#if defined(CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT) + err = lua_module_audio_register(); + if (err != ESP_OK) { + return err; + } +#endif + + err = lua_module_button_register(); + if (err != ESP_OK) { + return err; + } + + err = lua_module_display_register(); + if (err != ESP_OK) { + return err; + } + + err = lua_module_board_manager_register(); + if (err != ESP_OK) { + return err; + } + +#if defined(CONFIG_ESP_BOARD_DEV_LCD_TOUCH_I2C_SUPPORT) + err = lua_module_lcd_touch_register(); + if (err != ESP_OK) { + return err; + } +#endif + +#if defined(CONFIG_ESP_BOARD_DEV_CAMERA_SUPPORT) + err = lua_module_camera_register(); + if (err != ESP_OK) { + return err; + } +#endif + + err = lua_module_esp_heap_register(); + if (err != ESP_OK) { + return err; + } + return lua_module_event_publisher_register(); } diff --git a/application/basic_demo/main/idf_component.yml b/application/basic_demo/main/idf_component.yml index 48d23d0..8efb716 100644 --- a/application/basic_demo/main/idf_component.yml +++ b/application/basic_demo/main/idf_component.yml @@ -1,3 +1,116 @@ ## IDF Component Manager Manifest File dependencies: - espressif/led_strip: ^3.0.3 + espressif/esp_board_manager: + version: "^0.5.7" + public: true + + cap_cli: + path: ../../../components/claw_capabilities/cap_cli + + cap_files: + path: ../../../components/claw_capabilities/cap_files + + cap_im_attachment: + path: ../../../components/claw_capabilities/cap_im_attachment + + cap_im_feishu: + path: ../../../components/claw_capabilities/cap_im_feishu + + cap_im_qq: + path: ../../../components/claw_capabilities/cap_im_qq + + cap_im_tg: + path: ../../../components/claw_capabilities/cap_im_tg + + cap_im_wechat: + path: ../../../components/claw_capabilities/cap_im_wechat + + cap_llm_inspect: + path: ../../../components/claw_capabilities/cap_llm_inspect + + cap_lua: + path: ../../../components/claw_capabilities/cap_lua + + cap_mcp_client: + path: ../../../components/claw_capabilities/cap_mcp_client + + cap_mcp_server: + path: ../../../components/claw_capabilities/cap_mcp_server + + cap_router_mgr: + path: ../../../components/claw_capabilities/cap_router_mgr + + cap_session_mng: + path: ../../../components/claw_capabilities/cap_session_mng + + cap_skill: + path: ../../../components/claw_capabilities/cap_skill + + cap_scheduler: + path: ../../../components/claw_capabilities/cap_scheduler + + cap_time: + path: ../../../components/claw_capabilities/cap_time + + cap_web_search: + path: ../../../components/claw_capabilities/cap_web_search + + claw_cap: + path: ../../../components/claw_modules/claw_cap + + claw_core: + path: ../../../components/claw_modules/claw_core + + claw_event_router: + path: ../../../components/claw_modules/claw_event_router + + claw_memory: + path: ../../../components/claw_modules/claw_memory + + claw_skill: + path: ../../../components/claw_modules/claw_skill + + esp_painter: + path: ../../../components/lua_modules/esp_painter + + lua_module_audio: + matches: + - if: $CONFIG{ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT} == True + path: ../../../components/lua_modules/lua_module_audio + + lua_module_board_manager: + path: ../../../components/lua_modules/lua_module_board_manager + + lua_module_button: + path: ../../../components/lua_modules/lua_module_button + + lua_module_camera: + matches: + - if: $CONFIG{ESP_BOARD_DEV_CAMERA_SUPPORT} == True + path: ../../../components/lua_modules/lua_module_camera + + lua_module_delay: + path: ../../../components/lua_modules/lua_module_delay + + lua_module_display: + path: ../../../components/lua_modules/lua_module_display + + lua_module_esp_heap: + path: ../../../components/lua_modules/lua_module_esp_heap + + lua_module_event_publisher: + path: ../../../components/lua_modules/lua_module_event_publisher + + lua_module_gpio: + path: ../../../components/lua_modules/lua_module_gpio + + lua_module_lcd_touch: + matches: + - if: $CONFIG{ESP_BOARD_DEV_LCD_TOUCH_I2C_SUPPORT} == True + path: ../../../components/lua_modules/lua_module_lcd_touch + + lua_module_led_strip: + path: ../../../components/lua_modules/lua_module_led_strip + + lua_module_storage: + path: ../../../components/lua_modules/lua_module_storage diff --git a/application/basic_demo/main/main.c b/application/basic_demo/main/main.c index b6cc928..a355e7a 100644 --- a/application/basic_demo/main/main.c +++ b/application/basic_demo/main/main.c @@ -13,6 +13,7 @@ #include "freertos/task.h" #include "nvs_flash.h" #include "wear_levelling.h" +#include "esp_board_manager_includes.h" static const char *TAG = "basic_demo"; static basic_demo_settings_t s_settings = {0}; @@ -110,6 +111,7 @@ void app_main(void) ESP_ERROR_CHECK(init_nvs()); ESP_ERROR_CHECK(basic_demo_settings_init()); ESP_ERROR_CHECK(basic_demo_settings_load(&s_settings)); + ESP_ERROR_CHECK(esp_board_manager_init()); ESP_ERROR_CHECK(init_fatfs()); ESP_ERROR_CHECK(basic_demo_wifi_init()); ESP_ERROR_CHECK(config_http_server_init(BASIC_DEMO_FATFS_BASE_PATH)); diff --git a/application/basic_demo/partitions.csv b/application/basic_demo/partitions.csv deleted file mode 100644 index 6cc8b92..0000000 --- a/application/basic_demo/partitions.csv +++ /dev/null @@ -1,8 +0,0 @@ -# Name, Type, SubType, Offset, Size -nvs, data, nvs, 0x9000, 0x6000 -otadata, data, ota, 0xF000, 0x2000 -phy_init, data, phy, 0x11000, 0x1000 -ota_0, app, ota_0, 0x20000, 0x200000 -ota_1, app, ota_1, 0x220000, 0x200000 -storage, data, fat, 0x420000, 0xBD0000 -coredump, data, coredump,0xFF0000, 0x10000 diff --git a/application/basic_demo/partitions_16MB.csv b/application/basic_demo/partitions_16MB.csv new file mode 100644 index 0000000..cc5ec83 --- /dev/null +++ b/application/basic_demo/partitions_16MB.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x6000 +otadata, data, ota, 0xF000, 0x2000 +phy_init, data, phy, 0x11000, 0x1000 +ota_0, app, ota_0, , 4M +ota_1, app, ota_1, , 4M +storage, data, fat, , 7M diff --git a/application/basic_demo/partitions_4MB.csv b/application/basic_demo/partitions_4MB.csv new file mode 100644 index 0000000..c15cf35 --- /dev/null +++ b/application/basic_demo/partitions_4MB.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x6000 +otadata, data, ota, 0xF000, 0x2000 +phy_init, data, phy, 0x11000, 0x1000 +ota_0, app, ota_0, , 3M +storage, data, fat, , 800K diff --git a/application/basic_demo/partitions_8MB.csv b/application/basic_demo/partitions_8MB.csv new file mode 100644 index 0000000..49e003a --- /dev/null +++ b/application/basic_demo/partitions_8MB.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x6000 +otadata, data, ota, 0xF000, 0x2000 +phy_init, data, phy, 0x11000, 0x1000 +ota_0, app, ota_0, , 3M +ota_1, app, ota_1, , 3M +storage, data, fat, , 1500K diff --git a/application/basic_demo/partitions_8mb.csv b/application/basic_demo/partitions_8mb.csv deleted file mode 100644 index ed10197..0000000 --- a/application/basic_demo/partitions_8mb.csv +++ /dev/null @@ -1,8 +0,0 @@ -# Name, Type, SubType, Offset, Size -nvs, data, nvs, 0x9000, 0x6000 -otadata, data, ota, 0xF000, 0x2000 -phy_init, data, phy, 0x11000, 0x1000 -ota_0, app, ota_0, 0x20000, 0x200000 -ota_1, app, ota_1, 0x220000, 0x200000 -storage, data, fat, 0x420000, 0x3D0000 -coredump, data, coredump,0x7F0000, 0x10000 diff --git a/application/basic_demo/sdkconfig.defaults b/application/basic_demo/sdkconfig.defaults index 8781e58..d9b1fee 100644 --- a/application/basic_demo/sdkconfig.defaults +++ b/application/basic_demo/sdkconfig.defaults @@ -1,15 +1,8 @@ # This file was generated using idf.py save-defconfig. It can be edited manually. # Espressif IoT Development Framework (ESP-IDF) 5.5.1 Project Minimal Configuration # -CONFIG_IDF_TARGET="esp32s3" -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_ESPTOOLPY_FLASHFREQ_120M=y -CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y -CONFIG_PARTITION_TABLE_CUSTOM=y + CONFIG_HTTPD_WS_SUPPORT=y -CONFIG_SPIRAM=y -CONFIG_SPIRAM_MODE_OCT=y -CONFIG_SPIRAM_SPEED_120M=y CONFIG_SPIRAM_MEMTEST=n CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=2048 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y diff --git a/components/claw_capabilities/cap_lua/src/cap_lua_async.c b/components/claw_capabilities/cap_lua/src/cap_lua_async.c index 4678f4a..0cf0709 100644 --- a/components/claw_capabilities/cap_lua/src/cap_lua_async.c +++ b/components/claw_capabilities/cap_lua/src/cap_lua_async.c @@ -24,11 +24,11 @@ typedef struct { char job_id[9]; char path[192]; char *args_json; + char *summary; uint32_t timeout_ms; time_t created_at; time_t started_at; time_t finished_at; - char summary[CAP_LUA_OUTPUT_SIZE]; TaskHandle_t task_handle; } cap_lua_job_record_t; @@ -111,6 +111,16 @@ static int cap_lua_find_slot_by_id_locked(const char *job_id) return -1; } +static void cap_lua_clear_slot(cap_lua_job_record_t *job) +{ + if (!job) { + return; + } + free(job->args_json); + free(job->summary); + memset(job, 0, sizeof(*job)); +} + static void cap_lua_finish_job(cap_lua_job_ctx_t *ctx, bool ok, bool timed_out, @@ -129,7 +139,8 @@ static void cap_lua_finish_job(cap_lua_job_ctx_t *ctx, s_jobs[ctx->slot].finished_at = time(NULL); s_jobs[ctx->slot].task_handle = NULL; if (summary && summary[0]) { - strlcpy(s_jobs[ctx->slot].summary, summary, sizeof(s_jobs[ctx->slot].summary)); + free(s_jobs[ctx->slot].summary); + s_jobs[ctx->slot].summary = strdup(summary); } } @@ -179,6 +190,8 @@ static void cap_lua_job_task(void *arg) esp_err_t cap_lua_async_init(void) { + int i; + if (!s_job_lock) { s_job_lock = xSemaphoreCreateMutex(); } @@ -186,6 +199,9 @@ esp_err_t cap_lua_async_init(void) return ESP_ERR_NO_MEM; } + for (i = 0; i < CAP_LUA_ASYNC_MAX_JOBS; i++) { + cap_lua_clear_slot(&s_jobs[i]); + } memset(s_jobs, 0, sizeof(s_jobs)); s_running_jobs = 0; s_runner_started = false; @@ -254,7 +270,7 @@ esp_err_t cap_lua_async_submit(const cap_lua_async_job_t *job, return ESP_ERR_NO_MEM; } - memset(&s_jobs[slot], 0, sizeof(s_jobs[slot])); + cap_lua_clear_slot(&s_jobs[slot]); s_jobs[slot].used = true; s_jobs[slot].status = CAP_LUA_JOB_QUEUED; s_jobs[slot].created_at = job->created_at ? job->created_at : now; @@ -263,7 +279,7 @@ esp_err_t cap_lua_async_submit(const cap_lua_async_job_t *job, if (ctx->args_json) { s_jobs[slot].args_json = strdup(ctx->args_json); if (!s_jobs[slot].args_json) { - memset(&s_jobs[slot], 0, sizeof(s_jobs[slot])); + cap_lua_clear_slot(&s_jobs[slot]); xSemaphoreGive(s_job_lock); free(ctx->args_json); free(ctx); @@ -282,8 +298,7 @@ esp_err_t cap_lua_async_submit(const cap_lua_async_job_t *job, CAP_LUA_ASYNC_PRIO, &s_jobs[slot].task_handle) != pdPASS) { if (xSemaphoreTake(s_job_lock, pdMS_TO_TICKS(1000)) == pdTRUE) { - free(s_jobs[slot].args_json); - memset(&s_jobs[slot], 0, sizeof(s_jobs[slot])); + cap_lua_clear_slot(&s_jobs[slot]); if (s_running_jobs > 0) { s_running_jobs--; } @@ -381,7 +396,7 @@ esp_err_t cap_lua_async_get_job(const char *job_id, s_jobs[slot].job_id, cap_lua_job_status_name(s_jobs[slot].status), s_jobs[slot].path, - s_jobs[slot].summary[0] ? s_jobs[slot].summary : "(empty)"); + (s_jobs[slot].summary && s_jobs[slot].summary[0]) ? s_jobs[slot].summary : "(empty)"); xSemaphoreGive(s_job_lock); return ESP_OK; } diff --git a/components/claw_capabilities/cap_lua/src/cap_lua_runtime.c b/components/claw_capabilities/cap_lua/src/cap_lua_runtime.c index aa78d98..cf0fa4f 100644 --- a/components/claw_capabilities/cap_lua/src/cap_lua_runtime.c +++ b/components/claw_capabilities/cap_lua/src/cap_lua_runtime.c @@ -107,12 +107,16 @@ static int cap_lua_print_capture(lua_State *L) if (i > 1) { cap_lua_output_append(ctx, "\t", 1); + fwrite("\t", sizeof(char), 1, stdout); } cap_lua_output_append(ctx, text, len); + fwrite(text, sizeof(char), len, stdout); lua_pop(L, 1); } cap_lua_output_append(ctx, "\n", 1); + fwrite("\n", sizeof(char), 1, stdout); + fflush(stdout); return 0; } diff --git a/components/claw_capabilities/cap_lua/src/cmd_cap_lua.c b/components/claw_capabilities/cap_lua/src/cmd_cap_lua.c index f067ed0..b6cfd7f 100644 --- a/components/claw_capabilities/cap_lua/src/cmd_cap_lua.c +++ b/components/claw_capabilities/cap_lua/src/cmd_cap_lua.c @@ -7,6 +7,7 @@ #include #include +#include #include "argtable3/argtable3.h" #include "cap_lua.h" @@ -37,6 +38,71 @@ static void print_lua_result(const char *result) } } +static const char *lua_result_last_nonempty_line(const char *result, size_t *len_out) +{ + const char *line_start = NULL; + const char *cursor = NULL; + const char *last_start = NULL; + size_t last_len = 0; + + if (len_out) { + *len_out = 0; + } + if (!result || !result[0]) { + return NULL; + } + + line_start = result; + cursor = result; + while (1) { + if (*cursor == '\n' || *cursor == '\0') { + size_t line_len = (size_t)(cursor - line_start); + if (line_len > 0) { + last_start = line_start; + last_len = line_len; + } + if (*cursor == '\0') { + break; + } + line_start = cursor + 1; + } + cursor++; + } + + if (len_out) { + *len_out = last_len; + } + return last_start; +} + +static void print_lua_run_tail(const char *result, bool is_error) +{ + size_t line_len = 0; + const char *line = NULL; + + if (!result || !result[0]) { + return; + } + + if (!is_error) { + if (strcmp(result, "Lua script completed with no output.\n") == 0) { + printf("%s", result); + return; + } + line = strstr(result, "[output truncated]\n"); + if (line) { + printf("%s", line); + } + return; + } + + line = lua_result_last_nonempty_line(result, &line_len); + if (!line || line_len == 0) { + return; + } + printf("%.*s\n", (int)line_len, line); +} + static int lua_func(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&lua_args); @@ -44,6 +110,7 @@ static int lua_func(int argc, char **argv) char *result = NULL; esp_err_t err = ESP_OK; uint32_t timeout_ms = 0; + bool sync_run = false; if (nerrors != 0) { arg_print_errors(stderr, lua_args.end, argv[0]); @@ -95,6 +162,7 @@ static int lua_func(int argc, char **argv) result, 4096); } else if (lua_args.run->count) { + sync_run = true; if (!lua_args.path->count) { printf("'--run' requires '--path'\n"); free(result); @@ -125,13 +193,21 @@ static int lua_func(int argc, char **argv) } if (err != ESP_OK) { - print_lua_result(result); + if (sync_run) { + print_lua_run_tail(result, true); + } else { + print_lua_result(result); + } printf("lua command failed: %s\n", esp_err_to_name(err)); free(result); return 1; } - print_lua_result(result); + if (sync_run) { + print_lua_run_tail(result, false); + } else { + print_lua_result(result); + } free(result); return 0; } diff --git a/components/lua_modules/esp_painter/CMakeLists.txt b/components/lua_modules/esp_painter/CMakeLists.txt new file mode 100644 index 0000000..ab065e1 --- /dev/null +++ b/components/lua_modules/esp_painter/CMakeLists.txt @@ -0,0 +1,16 @@ +file(GLOB_RECURSE FONT_SRCS font/*.c) + +set(painter_reqs esp_mm) +if(CONFIG_SOC_PPA_SUPPORTED) + list(APPEND painter_reqs esp_driver_ppa) +endif() + +idf_component_register( + SRCS + ${FONT_SRCS} + "esp_painter.c" + INCLUDE_DIRS + "include" + REQUIRES + ${painter_reqs} +) diff --git a/components/lua_modules/esp_painter/Kconfig b/components/lua_modules/esp_painter/Kconfig new file mode 100644 index 0000000..e9095a9 --- /dev/null +++ b/components/lua_modules/esp_painter/Kconfig @@ -0,0 +1,49 @@ +menu "ESP Painter" + config ESP_PAINTER_FORMAT_SIZE_MAX + int "Size of format string buffer" + default 128 + help + Maximum size of the buffer used for formatted string output. + + menu "Fonts" + config ESP_PAINTER_BASIC_FONT_12 + bool "Enable basic_font_12" + default n + + config ESP_PAINTER_BASIC_FONT_16 + bool "Enable basic_font_16" + default n + + config ESP_PAINTER_BASIC_FONT_20 + bool "Enable basic_font_20" + default n + + config ESP_PAINTER_BASIC_FONT_24 + bool "Enable basic_font_24" + default y + + config ESP_PAINTER_BASIC_FONT_28 + bool "Enable basic_font_28" + default n + + config ESP_PAINTER_BASIC_FONT_32 + bool "Enable basic_font_32" + default n + + config ESP_PAINTER_BASIC_FONT_36 + bool "Enable basic_font_36" + default n + + config ESP_PAINTER_BASIC_FONT_40 + bool "Enable basic_font_40" + default n + + config ESP_PAINTER_BASIC_FONT_44 + bool "Enable basic_font_44" + default n + + config ESP_PAINTER_BASIC_FONT_48 + bool "Enable basic_font_48" + default n + endmenu +endmenu diff --git a/components/lua_modules/esp_painter/esp_painter.c b/components/lua_modules/esp_painter/esp_painter.c new file mode 100644 index 0000000..63eb8ba --- /dev/null +++ b/components/lua_modules/esp_painter/esp_painter.c @@ -0,0 +1,622 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_painter.h" +#include "esp_cache.h" +#include "esp_heap_caps.h" +#if CONFIG_SOC_PPA_SUPPORTED +#include "esp_private/esp_cache_private.h" +#include "driver/ppa.h" +#endif + +static const char *TAG = "esp_painter"; + +#if CONFIG_SOC_PPA_SUPPORTED +#define ALIGN_UP(size) (((size) + data_cache_line_size - 1) & ~(data_cache_line_size - 1)) +#endif + +typedef struct { + struct { + uint16_t width; + uint16_t height; + } canvas; + struct { + uint16_t width; + uint16_t height; + } text_canvas; + esp_painter_color_format_t color_format; + const esp_painter_basic_font_t *default_font; + bool swap_rgb565; // Whether to swap RGB565 bytes +#if CONFIG_SOC_PPA_SUPPORTED + ppa_client_handle_t ppa_client; + uint8_t *ppa_output_buffer; +#endif +} esp_painter_t; + +#if CONFIG_SOC_PPA_SUPPORTED +static size_t data_cache_line_size = 0; +#endif + +static const struct { + uint8_t r; + uint8_t g; + uint8_t b; +} rgb_colors[] = { + {0x00, 0x00, 0x00}, // BLACK + {0x00, 0x00, 0x80}, // NAVY + {0x00, 0x80, 0x00}, // DARKGREEN + {0x00, 0x80, 0x80}, // DARKCYAN + {0x80, 0x00, 0x00}, // MAROON + {0x80, 0x00, 0x80}, // PURPLE + {0x80, 0x80, 0x00}, // OLIVE + {0xC0, 0xC0, 0xC0}, // LIGHTGREY + {0x80, 0x80, 0x80}, // DARKGREY + {0x00, 0x00, 0xFF}, // BLUE + {0x00, 0xFF, 0x00}, // GREEN + {0x00, 0xFF, 0xFF}, // CYAN + {0xFF, 0x00, 0x00}, // RED + {0xFF, 0x00, 0xFF}, // MAGENTA + {0xFF, 0xFF, 0x00}, // YELLOW + {0xFF, 0xFF, 0xFF}, // WHITE + {0xFF, 0xA5, 0x00}, // ORANGE + {0xAD, 0xFF, 0x2F}, // GREENYELLOW + {0xFF, 0xC0, 0xCB}, // PINK +}; + +static uint32_t esp_painter_get_color(esp_painter_handle_t handle, esp_painter_color_t color) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter || color >= sizeof(rgb_colors) / sizeof(rgb_colors[0])) { + return 0; + } + + uint8_t r = rgb_colors[color].r; + uint8_t g = rgb_colors[color].g; + uint8_t b = rgb_colors[color].b; + + uint32_t color_value = 0; + switch (painter->color_format) { + case ESP_PAINTER_COLOR_FORMAT_YUV420: + case ESP_PAINTER_COLOR_FORMAT_YUV422: + case ESP_PAINTER_COLOR_FORMAT_RGB565: + color_value = RGB565(r, g, b); + // Swap bytes if needed for RGB565 + if (painter->swap_rgb565) { + color_value = ((color_value & 0xFF) << 8) | ((color_value >> 8) & 0xFF); + } + return color_value; + case ESP_PAINTER_COLOR_FORMAT_RGB888: + return RGB888(r, g, b); + default: + return 0; + } +} + +static uint16_t esp_painter_get_rgb565_color_value(esp_painter_handle_t handle, uint16_t color565) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter) { + return 0; + } + + if (painter->swap_rgb565) { + return (uint16_t)((color565 << 8) | (color565 >> 8)); + } + + return color565; +} + +static void esp_painter_measure_text(const esp_painter_basic_font_t *font, const char *text, + uint16_t *out_width, uint16_t *out_height) +{ + uint16_t max_cols = 0; + uint16_t cols = 0; + uint16_t lines = 1; + + if (!font || !text) { + if (out_width) { + *out_width = 0; + } + if (out_height) { + *out_height = 0; + } + return; + } + + for (const char *p = text; *p; ++p) { + if (*p == '\n') { + if (cols > max_cols) { + max_cols = cols; + } + cols = 0; + lines++; + } else if (*p != '\r') { + cols++; + } + } + if (cols > max_cols) { + max_cols = cols; + } + + if (out_width) { + *out_width = (uint16_t)(max_cols * font->width); + } + if (out_height) { + *out_height = (uint16_t)(lines * font->height); + } +} + +#if CONFIG_SOC_PPA_SUPPORTED +static esp_err_t esp_painter_convert_yuv420_to_rgb565(esp_painter_handle_t handle, uint8_t *in_buffer, uint8_t *out_buffer, + uint32_t out_buffer_size, + uint32_t block_w, uint32_t block_h, + uint32_t block_offset_x, uint32_t block_offset_y) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter || !in_buffer || !out_buffer) { + return ESP_ERR_INVALID_ARG; + } + + ppa_srm_oper_config_t srm_config = { + .in.buffer = in_buffer, + .in.pic_w = painter->canvas.width, + .in.pic_h = painter->canvas.height, + .in.block_w = block_w, + .in.block_h = block_h, + .in.block_offset_x = block_offset_x, + .in.block_offset_y = block_offset_y, + .in.srm_cm = PPA_SRM_COLOR_MODE_YUV420, + .out.buffer = out_buffer, + .out.buffer_size = out_buffer_size, + .out.pic_w = block_w, + .out.pic_h = block_h, + .out.block_offset_x = 0, + .out.block_offset_y = 0, + .out.srm_cm = PPA_SRM_COLOR_MODE_RGB565, + .rotation_angle = PPA_SRM_ROTATION_ANGLE_0, + .scale_x = 1, + .scale_y = 1, + .rgb_swap = 0, + .byte_swap = 0, + .mode = PPA_TRANS_MODE_BLOCKING, + }; + + int ret = ppa_do_scale_rotate_mirror(painter->ppa_client, &srm_config); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "First PPA conversion failed"); + } + + return ret; +} + +static esp_err_t esp_painter_convert_rgb565_to_yuv420(esp_painter_handle_t handle, uint8_t *in_buffer, uint8_t *out_buffer, uint32_t buffer_size, + uint32_t in_width, uint32_t in_height, + uint32_t out_width, uint32_t out_height, + uint32_t out_offset_x, uint32_t out_offset_y) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter || !in_buffer || !out_buffer) { + return ESP_ERR_INVALID_ARG; + } + + ppa_srm_oper_config_t srm_out_config = { + .in.buffer = in_buffer, + .in.pic_w = in_width, + .in.pic_h = in_height, + .in.block_w = in_width, + .in.block_h = in_height, + .in.block_offset_x = 0, + .in.block_offset_y = 0, + .in.srm_cm = PPA_SRM_COLOR_MODE_RGB565, + .out.buffer = out_buffer, + .out.buffer_size = buffer_size, + .out.pic_w = out_width, + .out.pic_h = out_height, + .out.block_offset_x = out_offset_x, + .out.block_offset_y = out_offset_y, + .out.srm_cm = PPA_SRM_COLOR_MODE_YUV420, + .rotation_angle = PPA_SRM_ROTATION_ANGLE_0, + .scale_x = 1, + .scale_y = 1, + .rgb_swap = 0, + .byte_swap = 0, + .mode = PPA_TRANS_MODE_BLOCKING, + }; + + int ret = ppa_do_scale_rotate_mirror(painter->ppa_client, &srm_out_config); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Second PPA conversion failed"); + } + + return ESP_OK; +} +#endif + +static esp_err_t esp_painter_draw_pixel(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, uint16_t color_value) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter || !buffer) { + return ESP_ERR_INVALID_ARG; + } + +#if CONFIG_SOC_PPA_SUPPORTED + bool using_ppa = (painter->color_format == ESP_PAINTER_COLOR_FORMAT_YUV420 || + painter->color_format == ESP_PAINTER_COLOR_FORMAT_YUV422); +#else + bool using_ppa = false; +#endif + + if (using_ppa) { + ESP_LOGD(TAG, "Drawing pixel at (%d,%d) with color 0x%04" PRIx32, x, y, color_value); + + uint32_t offset = (y * painter->text_canvas.width + x) * 2; + if (offset + 2 > buffer_size) { + ESP_LOGW(TAG, "Buffer overflow: offset %" PRIu32 ", size %" PRIu32, offset, buffer_size); + return ESP_ERR_INVALID_SIZE; + } + + uint8_t low_byte = color_value & 0xFF; + uint8_t high_byte = (color_value >> 8) & 0xFF; + buffer[offset] = low_byte; + buffer[offset + 1] = high_byte; + + return ESP_OK; + } + + switch (painter->color_format) { + case ESP_PAINTER_COLOR_FORMAT_RGB565: { + uint32_t offset = (y * painter->canvas.width + x) * 2; + if (offset + 2 > buffer_size) { + return ESP_ERR_INVALID_SIZE; + } + buffer[offset] = color_value & 0xFF; + buffer[offset + 1] = (color_value >> 8) & 0xFF; + break; + } + case ESP_PAINTER_COLOR_FORMAT_RGB888: { + uint32_t offset = (y * painter->canvas.width + x) * 3; + if (offset + 3 > buffer_size) { + return ESP_ERR_INVALID_SIZE; + } + buffer[offset] = color_value & 0xFF; + buffer[offset + 1] = (color_value >> 8) & 0xFF; + buffer[offset + 2] = (color_value >> 16) & 0xFF; + break; + } + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +static esp_err_t esp_painter_draw_char(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + uint16_t color_value, char c) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter || !buffer) { + return ESP_ERR_INVALID_ARG; + } + + if (!font) { + font = painter->default_font; + } + if (!font) { + ESP_LOGE(TAG, "No font specified"); + return ESP_ERR_INVALID_ARG; + } + + if (c < 32 || c > 127) { + return ESP_ERR_INVALID_ARG; + } + + uint32_t char_offset = (c - 32) * font->height * ((font->width + 7) / 8); + const uint8_t *char_bitmap = font->bitmap + char_offset; + ESP_LOGD(TAG, "Drawing char '%c' at (%d,%d)", c, x, y); + + for (int dy = 0; dy < font->height; dy++) { + for (int dx = 0; dx < font->width; dx++) { + uint8_t byte = char_bitmap[dy * ((font->width + 7) / 8) + (dx / 8)]; + if (byte & (0x80 >> (dx % 8))) { + ESP_LOGD(TAG, "Setting pixel at relative pos (%d,%d)", dx, dy); + esp_err_t ret = esp_painter_draw_pixel(handle, buffer, buffer_size, x + dx, y + dy, color_value); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to draw pixel at (%d,%d)", x + dx, y + dy); + return ret; + } + } + } + } + + return ESP_OK; +} + +static esp_err_t esp_painter_draw_text(esp_painter_t *painter, uint8_t *buffer, + uint32_t buffer_size, uint16_t x, uint16_t y, + uint32_t text_width, uint32_t text_height, + const esp_painter_basic_font_t *font, + uint16_t color_value, const char *text) +{ + uint16_t cursor_x = x; + uint16_t cursor_y = y; + esp_err_t ret = ESP_OK; + + while (*text) { + if (cursor_y >= text_height) { + break; + } + + switch (*text) { + case '\n': + cursor_x = x; + cursor_y += font->height; + break; + case '\r': + cursor_x = x; + break; + default: + if (cursor_x + font->width <= text_width) { + ret = esp_painter_draw_char(painter, buffer, buffer_size, + cursor_x, cursor_y, font, color_value, *text); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to draw char at (%d,%d)", cursor_x, cursor_y); + return ret; + } + } + cursor_x += font->width; + + if (cursor_x >= text_width) { + cursor_x = x; + cursor_y += font->height; + } + break; + } + text++; + } + return ret; +} + +esp_err_t esp_painter_draw_string(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + esp_painter_color_t color, const char* text) +{ + esp_err_t ret = ESP_OK; + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter || !buffer || !text) { + return ESP_ERR_INVALID_ARG; + } + + if (!font) { + font = painter->default_font; + if (!font) { + ESP_LOGE(TAG, "No font specified"); + return ESP_ERR_INVALID_ARG; + } + } + + if (x >= painter->canvas.width || y >= painter->canvas.height) { + ESP_LOGW(TAG, "Starting position out of bounds: (%d,%d)", x, y); + return ESP_ERR_INVALID_ARG; + } + + uint16_t color_value = (uint16_t)esp_painter_get_color(handle, color); + +#if CONFIG_SOC_PPA_SUPPORTED + bool using_ppa = (painter->color_format == ESP_PAINTER_COLOR_FORMAT_YUV420 || + painter->color_format == ESP_PAINTER_COLOR_FORMAT_YUV422); + if (using_ppa) { + uint16_t text_width = strlen(text) * font->width; + uint16_t text_height = font->height; + + painter->text_canvas.width = text_width; + painter->text_canvas.height = text_height; + + uint32_t aligned_size = ALIGN_UP(text_width * text_height * 2); + if (aligned_size > buffer_size) { + ESP_LOGE(TAG, "Buffer too small: need %" PRIu32 ", have %" PRIu32, aligned_size, buffer_size); + return ESP_ERR_INVALID_SIZE; + } + + uint8_t *ppa_output_buffer = heap_caps_aligned_alloc( + data_cache_line_size, + aligned_size, + MALLOC_CAP_SPIRAM + ); + if (!ppa_output_buffer) { + ESP_LOGE(TAG, "Failed to allocate PPA output buffer"); + return ESP_ERR_NO_MEM; + } + + int ret = esp_painter_convert_yuv420_to_rgb565(painter, buffer, ppa_output_buffer, + aligned_size, + text_width, text_height, + x, y); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "First PPA conversion failed"); + goto cleanup; + } + + ret = esp_painter_draw_text(painter, ppa_output_buffer, aligned_size, 0, 0, text_width, text_height, font, color_value, text); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to draw text"); + goto cleanup; + } + + ret = esp_painter_convert_rgb565_to_yuv420(painter, ppa_output_buffer, buffer, + buffer_size, + text_width, text_height, + painter->canvas.width, painter->canvas.height, + x, y); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Second PPA conversion failed"); + goto cleanup; + } + +cleanup: + if (ppa_output_buffer) { + heap_caps_free(ppa_output_buffer); + ppa_output_buffer = NULL; + } + + if (ret != ESP_OK) { + return ret; + } + } else { + ret = esp_painter_draw_text(painter, buffer, buffer_size, x, y, painter->canvas.width, painter->canvas.height, font, color_value, text); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to draw text"); + return ret; + } + } +#else + ret = esp_painter_draw_text(painter, buffer, buffer_size, x, y, painter->canvas.width, painter->canvas.height, font, color_value, text); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to draw text"); + return ret; + } +#endif + + ret = esp_cache_msync(buffer, buffer_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Cache sync failed"); + } + + return ret; +} + +esp_err_t esp_painter_draw_string_rgb565(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + uint16_t color565, const char *text) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + esp_painter_t local_painter; + uint16_t text_width = 0; + uint16_t text_height = 0; + esp_err_t ret; + + if (!painter || !buffer || !text) { + return ESP_ERR_INVALID_ARG; + } + if (painter->color_format != ESP_PAINTER_COLOR_FORMAT_RGB565) { + return ESP_ERR_NOT_SUPPORTED; + } + if (!font) { + font = painter->default_font; + if (!font) { + ESP_LOGE(TAG, "No font specified"); + return ESP_ERR_INVALID_ARG; + } + } + if (x >= painter->canvas.width || y >= painter->canvas.height) { + ESP_LOGW(TAG, "Starting position out of bounds: (%d,%d)", x, y); + return ESP_ERR_INVALID_ARG; + } + + esp_painter_measure_text(font, text, &text_width, &text_height); + if (text_width == 0 || text_height == 0) { + return ESP_OK; + } + if (buffer_size < (uint32_t)text_width * text_height * 2) { + return ESP_ERR_INVALID_SIZE; + } + + local_painter = *painter; + local_painter.canvas.width = text_width; + local_painter.canvas.height = text_height; + + ret = esp_painter_draw_text(&local_painter, buffer, buffer_size, 0, 0, + text_width, text_height, + font, esp_painter_get_rgb565_color_value(handle, color565), text); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to draw RGB565 text"); + return ret; + } + + ret = esp_cache_msync(buffer, buffer_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Cache sync failed"); + } + + return ret; +} + +esp_err_t esp_painter_draw_string_format(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + esp_painter_color_t color, const char* fmt, ...) +{ + char buf[CONFIG_ESP_PAINTER_FORMAT_SIZE_MAX]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + return esp_painter_draw_string(handle, buffer, buffer_size, x, y, font, color, buf); +} + +esp_err_t esp_painter_init(esp_painter_config_t *config, esp_painter_handle_t *handle) +{ + if (!config || !handle) { + ESP_LOGE(TAG, "Invalid arguments"); + return ESP_ERR_INVALID_ARG; + } + + esp_painter_t *painter = (esp_painter_t *)calloc(1, sizeof(esp_painter_t)); + if (!painter) { + ESP_LOGE(TAG, "Memory allocation failed"); + return ESP_ERR_NO_MEM; + } + + painter->canvas.width = config->canvas.width; + painter->canvas.height = config->canvas.height; + painter->color_format = config->color_format; + painter->default_font = config->default_font; + painter->swap_rgb565 = config->swap_rgb565; + + if (config->color_format == ESP_PAINTER_COLOR_FORMAT_YUV420 || + config->color_format == ESP_PAINTER_COLOR_FORMAT_YUV422) { +#if CONFIG_SOC_PPA_SUPPORTED + ppa_client_config_t ppa_srm_config = { + .oper_type = PPA_OPERATION_SRM, + }; + ESP_ERROR_CHECK(ppa_register_client(&ppa_srm_config, &painter->ppa_client)); + ESP_ERROR_CHECK(esp_cache_get_alignment(MALLOC_CAP_SPIRAM, &data_cache_line_size)); +#else + free(painter); + ESP_LOGE(TAG, "YUV painter mode requires PPA support on this target"); + return ESP_ERR_NOT_SUPPORTED; +#endif + } + + *handle = painter; + ESP_LOGI(TAG, "Painter initialized: %dx%d, format: %d", + config->canvas.width, config->canvas.height, config->color_format); + return ESP_OK; +} + +esp_err_t esp_painter_deinit(esp_painter_handle_t handle) +{ + esp_painter_t *painter = (esp_painter_t *)handle; + if (!painter) { + return ESP_ERR_INVALID_ARG; + } + + +#if CONFIG_SOC_PPA_SUPPORTED + if(painter->ppa_client) { + ppa_unregister_client(painter->ppa_client); + painter->ppa_client = NULL; + } +#endif + + free(painter); + return ESP_OK; +} diff --git a/components/lua_modules/esp_painter/font/basic_font_12.c b/components/lua_modules/esp_painter/font/basic_font_12.c new file mode 100644 index 0000000..594afc3 --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_12.c @@ -0,0 +1,212 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_12 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, /*"!",1*/ + + 0x28, 0x28, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*""",2*/ + + 0x00, 0x00, 0x50, 0x50, 0xF8, 0x50, 0x50, 0xF8, 0x50, 0x50, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x20, 0x70, 0xA8, 0xA0, 0x60, 0x30, 0x28, 0xA8, 0x70, 0x20, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x48, 0xA8, 0xB0, 0xA8, 0x74, 0x34, 0x54, 0x48, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x20, 0x50, 0x50, 0x6C, 0xA8, 0xA8, 0x94, 0x68, 0x00, 0x00, /*"&",6*/ + + 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x00, /*"(",8*/ + + 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, /*")",9*/ + + 0x00, 0x00, 0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, /*".",14*/ + + 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x10, 0x30, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x38, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0xF8, 0x80, 0x80, 0xF0, 0x88, 0x08, 0x88, 0x70, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x30, 0x48, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x70, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x78, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x98, 0x68, 0x08, 0x90, 0x60, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, /*";",27*/ + + 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, /*"=",29*/ + + 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x38, 0x44, 0x94, 0xB4, 0xB4, 0xB8, 0x44, 0x38, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x20, 0x20, 0x30, 0x50, 0x50, 0x78, 0x48, 0xCC, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x78, 0x88, 0x80, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x48, 0xF8, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x40, 0xE0, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x38, 0x48, 0x80, 0x80, 0x9C, 0x88, 0x48, 0x30, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0xCC, 0x48, 0x48, 0x78, 0x48, 0x48, 0x48, 0xCC, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x90, 0xE0, /*"J",42*/ + + 0x00, 0x00, 0xEC, 0x48, 0x50, 0x60, 0x50, 0x48, 0x48, 0xEC, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0xFC, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0xDC, 0xD8, 0xD8, 0xD8, 0xA8, 0xA8, 0xA8, 0xAC, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0xDC, 0x48, 0x68, 0x68, 0x58, 0x58, 0x48, 0xE8, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0xE8, 0x98, 0x70, 0x18, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x50, 0x48, 0x48, 0xEC, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x78, 0x88, 0x80, 0x60, 0x10, 0x08, 0x88, 0xF0, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0xCC, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0xCC, 0x48, 0x48, 0x50, 0x50, 0x30, 0x20, 0x20, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0xA8, 0xA8, 0xA8, 0xA8, 0x70, 0x50, 0x50, 0x50, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x50, 0x50, 0xD8, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0xD8, 0x50, 0x50, 0x50, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0xF8, 0x90, 0x10, 0x20, 0x20, 0x40, 0x48, 0xF8, 0x00, 0x00, /*"Z",58*/ + + 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, /*"[",59*/ + + 0x00, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, /*"\",60*/ + + 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, /*"]",61*/ + + 0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, /*"_",63*/ + + 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x38, 0x48, 0x3C, 0x00, 0x00, /*"a",65*/ + + 0x00, 0xC0, 0x40, 0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0x70, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x40, 0x48, 0x30, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x18, 0x08, 0x08, 0x08, 0x38, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x78, 0x40, 0x38, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x18, 0x24, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x78, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x48, 0x30, 0x40, 0x38, 0x44, 0x38, /*"g",71*/ + + 0x00, 0xC0, 0x40, 0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0xEC, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x20, 0x20, 0x00, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x10, 0x10, 0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0xE0, /*"j",74*/ + + 0x00, 0xC0, 0x40, 0x40, 0x40, 0x58, 0x50, 0x60, 0x50, 0xC8, 0x00, 0x00, /*"k",75*/ + + 0x00, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0xEC, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0x70, 0x40, 0xE0, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x38, 0x08, 0x1C, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x60, 0x40, 0x40, 0xE0, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x40, 0x30, 0x08, 0x78, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xA8, 0x70, 0x50, 0x50, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x50, 0x20, 0x50, 0xD8, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x48, 0x48, 0x30, 0x10, 0x20, 0xC0, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x10, 0x20, 0x20, 0x78, 0x00, 0x00, /*"z",90*/ + + 0x18, 0x10, 0x10, 0x10, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, /*"{",91*/ + + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /*"|",92*/ + + 0x60, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x60, 0x00, /*"}",93*/ + + 0x68, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_12 = { + .bitmap = bitmap, + .width = 6, + .height = 12, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_16.c b/components/lua_modules/esp_painter/font/basic_font_16.c new file mode 100644 index 0000000..18f8fde --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_16.c @@ -0,0 +1,212 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_16 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x12, 0x24, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*""",2*/ + + 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x7E, 0x24, 0x24, 0x24, 0x7E, 0x24, 0x24, 0x24, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x08, 0x3C, 0x4A, 0x4A, 0x48, 0x38, 0x0C, 0x0A, 0x0A, 0x4A, 0x4A, 0x3C, 0x08, 0x08, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x44, 0xA4, 0xA8, 0xA8, 0xB0, 0x54, 0x1A, 0x2A, 0x2A, 0x4A, 0x44, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x50, 0x6E, 0xA4, 0x94, 0x98, 0x89, 0x76, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x60, 0x20, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x00, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00, /*"(",8*/ + + 0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x00, /*")",9*/ + + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0xD6, 0x38, 0x38, 0xD6, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x7F, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x20, 0x40, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x08, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x02, 0x04, 0x08, 0x10, 0x20, 0x42, 0x7E, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x02, 0x04, 0x18, 0x04, 0x02, 0x42, 0x42, 0x3C, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x00, 0x04, 0x0C, 0x0C, 0x14, 0x24, 0x24, 0x44, 0x7F, 0x04, 0x04, 0x1F, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x78, 0x44, 0x02, 0x02, 0x42, 0x44, 0x38, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x00, 0x18, 0x24, 0x40, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x22, 0x1C, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x7E, 0x42, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x38, 0x44, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x02, 0x02, 0x24, 0x18, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, /*";",27*/ + + 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x62, 0x04, 0x08, 0x08, 0x08, 0x00, 0x18, 0x18, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x38, 0x44, 0x5A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x5C, 0x42, 0x3C, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x28, 0x28, 0x24, 0x3C, 0x44, 0x42, 0x42, 0xE7, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0xF8, 0x44, 0x44, 0x44, 0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0xF8, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x80, 0x80, 0x80, 0x80, 0x80, 0x42, 0x44, 0x38, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0xF8, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0xF8, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0xFC, 0x42, 0x48, 0x48, 0x78, 0x48, 0x48, 0x40, 0x42, 0x42, 0xFC, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0xFC, 0x42, 0x48, 0x48, 0x78, 0x48, 0x48, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x3C, 0x44, 0x44, 0x80, 0x80, 0x80, 0x8E, 0x84, 0x44, 0x44, 0x38, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x88, 0xF0, /*"J",42*/ + + 0x00, 0x00, 0x00, 0xEE, 0x44, 0x48, 0x50, 0x70, 0x50, 0x48, 0x48, 0x44, 0x44, 0xEE, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0xFE, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0xEE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x54, 0x54, 0x54, 0x54, 0xD6, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0xC7, 0x62, 0x62, 0x52, 0x52, 0x4A, 0x4A, 0x4A, 0x46, 0x46, 0xE2, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0xFC, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xB2, 0x4C, 0x38, 0x06, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0xFC, 0x42, 0x42, 0x42, 0x7C, 0x48, 0x48, 0x44, 0x44, 0x42, 0xE3, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x42, 0x42, 0x7C, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0xFE, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x44, 0x24, 0x24, 0x28, 0x28, 0x18, 0x10, 0x10, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0xD6, 0x54, 0x54, 0x54, 0x54, 0x54, 0x6C, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0xE7, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0xEE, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x7E, 0x84, 0x04, 0x08, 0x08, 0x10, 0x20, 0x20, 0x42, 0x42, 0xFC, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, /*"\",60*/ + + 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, /*"]",61*/ + + 0x00, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, /*"_",63*/ + + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x0C, 0x34, 0x44, 0x4C, 0x36, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1C, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x02, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3B, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x44, 0x44, 0x38, 0x40, 0x3C, 0x42, 0x42, 0x3C, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x40, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x78, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x40, 0x40, 0x4E, 0x48, 0x50, 0x70, 0x48, 0x44, 0xEE, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x10, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x49, 0x49, 0x49, 0x49, 0x49, 0xED, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x62, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0xE0, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1A, 0x02, 0x07, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x32, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x40, 0x3C, 0x02, 0x42, 0x7C, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3B, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0x89, 0x4A, 0x5A, 0x54, 0x24, 0x24, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x24, 0x18, 0x18, 0x18, 0x24, 0x6E, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x18, 0x18, 0x10, 0x10, 0x60, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x44, 0x08, 0x10, 0x10, 0x22, 0x7E, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, /*"{",91*/ + + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /*"|",92*/ + + 0x00, 0xC0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0xC0, 0x00, /*"}",93*/ + + 0x20, 0x5A, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_16 = { + .bitmap = bitmap, + .width = 8, + .height = 16, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_20.c b/components/lua_modules/esp_painter/font/basic_font_20.c new file mode 100644 index 0000000..4876f47 --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_20.c @@ -0,0 +1,402 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_20 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x1B, 0x00, 0x1B, 0x00, 0x36, 0x00, 0x24, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*""",2*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x7F, 0x80, 0x7F, 0x80, + 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x7F, 0x80, 0x7F, 0x80, 0x22, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1E, 0x00, 0x29, 0x00, 0x49, 0x00, 0x49, 0x00, 0x48, 0x00, + 0x28, 0x00, 0x1C, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, 0x49, 0x00, 0x49, 0x00, 0x4A, 0x00, + 0x3C, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x92, 0x00, 0x94, 0x00, 0x94, 0x00, 0x94, 0x00, + 0x98, 0x00, 0x9B, 0x00, 0x6C, 0x80, 0x14, 0x80, 0x14, 0x80, 0x14, 0x80, 0x24, 0x80, 0x24, 0x80, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, + 0x28, 0x00, 0x33, 0x80, 0x51, 0x00, 0x91, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x86, 0x00, 0x46, 0x40, + 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 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, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, /*")",9*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC9, 0x80, + 0xEB, 0x80, 0x1C, 0x00, 0x1C, 0x00, 0xEB, 0x80, 0xC9, 0x80, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x7F, 0xC0, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 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, 0x60, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, + 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x21, 0x00, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, + 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x80, 0x40, 0x80, + 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x42, 0x00, 0x41, 0x00, 0x41, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x0E, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x40, 0x80, 0x40, 0x80, 0x41, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x12, 0x00, 0x22, 0x00, 0x22, 0x00, 0x42, 0x00, 0x7F, 0x80, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x2E, 0x00, 0x31, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x40, 0x80, 0x40, 0x80, 0x41, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x11, 0x00, 0x21, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x5E, 0x00, 0x61, 0x00, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x20, 0x80, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x40, 0x80, 0x41, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, + 0x21, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x41, 0x00, 0x40, 0x80, 0x40, 0x80, + 0x40, 0x80, 0x41, 0x80, 0x22, 0x80, 0x1C, 0x80, 0x00, 0x80, 0x01, 0x00, 0x21, 0x00, 0x22, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, + 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, + 0x60, 0x80, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x4E, 0x80, 0x92, 0x80, + 0x92, 0x80, 0xA4, 0x80, 0xA4, 0x80, 0xA4, 0x80, 0xA5, 0x00, 0x9E, 0x00, 0x40, 0x80, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x3E, 0x00, 0x22, 0x00, 0x41, 0x00, 0x41, 0x00, + 0xE3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, + 0x44, 0x00, 0x7C, 0x00, 0x42, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x42, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x80, 0x21, 0x80, 0x40, 0x80, 0x40, 0x80, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x40, 0x80, 0x61, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x42, 0x00, 0x41, 0x00, 0x40, 0x80, + 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x41, 0x00, 0x40, 0x80, 0x42, 0x00, + 0x42, 0x00, 0x7E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x80, 0x41, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x41, 0x00, 0x40, 0x80, 0x42, 0x00, + 0x42, 0x00, 0x7E, 0x00, 0x42, 0x00, 0x42, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x80, 0x11, 0x80, 0x20, 0x80, 0x40, 0x80, + 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x41, 0xC0, 0x40, 0x80, 0x40, 0x80, 0x20, 0x80, 0x30, 0x80, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x80, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, + 0x41, 0x00, 0x41, 0x00, 0x7F, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, + 0xE3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x84, 0x00, 0x88, 0x00, 0x70, 0x00, /*"J",42*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x80, 0x42, 0x00, 0x44, 0x00, 0x44, 0x00, + 0x48, 0x00, 0x58, 0x00, 0x68, 0x00, 0x44, 0x00, 0x44, 0x00, 0x42, 0x00, 0x42, 0x00, 0x41, 0x00, + 0xE3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x80, 0x41, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x80, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, + 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, + 0xEB, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x80, 0x61, 0x00, 0x51, 0x00, 0x51, 0x00, + 0x51, 0x00, 0x49, 0x00, 0x49, 0x00, 0x45, 0x00, 0x45, 0x00, 0x43, 0x00, 0x43, 0x00, 0x43, 0x00, + 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x00, 0x63, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x41, 0x00, 0x40, 0x80, 0x40, 0x80, + 0x40, 0x80, 0x41, 0x00, 0x7E, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x63, 0x00, 0x41, 0x00, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xB8, 0x80, 0x45, 0x00, 0x63, 0x00, + 0x1E, 0x00, 0x02, 0x80, 0x01, 0x00, 0x00, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x42, 0x00, 0x41, 0x00, 0x41, 0x00, + 0x42, 0x00, 0x7C, 0x00, 0x48, 0x00, 0x44, 0x00, 0x44, 0x00, 0x42, 0x00, 0x42, 0x00, 0x41, 0x00, + 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x23, 0x00, 0x41, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x01, 0x00, 0x41, 0x00, 0x41, 0x00, 0x62, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x88, 0x80, 0x88, 0x80, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x80, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, + 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x80, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, + 0x49, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x80, 0x21, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x14, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x14, 0x00, 0x12, 0x00, 0x22, 0x00, 0x21, 0x00, + 0x73, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x21, 0x00, 0x41, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x80, 0x21, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x0F, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x1C, 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, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC0, /*"_",63*/ + + 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x41, 0x00, 0x41, 0x00, 0x07, 0x00, 0x39, 0x00, 0x41, 0x00, 0x41, 0x00, 0x43, 0x40, + 0x3D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x2E, 0x00, 0x31, 0x00, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x21, 0x00, 0x41, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x80, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x1D, 0x00, 0x23, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x23, 0x00, + 0x1D, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, 0x7F, 0x80, 0x40, 0x00, 0x40, 0x80, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 0x80, 0x08, 0x00, 0x08, 0x00, + 0x3F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x80, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x1E, 0x00, 0x20, 0x00, 0x3F, 0x00, + 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x3F, 0x00, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x2E, 0x00, 0x31, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, + 0x73, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x22, 0x00, 0x3C, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x27, 0x00, 0x22, 0x00, 0x24, 0x00, 0x28, 0x00, 0x34, 0x00, 0x24, 0x00, 0x22, 0x00, 0x21, 0x00, + 0x73, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x78, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x69, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, + 0xED, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x31, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, + 0x73, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x21, 0x00, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x21, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x31, 0x00, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x31, 0x00, + 0x2E, 0x00, 0x20, 0x00, 0x20, 0x00, 0x70, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x23, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x23, 0x00, + 0x1D, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x80, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x73, 0x80, 0x14, 0x80, 0x18, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x43, 0x00, 0x41, 0x00, 0x60, 0x00, 0x1C, 0x00, 0x03, 0x00, 0x41, 0x00, 0x61, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x3F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x80, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x23, 0x00, + 0x1D, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE3, 0x80, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x22, 0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x80, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x73, 0x80, 0x21, 0x00, 0x12, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x12, 0x00, 0x21, 0x00, + 0x73, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x73, 0x80, 0x21, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x28, 0x00, 0x30, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x42, 0x00, 0x44, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x80, 0x20, 0x80, 0x21, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x00, /*"{",91*/ + + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x60, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x60, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x30, 0x00, 0x48, 0x80, 0x44, 0x80, 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, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_20 = { + .bitmap = bitmap, + .width = 10, + .height = 20, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_24.c b/components/lua_modules/esp_painter/font/basic_font_24.c new file mode 100644 index 0000000..46da691 --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_24.c @@ -0,0 +1,402 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_24 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x06, 0x60, 0x0C, 0xC0, 0x19, 0x80, 0x11, 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, /*""",2*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x08, 0x40, 0x08, 0x40, 0x08, 0x40, + 0x7F, 0xE0, 0x7F, 0xE0, 0x10, 0x40, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x7F, 0xE0, + 0x7F, 0xE0, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0F, 0x80, 0x1A, 0xC0, 0x32, 0xC0, + 0x33, 0xC0, 0x32, 0x00, 0x1A, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x02, 0xC0, + 0x32, 0xC0, 0x3A, 0xC0, 0x32, 0xC0, 0x12, 0x80, 0x0F, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x50, 0x80, 0x89, 0x00, 0x89, 0x00, + 0x89, 0x00, 0x8A, 0x00, 0x8A, 0x00, 0x5C, 0x00, 0x75, 0xC0, 0x05, 0x40, 0x0A, 0x20, 0x0A, 0x20, + 0x12, 0x20, 0x12, 0x20, 0x12, 0x20, 0x21, 0x40, 0x21, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x36, 0x00, 0x36, 0x00, 0x36, 0x00, + 0x36, 0x00, 0x36, 0x00, 0x34, 0x00, 0x19, 0xE0, 0x38, 0x80, 0x58, 0x80, 0xCC, 0x80, 0xCC, 0x80, + 0xC6, 0x80, 0xC7, 0x00, 0xC3, 0x10, 0x63, 0x90, 0x3C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 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, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, /*")",9*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x62, 0x30, 0x72, 0xF0, 0x0B, 0x80, 0x0F, 0x80, 0x7A, 0xF0, 0x62, 0x30, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7F, 0xF0, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x38, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, /*",",12*/ + + 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, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x60, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x80, + 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x80, 0x30, 0xC0, + 0x30, 0xC0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x30, 0xC0, 0x30, 0xC0, 0x19, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x21, 0x80, 0x40, 0xC0, + 0x60, 0xC0, 0x60, 0xC0, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x10, 0x40, 0x20, 0x40, 0x60, 0x40, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x63, 0x00, 0x61, 0x80, + 0x61, 0x80, 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0xC0, + 0x00, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x61, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x03, 0x80, + 0x05, 0x80, 0x05, 0x80, 0x09, 0x80, 0x11, 0x80, 0x11, 0x80, 0x21, 0x80, 0x41, 0x80, 0x7F, 0xF0, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x2F, 0x00, 0x31, 0x80, 0x20, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x60, 0xC0, 0x60, 0xC0, 0x41, 0x80, 0x21, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x18, 0xC0, 0x30, 0xC0, + 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0x67, 0x80, 0x68, 0xC0, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x20, 0x60, 0x30, 0x40, 0x18, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x30, 0x60, 0x20, 0x40, + 0x20, 0x80, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x30, 0xC0, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x30, 0x40, 0x38, 0xC0, 0x0F, 0x00, 0x13, 0x80, 0x30, 0xC0, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x30, 0xC0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x30, 0x80, 0x30, 0xC0, + 0x60, 0x40, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xE0, 0x31, 0x60, 0x1E, 0x60, 0x00, 0x60, + 0x00, 0xC0, 0x00, 0xC0, 0x30, 0x80, 0x31, 0x80, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x18, 0x60, 0x20, 0x30, + 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0xE0, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x18, 0xC0, 0x30, 0x40, 0x33, 0xA0, + 0x26, 0xA0, 0x66, 0xA0, 0x65, 0xA0, 0x6D, 0x20, 0x6D, 0x20, 0x6D, 0x20, 0x6D, 0x20, 0x6D, 0x40, + 0x27, 0x80, 0x30, 0x20, 0x30, 0x40, 0x18, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0A, 0x00, + 0x0B, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x11, 0x80, 0x10, 0x80, 0x1F, 0x80, 0x20, 0xC0, + 0x20, 0xC0, 0x20, 0x40, 0x40, 0x40, 0x40, 0x60, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x31, 0xC0, 0x30, 0xC0, + 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x31, 0x80, 0x3F, 0x00, 0x30, 0xC0, 0x30, 0x40, 0x30, 0x60, + 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0xC0, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x18, 0xC0, 0x30, 0x60, + 0x30, 0x20, 0x20, 0x20, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x20, 0x30, 0x20, 0x30, 0x40, 0x18, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x31, 0x80, 0x30, 0xC0, + 0x30, 0xC0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, + 0x30, 0x60, 0x30, 0xC0, 0x30, 0xC0, 0x31, 0x80, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x60, 0xC0, 0x60, 0x20, + 0x60, 0x20, 0x60, 0x00, 0x61, 0x00, 0x61, 0x00, 0x7F, 0x00, 0x61, 0x00, 0x61, 0x00, 0x61, 0x00, + 0x60, 0x00, 0x60, 0x20, 0x60, 0x20, 0x60, 0x40, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x60, 0xC0, 0x60, 0x20, + 0x60, 0x20, 0x60, 0x00, 0x61, 0x00, 0x61, 0x00, 0x7F, 0x00, 0x61, 0x00, 0x61, 0x00, 0x61, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x18, 0x80, 0x30, 0x40, + 0x30, 0x40, 0x20, 0x40, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x63, 0xF0, 0x60, 0xC0, + 0x60, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x18, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7F, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 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, 0x00, 0x03, 0x00, 0x63, 0x00, 0x66, 0x00, 0x3C, 0x00, /*"J",42*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xC0, 0x61, 0x80, 0x63, 0x00, + 0x62, 0x00, 0x64, 0x00, 0x68, 0x00, 0x6C, 0x00, 0x74, 0x00, 0x76, 0x00, 0x62, 0x00, 0x63, 0x00, + 0x61, 0x00, 0x61, 0x80, 0x60, 0x80, 0x60, 0xC0, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x20, 0x60, 0x20, 0x60, 0x40, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0x61, 0xC0, 0x61, 0xC0, + 0x71, 0xC0, 0x71, 0xC0, 0x72, 0xC0, 0x72, 0xC0, 0x52, 0xC0, 0x5A, 0xC0, 0x5A, 0xC0, 0x5C, 0xC0, + 0x4C, 0xC0, 0x4C, 0xC0, 0x4C, 0xC0, 0x48, 0xC0, 0xE1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xF0, 0x30, 0x40, 0x38, 0x40, + 0x38, 0x40, 0x2C, 0x40, 0x2C, 0x40, 0x26, 0x40, 0x26, 0x40, 0x22, 0x40, 0x23, 0x40, 0x21, 0x40, + 0x21, 0xC0, 0x21, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0xF8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x80, 0x30, 0xC0, + 0x30, 0x40, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x30, 0x40, 0x30, 0xC0, 0x19, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x60, 0xC0, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0xC0, 0x7F, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x80, 0x30, 0xC0, + 0x30, 0x40, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x6E, 0x60, 0x32, 0x40, 0x33, 0xC0, 0x19, 0x80, 0x0F, 0x00, 0x01, 0xE0, 0x00, 0xC0, 0x00, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x60, 0xC0, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xC0, 0x7F, 0x00, 0x62, 0x00, 0x63, 0x00, 0x61, 0x00, + 0x61, 0x80, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0x60, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x40, 0x30, 0xC0, 0x60, 0x40, + 0x60, 0x40, 0x60, 0x00, 0x70, 0x00, 0x3C, 0x00, 0x1F, 0x00, 0x07, 0xC0, 0x01, 0xC0, 0x00, 0xE0, + 0x40, 0x60, 0x40, 0x60, 0x60, 0x60, 0x30, 0xC0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x46, 0x20, 0x86, 0x10, + 0x86, 0x10, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xE0, 0x30, 0x40, 0x30, 0x40, + 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, + 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x18, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xE0, 0x60, 0x40, 0x20, 0x80, + 0x20, 0x80, 0x30, 0x80, 0x30, 0x80, 0x11, 0x00, 0x11, 0x00, 0x19, 0x00, 0x19, 0x00, 0x0A, 0x00, + 0x0A, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x70, 0x46, 0x20, 0x42, 0x20, + 0x62, 0x20, 0x62, 0x20, 0x26, 0x40, 0x26, 0x40, 0x27, 0x40, 0x27, 0x40, 0x39, 0x40, 0x39, 0x80, + 0x19, 0x80, 0x19, 0x80, 0x11, 0x80, 0x11, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xE0, 0x30, 0x80, 0x10, 0x80, + 0x18, 0x80, 0x09, 0x00, 0x0D, 0x00, 0x06, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0B, 0x00, + 0x09, 0x00, 0x11, 0x80, 0x10, 0x80, 0x20, 0xC0, 0x71, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x60, 0x20, 0x20, 0x40, + 0x30, 0x40, 0x10, 0x80, 0x18, 0x80, 0x1D, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x30, 0x40, 0x60, 0xC0, + 0x40, 0x80, 0x01, 0x80, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x18, 0x00, 0x10, 0x20, 0x30, 0x20, 0x20, 0x40, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x07, 0xC0, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0x10, 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, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF0, /*"_",63*/ + + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x30, 0xC0, 0x30, 0xC0, 0x00, 0xC0, 0x07, 0xC0, 0x38, 0xC0, + 0x70, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x71, 0xD0, 0x3E, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x33, 0x80, 0x3C, 0xC0, 0x38, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, + 0x30, 0x60, 0x30, 0x60, 0x30, 0x40, 0x38, 0xC0, 0x27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x80, 0x31, 0x80, 0x61, 0x80, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x40, 0x30, 0x40, 0x30, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x00, 0xC0, 0x00, 0xC0, 0x1E, 0xC0, 0x31, 0xC0, 0x30, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, + 0x60, 0xC0, 0x60, 0xC0, 0x20, 0xC0, 0x31, 0xE0, 0x1E, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x18, 0xC0, 0x10, 0x40, 0x30, 0x60, 0x30, 0x60, 0x3F, 0xE0, + 0x30, 0x00, 0x30, 0x00, 0x18, 0x20, 0x18, 0x40, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x06, 0x60, 0x0C, 0x60, + 0x0C, 0x00, 0x0C, 0x00, 0x7F, 0x80, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1B, 0x60, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x19, 0x80, + 0x1F, 0x00, 0x30, 0x00, 0x3F, 0x00, 0x33, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x71, 0xC0, 0x1F, 0x00, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x37, 0x80, 0x38, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, + 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x79, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x0F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x33, 0x00, 0x3E, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x31, 0xC0, 0x31, 0x00, 0x31, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, + 0x31, 0x00, 0x31, 0x80, 0x30, 0x80, 0x30, 0xC0, 0x79, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEC, 0xE0, 0x77, 0x60, 0x66, 0x60, 0x66, 0x60, 0x66, 0x60, 0x66, 0x60, + 0x66, 0x60, 0x66, 0x60, 0x66, 0x60, 0x66, 0x60, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, 0x38, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, + 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x79, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x80, 0x30, 0xC0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x30, 0xC0, 0x30, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, 0x38, 0xC0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, + 0x30, 0x60, 0x30, 0x60, 0x30, 0xC0, 0x38, 0xC0, 0x37, 0x80, 0x30, 0x00, 0x30, 0x00, 0x7C, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x40, 0x31, 0xC0, 0x30, 0xC0, 0x60, 0xC0, 0x60, 0xC0, 0x60, 0xC0, + 0x60, 0xC0, 0x60, 0xC0, 0x20, 0xC0, 0x31, 0xC0, 0x1E, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x03, 0xE0, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF9, 0xC0, 0x1A, 0x60, 0x1C, 0x60, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x38, 0xC0, 0x30, 0x40, 0x30, 0x40, 0x1C, 0x00, 0x0F, 0x00, + 0x03, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x31, 0xC0, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x7F, 0x80, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x40, 0x0C, 0x40, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x40, 0x71, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, + 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x39, 0xE0, 0x1E, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0xE0, 0x30, 0x40, 0x10, 0x80, 0x10, 0x80, 0x18, 0x80, 0x09, 0x00, + 0x0D, 0x00, 0x0D, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEF, 0x70, 0x46, 0x20, 0x62, 0x20, 0x26, 0x40, 0x26, 0x40, 0x37, 0x40, + 0x39, 0x80, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3D, 0xE0, 0x18, 0x80, 0x08, 0x80, 0x0D, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x09, 0x00, 0x10, 0x80, 0x10, 0xC0, 0x79, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x79, 0xE0, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x09, 0x00, 0x09, 0x00, + 0x0D, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x24, 0x00, 0x38, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x21, 0x80, 0x23, 0x00, 0x22, 0x00, 0x06, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x18, 0x40, 0x10, 0x40, 0x30, 0xC0, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xC0, 0x00, 0x00, /*"{",91*/ + + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x00, 0x00, 0x38, 0x00, 0x44, 0x20, 0x43, 0x20, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_24 = { + .bitmap = bitmap, + .width = 12, + .height = 24, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_28.c b/components/lua_modules/esp_painter/font/basic_font_28.c new file mode 100644 index 0000000..d20996b --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_28.c @@ -0,0 +1,497 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_28 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x0E, 0xE0, 0x0C, 0xC0, 0x19, 0x80, 0x19, 0x80, 0x33, 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, /*""",2*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, + 0x08, 0x20, 0x7F, 0xF8, 0x7F, 0xF8, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x10, 0x40, 0x10, 0x40, + 0x10, 0x40, 0x7F, 0xF8, 0x7F, 0xF8, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x07, 0xC0, 0x0D, 0x60, 0x19, 0x30, + 0x19, 0x30, 0x19, 0x70, 0x19, 0x00, 0x0D, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x01, 0xC0, 0x01, 0xE0, + 0x01, 0x60, 0x01, 0x30, 0x31, 0x30, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30, 0x19, 0x60, 0x07, 0x80, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20, 0x48, 0x20, 0x84, 0x40, + 0x84, 0x40, 0x84, 0x80, 0x84, 0x80, 0x85, 0x00, 0x85, 0x00, 0x4A, 0x00, 0x3A, 0x60, 0x02, 0x90, + 0x05, 0x08, 0x05, 0x08, 0x09, 0x08, 0x09, 0x08, 0x11, 0x08, 0x11, 0x08, 0x20, 0x90, 0x20, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x80, 0x31, 0x80, + 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x33, 0x00, 0x3E, 0x00, 0x18, 0xF8, 0x38, 0x20, 0x4C, 0x20, + 0x4C, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC3, 0x40, 0xC3, 0x80, 0x61, 0x84, 0x71, 0xCC, 0x3E, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x18, 0x00, 0x18, 0x00, 0x10, 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, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, + 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, + 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /*")",9*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, + 0x03, 0x80, 0x01, 0x80, 0x61, 0x0C, 0x79, 0x3C, 0x1D, 0x70, 0x03, 0x80, 0x03, 0x80, 0x1D, 0x70, + 0x79, 0x3C, 0x61, 0x0C, 0x03, 0x00, 0x03, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x3F, 0xF8, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 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, 0x38, 0x00, 0x38, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, /*",",12*/ + + 0x00, 0x00, 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, 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, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0x38, 0x00, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, + 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, + 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0C, 0x60, 0x18, 0x20, + 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, + 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x20, 0x0C, 0x40, 0x07, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x1F, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x30, 0xE0, 0x40, 0x70, + 0x40, 0x30, 0x60, 0x30, 0x60, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, + 0x03, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x10, 0x30, 0x10, 0x60, 0x30, 0x7F, 0xF0, 0x7F, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x10, 0xC0, 0x30, 0x60, + 0x30, 0x60, 0x30, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0xC0, 0x03, 0x80, 0x00, 0xC0, 0x00, 0x60, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x10, 0xC0, 0x0F, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, + 0x03, 0xC0, 0x02, 0xC0, 0x04, 0xC0, 0x04, 0xC0, 0x08, 0xC0, 0x10, 0xC0, 0x10, 0xC0, 0x20, 0xC0, + 0x40, 0xC0, 0x7F, 0xF8, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x07, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x17, 0xC0, 0x18, 0x60, 0x10, 0x60, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x60, 0x10, 0xE0, 0x0F, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x0C, 0x30, 0x18, 0x30, + 0x30, 0x30, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0x67, 0xC0, 0x68, 0x70, 0x70, 0x30, 0x60, 0x18, + 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x20, 0x18, 0x30, 0x18, 0x30, 0x30, 0x1C, 0x60, 0x07, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0xF0, 0x30, 0x20, + 0x20, 0x20, 0x20, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x30, 0x60, 0x30, 0x70, + 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x20, 0x38, 0x60, 0x0F, 0x80, 0x0B, 0x80, 0x31, 0xC0, + 0x30, 0x60, 0x60, 0x70, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x30, 0x60, 0x18, 0x60, 0x0F, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x18, 0xC0, 0x30, 0x60, + 0x60, 0x20, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x70, 0x30, 0x70, 0x38, 0xB0, + 0x1F, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x30, 0x60, 0x30, 0xC0, 0x31, 0x80, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, + 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, + 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x20, + 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x10, 0xE0, 0x20, 0x60, + 0x40, 0x30, 0x40, 0x30, 0x70, 0x30, 0x70, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x0C, 0x60, 0x18, 0x10, + 0x31, 0xB0, 0x33, 0x68, 0x22, 0x68, 0x66, 0x68, 0x66, 0x48, 0x6C, 0x48, 0x6C, 0x48, 0x6C, 0x48, + 0x6C, 0x48, 0x6C, 0xD0, 0x6D, 0x50, 0x36, 0x60, 0x30, 0x08, 0x18, 0x10, 0x0C, 0x20, 0x07, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x09, 0x80, 0x09, 0x80, 0x08, 0x80, 0x08, 0x80, 0x10, 0xC0, 0x10, 0xC0, + 0x1F, 0xC0, 0x10, 0x40, 0x20, 0x60, 0x20, 0x60, 0x20, 0x60, 0x20, 0x20, 0x60, 0x30, 0xF0, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x30, 0x60, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30, 0xC0, 0x3F, 0x80, 0x30, 0x60, 0x30, 0x30, + 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x70, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x0C, 0x30, 0x18, 0x18, + 0x30, 0x08, 0x30, 0x08, 0x20, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x08, 0x30, 0x08, 0x18, 0x10, 0x1C, 0x20, 0x07, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x30, 0xC0, 0x30, 0x60, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, + 0x30, 0x18, 0x30, 0x18, 0x30, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30, 0xC0, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x30, 0x30, 0x30, 0x18, + 0x30, 0x08, 0x30, 0x00, 0x30, 0x40, 0x30, 0x40, 0x30, 0xC0, 0x3F, 0xC0, 0x30, 0xC0, 0x30, 0x40, + 0x30, 0x40, 0x30, 0x00, 0x30, 0x00, 0x30, 0x08, 0x30, 0x08, 0x30, 0x10, 0x30, 0x30, 0xFF, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x30, 0x30, 0x30, 0x10, + 0x30, 0x08, 0x30, 0x08, 0x30, 0x40, 0x30, 0x40, 0x30, 0x40, 0x3F, 0xC0, 0x30, 0xC0, 0x30, 0x40, + 0x30, 0x40, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xFC, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0C, 0x60, 0x18, 0x30, + 0x30, 0x10, 0x30, 0x10, 0x20, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0xFC, 0x60, 0x30, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x30, 0x0C, 0x70, 0x07, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0xF0, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xFC, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 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, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x60, 0xC0, 0x61, 0x80, 0x63, 0x80, 0x3E, 0x00, /*"J",42*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xF0, 0x30, 0x40, 0x30, 0x80, + 0x30, 0x80, 0x31, 0x00, 0x32, 0x00, 0x32, 0x00, 0x36, 0x00, 0x36, 0x00, 0x3B, 0x00, 0x33, 0x00, + 0x31, 0x80, 0x31, 0x80, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x70, 0xFC, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x08, 0x18, 0x08, 0x18, 0x18, 0x18, 0x30, 0x7F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x38, 0x30, 0x70, 0x30, 0x70, + 0x38, 0x70, 0x38, 0x70, 0x38, 0x70, 0x28, 0xB0, 0x28, 0xB0, 0x2C, 0xB0, 0x2C, 0xB0, 0x2D, 0x30, + 0x25, 0x30, 0x25, 0x30, 0x27, 0x30, 0x27, 0x30, 0x26, 0x30, 0x22, 0x30, 0x22, 0x30, 0x72, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7C, 0x38, 0x10, 0x38, 0x10, + 0x3C, 0x10, 0x2C, 0x10, 0x2E, 0x10, 0x26, 0x10, 0x26, 0x10, 0x23, 0x10, 0x23, 0x10, 0x21, 0x90, + 0x21, 0x90, 0x20, 0xD0, 0x20, 0xD0, 0x20, 0x70, 0x20, 0x70, 0x20, 0x30, 0x20, 0x30, 0xF8, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x08, 0x40, 0x10, 0x20, + 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, + 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x10, 0x30, 0x30, 0x10, 0x20, 0x08, 0x40, 0x07, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x30, 0x70, 0x30, 0x30, + 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x30, 0x70, 0x3F, 0xC0, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xFC, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x18, 0x60, 0x10, 0x20, + 0x30, 0x30, 0x30, 0x10, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, + 0x60, 0x18, 0x60, 0x18, 0x67, 0x18, 0x29, 0x10, 0x31, 0xB0, 0x18, 0xA0, 0x18, 0xE0, 0x07, 0xC0, + 0x00, 0x78, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x18, 0x60, 0x18, 0x30, + 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x60, 0x18, 0x60, 0x1F, 0xC0, 0x19, 0x80, + 0x18, 0x80, 0x18, 0xC0, 0x18, 0xC0, 0x18, 0x40, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x7E, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x20, 0x30, 0xE0, 0x20, 0x60, + 0x60, 0x20, 0x60, 0x20, 0x60, 0x00, 0x70, 0x00, 0x3C, 0x00, 0x1F, 0x00, 0x07, 0xC0, 0x01, 0xE0, + 0x00, 0x60, 0x00, 0x70, 0x40, 0x30, 0x40, 0x30, 0x60, 0x30, 0x20, 0x60, 0x38, 0x60, 0x07, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x23, 0x10, 0x63, 0x08, + 0x43, 0x08, 0x43, 0x08, 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, 0x0F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x7C, 0x30, 0x10, 0x30, 0x10, + 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, + 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x30, 0x18, 0x60, 0x07, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x78, 0x70, 0x30, 0x30, 0x20, + 0x30, 0x20, 0x30, 0x20, 0x10, 0x40, 0x18, 0x40, 0x18, 0x40, 0x18, 0x40, 0x08, 0x80, 0x0C, 0x80, + 0x0C, 0x80, 0x0D, 0x00, 0x05, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x9C, 0x63, 0x08, 0x63, 0x08, + 0x61, 0x10, 0x21, 0x10, 0x23, 0x10, 0x23, 0x90, 0x33, 0x90, 0x33, 0x90, 0x33, 0xA0, 0x34, 0xA0, + 0x14, 0xA0, 0x14, 0xA0, 0x14, 0xE0, 0x18, 0xC0, 0x18, 0xC0, 0x18, 0x40, 0x08, 0x40, 0x08, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x78, 0x18, 0x20, 0x18, 0x20, + 0x08, 0x40, 0x0C, 0x40, 0x04, 0x80, 0x06, 0x80, 0x07, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x05, 0x80, 0x04, 0x80, 0x08, 0xC0, 0x08, 0xC0, 0x08, 0x60, 0x10, 0x60, 0x10, 0x30, 0x78, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x78, 0x30, 0x30, 0x18, 0x20, + 0x18, 0x20, 0x18, 0x40, 0x0C, 0x40, 0x0C, 0x40, 0x04, 0x80, 0x06, 0x80, 0x07, 0x80, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x18, 0x10, 0x30, 0x30, + 0x20, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x18, 0x08, 0x18, 0x08, 0x30, 0x10, 0x20, 0x30, 0x7F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 0x80, 0x10, 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, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFC, /*"_",63*/ + + 0x00, 0x00, 0x3C, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x10, 0xE0, 0x30, 0x60, 0x30, 0x60, 0x00, 0x60, + 0x07, 0xE0, 0x18, 0x60, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x68, 0x31, 0xE8, 0x1E, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xF0, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0xC0, 0x34, 0x60, 0x38, 0x60, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x38, 0x60, 0x27, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0C, 0x60, 0x18, 0x60, 0x18, 0x60, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x10, 0x18, 0x20, 0x0C, 0x20, 0x07, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xF0, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x07, 0xB0, 0x0C, 0x70, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x70, 0x18, 0xFC, 0x07, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0C, 0x60, 0x18, 0x60, 0x10, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x3F, 0xF0, 0x30, 0x00, 0x30, 0x00, 0x30, 0x10, 0x18, 0x10, 0x0C, 0x20, 0x07, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x03, 0x18, 0x06, 0x18, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3F, 0xE0, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xB8, 0x0C, 0xD8, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, + 0x18, 0x60, 0x0C, 0xC0, 0x0F, 0x80, 0x18, 0x00, 0x18, 0x00, 0x0F, 0xC0, 0x19, 0xF0, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x18, 0x60, 0x0F, 0xC0, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xF0, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0xE0, 0x34, 0x70, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xFC, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1F, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, 0xE0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x30, 0x40, 0x30, 0xC0, 0x1F, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x78, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0xF0, 0x18, 0x40, 0x18, 0x80, 0x18, 0x80, 0x19, 0x00, + 0x1B, 0x00, 0x1D, 0x80, 0x1C, 0x80, 0x18, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x7E, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1F, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x70, 0x73, 0x98, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, + 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0x63, 0x18, 0xF7, 0xBC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xC0, 0xF4, 0x60, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xFC, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x18, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x18, + 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x20, 0x10, 0x30, 0x30, 0x18, 0x60, 0x07, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xC0, 0xF4, 0x70, 0x38, 0x30, 0x30, 0x18, 0x30, 0x18, + 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x38, 0x60, 0x37, 0xC0, + 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xFC, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x20, 0x18, 0xE0, 0x30, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x30, 0x60, 0x30, 0xE0, 0x0F, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x01, 0xF8, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x7C, 0x98, 0x0D, 0x18, 0x0E, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x7F, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x90, 0x18, 0x70, 0x30, 0x30, 0x30, 0x10, 0x38, 0x00, + 0x1E, 0x00, 0x07, 0xC0, 0x01, 0xE0, 0x20, 0x70, 0x20, 0x30, 0x30, 0x30, 0x38, 0x60, 0x27, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x3F, 0xE0, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x10, 0x06, 0x10, 0x03, 0x20, 0x03, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0xF1, 0xE0, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, + 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x30, 0x60, 0x38, 0xF8, 0x1F, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x78, 0x10, 0x30, 0x18, 0x20, 0x18, 0x20, 0x08, 0x40, + 0x0C, 0x40, 0x0C, 0x40, 0x04, 0x80, 0x06, 0x80, 0x06, 0x80, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xBC, 0x63, 0x08, 0x23, 0x10, 0x23, 0x10, 0x33, 0x10, + 0x33, 0x90, 0x37, 0xA0, 0x14, 0xA0, 0x1C, 0xA0, 0x1C, 0xC0, 0x18, 0xC0, 0x08, 0x40, 0x08, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xF8, 0x0C, 0x20, 0x0C, 0x40, 0x06, 0x40, 0x06, 0x80, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x80, 0x04, 0xC0, 0x08, 0xC0, 0x08, 0x60, 0x10, 0x30, 0x78, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xF8, 0x10, 0x20, 0x18, 0x20, 0x18, 0x40, 0x08, 0x40, + 0x0C, 0x40, 0x0C, 0x80, 0x04, 0x80, 0x06, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x34, 0x00, 0x38, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x30, 0x60, 0x20, 0xC0, 0x21, 0x80, 0x01, 0x80, + 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0C, 0x10, 0x08, 0x10, 0x18, 0x10, 0x30, 0x20, 0x3F, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x40, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, /*"{",91*/ + + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x1C, 0x00, 0x26, 0x08, 0x43, 0x08, 0x41, 0x90, 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, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_28 = { + .bitmap = bitmap, + .width = 14, + .height = 28, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_32.c b/components/lua_modules/esp_painter/font/basic_font_32.c new file mode 100644 index 0000000..ab6959e --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_32.c @@ -0,0 +1,497 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_32 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x03, 0xC0, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x07, 0x38, 0x07, 0x38, 0x0E, 0x70, 0x0C, 0x60, 0x18, 0xC0, + 0x31, 0x80, 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*""",2*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x04, 0x08, + 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x08, 0x10, 0x08, 0x10, + 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x18, 0x30, + 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0xC0, 0x0D, 0x30, + 0x09, 0x18, 0x19, 0x18, 0x19, 0x38, 0x19, 0x38, 0x1D, 0x00, 0x0D, 0x00, 0x0F, 0x00, 0x07, 0x00, + 0x03, 0xC0, 0x01, 0xE0, 0x01, 0xF0, 0x01, 0x30, 0x01, 0x38, 0x01, 0x18, 0x39, 0x18, 0x39, 0x18, + 0x31, 0x18, 0x31, 0x30, 0x19, 0x60, 0x07, 0xC0, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x10, 0x6C, 0x10, + 0x44, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0xC6, 0x40, 0xC6, 0x80, 0xC6, 0x80, 0x44, 0x80, + 0x6D, 0x38, 0x39, 0x6C, 0x02, 0x44, 0x02, 0xC6, 0x02, 0xC6, 0x04, 0xC6, 0x04, 0xC6, 0x08, 0xC6, + 0x08, 0xC6, 0x08, 0x44, 0x10, 0x6C, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x00, + 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x00, 0x33, 0x00, 0x3A, 0x00, 0x1C, 0x00, + 0x38, 0x7C, 0x3C, 0x10, 0x4C, 0x10, 0xCE, 0x10, 0xC6, 0x20, 0xC7, 0x20, 0xC3, 0x20, 0xC1, 0xC0, + 0xC1, 0xC2, 0x60, 0xE6, 0x31, 0x7C, 0x1E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x18, 0x00, 0x30, 0x00, 0x20, + 0x00, 0x60, 0x00, 0x40, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x40, + 0x00, 0x60, 0x00, 0x20, 0x00, 0x30, 0x00, 0x18, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, /*")",9*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x30, 0xC6, 0x38, 0x8E, 0x1C, 0x9C, 0x06, 0xB0, 0x01, 0xC0, + 0x01, 0xC0, 0x06, 0xB0, 0x1C, 0x9C, 0x38, 0x8E, 0x31, 0x86, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x3F, 0xFE, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3C, 0x00, 0x3C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x30, 0x00, 0x60, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x08, + 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, + 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x06, 0x20, + 0x0C, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, + 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x18, 0x08, 0x18, 0x18, + 0x18, 0x18, 0x0C, 0x30, 0x06, 0x20, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, + 0x1F, 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, + 0x01, 0x80, 0x01, 0x80, 0x03, 0xC0, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x08, 0x38, + 0x10, 0x18, 0x20, 0x0C, 0x20, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x18, + 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x02, 0x00, 0x04, 0x04, 0x08, 0x04, + 0x10, 0x04, 0x20, 0x0C, 0x3F, 0xF8, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x18, 0x60, + 0x30, 0x30, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, + 0x03, 0xC0, 0x00, 0x70, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0C, 0x30, 0x0C, 0x30, 0x0C, + 0x30, 0x08, 0x30, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, + 0x00, 0xE0, 0x00, 0xE0, 0x01, 0x60, 0x01, 0x60, 0x02, 0x60, 0x04, 0x60, 0x04, 0x60, 0x08, 0x60, + 0x08, 0x60, 0x10, 0x60, 0x30, 0x60, 0x20, 0x60, 0x40, 0x60, 0x7F, 0xFC, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x0F, 0xFC, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x13, 0xE0, 0x14, 0x30, + 0x18, 0x18, 0x10, 0x08, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x30, 0x0C, 0x30, 0x0C, + 0x20, 0x18, 0x20, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x06, 0x18, + 0x0C, 0x18, 0x08, 0x18, 0x18, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x33, 0xE0, 0x36, 0x30, + 0x38, 0x18, 0x38, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x18, 0x0C, + 0x18, 0x08, 0x0C, 0x18, 0x0E, 0x30, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, + 0x10, 0x08, 0x30, 0x10, 0x20, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x0C, 0x30, + 0x18, 0x18, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x38, 0x0C, 0x38, 0x08, 0x1E, 0x18, 0x0F, 0x20, + 0x07, 0xC0, 0x18, 0xF0, 0x30, 0x78, 0x30, 0x38, 0x60, 0x1C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, + 0x60, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x18, 0x20, + 0x30, 0x10, 0x30, 0x18, 0x60, 0x08, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, + 0x70, 0x1C, 0x30, 0x2C, 0x18, 0x6C, 0x0F, 0x8C, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x18, 0x00, 0x10, + 0x30, 0x30, 0x30, 0x60, 0x30, 0xC0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 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, 0x80, 0x03, 0xC0, 0x03, 0xC0, + 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 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, + 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, + 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, + 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x7F, 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, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, + 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0C, 0x18, + 0x18, 0x0C, 0x10, 0x06, 0x30, 0x06, 0x38, 0x06, 0x38, 0x06, 0x38, 0x06, 0x00, 0x0C, 0x00, 0x18, + 0x00, 0x70, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x80, 0x03, 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x06, 0x10, + 0x0C, 0x08, 0x18, 0x04, 0x30, 0xD4, 0x31, 0xB2, 0x21, 0x32, 0x63, 0x32, 0x63, 0x22, 0x66, 0x22, + 0x66, 0x22, 0x66, 0x22, 0x66, 0x62, 0x66, 0x64, 0x66, 0x64, 0x26, 0xE8, 0x33, 0x30, 0x30, 0x02, + 0x10, 0x04, 0x18, 0x0C, 0x0C, 0x18, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, + 0x03, 0x80, 0x03, 0x80, 0x04, 0xC0, 0x04, 0xC0, 0x04, 0xC0, 0x04, 0xC0, 0x0C, 0x40, 0x08, 0x60, + 0x08, 0x60, 0x08, 0x60, 0x18, 0x20, 0x1F, 0xF0, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x20, 0x18, + 0x20, 0x18, 0x20, 0x18, 0x60, 0x1C, 0xF8, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x18, 0x38, + 0x18, 0x18, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x18, 0x18, 0x30, + 0x1F, 0xE0, 0x18, 0x18, 0x18, 0x0C, 0x18, 0x04, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, + 0x18, 0x06, 0x18, 0x0C, 0x18, 0x18, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x06, 0x1C, + 0x08, 0x0C, 0x18, 0x06, 0x30, 0x02, 0x30, 0x02, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x02, 0x30, 0x02, + 0x10, 0x04, 0x18, 0x08, 0x0C, 0x10, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x18, 0x70, + 0x18, 0x18, 0x18, 0x08, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, + 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x04, 0x18, 0x0C, 0x18, 0x0C, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x60, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x18, 0x0C, + 0x18, 0x04, 0x18, 0x02, 0x18, 0x02, 0x18, 0x00, 0x18, 0x00, 0x18, 0x10, 0x18, 0x10, 0x18, 0x30, + 0x1F, 0xF0, 0x18, 0x30, 0x18, 0x10, 0x18, 0x10, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, + 0x18, 0x02, 0x18, 0x04, 0x18, 0x0C, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x18, 0x1C, + 0x18, 0x04, 0x18, 0x02, 0x18, 0x02, 0x18, 0x00, 0x18, 0x00, 0x18, 0x10, 0x18, 0x10, 0x18, 0x30, + 0x1F, 0xF0, 0x18, 0x30, 0x18, 0x10, 0x18, 0x10, 0x18, 0x10, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x0C, 0x30, + 0x08, 0x10, 0x18, 0x18, 0x30, 0x08, 0x30, 0x08, 0x20, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, + 0x60, 0x00, 0x60, 0x00, 0x60, 0x7E, 0x60, 0x18, 0x60, 0x18, 0x20, 0x18, 0x30, 0x18, 0x30, 0x18, + 0x10, 0x18, 0x18, 0x18, 0x0C, 0x20, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x30, 0x0C, + 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, + 0x3F, 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, + 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 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, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x70, 0x60, 0x70, 0xC0, 0x71, 0x80, 0x3F, 0x00, /*"J",42*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7C, 0x18, 0x30, + 0x18, 0x20, 0x18, 0x60, 0x18, 0x40, 0x18, 0x80, 0x18, 0x80, 0x19, 0x00, 0x19, 0x00, 0x1B, 0x00, + 0x1D, 0x80, 0x1D, 0x80, 0x18, 0xC0, 0x18, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x18, 0x30, + 0x18, 0x30, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, + 0x18, 0x02, 0x18, 0x04, 0x18, 0x0C, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x38, 0x1C, + 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x4C, + 0x2C, 0x4C, 0x26, 0x4C, 0x26, 0x4C, 0x26, 0x4C, 0x26, 0x8C, 0x22, 0x8C, 0x23, 0x8C, 0x23, 0x8C, + 0x23, 0x0C, 0x23, 0x0C, 0x21, 0x0C, 0xF1, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1F, 0x38, 0x04, + 0x38, 0x04, 0x2C, 0x04, 0x2C, 0x04, 0x26, 0x04, 0x26, 0x04, 0x23, 0x04, 0x23, 0x04, 0x21, 0x84, + 0x21, 0x84, 0x20, 0xC4, 0x20, 0xC4, 0x20, 0x64, 0x20, 0x64, 0x20, 0x34, 0x20, 0x34, 0x20, 0x1C, + 0x20, 0x1C, 0x20, 0x0C, 0x20, 0x0C, 0xF8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x0C, 0x30, + 0x18, 0x18, 0x10, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x04, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, + 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x20, 0x06, 0x30, 0x0C, 0x30, 0x0C, + 0x10, 0x08, 0x18, 0x18, 0x0C, 0x30, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x18, 0x18, + 0x18, 0x0C, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x0C, + 0x18, 0x18, 0x1F, 0xE0, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x0C, 0x30, + 0x18, 0x18, 0x10, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, + 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x27, 0x84, 0x38, 0xCC, + 0x38, 0x6C, 0x18, 0x78, 0x0C, 0x70, 0x03, 0xE0, 0x00, 0x32, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x18, 0x38, + 0x18, 0x18, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x18, 0x18, 0x30, + 0x1F, 0xE0, 0x18, 0xC0, 0x18, 0xC0, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x18, 0x30, + 0x18, 0x30, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC8, 0x18, 0x78, + 0x30, 0x18, 0x60, 0x18, 0x60, 0x08, 0x60, 0x08, 0x60, 0x00, 0x70, 0x00, 0x3C, 0x00, 0x1F, 0x00, + 0x07, 0xC0, 0x01, 0xF0, 0x00, 0x78, 0x00, 0x18, 0x00, 0x1C, 0x40, 0x0C, 0x40, 0x0C, 0x60, 0x0C, + 0x20, 0x0C, 0x30, 0x18, 0x38, 0x30, 0x27, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x31, 0x84, + 0x21, 0x86, 0x41, 0x82, 0x41, 0x82, 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, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3E, 0x30, 0x08, + 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, + 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x08, + 0x30, 0x08, 0x18, 0x10, 0x1C, 0x20, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x1E, 0x18, 0x0C, + 0x18, 0x08, 0x18, 0x08, 0x18, 0x08, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x20, + 0x06, 0x20, 0x06, 0x20, 0x06, 0x20, 0x06, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xCF, 0x61, 0x86, + 0x61, 0x84, 0x21, 0x84, 0x20, 0x84, 0x30, 0xC4, 0x31, 0xC4, 0x31, 0xC4, 0x31, 0xC8, 0x31, 0xC8, + 0x11, 0xC8, 0x12, 0x48, 0x1A, 0x68, 0x1A, 0x68, 0x1A, 0x70, 0x1C, 0x70, 0x0C, 0x70, 0x0C, 0x70, + 0x0C, 0x30, 0x0C, 0x20, 0x08, 0x20, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x3E, 0x18, 0x08, + 0x18, 0x10, 0x0C, 0x10, 0x0C, 0x20, 0x06, 0x20, 0x06, 0x40, 0x03, 0x40, 0x03, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x02, 0xC0, 0x02, 0x60, 0x04, 0x60, 0x04, 0x70, 0x08, 0x30, + 0x08, 0x30, 0x18, 0x18, 0x10, 0x1C, 0x7C, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x3E, 0x38, 0x08, + 0x18, 0x08, 0x18, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x20, 0x06, 0x20, 0x06, 0x20, 0x03, 0x40, + 0x03, 0x40, 0x03, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFE, 0x1C, 0x0C, + 0x18, 0x0C, 0x30, 0x18, 0x20, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x00, 0xC0, + 0x01, 0x80, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x02, + 0x18, 0x06, 0x30, 0x04, 0x30, 0x1C, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, + 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x80, + 0x01, 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 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, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, + 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x03, 0xE0, 0x06, 0x20, 0x08, 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, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, /*"_",63*/ + + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 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, 0x18, 0x30, 0x30, 0x18, + 0x30, 0x18, 0x30, 0x18, 0x00, 0x38, 0x07, 0xD8, 0x1C, 0x18, 0x30, 0x18, 0x60, 0x18, 0x60, 0x18, + 0x60, 0x18, 0x60, 0x19, 0x30, 0x79, 0x1F, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x78, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x19, 0xE0, 0x1A, 0x38, 0x1C, 0x18, + 0x1C, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, + 0x18, 0x08, 0x1C, 0x18, 0x1C, 0x30, 0x13, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 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, 0xE0, 0x0E, 0x10, 0x0C, 0x18, + 0x18, 0x18, 0x30, 0x18, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x04, + 0x18, 0x04, 0x18, 0x08, 0x0C, 0x10, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x78, 0x00, 0x18, + 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x07, 0xD8, 0x0C, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, + 0x10, 0x18, 0x18, 0x38, 0x0C, 0x5E, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 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, 0x0C, 0x30, 0x08, 0x18, + 0x18, 0x08, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x3F, 0xFC, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x18, 0x04, 0x18, 0x08, 0x0E, 0x18, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x01, 0x86, + 0x01, 0x06, 0x03, 0x06, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF8, 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, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 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, 0xEE, 0x0C, 0x36, 0x08, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x18, 0x0C, 0x30, 0x0F, 0xE0, 0x18, 0x00, 0x18, 0x00, + 0x1F, 0xC0, 0x0F, 0xF8, 0x18, 0x1C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x18, 0x18, 0x07, 0xE0, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x78, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x19, 0xE0, 0x1A, 0x30, 0x1C, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, + 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 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, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x78, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0xF0, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x18, 0x60, 0x18, 0x40, 0x0F, 0x80, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x78, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x7C, 0x18, 0x30, 0x18, 0x20, + 0x18, 0x40, 0x18, 0x80, 0x19, 0x80, 0x1B, 0x80, 0x1E, 0xC0, 0x1C, 0xC0, 0x18, 0x60, 0x18, 0x30, + 0x18, 0x30, 0x18, 0x18, 0x18, 0x1C, 0x7E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 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, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 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, 0xEF, 0x3C, 0x71, 0xC6, 0x61, 0x86, + 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, + 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0xF3, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xE0, 0x7A, 0x30, 0x1C, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 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, 0x0C, 0x30, 0x08, 0x18, + 0x18, 0x18, 0x10, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, + 0x18, 0x18, 0x18, 0x18, 0x0C, 0x30, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xE0, 0x7A, 0x30, 0x1C, 0x18, + 0x18, 0x08, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, + 0x18, 0x18, 0x1C, 0x18, 0x1E, 0x30, 0x19, 0xE0, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, 0x00, /*"p",80*/ + + 0x00, 0x00, 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, 0xC8, 0x0C, 0x78, 0x18, 0x38, + 0x18, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, + 0x10, 0x18, 0x18, 0x38, 0x0C, 0x78, 0x07, 0x98, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1C, 0x7E, 0x66, 0x06, 0x86, + 0x07, 0x80, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 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, 0xE4, 0x06, 0x1C, 0x0C, 0x0C, + 0x0C, 0x04, 0x0C, 0x04, 0x0E, 0x00, 0x07, 0xC0, 0x01, 0xF0, 0x00, 0x78, 0x00, 0x1C, 0x10, 0x0C, + 0x10, 0x0C, 0x18, 0x0C, 0x1C, 0x18, 0x13, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x3F, 0xF8, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x04, 0x03, 0x04, 0x01, 0x88, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 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, 0x08, 0x78, 0x78, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x38, 0x0C, 0x5E, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 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, 0x3E, 0x18, 0x0C, 0x18, 0x08, + 0x18, 0x18, 0x0C, 0x10, 0x0C, 0x10, 0x04, 0x20, 0x06, 0x20, 0x06, 0x20, 0x03, 0x40, 0x03, 0x40, + 0x03, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xCF, 0x61, 0x86, 0x21, 0x84, + 0x31, 0x84, 0x31, 0x84, 0x31, 0xC8, 0x11, 0xC8, 0x1A, 0xC8, 0x1A, 0x48, 0x1A, 0x70, 0x0E, 0x70, + 0x0C, 0x70, 0x0C, 0x30, 0x0C, 0x20, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 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, 0x7C, 0x0C, 0x10, 0x0E, 0x10, + 0x06, 0x20, 0x03, 0x40, 0x03, 0x40, 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x02, 0x60, 0x04, 0x60, + 0x04, 0x30, 0x08, 0x18, 0x18, 0x18, 0x7C, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 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, 0x3E, 0x18, 0x18, 0x18, 0x10, + 0x08, 0x10, 0x0C, 0x10, 0x04, 0x20, 0x06, 0x20, 0x06, 0x20, 0x02, 0x40, 0x03, 0x40, 0x01, 0x40, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x3C, 0x00, /*"y",89*/ + + 0x00, 0x00, 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, 0xF8, 0x30, 0x38, 0x30, 0x30, + 0x20, 0x60, 0x20, 0xE0, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x03, 0x00, 0x06, 0x00, 0x0E, 0x04, + 0x0C, 0x04, 0x18, 0x0C, 0x30, 0x18, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xC0, + 0x01, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, /*"{",91*/ + + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x80, + 0x00, 0xC0, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x00, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x41, 0x82, 0x40, 0x82, 0x00, 0xE4, 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, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_32 = { + .bitmap = bitmap, + .width = 16, + .height = 32, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_36.c b/components/lua_modules/esp_painter/font/basic_font_36.c new file mode 100644 index 0000000..a5510f7 --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_36.c @@ -0,0 +1,782 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_36 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 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, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, + 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC7, 0x00, 0x01, 0xC7, 0x00, 0x03, 0xCF, 0x00, 0x03, + 0x8E, 0x00, 0x07, 0x1C, 0x00, 0x06, 0x18, 0x00, 0x0C, 0x30, 0x00, 0x18, 0x60, 0x00, 0x10, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*""",2*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x7F, 0xFF, 0x80, 0x7F, 0xFF, 0x80, 0x7F, 0xFF, 0x80, 0x0C, 0x0C, 0x00, + 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, + 0x08, 0x00, 0x7F, 0xFF, 0x80, 0x7F, 0xFF, 0x80, 0x7F, 0xFF, 0x80, 0x18, 0x18, 0x00, 0x18, 0x18, + 0x00, 0x18, 0x18, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x80, 0x00, 0x03, 0xF0, 0x00, 0x06, 0x88, 0x00, 0x0C, 0x84, 0x00, 0x18, 0x86, 0x00, 0x18, 0x86, + 0x00, 0x18, 0x8E, 0x00, 0x18, 0x8E, 0x00, 0x1C, 0x80, 0x00, 0x0E, 0x80, 0x00, 0x0F, 0x80, 0x00, + 0x07, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xBC, 0x00, 0x00, + 0x9C, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x86, 0x00, 0x38, 0x86, 0x00, 0x38, 0x86, 0x00, 0x38, 0x86, + 0x00, 0x30, 0x84, 0x00, 0x10, 0x8C, 0x00, 0x08, 0x98, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x04, 0x00, 0x66, 0x0C, 0x00, 0x42, 0x08, 0x00, 0xC3, 0x08, 0x00, 0xC3, 0x10, + 0x00, 0xC3, 0x10, 0x00, 0xC3, 0x20, 0x00, 0xC3, 0x20, 0x00, 0xC3, 0x20, 0x00, 0xC3, 0x40, 0x00, + 0x42, 0x40, 0x00, 0x66, 0x80, 0x00, 0x3C, 0x9E, 0x00, 0x00, 0xB3, 0x00, 0x01, 0x31, 0x00, 0x01, + 0x61, 0x80, 0x02, 0x61, 0x80, 0x02, 0x61, 0x80, 0x06, 0x61, 0x80, 0x04, 0x61, 0x80, 0x04, 0x61, + 0x80, 0x08, 0x61, 0x80, 0x08, 0x21, 0x00, 0x10, 0x33, 0x00, 0x10, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x80, 0x00, 0x0C, 0x80, 0x00, 0x08, 0xC0, 0x00, 0x18, 0xC0, 0x00, 0x18, 0xC0, + 0x00, 0x18, 0xC0, 0x00, 0x18, 0xC0, 0x00, 0x18, 0x80, 0x00, 0x19, 0x80, 0x00, 0x1D, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0C, 0x3E, 0x00, 0x1E, 0x18, 0x00, 0x26, 0x08, 0x00, 0x67, 0x08, 0x00, 0x43, + 0x08, 0x00, 0xC3, 0x10, 0x00, 0xC3, 0x90, 0x00, 0xC1, 0xD0, 0x00, 0xC0, 0xD0, 0x00, 0xC0, 0xE0, + 0x00, 0x60, 0x70, 0x80, 0x60, 0x79, 0x80, 0x30, 0x9F, 0x00, 0x1F, 0x0E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*")",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, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x01, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x70, 0xC7, 0x00, 0x78, 0x8F, 0x00, 0x3C, 0x9E, 0x00, + 0x0E, 0xB8, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x0E, 0xB8, 0x00, 0x3C, 0x9E, 0x00, 0x78, + 0x8F, 0x00, 0x71, 0x87, 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, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 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, 0x40, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 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, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 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, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xE0, 0x00, 0x06, 0x18, 0x00, 0x04, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, + 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, + 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x0C, 0x0C, 0x00, 0x04, 0x08, 0x00, 0x06, 0x18, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x0C, 0x1C, 0x00, 0x18, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x03, + 0x00, 0x38, 0x03, 0x00, 0x38, 0x03, 0x00, 0x38, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, + 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x00, 0x08, 0x01, + 0x00, 0x10, 0x03, 0x00, 0x30, 0x07, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xE0, 0x00, 0x08, 0x38, 0x00, 0x10, 0x0C, 0x00, 0x20, 0x0E, 0x00, 0x30, 0x06, + 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x30, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x18, 0x03, 0x00, 0x38, 0x03, 0x00, 0x38, 0x03, + 0x00, 0x38, 0x06, 0x00, 0x18, 0x04, 0x00, 0x0C, 0x18, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 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, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x58, + 0x00, 0x00, 0xD8, 0x00, 0x00, 0x98, 0x00, 0x01, 0x18, 0x00, 0x03, 0x18, 0x00, 0x02, 0x18, 0x00, + 0x04, 0x18, 0x00, 0x0C, 0x18, 0x00, 0x08, 0x18, 0x00, 0x10, 0x18, 0x00, 0x10, 0x18, 0x00, 0x20, + 0x18, 0x00, 0x60, 0x18, 0x00, 0x7F, 0xFF, 0x80, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0xF0, 0x00, + 0x16, 0x0C, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x18, 0x03, 0x00, 0x38, 0x03, 0x00, 0x38, 0x06, + 0x00, 0x30, 0x06, 0x00, 0x10, 0x0C, 0x00, 0x0C, 0x18, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xF8, 0x00, 0x03, 0x04, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x06, 0x00, 0x08, 0x06, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0xF0, 0x00, + 0x36, 0x1C, 0x00, 0x34, 0x06, 0x00, 0x38, 0x06, 0x00, 0x38, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, + 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x02, + 0x00, 0x0C, 0x06, 0x00, 0x0C, 0x04, 0x00, 0x06, 0x08, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x1F, 0xFF, 0x00, 0x18, 0x02, 0x00, 0x30, 0x04, 0x00, 0x20, 0x04, + 0x00, 0x20, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, + 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xF0, 0x00, 0x06, 0x0C, 0x00, 0x0C, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, + 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x1C, 0x03, 0x00, 0x0E, 0x06, 0x00, 0x0F, 0x06, 0x00, + 0x07, 0x88, 0x00, 0x03, 0xF0, 0x00, 0x06, 0xF8, 0x00, 0x0C, 0x3C, 0x00, 0x18, 0x1E, 0x00, 0x18, + 0x0E, 0x00, 0x30, 0x07, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, + 0x00, 0x18, 0x02, 0x00, 0x18, 0x06, 0x00, 0x0E, 0x0C, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE0, 0x00, 0x0E, 0x18, 0x00, 0x08, 0x0C, 0x00, 0x18, 0x04, 0x00, 0x10, 0x06, + 0x00, 0x30, 0x02, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, + 0x30, 0x07, 0x00, 0x18, 0x07, 0x00, 0x18, 0x0B, 0x00, 0x0E, 0x13, 0x00, 0x03, 0xE3, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x18, 0x0C, + 0x00, 0x18, 0x08, 0x00, 0x18, 0x18, 0x00, 0x08, 0x70, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 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, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xFF, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 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, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x06, 0x0C, 0x00, 0x08, 0x06, 0x00, 0x10, 0x02, 0x00, 0x30, 0x03, + 0x00, 0x30, 0x03, 0x00, 0x3C, 0x03, 0x00, 0x3C, 0x03, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xF0, 0x00, 0x07, 0x0C, 0x00, 0x0C, 0x02, 0x00, 0x08, 0x01, 0x00, 0x18, 0x7D, + 0x00, 0x30, 0xCD, 0x00, 0x31, 0x8C, 0x80, 0x21, 0x8C, 0x80, 0x63, 0x08, 0x80, 0x63, 0x08, 0x80, + 0x63, 0x18, 0x80, 0x66, 0x18, 0x80, 0x66, 0x18, 0x80, 0x66, 0x18, 0x80, 0x66, 0x18, 0x80, 0x66, + 0x31, 0x00, 0x66, 0x31, 0x00, 0x22, 0x52, 0x00, 0x33, 0x9C, 0x00, 0x30, 0x00, 0x80, 0x10, 0x01, + 0x00, 0x18, 0x03, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x0C, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 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, 0x03, 0x60, + 0x00, 0x02, 0x60, 0x00, 0x02, 0x60, 0x00, 0x02, 0x60, 0x00, 0x06, 0x30, 0x00, 0x04, 0x30, 0x00, + 0x04, 0x30, 0x00, 0x04, 0x30, 0x00, 0x0C, 0x38, 0x00, 0x08, 0x18, 0x00, 0x08, 0x18, 0x00, 0x0F, + 0xF8, 0x00, 0x18, 0x18, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x0C, 0x00, 0x10, 0x0C, 0x00, 0x30, 0x0C, + 0x00, 0x20, 0x0E, 0x00, 0x20, 0x06, 0x00, 0x30, 0x06, 0x00, 0xF8, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x18, 0x1E, 0x00, 0x18, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, + 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, + 0x18, 0x18, 0x00, 0x1F, 0xF0, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, + 0x01, 0x00, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, + 0x80, 0x18, 0x03, 0x00, 0x18, 0x07, 0x00, 0x18, 0x0E, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xF9, 0x00, 0x02, 0x0F, 0x00, 0x0C, 0x03, 0x00, 0x08, 0x01, 0x00, 0x18, 0x01, + 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x80, 0x30, 0x00, 0x80, 0x30, 0x01, + 0x00, 0x18, 0x01, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x0C, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x18, 0x38, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x06, 0x00, 0x18, 0x02, + 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, + 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x38, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x18, 0x07, 0x00, 0x18, 0x03, 0x00, 0x18, 0x01, 0x80, 0x18, 0x00, + 0x80, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x08, 0x00, 0x18, 0x08, 0x00, 0x18, 0x08, 0x00, + 0x18, 0x18, 0x00, 0x1F, 0xF8, 0x00, 0x18, 0x18, 0x00, 0x18, 0x08, 0x00, 0x18, 0x08, 0x00, 0x18, + 0x08, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x80, 0x18, 0x00, + 0x80, 0x18, 0x01, 0x00, 0x18, 0x03, 0x00, 0x18, 0x07, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x18, 0x0F, 0x00, 0x18, 0x03, 0x00, 0x18, 0x01, 0x00, 0x18, 0x00, + 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x08, 0x00, 0x18, 0x08, 0x00, + 0x18, 0x18, 0x00, 0x1F, 0xF8, 0x00, 0x18, 0x18, 0x00, 0x18, 0x08, 0x00, 0x18, 0x08, 0x00, 0x18, + 0x08, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xE0, 0x00, 0x06, 0x1C, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x04, 0x00, 0x10, 0x06, + 0x00, 0x30, 0x02, 0x00, 0x30, 0x02, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x3F, 0x80, 0x60, + 0x06, 0x00, 0x60, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x10, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x08, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x1F, 0x80, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, + 0x18, 0x06, 0x00, 0x1F, 0xFE, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, + 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x7E, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x70, 0x18, 0x00, + 0x70, 0x30, 0x00, 0x70, 0x30, 0x00, 0x30, 0x40, 0x00, 0x1F, 0x80, 0x00, /*"J",42*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x3F, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x08, 0x00, 0x18, 0x10, 0x00, 0x18, 0x30, + 0x00, 0x18, 0x20, 0x00, 0x18, 0x40, 0x00, 0x18, 0xC0, 0x00, 0x18, 0x80, 0x00, 0x19, 0x80, 0x00, + 0x19, 0x80, 0x00, 0x1B, 0xC0, 0x00, 0x1C, 0xC0, 0x00, 0x1C, 0xE0, 0x00, 0x18, 0x60, 0x00, 0x18, + 0x60, 0x00, 0x18, 0x30, 0x00, 0x18, 0x30, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x1C, + 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x7E, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x80, 0x18, 0x00, + 0x80, 0x18, 0x01, 0x00, 0x18, 0x03, 0x00, 0x18, 0x07, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0x07, 0xC0, 0x38, 0x07, 0x00, 0x38, 0x07, 0x00, 0x38, 0x07, 0x00, 0x38, 0x07, + 0x00, 0x2C, 0x0B, 0x00, 0x2C, 0x0B, 0x00, 0x2C, 0x0B, 0x00, 0x2C, 0x0B, 0x00, 0x2E, 0x13, 0x00, + 0x26, 0x13, 0x00, 0x26, 0x13, 0x00, 0x26, 0x13, 0x00, 0x26, 0x23, 0x00, 0x23, 0x23, 0x00, 0x23, + 0x23, 0x00, 0x23, 0x23, 0x00, 0x23, 0x43, 0x00, 0x23, 0xC3, 0x00, 0x21, 0xC3, 0x00, 0x21, 0xC3, + 0x00, 0x21, 0xC3, 0x00, 0x21, 0x83, 0x00, 0x20, 0x83, 0x00, 0xF8, 0x8F, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0F, 0x80, 0x1C, 0x02, 0x00, 0x1C, 0x02, 0x00, 0x16, 0x02, 0x00, 0x16, 0x02, + 0x00, 0x16, 0x02, 0x00, 0x13, 0x02, 0x00, 0x13, 0x02, 0x00, 0x11, 0x82, 0x00, 0x11, 0x82, 0x00, + 0x10, 0xC2, 0x00, 0x10, 0xC2, 0x00, 0x10, 0xE2, 0x00, 0x10, 0x62, 0x00, 0x10, 0x62, 0x00, 0x10, + 0x32, 0x00, 0x10, 0x32, 0x00, 0x10, 0x1A, 0x00, 0x10, 0x1A, 0x00, 0x10, 0x0E, 0x00, 0x10, 0x0E, + 0x00, 0x10, 0x0E, 0x00, 0x10, 0x06, 0x00, 0x10, 0x06, 0x00, 0x7C, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x06, 0x18, 0x00, 0x0C, 0x04, 0x00, 0x18, 0x06, 0x00, 0x10, 0x02, + 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x20, 0x01, 0x00, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, + 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, + 0x01, 0x80, 0x60, 0x01, 0x80, 0x20, 0x01, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x10, 0x02, + 0x00, 0x18, 0x06, 0x00, 0x0C, 0x04, 0x00, 0x06, 0x18, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x18, 0x0E, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x03, 0x00, + 0x18, 0x07, 0x00, 0x18, 0x0E, 0x00, 0x1F, 0xF8, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x06, 0x18, 0x00, 0x0C, 0x04, 0x00, 0x18, 0x06, 0x00, 0x10, 0x02, + 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, + 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, + 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x27, 0xC1, 0x00, 0x3C, 0x63, 0x00, 0x38, 0x33, + 0x00, 0x18, 0x32, 0x00, 0x08, 0x3C, 0x00, 0x06, 0x18, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x1C, 0x80, + 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x18, 0x1C, 0x00, 0x18, 0x06, 0x00, 0x18, 0x07, 0x00, 0x18, 0x03, + 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, + 0x18, 0x1C, 0x00, 0x1F, 0xF0, 0x00, 0x18, 0x60, 0x00, 0x18, 0x60, 0x00, 0x18, 0x70, 0x00, 0x18, + 0x30, 0x00, 0x18, 0x30, 0x00, 0x18, 0x38, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x1C, + 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x7E, 0x07, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE0, 0x00, 0x0C, 0x1E, 0x00, 0x18, 0x0E, 0x00, 0x10, 0x06, 0x00, 0x30, 0x02, + 0x00, 0x30, 0x02, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00, 0x20, 0x03, 0x00, 0x20, 0x03, 0x00, 0x30, 0x03, + 0x00, 0x10, 0x06, 0x00, 0x18, 0x06, 0x00, 0x1E, 0x0C, 0x00, 0x11, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x30, 0xC3, 0x00, 0x20, 0xC1, 0x00, 0x20, 0xC1, 0x80, 0x40, 0xC0, + 0x80, 0x40, 0xC0, 0x80, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x0F, 0x80, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, + 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, + 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, + 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, + 0x00, 0x18, 0x04, 0x00, 0x0C, 0x04, 0x00, 0x06, 0x18, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x0F, 0x80, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x1C, 0x06, 0x00, 0x0C, 0x04, + 0x00, 0x0C, 0x04, 0x00, 0x0C, 0x04, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x08, 0x00, 0x06, 0x08, 0x00, + 0x06, 0x08, 0x00, 0x06, 0x18, 0x00, 0x07, 0x10, 0x00, 0x03, 0x10, 0x00, 0x03, 0x10, 0x00, 0x03, + 0x20, 0x00, 0x03, 0xA0, 0x00, 0x01, 0xA0, 0x00, 0x01, 0xA0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF9, 0xF3, 0xC0, 0x70, 0xC1, 0x80, 0x30, 0xC1, 0x00, 0x30, 0xC1, 0x00, 0x30, 0xC1, + 0x00, 0x30, 0x61, 0x00, 0x30, 0xE1, 0x00, 0x30, 0xE2, 0x00, 0x30, 0xE2, 0x00, 0x18, 0xE2, 0x00, + 0x18, 0xE2, 0x00, 0x19, 0x62, 0x00, 0x19, 0x32, 0x00, 0x19, 0x34, 0x00, 0x19, 0x34, 0x00, 0x19, + 0x34, 0x00, 0x0E, 0x34, 0x00, 0x0E, 0x34, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x18, 0x00, 0x0E, 0x18, + 0x00, 0x0E, 0x18, 0x00, 0x04, 0x18, 0x00, 0x04, 0x18, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x1F, 0x00, 0x1C, 0x06, 0x00, 0x0C, 0x04, 0x00, 0x0C, 0x08, 0x00, 0x0E, 0x08, + 0x00, 0x06, 0x18, 0x00, 0x07, 0x10, 0x00, 0x03, 0x30, 0x00, 0x03, 0xA0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, + 0x70, 0x00, 0x03, 0x30, 0x00, 0x02, 0x30, 0x00, 0x06, 0x18, 0x00, 0x04, 0x18, 0x00, 0x04, 0x1C, + 0x00, 0x08, 0x0C, 0x00, 0x08, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x7C, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x0F, 0x80, 0x38, 0x06, 0x00, 0x18, 0x06, 0x00, 0x1C, 0x04, 0x00, 0x0C, 0x04, + 0x00, 0x0C, 0x08, 0x00, 0x06, 0x08, 0x00, 0x06, 0x08, 0x00, 0x07, 0x10, 0x00, 0x03, 0x10, 0x00, + 0x03, 0x30, 0x00, 0x01, 0xA0, 0x00, 0x01, 0xA0, 0x00, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x1C, 0x06, 0x00, 0x18, 0x0E, 0x00, 0x30, 0x0C, 0x00, 0x20, 0x1C, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x1C, 0x01, + 0x00, 0x18, 0x02, 0x00, 0x38, 0x06, 0x00, 0x30, 0x0E, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x03, 0x60, 0x00, 0x06, 0x10, 0x00, 0x08, + 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0xC0, /*"_",63*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, + 0x0C, 0x18, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x01, + 0xFC, 0x00, 0x07, 0x0C, 0x00, 0x1C, 0x0C, 0x00, 0x18, 0x0C, 0x00, 0x30, 0x0C, 0x00, 0x30, 0x0C, + 0x00, 0x30, 0x0C, 0x80, 0x30, 0x1C, 0x80, 0x18, 0x3C, 0x80, 0x0F, 0xC7, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0xF8, 0x00, + 0x1B, 0x0C, 0x00, 0x1E, 0x06, 0x00, 0x1C, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, + 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, + 0x00, 0x18, 0x06, 0x00, 0x1C, 0x06, 0x00, 0x1E, 0x0C, 0x00, 0x11, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x00, + 0x07, 0x0C, 0x00, 0x0C, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x01, + 0x00, 0x18, 0x02, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x0C, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x03, 0xE6, 0x00, + 0x06, 0x1E, 0x00, 0x0C, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, + 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, + 0x00, 0x18, 0x0E, 0x00, 0x18, 0x0E, 0x00, 0x0C, 0x17, 0x80, 0x03, 0xE4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, + 0x06, 0x0C, 0x00, 0x0C, 0x06, 0x00, 0x18, 0x06, 0x00, 0x10, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, + 0x03, 0x00, 0x3F, 0xFF, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x01, + 0x00, 0x18, 0x01, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x0C, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xC1, 0x00, 0x01, 0x81, 0x80, 0x01, 0x01, 0x80, 0x03, 0x01, + 0x80, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE3, 0x80, + 0x06, 0x3D, 0x80, 0x0C, 0x18, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0C, 0x00, 0x18, + 0x0C, 0x00, 0x0C, 0x18, 0x00, 0x06, 0x18, 0x00, 0x0F, 0xE0, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x1F, 0xC0, 0x00, 0x07, 0xFC, 0x00, 0x18, 0x1E, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, + 0x30, 0x03, 0x00, 0x38, 0x02, 0x00, 0x1C, 0x0E, 0x00, 0x07, 0xF8, 0x00, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0xF8, 0x00, + 0x1B, 0x0C, 0x00, 0x1C, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, + 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x7E, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0F, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xFC, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x18, 0x08, 0x00, 0x18, 0x18, 0x00, 0x18, 0x30, 0x00, 0x0F, 0xC0, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x3F, 0x00, + 0x18, 0x1C, 0x00, 0x18, 0x10, 0x00, 0x18, 0x30, 0x00, 0x18, 0x60, 0x00, 0x18, 0xC0, 0x00, 0x19, + 0xC0, 0x00, 0x1B, 0xE0, 0x00, 0x1E, 0x60, 0x00, 0x1C, 0x70, 0x00, 0x18, 0x38, 0x00, 0x18, 0x18, + 0x00, 0x18, 0x1C, 0x00, 0x18, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x7E, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x77, 0x9E, 0x00, + 0x38, 0xE3, 0x00, 0x38, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, + 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, + 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x30, 0xC3, 0x00, 0x79, 0xE7, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x00, + 0x7B, 0x0C, 0x00, 0x1E, 0x06, 0x00, 0x1C, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, + 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x7E, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, + 0x06, 0x18, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x30, 0x03, 0x00, 0x30, + 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x10, 0x02, + 0x00, 0x18, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x06, 0x18, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xF0, 0x00, + 0x7B, 0x0C, 0x00, 0x1C, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, + 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x1C, 0x0C, 0x00, 0x1A, 0x18, 0x00, 0x19, 0xF0, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x7E, 0x00, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE2, 0x00, + 0x06, 0x1E, 0x00, 0x0C, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, + 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x0E, 0x00, 0x0C, 0x16, 0x00, 0x03, 0xE6, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1F, 0x80, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1E, 0x00, + 0x7E, 0x23, 0x00, 0x06, 0xC3, 0x00, 0x06, 0x83, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF2, 0x00, + 0x06, 0x0E, 0x00, 0x0C, 0x06, 0x00, 0x0C, 0x02, 0x00, 0x0C, 0x02, 0x00, 0x0E, 0x00, 0x00, 0x07, + 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1C, 0x00, 0x10, 0x0E, 0x00, 0x10, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x1E, 0x0C, 0x00, 0x11, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x02, 0x00, 0x03, 0x04, 0x00, 0x01, 0x84, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0x02, 0x00, 0x78, 0x1E, 0x00, + 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, + 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x18, 0x06, 0x00, 0x18, 0x0E, 0x00, 0x0C, 0x17, 0x80, 0x07, 0xE4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1F, 0x00, + 0x18, 0x0C, 0x00, 0x18, 0x04, 0x00, 0x0C, 0x08, 0x00, 0x0C, 0x08, 0x00, 0x0C, 0x18, 0x00, 0x06, + 0x10, 0x00, 0x06, 0x10, 0x00, 0x06, 0x20, 0x00, 0x03, 0x20, 0x00, 0x03, 0x20, 0x00, 0x03, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xE7, 0xC0, + 0x70, 0xC1, 0x00, 0x30, 0xC1, 0x00, 0x30, 0xC1, 0x00, 0x30, 0xE2, 0x00, 0x10, 0xE2, 0x00, 0x18, + 0xE2, 0x00, 0x19, 0x66, 0x00, 0x19, 0x34, 0x00, 0x0D, 0x34, 0x00, 0x0F, 0x34, 0x00, 0x0E, 0x38, + 0x00, 0x0E, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3E, 0x00, + 0x0E, 0x08, 0x00, 0x06, 0x10, 0x00, 0x06, 0x10, 0x00, 0x03, 0x20, 0x00, 0x03, 0xE0, 0x00, 0x01, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x60, 0x00, 0x02, 0x30, 0x00, 0x06, 0x30, + 0x00, 0x04, 0x18, 0x00, 0x08, 0x18, 0x00, 0x18, 0x0C, 0x00, 0x7C, 0x3F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1F, 0x80, + 0x0C, 0x06, 0x00, 0x0C, 0x04, 0x00, 0x06, 0x04, 0x00, 0x06, 0x0C, 0x00, 0x02, 0x08, 0x00, 0x03, + 0x08, 0x00, 0x03, 0x18, 0x00, 0x01, 0x90, 0x00, 0x01, 0x90, 0x00, 0x01, 0xB0, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x19, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFC, 0x00, + 0x38, 0x1C, 0x00, 0x30, 0x38, 0x00, 0x20, 0x30, 0x00, 0x20, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x0E, 0x02, + 0x00, 0x0C, 0x06, 0x00, 0x18, 0x04, 0x00, 0x38, 0x0C, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"{",91*/ + + 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x23, 0x00, 0x00, 0x21, 0x80, 0x80, 0x40, 0xC0, 0x80, 0x40, + 0x61, 0x00, 0x00, 0x31, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_36 = { + .bitmap = bitmap, + .width = 18, + .height = 36, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_40.c b/components/lua_modules/esp_painter/font/basic_font_40.c new file mode 100644 index 0000000..a9c5a5c --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_40.c @@ -0,0 +1,877 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_40 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x01, 0xE7, 0x80, 0x01, 0xE7, 0x80, 0x03, + 0xCF, 0x00, 0x03, 0x8E, 0x00, 0x07, 0x1C, 0x00, 0x06, 0x18, 0x00, 0x0C, 0x30, 0x00, 0x18, 0x60, + 0x00, 0x10, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*""",2*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x7F, 0xFF, 0xC0, 0x7F, 0xFF, 0xC0, 0x7F, 0xFF, 0xC0, + 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x04, + 0x04, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x7F, 0xFF, 0xC0, 0x7F, 0xFF, 0xC0, 0x7F, 0xFF, + 0xC0, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, + 0x0C, 0x0C, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0xFC, 0x00, 0x03, 0x22, 0x00, 0x06, 0x21, 0x00, 0x04, 0x21, + 0x80, 0x0C, 0x21, 0x80, 0x0C, 0x23, 0x80, 0x0C, 0x23, 0x80, 0x0E, 0x20, 0x00, 0x07, 0x20, 0x00, + 0x07, 0xA0, 0x00, 0x03, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x27, 0x00, 0x00, 0x23, 0x80, 0x00, 0x23, 0x80, 0x0C, 0x21, + 0x80, 0x1C, 0x21, 0x80, 0x1C, 0x21, 0x80, 0x18, 0x21, 0x80, 0x18, 0x21, 0x00, 0x08, 0x23, 0x00, + 0x06, 0x24, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"$",4*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x01, 0x00, 0x66, 0x03, 0x00, 0x62, 0x02, 0x00, 0x42, 0x06, 0x00, 0xC3, 0x04, + 0x00, 0xC3, 0x0C, 0x00, 0xC3, 0x08, 0x00, 0xC3, 0x08, 0x00, 0xC3, 0x18, 0x00, 0xC3, 0x10, 0x00, + 0xC3, 0x30, 0x00, 0xC3, 0x20, 0x00, 0x66, 0x60, 0x00, 0x66, 0x47, 0x80, 0x3C, 0x44, 0xC0, 0x00, + 0x8C, 0xC0, 0x00, 0x88, 0x40, 0x01, 0x98, 0x60, 0x01, 0x18, 0x60, 0x03, 0x18, 0x60, 0x02, 0x18, + 0x60, 0x02, 0x18, 0x60, 0x04, 0x18, 0x60, 0x04, 0x18, 0x60, 0x0C, 0x08, 0x60, 0x08, 0x08, 0x40, + 0x18, 0x04, 0xC0, 0x10, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",5*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xC0, 0x00, 0x04, 0x60, 0x00, 0x08, 0x30, 0x00, 0x18, 0x30, 0x00, 0x18, 0x30, + 0x00, 0x18, 0x30, 0x00, 0x18, 0x30, 0x00, 0x18, 0x30, 0x00, 0x18, 0x60, 0x00, 0x1C, 0x60, 0x00, + 0x0C, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x0E, 0x1F, 0xC0, 0x1E, 0x07, 0x00, 0x36, 0x06, 0x00, 0x27, + 0x06, 0x00, 0x67, 0x06, 0x00, 0x43, 0x84, 0x00, 0xC3, 0x84, 0x00, 0xC1, 0xC4, 0x00, 0xC1, 0xCC, + 0x00, 0xC0, 0xE8, 0x00, 0xC0, 0x78, 0x00, 0xC0, 0x70, 0x00, 0x60, 0x38, 0x20, 0x60, 0x3C, 0x60, + 0x38, 0x4F, 0xC0, 0x0F, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x18, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x00, + 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*")",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, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x70, 0xE1, 0xC0, 0x78, 0x43, 0xC0, 0x7C, 0x47, 0xC0, + 0x1E, 0x4F, 0x00, 0x07, 0x5C, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x5C, 0x00, 0x1E, + 0x4F, 0x00, 0x7C, 0x47, 0xC0, 0x78, 0x43, 0xC0, 0x70, 0xE1, 0xC0, 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, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x20, 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, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 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, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x03, 0x0C, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x03, + 0x00, 0x0C, 0x01, 0x00, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x30, 0x00, 0xC0, + 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, + 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x0C, 0x01, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x06, 0x00, + 0x03, 0x0C, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 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, 0x60, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0xF0, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x06, 0x0E, 0x00, 0x1C, 0x03, 0x00, 0x18, 0x03, + 0x00, 0x38, 0x01, 0x80, 0x38, 0x01, 0x80, 0x3C, 0x01, 0x80, 0x3C, 0x01, 0x80, 0x1C, 0x01, 0x80, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x80, 0x0C, 0x00, 0x80, 0x18, 0x01, 0x80, 0x30, 0x03, 0x00, + 0x3F, 0xFF, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x0C, 0x1C, 0x00, 0x18, 0x06, 0x00, 0x30, 0x06, + 0x00, 0x38, 0x03, 0x00, 0x38, 0x03, 0x00, 0x38, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x3C, 0x01, 0x80, 0x3C, 0x01, 0x00, 0x38, 0x03, 0x00, 0x1C, 0x06, 0x00, + 0x0E, 0x0C, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x2C, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x8C, 0x00, 0x01, 0x8C, 0x00, + 0x01, 0x0C, 0x00, 0x02, 0x0C, 0x00, 0x06, 0x0C, 0x00, 0x04, 0x0C, 0x00, 0x08, 0x0C, 0x00, 0x18, + 0x0C, 0x00, 0x10, 0x0C, 0x00, 0x20, 0x0C, 0x00, 0x60, 0x0C, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0x80, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x11, 0xF8, 0x00, 0x16, 0x0C, 0x00, 0x1C, 0x06, 0x00, 0x18, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x1C, 0x01, + 0x80, 0x3C, 0x01, 0x80, 0x3C, 0x01, 0x80, 0x38, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x06, 0x00, + 0x0E, 0x0C, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 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, 0x83, 0x00, 0x02, 0x03, 0x80, 0x04, 0x03, + 0x80, 0x08, 0x03, 0x80, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0xFC, 0x00, 0x33, 0x06, 0x00, 0x34, 0x03, 0x00, 0x3C, 0x01, 0x80, 0x38, + 0x01, 0x80, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, + 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x0C, 0x01, 0x80, 0x06, 0x03, 0x00, + 0x03, 0x06, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x0C, 0x00, 0x80, 0x18, 0x01, + 0x80, 0x10, 0x03, 0x00, 0x10, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, + 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, 0x00, + 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x07, 0x07, 0x00, 0x0C, 0x01, 0x80, 0x0C, 0x01, + 0x80, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x1C, 0x00, 0xC0, + 0x0E, 0x01, 0x80, 0x0F, 0x83, 0x00, 0x07, 0xE6, 0x00, 0x01, 0xF8, 0x00, 0x03, 0x7C, 0x00, 0x06, + 0x1E, 0x00, 0x0C, 0x07, 0x00, 0x18, 0x03, 0x80, 0x38, 0x01, 0xC0, 0x30, 0x01, 0xC0, 0x30, 0x00, + 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x0C, 0x01, 0x00, + 0x06, 0x06, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x06, 0x04, 0x00, 0x0C, 0x02, 0x00, 0x18, 0x01, + 0x00, 0x18, 0x01, 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, + 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x18, 0x01, 0xC0, 0x18, 0x03, 0xC0, 0x0C, + 0x06, 0xC0, 0x06, 0x0C, 0xC0, 0x03, 0xF0, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x1C, 0x03, 0x00, 0x1C, 0x06, 0x00, 0x1C, 0x0C, 0x00, + 0x0C, 0x18, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 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, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 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, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x00, 0x03, 0x06, 0x00, 0x06, 0x01, 0x00, 0x0C, 0x01, 0x80, 0x08, 0x00, + 0xC0, 0x18, 0x00, 0xC0, 0x1C, 0x00, 0xC0, 0x1E, 0x00, 0xC0, 0x1E, 0x00, 0xC0, 0x0E, 0x00, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x80, 0x06, 0x00, 0x80, 0x0C, 0x00, + 0x40, 0x08, 0x1F, 0x40, 0x18, 0x67, 0x20, 0x18, 0x63, 0x20, 0x10, 0xC3, 0x20, 0x30, 0x86, 0x20, + 0x31, 0x86, 0x20, 0x31, 0x86, 0x20, 0x33, 0x06, 0x20, 0x33, 0x06, 0x20, 0x33, 0x06, 0x20, 0x33, + 0x0E, 0x20, 0x33, 0x0C, 0x40, 0x33, 0x0C, 0x40, 0x33, 0x1C, 0x40, 0x11, 0x14, 0x80, 0x18, 0xE7, + 0x00, 0x18, 0x00, 0x20, 0x08, 0x00, 0x40, 0x0C, 0x00, 0x40, 0x04, 0x00, 0x80, 0x02, 0x01, 0x00, + 0x01, 0x86, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xF0, + 0x00, 0x01, 0x30, 0x00, 0x01, 0x30, 0x00, 0x01, 0x30, 0x00, 0x03, 0x38, 0x00, 0x03, 0x38, 0x00, + 0x02, 0x18, 0x00, 0x02, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x1C, 0x00, 0x04, 0x0C, 0x00, 0x04, + 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x0F, 0xFE, 0x00, 0x08, 0x06, 0x00, 0x08, 0x06, 0x00, 0x18, 0x06, + 0x00, 0x10, 0x07, 0x00, 0x10, 0x07, 0x00, 0x10, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x80, + 0x30, 0x03, 0x80, 0xFC, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x18, 0x07, 0x00, 0x18, 0x01, 0x80, 0x18, 0x01, + 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, + 0x18, 0x01, 0x80, 0x18, 0x03, 0x00, 0x18, 0x0E, 0x00, 0x1F, 0xF8, 0x00, 0x18, 0x06, 0x00, 0x18, + 0x01, 0x80, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, + 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0xE0, 0x18, 0x00, 0xC0, 0x18, 0x01, 0x80, + 0x18, 0x07, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x40, 0x03, 0x03, 0xC0, 0x06, 0x01, 0xC0, 0x0C, 0x00, + 0xC0, 0x18, 0x00, 0x40, 0x18, 0x00, 0x60, 0x30, 0x00, 0x20, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x20, 0x30, 0x00, 0x40, 0x18, 0x00, 0x40, 0x18, 0x00, 0x80, 0x0C, 0x01, 0x00, + 0x03, 0x06, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x18, 0x1C, 0x00, 0x18, 0x06, 0x00, 0x18, 0x03, + 0x00, 0x18, 0x01, 0x80, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0x60, + 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, + 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x60, 0x18, 0x00, 0x40, 0x18, 0x00, + 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0x80, 0x18, 0x01, 0x80, 0x18, 0x03, 0x00, 0x18, 0x06, 0x00, + 0x18, 0x1C, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x80, 0x18, 0x03, 0xC0, 0x18, 0x01, 0xC0, 0x18, 0x00, + 0xC0, 0x18, 0x00, 0x60, 0x18, 0x00, 0x20, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x04, 0x00, + 0x18, 0x04, 0x00, 0x18, 0x04, 0x00, 0x18, 0x0C, 0x00, 0x1F, 0xFC, 0x00, 0x18, 0x0C, 0x00, 0x18, + 0x04, 0x00, 0x18, 0x04, 0x00, 0x18, 0x04, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x20, 0x18, 0x00, 0x60, 0x18, 0x00, 0x40, 0x18, 0x00, 0xC0, + 0x18, 0x03, 0xC0, 0x7F, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x80, 0x18, 0x03, 0xC0, 0x18, 0x01, 0xC0, 0x18, 0x00, + 0xC0, 0x18, 0x00, 0x60, 0x18, 0x00, 0x20, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x02, 0x00, + 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x06, 0x00, 0x1F, 0xFE, 0x00, 0x18, 0x06, 0x00, 0x18, + 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x02, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x03, 0x0F, 0x00, 0x04, 0x03, 0x00, 0x0C, 0x03, + 0x00, 0x18, 0x01, 0x80, 0x10, 0x00, 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x0F, 0xF0, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, 0x30, 0x01, 0x80, 0x30, 0x01, + 0x80, 0x30, 0x01, 0x80, 0x10, 0x01, 0x80, 0x18, 0x01, 0x80, 0x0C, 0x01, 0x80, 0x0C, 0x01, 0x80, + 0x07, 0x06, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x07, 0xE0, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, + 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x1F, 0xFF, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, + 0x18, 0x01, 0x80, 0x7E, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x18, 0x00, 0x70, 0x10, 0x00, 0x30, + 0x60, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, /*"J",42*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1F, 0xC0, 0x18, 0x07, 0x00, 0x18, 0x06, 0x00, 0x18, 0x04, + 0x00, 0x18, 0x08, 0x00, 0x18, 0x18, 0x00, 0x18, 0x30, 0x00, 0x18, 0x20, 0x00, 0x18, 0x40, 0x00, + 0x18, 0xC0, 0x00, 0x18, 0xC0, 0x00, 0x19, 0xC0, 0x00, 0x1A, 0xE0, 0x00, 0x1E, 0xE0, 0x00, 0x1C, + 0x70, 0x00, 0x18, 0x70, 0x00, 0x18, 0x38, 0x00, 0x18, 0x38, 0x00, 0x18, 0x1C, 0x00, 0x18, 0x1C, + 0x00, 0x18, 0x0E, 0x00, 0x18, 0x0E, 0x00, 0x18, 0x06, 0x00, 0x18, 0x07, 0x00, 0x18, 0x03, 0x00, + 0x18, 0x03, 0x80, 0x7E, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x20, 0x0C, 0x00, 0x20, 0x0C, 0x00, 0x40, 0x0C, 0x00, 0xC0, + 0x0C, 0x01, 0xC0, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xE0, 0x38, 0x03, 0x80, 0x38, 0x03, 0x80, 0x38, 0x03, + 0x80, 0x3C, 0x07, 0x80, 0x2C, 0x05, 0x80, 0x2C, 0x05, 0x80, 0x2C, 0x05, 0x80, 0x2C, 0x05, 0x80, + 0x26, 0x09, 0x80, 0x26, 0x09, 0x80, 0x26, 0x09, 0x80, 0x26, 0x09, 0x80, 0x27, 0x11, 0x80, 0x23, + 0x11, 0x80, 0x23, 0x11, 0x80, 0x23, 0x11, 0x80, 0x23, 0x21, 0x80, 0x23, 0xA1, 0x80, 0x21, 0xA1, + 0x80, 0x21, 0xA1, 0x80, 0x21, 0xE1, 0x80, 0x21, 0xC1, 0x80, 0x20, 0xC1, 0x80, 0x20, 0xC1, 0x80, + 0x20, 0xC1, 0x80, 0xF8, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x07, 0xF0, 0x1C, 0x00, 0x80, 0x1C, 0x00, 0x80, 0x16, 0x00, + 0x80, 0x16, 0x00, 0x80, 0x13, 0x00, 0x80, 0x13, 0x00, 0x80, 0x11, 0x80, 0x80, 0x11, 0x80, 0x80, + 0x10, 0xC0, 0x80, 0x10, 0xC0, 0x80, 0x10, 0x60, 0x80, 0x10, 0x60, 0x80, 0x10, 0x30, 0x80, 0x10, + 0x30, 0x80, 0x10, 0x38, 0x80, 0x10, 0x18, 0x80, 0x10, 0x1C, 0x80, 0x10, 0x0C, 0x80, 0x10, 0x0E, + 0x80, 0x10, 0x06, 0x80, 0x10, 0x07, 0x80, 0x10, 0x03, 0x80, 0x10, 0x03, 0x80, 0x10, 0x01, 0x80, + 0x10, 0x01, 0x80, 0xFE, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x03, 0x04, 0x00, 0x0C, 0x03, 0x00, 0x08, 0x01, + 0x00, 0x18, 0x01, 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x20, 0x00, 0x40, + 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, + 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x20, 0x00, 0x40, 0x30, 0x00, + 0xC0, 0x30, 0x00, 0xC0, 0x10, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x08, 0x01, 0x00, 0x04, 0x03, 0x00, + 0x03, 0x0C, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x18, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, 0x01, + 0x80, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, + 0x18, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x18, 0x03, 0x00, 0x18, 0x0E, 0x00, 0x1F, 0xF8, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x07, 0x06, 0x00, 0x0C, 0x03, 0x00, 0x08, 0x01, + 0x00, 0x18, 0x00, 0x80, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x60, 0x00, 0x60, + 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, + 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0x23, 0xE0, + 0x40, 0x37, 0xF0, 0xC0, 0x3E, 0x38, 0xC0, 0x1C, 0x1C, 0x80, 0x18, 0x1D, 0x80, 0x0C, 0x1F, 0x00, + 0x06, 0x0E, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Q",49*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x0C, 0x0E, 0x00, 0x0C, 0x03, 0x00, 0x0C, 0x03, + 0x80, 0x0C, 0x01, 0x80, 0x0C, 0x01, 0x80, 0x0C, 0x01, 0x80, 0x0C, 0x01, 0x80, 0x0C, 0x01, 0x80, + 0x0C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0x0C, 0x0E, 0x00, 0x0F, 0xF8, 0x00, 0x0C, 0x30, 0x00, 0x0C, + 0x30, 0x00, 0x0C, 0x38, 0x00, 0x0C, 0x18, 0x00, 0x0C, 0x1C, 0x00, 0x0C, 0x1C, 0x00, 0x0C, 0x0C, + 0x00, 0x0C, 0x0E, 0x00, 0x0C, 0x06, 0x00, 0x0C, 0x07, 0x00, 0x0C, 0x07, 0x00, 0x0C, 0x03, 0x00, + 0x0C, 0x03, 0x80, 0x3F, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x06, 0x0F, 0x00, 0x08, 0x03, 0x80, 0x18, 0x03, + 0x80, 0x30, 0x01, 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0x80, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x00, 0xC0, 0x20, 0x00, + 0xC0, 0x20, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x10, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x1C, 0x01, 0x00, + 0x1F, 0x06, 0x00, 0x10, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xC0, 0x38, 0x60, 0xC0, 0x30, 0x60, 0x40, 0x20, 0x60, + 0x40, 0x60, 0x60, 0x20, 0x40, 0x60, 0x20, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x03, 0xE0, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, + 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, + 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, + 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, + 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x00, 0x80, 0x08, 0x01, 0x00, 0x0C, 0x03, 0x00, + 0x06, 0x06, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x07, 0xE0, 0x1C, 0x01, 0x80, 0x1C, 0x01, 0x80, 0x0C, 0x01, + 0x00, 0x0C, 0x01, 0x00, 0x0E, 0x01, 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x02, 0x00, 0x06, 0x02, 0x00, + 0x07, 0x02, 0x00, 0x07, 0x04, 0x00, 0x07, 0x04, 0x00, 0x03, 0x04, 0x00, 0x03, 0x04, 0x00, 0x03, + 0x88, 0x00, 0x03, 0x88, 0x00, 0x01, 0x88, 0x00, 0x01, 0x98, 0x00, 0x01, 0xD0, 0x00, 0x01, 0xD0, + 0x00, 0x00, 0xD0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xF9, 0xF0, 0x70, 0x60, 0x40, 0x30, 0x60, 0x40, 0x30, 0x60, + 0x40, 0x30, 0x70, 0x40, 0x30, 0x70, 0xC0, 0x38, 0x30, 0x80, 0x38, 0x70, 0x80, 0x18, 0x70, 0x80, + 0x18, 0x70, 0x80, 0x18, 0x70, 0x80, 0x18, 0xF9, 0x00, 0x18, 0xB9, 0x00, 0x1C, 0x99, 0x00, 0x0C, + 0x99, 0x00, 0x0C, 0x99, 0x00, 0x0D, 0x9B, 0x00, 0x0D, 0x1A, 0x00, 0x0D, 0x1E, 0x00, 0x0D, 0x0E, + 0x00, 0x0F, 0x0E, 0x00, 0x07, 0x0E, 0x00, 0x06, 0x0E, 0x00, 0x06, 0x0C, 0x00, 0x06, 0x0C, 0x00, + 0x06, 0x04, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x0F, 0xC0, 0x1C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0x0E, 0x02, + 0x00, 0x06, 0x06, 0x00, 0x07, 0x04, 0x00, 0x03, 0x0C, 0x00, 0x03, 0x88, 0x00, 0x01, 0x98, 0x00, + 0x01, 0xD0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xB8, 0x00, 0x01, 0x98, 0x00, 0x01, 0x1C, 0x00, 0x03, 0x0C, + 0x00, 0x02, 0x0E, 0x00, 0x06, 0x0E, 0x00, 0x04, 0x07, 0x00, 0x0C, 0x07, 0x00, 0x08, 0x03, 0x00, + 0x18, 0x03, 0x80, 0x7E, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x07, 0xE0, 0x1C, 0x01, 0x80, 0x1C, 0x01, 0x00, 0x0C, 0x01, + 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x02, 0x00, 0x06, 0x06, 0x00, 0x07, 0x04, 0x00, 0x03, 0x04, 0x00, + 0x03, 0x08, 0x00, 0x01, 0x88, 0x00, 0x01, 0x98, 0x00, 0x01, 0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x1E, 0x01, 0x80, 0x18, 0x03, 0x80, 0x18, 0x03, + 0x00, 0x30, 0x07, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x40, 0x1C, 0x00, 0xC0, 0x18, 0x00, 0x80, 0x38, 0x01, 0x80, + 0x30, 0x07, 0x80, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x01, 0xF8, 0x00, 0x01, 0x9C, 0x00, 0x03, 0x0C, 0x00, 0x04, + 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF0, 0x00, 0x00, 0x00, /*"_",63*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0xC0, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x0C, 0x06, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0xFB, 0x00, 0x07, 0x03, 0x00, 0x0C, 0x03, 0x00, 0x18, 0x03, + 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x20, 0x18, 0x07, 0x20, + 0x1C, 0x1B, 0x20, 0x07, 0xE1, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x7C, 0x00, 0x19, 0x87, 0x00, 0x1A, 0x01, 0x00, 0x1C, 0x01, 0x80, 0x1C, 0x01, 0x80, 0x18, + 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, + 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x1C, 0x03, 0x00, + 0x1E, 0x06, 0x00, 0x11, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x00, 0x03, 0x06, 0x00, 0x0E, 0x02, 0x00, 0x0C, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, + 0x03, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x80, 0x18, 0x00, 0x80, 0x18, 0x01, 0x00, 0x0C, 0x03, 0x00, + 0x06, 0x06, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, + 0x01, 0xF9, 0x80, 0x06, 0x0D, 0x80, 0x0C, 0x03, 0x80, 0x08, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x80, 0x30, 0x01, 0x80, 0x30, 0x01, 0x80, 0x30, 0x01, 0x80, 0x30, 0x01, 0x80, 0x30, 0x01, + 0x80, 0x30, 0x01, 0x80, 0x30, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x03, 0x80, 0x0C, 0x07, 0x80, + 0x06, 0x0D, 0xE0, 0x01, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x03, 0x06, 0x00, 0x06, 0x03, 0x00, 0x04, 0x01, 0x80, 0x0C, 0x00, 0x80, 0x08, + 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x1F, 0xFF, 0xC0, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x40, 0x0C, 0x00, 0x80, 0x06, 0x01, 0x80, + 0x03, 0x83, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x70, 0x40, 0x00, 0xC0, 0x60, 0x00, 0xC0, 0x60, 0x01, 0x80, + 0x60, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x3F, 0xFF, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x01, 0x80, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0xE0, 0x06, 0x0F, 0xE0, 0x0C, 0x06, 0x60, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, + 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x0C, 0x00, 0x0D, 0xF8, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0xFE, 0x00, 0x0C, 0x7F, 0x80, + 0x18, 0x01, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x0E, + 0x03, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x7C, 0x00, 0x19, 0x87, 0x00, 0x1E, 0x03, 0x00, 0x1C, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, + 0x18, 0x01, 0x80, 0x7E, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x0F, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x18, 0x0C, 0x00, 0x18, 0x0C, 0x00, 0x1C, + 0x30, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x0C, 0x1F, 0xC0, 0x0C, 0x06, 0x00, 0x0C, 0x04, 0x00, 0x0C, 0x08, 0x00, 0x0C, 0x18, 0x00, 0x0C, + 0x30, 0x00, 0x0C, 0x60, 0x00, 0x0C, 0xE0, 0x00, 0x0D, 0xB0, 0x00, 0x0F, 0x38, 0x00, 0x0E, 0x18, + 0x00, 0x0C, 0x1C, 0x00, 0x0C, 0x0E, 0x00, 0x0C, 0x06, 0x00, 0x0C, 0x07, 0x00, 0x0C, 0x03, 0x00, + 0x0C, 0x03, 0x80, 0x3F, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x73, 0xC7, 0x80, 0x3C, 0x78, 0xC0, 0x38, 0x70, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, + 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, + 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, 0x30, 0x60, 0xC0, + 0x30, 0x60, 0xC0, 0xFD, 0xFB, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7C, 0x00, 0x79, 0x87, 0x00, 0x1E, 0x03, 0x00, 0x1C, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, + 0x18, 0x01, 0x80, 0x7E, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x00, 0x03, 0x0E, 0x00, 0x0C, 0x03, 0x00, 0x0C, 0x01, 0x00, 0x18, 0x01, 0x80, 0x18, + 0x00, 0x80, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, 0xC0, 0x30, 0x00, + 0xC0, 0x30, 0x00, 0xC0, 0x10, 0x00, 0x80, 0x18, 0x01, 0x80, 0x08, 0x01, 0x00, 0x0C, 0x03, 0x00, + 0x07, 0x0E, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x00, 0x7B, 0x86, 0x00, 0x1E, 0x03, 0x00, 0x1C, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, + 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x00, 0xC0, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x1C, 0x03, 0x00, + 0x1B, 0x0E, 0x00, 0x19, 0xF8, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x06, 0x09, 0x00, 0x0C, 0x07, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x30, + 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, + 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00, 0x10, 0x03, 0x00, 0x18, 0x03, 0x00, 0x0C, 0x07, 0x00, + 0x06, 0x1B, 0x00, 0x03, 0xF3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x07, 0x80, 0x3F, 0x18, 0xC0, 0x03, 0x30, 0xC0, 0x03, 0x60, 0xC0, 0x03, 0xC0, 0x00, 0x03, + 0x80, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x00, 0x03, 0x07, 0x80, 0x04, 0x03, 0x80, 0x0C, 0x01, 0x80, 0x0C, 0x00, 0x80, 0x0C, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x0F, + 0x00, 0x00, 0x03, 0x80, 0x10, 0x01, 0x80, 0x10, 0x01, 0x80, 0x18, 0x01, 0x80, 0x1C, 0x01, 0x00, + 0x1E, 0x07, 0x00, 0x11, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, + 0x3F, 0xFF, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x80, 0x01, 0x80, 0x80, 0x00, 0x81, 0x00, + 0x00, 0xC2, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x00, + 0x78, 0x0F, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, + 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, + 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x03, 0x00, 0x18, 0x07, 0x00, 0x0C, 0x07, 0x00, + 0x0E, 0x1B, 0xC0, 0x03, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x0F, 0xC0, 0x1C, 0x03, 0x00, 0x0C, 0x03, 0x00, 0x0C, 0x02, 0x00, 0x0E, 0x06, 0x00, 0x06, + 0x04, 0x00, 0x06, 0x04, 0x00, 0x07, 0x0C, 0x00, 0x03, 0x08, 0x00, 0x03, 0x08, 0x00, 0x03, 0x98, + 0x00, 0x01, 0x90, 0x00, 0x01, 0x90, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFD, 0xF1, 0xF0, 0x70, 0x60, 0x40, 0x30, 0x60, 0x40, 0x30, 0x60, 0x80, 0x38, 0x70, 0x80, 0x18, + 0x70, 0x80, 0x18, 0x71, 0x80, 0x18, 0xB1, 0x00, 0x1C, 0xB9, 0x00, 0x0C, 0x99, 0x00, 0x0C, 0x9B, + 0x00, 0x0D, 0x1A, 0x00, 0x0F, 0x1A, 0x00, 0x07, 0x0E, 0x00, 0x07, 0x0E, 0x00, 0x06, 0x0C, 0x00, + 0x06, 0x0C, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x9F, 0x80, 0x0E, 0x06, 0x00, 0x06, 0x04, 0x00, 0x07, 0x0C, 0x00, 0x03, 0x88, 0x00, 0x01, + 0x90, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xB0, + 0x00, 0x01, 0x38, 0x00, 0x03, 0x18, 0x00, 0x02, 0x0C, 0x00, 0x04, 0x0E, 0x00, 0x0C, 0x06, 0x00, + 0x1C, 0x07, 0x00, 0x7E, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x8F, 0xE0, 0x0E, 0x03, 0x80, 0x06, 0x01, 0x00, 0x06, 0x03, 0x00, 0x07, 0x02, 0x00, 0x03, + 0x06, 0x00, 0x03, 0x06, 0x00, 0x01, 0x84, 0x00, 0x01, 0x8C, 0x00, 0x01, 0x88, 0x00, 0x00, 0xC8, + 0x00, 0x00, 0xD8, 0x00, 0x00, 0x50, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x1C, 0x80, 0x00, 0x1F, + 0x80, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1C, 0x07, 0x00, 0x18, 0x0E, 0x00, 0x18, 0x0C, 0x00, 0x10, 0x1C, 0x00, 0x10, + 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, + 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x80, 0x07, 0x00, 0x80, 0x06, 0x01, 0x80, 0x0E, 0x01, 0x00, + 0x1C, 0x03, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"{",91*/ + + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC0, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x07, 0x80, 0x00, 0x19, 0xC0, 0x00, 0x10, 0xE0, 0x20, 0x20, 0x70, 0x20, 0x20, 0x38, 0x40, 0x00, + 0x1C, 0x80, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_40 = { + .bitmap = bitmap, + .width = 20, + .height = 40, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_44.c b/components/lua_modules/esp_painter/font/basic_font_44.c new file mode 100644 index 0000000..b920348 --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_44.c @@ -0,0 +1,972 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_44 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 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, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x80, 0x01, 0xE3, 0xC0, 0x01, + 0xE3, 0xC0, 0x03, 0xC7, 0x80, 0x03, 0x87, 0x00, 0x07, 0x8F, 0x00, 0x07, 0x0E, 0x00, 0x0E, 0x1C, + 0x00, 0x0C, 0x18, 0x00, 0x18, 0x30, 0x00, 0x10, 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, /*""",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, 0x01, 0x80, 0xC0, 0x01, 0x00, 0x80, 0x01, 0x00, + 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x3F, 0xFF, 0xF0, + 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x03, 0x01, 0x80, 0x03, 0x01, 0x80, 0x03, + 0x01, 0x80, 0x03, 0x01, 0x80, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, + 0x00, 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x06, 0x03, 0x00, + 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x06, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xB3, 0x00, 0x03, 0x31, + 0x80, 0x06, 0x31, 0xC0, 0x0E, 0x31, 0xC0, 0x0E, 0x33, 0xC0, 0x0E, 0x33, 0xC0, 0x0E, 0x33, 0x80, + 0x0F, 0x30, 0x00, 0x07, 0x30, 0x00, 0x07, 0xB0, 0x00, 0x03, 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x37, 0x80, 0x00, 0x33, + 0x80, 0x00, 0x33, 0xC0, 0x00, 0x31, 0xC0, 0x0E, 0x31, 0xC0, 0x1E, 0x31, 0xC0, 0x1E, 0x31, 0xC0, + 0x1E, 0x31, 0xC0, 0x1C, 0x31, 0x80, 0x0C, 0x31, 0x80, 0x0C, 0x33, 0x00, 0x07, 0x36, 0x00, 0x01, + 0xFC, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"$",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, 0x0E, 0x00, 0x80, 0x11, 0x01, 0x80, 0x31, 0x81, + 0x00, 0x20, 0x83, 0x00, 0x60, 0xC2, 0x00, 0x60, 0xC2, 0x00, 0x60, 0xC6, 0x00, 0x60, 0xC4, 0x00, + 0x60, 0xCC, 0x00, 0x60, 0xC8, 0x00, 0x60, 0xC8, 0x00, 0x60, 0xD8, 0x00, 0x20, 0x90, 0x00, 0x31, + 0xB0, 0x00, 0x11, 0xA1, 0xC0, 0x0E, 0x22, 0x20, 0x00, 0x46, 0x30, 0x00, 0x44, 0x10, 0x00, 0xCC, + 0x18, 0x00, 0x8C, 0x18, 0x00, 0x8C, 0x18, 0x01, 0x0C, 0x18, 0x01, 0x0C, 0x18, 0x03, 0x0C, 0x18, + 0x02, 0x0C, 0x18, 0x02, 0x0C, 0x18, 0x04, 0x04, 0x10, 0x04, 0x06, 0x30, 0x0C, 0x02, 0x20, 0x08, + 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"%",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, 0x01, 0xF0, 0x00, 0x03, 0x38, 0x00, 0x06, 0x18, + 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, + 0x0E, 0x18, 0x00, 0x0E, 0x38, 0x00, 0x0F, 0x30, 0x00, 0x07, 0x60, 0x00, 0x07, 0xC0, 0x00, 0x07, + 0x87, 0xF0, 0x0F, 0x81, 0xC0, 0x1B, 0x81, 0x80, 0x1B, 0xC1, 0x80, 0x31, 0xC1, 0x80, 0x31, 0xC1, + 0x80, 0x70, 0xE1, 0x00, 0x70, 0xE1, 0x00, 0x70, 0x73, 0x00, 0x70, 0x7A, 0x00, 0x70, 0x3A, 0x00, + 0x70, 0x3C, 0x00, 0x38, 0x1E, 0x08, 0x38, 0x1E, 0x18, 0x1E, 0x37, 0x10, 0x0F, 0xE3, 0xF0, 0x07, + 0xC1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x18, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, + 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*")",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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x70, 0x70, 0x70, 0x78, 0x20, 0xF0, 0x7E, 0x23, 0xF0, 0x1F, 0x27, 0xC0, 0x03, 0xAE, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x03, 0xAE, 0x00, 0x1F, 0x27, 0xC0, 0x7E, 0x23, 0xF0, 0x78, 0x20, + 0xF0, 0x70, 0x70, 0x70, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 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, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x7F, + 0xFF, 0xF8, 0x7F, 0xFF, 0xF8, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 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, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, + 0xFF, 0xF0, 0x7F, 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, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 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, 0x01, 0x86, 0x00, 0x03, 0x03, + 0x00, 0x06, 0x01, 0x80, 0x0E, 0x01, 0xC0, 0x0C, 0x00, 0xC0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x00, 0x60, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, + 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, + 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x1C, 0x00, 0x60, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x0C, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0x80, 0x03, 0x03, 0x00, 0x01, 0x86, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"0",16*/ + + 0x00, 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, 0x18, 0x00, 0x00, 0x38, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7C, 0x00, 0x07, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 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, 0x07, 0x00, 0x04, 0x03, + 0x80, 0x08, 0x01, 0xC0, 0x08, 0x00, 0xE0, 0x18, 0x00, 0xE0, 0x18, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x00, 0xE0, 0x0C, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, + 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, + 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x20, 0x06, 0x00, 0x20, + 0x0C, 0x00, 0x60, 0x18, 0x00, 0x60, 0x30, 0x00, 0xC0, 0x3F, 0xFF, 0xC0, 0x3F, 0xFF, 0xC0, 0x3F, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 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, 0x0E, 0x00, 0x06, 0x03, + 0x00, 0x0C, 0x03, 0x80, 0x0C, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x00, 0xC0, 0x1C, 0x01, 0xC0, 0x08, 0x01, 0x80, 0x0C, 0x03, 0x80, 0x06, 0x0F, 0x00, 0x01, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"3",19*/ + + 0x00, 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, 0x07, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x0F, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, + 0x00, 0x47, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x87, 0x00, 0x01, 0x07, 0x00, 0x01, 0x07, 0x00, 0x02, + 0x07, 0x00, 0x06, 0x07, 0x00, 0x04, 0x07, 0x00, 0x0C, 0x07, 0x00, 0x08, 0x07, 0x00, 0x10, 0x07, + 0x00, 0x30, 0x07, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x80, 0x00, + 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 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, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x7C, 0x00, 0x0D, 0xFF, 0x00, 0x0B, 0x07, 0x80, 0x0A, + 0x03, 0xC0, 0x0C, 0x01, 0xC0, 0x0C, 0x01, 0xC0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x01, 0xC0, 0x18, 0x01, 0xC0, 0x08, 0x01, 0x80, 0x04, 0x03, 0x80, 0x02, 0x07, 0x00, 0x01, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"5",21*/ + + 0x00, 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, 0xC1, 0x80, 0x03, 0x01, + 0x80, 0x06, 0x01, 0xC0, 0x06, 0x01, 0xC0, 0x0C, 0x01, 0xC0, 0x0C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x7E, 0x00, 0x39, 0xFF, 0x80, 0x3B, + 0x83, 0xC0, 0x3B, 0x01, 0xE0, 0x3E, 0x00, 0xE0, 0x3C, 0x00, 0xE0, 0x38, 0x00, 0x70, 0x38, 0x00, + 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x18, 0x00, 0x70, 0x1C, 0x00, 0x70, + 0x1C, 0x00, 0x60, 0x0C, 0x00, 0xE0, 0x0E, 0x00, 0xC0, 0x07, 0x01, 0x80, 0x03, 0x83, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 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, + 0xC0, 0x0C, 0x00, 0xC0, 0x08, 0x00, 0x80, 0x18, 0x01, 0x00, 0x10, 0x01, 0x00, 0x10, 0x02, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 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, 0x87, 0x00, 0x06, 0x01, + 0x80, 0x0E, 0x01, 0xC0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1E, 0x00, 0xE0, 0x1E, 0x00, 0xC0, 0x0F, 0x01, 0xC0, 0x0F, 0x81, 0x80, 0x07, 0xE3, 0x00, 0x01, + 0xFE, 0x00, 0x01, 0xFC, 0x00, 0x07, 0x3F, 0x00, 0x0E, 0x0F, 0x80, 0x0C, 0x07, 0x80, 0x1C, 0x03, + 0xC0, 0x38, 0x01, 0xE0, 0x38, 0x01, 0xE0, 0x38, 0x00, 0xE0, 0x38, 0x00, 0xE0, 0x38, 0x00, 0xE0, + 0x38, 0x00, 0xE0, 0x18, 0x00, 0xC0, 0x1C, 0x01, 0xC0, 0x0E, 0x01, 0x80, 0x07, 0x07, 0x00, 0x01, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"8",24*/ + + 0x00, 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, 0x07, 0x00, 0x06, 0x01, + 0x80, 0x0C, 0x00, 0xC0, 0x1C, 0x00, 0xC0, 0x18, 0x00, 0xE0, 0x38, 0x00, 0x60, 0x38, 0x00, 0x60, + 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0xF0, 0x3C, + 0x00, 0xF0, 0x1C, 0x01, 0xF0, 0x1E, 0x03, 0x70, 0x0F, 0x06, 0x70, 0x07, 0xFC, 0x70, 0x01, 0xF8, + 0x70, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, + 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0x80, 0x0E, 0x03, 0x00, 0x0E, 0x07, 0x00, 0x06, 0x0C, 0x00, 0x01, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, /*";",27*/ + + 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, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, + 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xF0, 0x7F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x7F, 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, /*"=",29*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, + 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*">",30*/ + + 0x00, 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, 0x03, + 0xC0, 0x0C, 0x00, 0xE0, 0x18, 0x00, 0xE0, 0x30, 0x00, 0x70, 0x30, 0x00, 0x70, 0x38, 0x00, 0x70, + 0x3C, 0x00, 0x70, 0x3C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, + 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"?",31*/ + + 0x00, 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, 0xC1, 0x80, 0x03, 0x80, + 0xC0, 0x03, 0x00, 0x60, 0x06, 0x00, 0x30, 0x0C, 0x0D, 0xB0, 0x0C, 0x1B, 0xB0, 0x1C, 0x33, 0x98, + 0x1C, 0x73, 0x18, 0x18, 0x63, 0x18, 0x38, 0xE3, 0x18, 0x38, 0xE3, 0x18, 0x38, 0xC3, 0x18, 0x39, + 0xC3, 0x18, 0x39, 0xC3, 0x18, 0x39, 0xC2, 0x18, 0x39, 0xC6, 0x18, 0x39, 0xC6, 0x30, 0x39, 0xC6, + 0x30, 0x39, 0xC6, 0x30, 0x19, 0xCE, 0x60, 0x1C, 0xF7, 0xC0, 0x1C, 0x63, 0x80, 0x0C, 0x00, 0x08, + 0x0E, 0x00, 0x10, 0x07, 0x00, 0x30, 0x07, 0x00, 0x60, 0x03, 0xC1, 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, /*"@",32*/ + + 0x00, 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, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x98, 0x00, 0x00, 0x98, 0x00, 0x01, 0x9C, 0x00, + 0x01, 0x9C, 0x00, 0x01, 0x0C, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x0E, 0x00, 0x03, 0x0E, 0x00, 0x02, + 0x06, 0x00, 0x02, 0x06, 0x00, 0x06, 0x07, 0x00, 0x06, 0x07, 0x00, 0x04, 0x07, 0x00, 0x07, 0xFF, + 0x00, 0x0C, 0x03, 0x80, 0x0C, 0x03, 0x80, 0x08, 0x03, 0x80, 0x08, 0x01, 0x80, 0x18, 0x01, 0xC0, + 0x18, 0x01, 0xC0, 0x10, 0x01, 0xC0, 0x10, 0x01, 0xC0, 0x30, 0x00, 0xE0, 0x38, 0x01, 0xE0, 0xFC, + 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 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, 0x0E, 0x07, 0x80, 0x0E, 0x01, + 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, + 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0x80, 0x0E, 0x07, 0x00, 0x0F, + 0xFC, 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, + 0x60, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0x80, 0x7F, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 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, 0x20, 0x01, 0x83, 0xE0, 0x03, 0x00, + 0xE0, 0x06, 0x00, 0x60, 0x0C, 0x00, 0x60, 0x1C, 0x00, 0x30, 0x18, 0x00, 0x30, 0x38, 0x00, 0x10, + 0x38, 0x00, 0x00, 0x30, 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, 0x38, 0x00, 0x10, 0x38, 0x00, 0x10, 0x38, 0x00, 0x20, + 0x1C, 0x00, 0x20, 0x1C, 0x00, 0x40, 0x0E, 0x00, 0xC0, 0x07, 0x83, 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, /*"C",35*/ + + 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, 0xF0, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x03, + 0x00, 0x0E, 0x01, 0x80, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, + 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, + 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, + 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0x80, 0x0E, 0x07, 0x00, 0x0E, 0x1C, 0x00, 0x7F, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 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, 0xC0, 0x0E, 0x01, 0xE0, 0x0E, 0x00, + 0x60, 0x0E, 0x00, 0x20, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x0E, 0x01, 0x00, 0x0E, 0x01, 0x00, 0x0E, 0x03, 0x00, 0x0F, + 0xFF, 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x01, 0x00, 0x0E, 0x01, 0x00, 0x0E, 0x01, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x08, + 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x10, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xF0, 0x7F, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 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, 0xFF, 0xE0, 0x0E, 0x01, 0xE0, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x10, 0x0E, 0x00, 0x18, 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x0E, + 0x01, 0x80, 0x0F, 0xFF, 0x80, 0x0E, 0x01, 0x80, 0x0E, 0x01, 0x80, 0x0E, 0x00, 0x80, 0x0E, 0x00, + 0x80, 0x0E, 0x00, 0x80, 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, 0x7F, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x80, 0x03, 0x87, 0x80, 0x07, 0x03, + 0x80, 0x0E, 0x01, 0x80, 0x0C, 0x00, 0x80, 0x1C, 0x00, 0xC0, 0x18, 0x00, 0x40, 0x38, 0x00, 0x40, + 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x0F, 0xF8, 0x70, 0x03, + 0xC0, 0x70, 0x01, 0xC0, 0x30, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, + 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x0C, 0x01, 0xC0, 0x06, 0x03, 0xC0, 0x03, 0x86, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"G",39*/ + + 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, 0x03, 0xF8, 0x1C, 0x00, 0xE0, 0x1C, 0x00, + 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, + 0x00, 0xE0, 0x1F, 0xFF, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, + 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x7F, + 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 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, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x0F, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 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, 0xF8, 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, 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, 0x18, 0x0E, 0x00, 0x3C, 0x0C, 0x00, 0x3C, 0x1C, 0x00, 0x3C, 0x18, 0x00, 0x1C, 0x30, + 0x00, 0x0F, 0xC0, 0x00, /*"J",42*/ + + 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, 0xC7, 0xF0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, + 0x80, 0x0E, 0x03, 0x00, 0x0E, 0x02, 0x00, 0x0E, 0x06, 0x00, 0x0E, 0x04, 0x00, 0x0E, 0x08, 0x00, + 0x0E, 0x18, 0x00, 0x0E, 0x10, 0x00, 0x0E, 0x20, 0x00, 0x0E, 0x20, 0x00, 0x0E, 0x70, 0x00, 0x0E, + 0xF0, 0x00, 0x0E, 0xB8, 0x00, 0x0F, 0x38, 0x00, 0x0F, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x0C, + 0x00, 0x0E, 0x0E, 0x00, 0x0E, 0x06, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x03, 0x80, + 0x0E, 0x03, 0x80, 0x0E, 0x01, 0x80, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x7F, + 0xC3, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 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, 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, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x08, + 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x10, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0xF0, 0x7F, + 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 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, 0x01, 0xF8, 0x1C, 0x01, 0xE0, 0x1C, 0x01, + 0xE0, 0x1C, 0x01, 0xE0, 0x1E, 0x01, 0xE0, 0x1E, 0x02, 0xE0, 0x1E, 0x02, 0xE0, 0x1E, 0x02, 0xE0, + 0x16, 0x02, 0xE0, 0x17, 0x06, 0xE0, 0x17, 0x04, 0xE0, 0x17, 0x04, 0xE0, 0x17, 0x04, 0xE0, 0x13, + 0x0C, 0xE0, 0x13, 0x88, 0xE0, 0x13, 0x88, 0xE0, 0x13, 0x88, 0xE0, 0x11, 0x88, 0xE0, 0x11, 0x98, + 0xE0, 0x11, 0xD0, 0xE0, 0x11, 0xD0, 0xE0, 0x11, 0xD0, 0xE0, 0x10, 0xF0, 0xE0, 0x10, 0xF0, 0xE0, + 0x10, 0xE0, 0xE0, 0x10, 0xE0, 0xE0, 0x10, 0x60, 0xE0, 0x10, 0x60, 0xE0, 0x10, 0x60, 0xE0, 0x7C, + 0x43, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 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, 0x01, 0xFC, 0x1C, 0x00, 0x20, 0x1E, 0x00, + 0x20, 0x1E, 0x00, 0x20, 0x1F, 0x00, 0x20, 0x17, 0x00, 0x20, 0x17, 0x80, 0x20, 0x13, 0x80, 0x20, + 0x13, 0xC0, 0x20, 0x11, 0xE0, 0x20, 0x10, 0xE0, 0x20, 0x10, 0xF0, 0x20, 0x10, 0x70, 0x20, 0x10, + 0x78, 0x20, 0x10, 0x38, 0x20, 0x10, 0x3C, 0x20, 0x10, 0x1C, 0x20, 0x10, 0x1E, 0x20, 0x10, 0x0E, + 0x20, 0x10, 0x0F, 0x20, 0x10, 0x07, 0x20, 0x10, 0x07, 0xA0, 0x10, 0x03, 0xE0, 0x10, 0x01, 0xE0, + 0x10, 0x01, 0xE0, 0x10, 0x00, 0xE0, 0x10, 0x00, 0xE0, 0x10, 0x00, 0x60, 0x10, 0x00, 0x60, 0xFE, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 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, 0x83, 0x00, 0x03, 0x01, + 0x80, 0x06, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x0C, 0x00, 0x60, 0x1C, 0x00, 0x60, 0x1C, 0x00, 0x70, + 0x18, 0x00, 0x30, 0x18, 0x00, 0x30, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, + 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, + 0x38, 0x38, 0x00, 0x38, 0x18, 0x00, 0x30, 0x1C, 0x00, 0x30, 0x1C, 0x00, 0x70, 0x0C, 0x00, 0x70, + 0x0C, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x06, 0x00, 0xC0, 0x03, 0x01, 0x80, 0x01, 0x83, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"O",47*/ + + 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, 0x0E, 0x03, 0x80, 0x0E, 0x01, + 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, + 0x01, 0xC0, 0x0E, 0x07, 0x80, 0x0F, 0xFE, 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, 0x7F, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 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, 0x83, 0x00, 0x06, 0x01, + 0x80, 0x0E, 0x00, 0xC0, 0x1C, 0x00, 0xE0, 0x18, 0x00, 0x60, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, + 0x38, 0x00, 0x30, 0x30, 0x00, 0x30, 0x70, 0x00, 0x38, 0x70, 0x00, 0x38, 0x70, 0x00, 0x38, 0x70, + 0x00, 0x38, 0x70, 0x00, 0x38, 0x70, 0x00, 0x38, 0x70, 0x00, 0x38, 0x70, 0x00, 0x38, 0x70, 0x00, + 0x38, 0x70, 0x00, 0x38, 0x70, 0x00, 0x38, 0x31, 0xF0, 0x30, 0x3B, 0xF8, 0x70, 0x3B, 0x1C, 0x70, + 0x1E, 0x0C, 0x60, 0x1C, 0x0E, 0x60, 0x0E, 0x0E, 0xC0, 0x06, 0x07, 0x80, 0x03, 0x87, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x07, 0x90, 0x00, 0x03, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"Q",49*/ + + 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, 0x0E, 0x07, 0x80, 0x0E, 0x03, + 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, + 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0x80, 0x0E, + 0x07, 0x00, 0x0F, 0xFC, 0x00, 0x0E, 0x18, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x0E, + 0x00, 0x0E, 0x0E, 0x00, 0x0E, 0x06, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x03, 0x80, + 0x0E, 0x03, 0x80, 0x0E, 0x01, 0x80, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x7F, + 0xC0, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 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, 0x07, 0x07, 0x80, 0x0C, 0x03, + 0xC0, 0x1C, 0x01, 0xC0, 0x18, 0x00, 0xC0, 0x38, 0x00, 0xC0, 0x38, 0x00, 0x40, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x07, + 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x07, 0xC0, 0x00, 0x03, + 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0xE0, 0x20, 0x00, 0xE0, 0x20, 0x00, 0xE0, 0x30, 0x00, 0xE0, + 0x10, 0x00, 0xE0, 0x18, 0x00, 0xC0, 0x18, 0x01, 0xC0, 0x1C, 0x03, 0x80, 0x1F, 0x07, 0x00, 0x10, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 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, 0xE0, 0x38, 0x70, 0xE0, 0x30, 0x70, + 0x60, 0x20, 0x70, 0x20, 0x20, 0x70, 0x30, 0x60, 0x70, 0x10, 0x40, 0x70, 0x10, 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, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"T",52*/ + + 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, 0x03, 0xF8, 0x1C, 0x00, 0x40, 0x1C, 0x00, + 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, + 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, + 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, + 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x40, + 0x1C, 0x00, 0x40, 0x1C, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x0E, 0x01, 0x00, 0x03, 0x86, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 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, 0x01, 0xF8, 0x1E, 0x00, 0x60, 0x0C, 0x00, + 0x40, 0x0E, 0x00, 0x40, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0x80, 0x07, 0x00, 0x80, + 0x07, 0x01, 0x80, 0x07, 0x01, 0x00, 0x07, 0x01, 0x00, 0x03, 0x01, 0x00, 0x03, 0x83, 0x00, 0x03, + 0x82, 0x00, 0x03, 0x82, 0x00, 0x01, 0x82, 0x00, 0x01, 0xC6, 0x00, 0x01, 0xC4, 0x00, 0x01, 0xC4, + 0x00, 0x00, 0xC4, 0x00, 0x00, 0xEC, 0x00, 0x00, 0xE8, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x68, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"V",54*/ + + 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, 0xFC, 0x7C, 0x30, 0x38, 0x30, 0x30, 0x30, + 0x10, 0x30, 0x38, 0x30, 0x38, 0x38, 0x30, 0x38, 0x38, 0x20, 0x38, 0x38, 0x20, 0x18, 0x38, 0x20, + 0x18, 0x38, 0x20, 0x18, 0x38, 0x60, 0x18, 0x3C, 0x40, 0x1C, 0x3C, 0x40, 0x1C, 0x7C, 0x40, 0x1C, + 0x5C, 0x40, 0x0C, 0x4C, 0x40, 0x0C, 0x4C, 0xC0, 0x0C, 0x4C, 0x80, 0x0C, 0xCE, 0x80, 0x0E, 0x8E, + 0x80, 0x0E, 0x8E, 0x80, 0x06, 0x86, 0x80, 0x06, 0x87, 0x80, 0x07, 0x87, 0x00, 0x07, 0x07, 0x00, + 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x03, 0x03, 0x00, 0x02, 0x02, 0x00, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 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, 0x87, 0xF0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, + 0x80, 0x06, 0x01, 0x80, 0x07, 0x01, 0x00, 0x07, 0x03, 0x00, 0x03, 0x82, 0x00, 0x03, 0x86, 0x00, + 0x01, 0xC6, 0x00, 0x01, 0xCC, 0x00, 0x00, 0xEC, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x5C, 0x00, 0x00, 0xDC, + 0x00, 0x00, 0x8E, 0x00, 0x01, 0x8E, 0x00, 0x01, 0x06, 0x00, 0x03, 0x07, 0x00, 0x03, 0x03, 0x00, + 0x02, 0x03, 0x80, 0x06, 0x03, 0x80, 0x04, 0x01, 0xC0, 0x0C, 0x01, 0xC0, 0x1C, 0x01, 0xE0, 0x7F, + 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 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, 0x83, 0xF8, 0x1C, 0x00, 0xE0, 0x1C, 0x00, + 0x40, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x07, 0x01, 0x00, 0x07, 0x01, 0x00, + 0x03, 0x03, 0x00, 0x03, 0x82, 0x00, 0x03, 0x82, 0x00, 0x01, 0xC4, 0x00, 0x01, 0xC4, 0x00, 0x01, + 0xCC, 0x00, 0x00, 0xE8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF0, 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, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"Y",57*/ + + 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, 0xF0, 0x0F, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x0C, 0x01, 0xC0, 0x18, 0x01, 0xC0, 0x10, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, + 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x10, + 0x07, 0x00, 0x30, 0x0E, 0x00, 0x20, 0x0E, 0x00, 0x60, 0x1C, 0x00, 0xE0, 0x1C, 0x01, 0xE0, 0x3F, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x7F, 0xE0, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x1F, 0xF8, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x1F, 0xF8, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x00, 0x01, + 0xC6, 0x00, 0x03, 0x03, 0x00, 0x04, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFC, /*"_",63*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, + 0x70, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x07, 0x07, 0x00, 0x0C, 0x03, 0x80, 0x1C, + 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x0F, 0xC0, 0x00, 0xF9, + 0xC0, 0x07, 0x81, 0xC0, 0x0E, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x38, 0x01, 0xC0, + 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC4, 0x38, 0x01, 0xC4, 0x1C, 0x03, 0xC4, 0x0E, 0x0D, 0xC8, 0x07, + 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x7E, 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, 0x1F, 0x00, 0x0E, 0x61, 0x80, 0x0E, 0x80, 0xC0, 0x0F, + 0x00, 0xE0, 0x0F, 0x00, 0xE0, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0x60, 0x0E, 0x00, 0xE0, 0x0F, 0x00, 0xC0, 0x0F, 0x01, 0xC0, 0x0C, 0x83, 0x80, 0x08, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC3, 0x00, 0x03, 0x81, 0x80, 0x07, + 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x00, 0x00, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x0E, 0x00, 0x20, 0x0E, 0x00, 0x40, 0x06, 0x00, 0x40, 0x07, 0x00, 0x80, 0x01, 0xC1, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 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, 0x0F, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, + 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0xF9, 0xC0, 0x03, 0x85, 0xC0, 0x07, 0x03, 0xC0, 0x06, + 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, + 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, + 0x0C, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0xC0, 0x07, 0x07, 0xC0, 0x03, 0x8D, 0xF8, 0x00, + 0xF1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x87, 0x00, 0x03, 0x03, 0x80, 0x06, + 0x01, 0xC0, 0x0E, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, + 0xE0, 0x1F, 0xFF, 0xE0, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x0C, 0x00, 0x40, 0x0E, 0x00, 0x40, 0x06, 0x00, 0x80, 0x07, 0x01, 0x00, 0x03, 0xC3, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"e",69*/ + + 0x00, 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, 0x18, 0x30, 0x00, 0x70, + 0x38, 0x00, 0x60, 0x38, 0x00, 0xE0, 0x38, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x1F, 0xFF, 0xC0, 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, 0xE0, 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, 0xE0, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x38, 0x03, 0x07, 0xF8, 0x06, 0x03, 0x98, 0x0E, + 0x03, 0x80, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, + 0xC0, 0x0E, 0x01, 0x80, 0x06, 0x03, 0x80, 0x03, 0x07, 0x00, 0x0E, 0xFC, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x07, 0xFF, 0x80, 0x0E, 0x3F, 0xE0, 0x1C, 0x00, 0xF0, 0x38, + 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x1C, 0x00, 0xE0, 0x0F, 0x03, + 0xC0, 0x01, 0xFE, 0x00, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3E, 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, 0x3E, 0x00, 0x0E, 0x43, 0x80, 0x0F, 0x81, 0x80, 0x0F, + 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, + 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, + 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x3F, + 0x87, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 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, 0x7C, 0x00, 0x00, 0x7C, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x07, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 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, 0x07, 0xC0, 0x00, 0x07, + 0xC0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x7F, 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, 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, 0x00, + 0x03, 0x80, 0x00, 0x03, 0x80, 0x1C, 0x03, 0x00, 0x1C, 0x07, 0x00, 0x1C, 0x06, 0x00, 0x0E, 0x1C, + 0x00, 0x07, 0xF0, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x7E, 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, 0x07, 0xF0, 0x0E, 0x01, 0x80, 0x0E, 0x03, 0x00, 0x0E, + 0x06, 0x00, 0x0E, 0x04, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x18, 0x00, 0x0E, 0x30, 0x00, 0x0E, 0x78, + 0x00, 0x0E, 0xDC, 0x00, 0x0F, 0x9C, 0x00, 0x0F, 0x0E, 0x00, 0x0E, 0x06, 0x00, 0x0E, 0x07, 0x00, + 0x0E, 0x03, 0x80, 0x0E, 0x03, 0x80, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x3F, + 0x83, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x0F, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF9, 0xF1, 0xE0, 0x3A, 0x3E, 0x30, 0x3C, 0x3C, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0xFE, + 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3E, 0x3E, 0x00, 0x0E, 0x43, 0x80, 0x0E, 0x83, 0x80, 0x0F, + 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, + 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, + 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x3F, + 0x87, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x87, 0x00, 0x07, 0x01, 0x80, 0x0E, + 0x01, 0xC0, 0x0C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x18, 0x00, 0x60, 0x38, 0x00, 0x70, 0x38, 0x00, + 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x18, 0x00, 0x70, + 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x0E, 0x00, 0xC0, 0x06, 0x01, 0x80, 0x03, 0x87, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3E, 0x00, 0x7E, 0x43, 0x80, 0x0E, 0x81, 0xC0, 0x0F, + 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x00, 0xC0, 0x0F, 0x01, 0xC0, 0x0E, 0xC3, 0x80, 0x0E, + 0x3E, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x7F, 0xC0, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xF8, 0x40, 0x03, 0x04, 0xC0, 0x06, 0x03, 0xC0, 0x0C, + 0x03, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, + 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, 0x38, 0x01, 0xC0, + 0x18, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x03, 0xC0, 0x0E, 0x03, 0xC0, 0x07, 0x0D, 0xC0, 0x01, + 0xF1, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x0F, 0xF8, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x80, 0x00, 0x7F, 0x83, 0xE0, 0x03, 0x8C, 0x70, 0x03, 0x98, 0x70, 0x03, + 0xB0, 0x70, 0x03, 0xA0, 0x70, 0x03, 0xC0, 0x00, 0x03, 0xC0, 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, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x7F, + 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0xC3, 0xC0, 0x03, 0x81, 0xC0, 0x07, + 0x00, 0xC0, 0x07, 0x00, 0x40, 0x07, 0x00, 0x40, 0x07, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xC0, 0x00, 0x03, 0xE0, 0x08, 0x01, 0xE0, + 0x08, 0x00, 0xE0, 0x0C, 0x00, 0xE0, 0x0C, 0x00, 0xE0, 0x0E, 0x01, 0xC0, 0x0F, 0x83, 0x80, 0x08, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0xE0, 0x00, 0x03, 0xE0, 0x00, 0x1F, 0xFF, 0xC0, 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, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x20, 0x00, 0xE0, 0x20, 0x00, 0x60, 0x40, 0x00, 0x70, 0x80, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x40, 0x7E, 0x0F, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, + 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, + 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, + 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0xC0, 0x07, 0x03, 0xC0, 0x07, 0x8D, 0xF8, 0x01, + 0xF1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x83, 0xF0, 0x0E, 0x00, 0xC0, 0x06, 0x00, 0x80, 0x07, + 0x00, 0x80, 0x07, 0x01, 0x80, 0x03, 0x01, 0x00, 0x03, 0x01, 0x00, 0x03, 0x83, 0x00, 0x01, 0x82, + 0x00, 0x01, 0x82, 0x00, 0x01, 0xC6, 0x00, 0x00, 0xC4, 0x00, 0x00, 0xC4, 0x00, 0x00, 0xEC, 0x00, + 0x00, 0x68, 0x00, 0x00, 0x68, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFC, 0xFC, 0x38, 0x70, 0x30, 0x38, 0x30, 0x30, 0x38, + 0x30, 0x20, 0x18, 0x38, 0x20, 0x18, 0x38, 0x60, 0x1C, 0x38, 0x40, 0x1C, 0x78, 0x40, 0x0C, 0x5C, + 0x40, 0x0C, 0x4C, 0x40, 0x0E, 0xCC, 0x80, 0x0E, 0xCC, 0x80, 0x06, 0x8C, 0x80, 0x07, 0x8E, 0x80, + 0x07, 0x87, 0x00, 0x07, 0x87, 0x00, 0x03, 0x07, 0x00, 0x03, 0x07, 0x00, 0x03, 0x02, 0x00, 0x03, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC7, 0xE0, 0x07, 0x81, 0x80, 0x03, 0x81, 0x00, 0x01, + 0x83, 0x00, 0x01, 0xC2, 0x00, 0x00, 0xC4, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x8E, 0x00, + 0x01, 0x86, 0x00, 0x01, 0x03, 0x00, 0x03, 0x03, 0x80, 0x06, 0x01, 0x80, 0x0E, 0x01, 0xC0, 0x3F, + 0x87, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x87, 0xF0, 0x0E, 0x01, 0xC0, 0x06, 0x01, 0x80, 0x06, + 0x01, 0x00, 0x07, 0x01, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x03, 0x82, 0x00, 0x01, 0x86, + 0x00, 0x01, 0x86, 0x00, 0x00, 0xC4, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x68, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x1C, 0xC0, 0x00, 0x1F, 0x80, + 0x00, 0x0F, 0x00, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC0, 0x0E, 0x01, 0xC0, 0x18, 0x03, 0x80, 0x18, + 0x07, 0x00, 0x10, 0x07, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x20, + 0x03, 0x80, 0x20, 0x07, 0x00, 0x60, 0x07, 0x00, 0x40, 0x0E, 0x00, 0xC0, 0x1C, 0x01, 0xC0, 0x1F, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x03, 0x80, 0x00, + 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"{",91*/ + + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x18, 0xF0, 0x08, 0x10, 0x78, 0x08, 0x20, + 0x3C, 0x10, 0x20, 0x1E, 0x30, 0x00, 0x0F, 0xE0, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_44 = { + .bitmap = bitmap, + .width = 22, + .height = 44, +}; + +#endif diff --git a/components/lua_modules/esp_painter/font/basic_font_48.c b/components/lua_modules/esp_painter/font/basic_font_48.c new file mode 100644 index 0000000..9c51beb --- /dev/null +++ b/components/lua_modules/esp_painter/font/basic_font_48.c @@ -0,0 +1,972 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "sdkconfig.h" + +#include "esp_painter_font.h" + +#if CONFIG_ESP_PAINTER_BASIC_FONT_48 + +static const uint8_t bitmap[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" ",0*/ + + 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, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 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, 0x38, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 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, /*"!",1*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0xF0, 0xF0, 0x01, + 0xF1, 0xF0, 0x01, 0xF1, 0xF0, 0x03, 0xE3, 0xE0, 0x03, 0xC3, 0xC0, 0x07, 0x87, 0x80, 0x07, 0x07, + 0x00, 0x0E, 0x0E, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 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, /*""",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, 0x01, 0x80, 0x60, 0x01, 0x80, 0x60, 0x01, 0x80, + 0x60, 0x01, 0x00, 0x40, 0x01, 0x00, 0x40, 0x01, 0x00, 0x40, 0x01, 0x00, 0x40, 0x01, 0x00, 0x40, + 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x03, + 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x03, 0x00, + 0xC0, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, + 0x3F, 0xFF, 0xFC, 0x06, 0x01, 0x80, 0x06, 0x01, 0x80, 0x06, 0x01, 0x80, 0x06, 0x01, 0x80, 0x06, + 0x01, 0x80, 0x06, 0x01, 0x80, 0x06, 0x01, 0x80, 0x06, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"#",3*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xD9, 0xC0, 0x03, 0x18, + 0xE0, 0x07, 0x18, 0x60, 0x06, 0x18, 0x70, 0x0E, 0x18, 0x70, 0x0E, 0x18, 0xF0, 0x0E, 0x18, 0xF0, + 0x0E, 0x18, 0xE0, 0x0F, 0x18, 0x00, 0x07, 0x98, 0x00, 0x07, 0xD8, 0x00, 0x03, 0xF8, 0x00, 0x01, + 0xF8, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x1F, + 0xC0, 0x00, 0x1B, 0xE0, 0x00, 0x19, 0xE0, 0x00, 0x18, 0xF0, 0x00, 0x18, 0xF0, 0x0E, 0x18, 0x70, + 0x1E, 0x18, 0x70, 0x1E, 0x18, 0x70, 0x1E, 0x18, 0x70, 0x1C, 0x18, 0x70, 0x0C, 0x18, 0x60, 0x0C, + 0x18, 0xE0, 0x06, 0x18, 0xC0, 0x03, 0x1B, 0x80, 0x00, 0xFE, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"$",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, 0x0F, 0x00, 0x20, 0x18, 0x80, 0x60, 0x30, 0xC0, + 0x40, 0x20, 0x40, 0xC0, 0x60, 0x60, 0x80, 0x60, 0x60, 0x80, 0x60, 0x61, 0x80, 0x60, 0x61, 0x00, + 0x60, 0x63, 0x00, 0x60, 0x62, 0x00, 0x60, 0x62, 0x00, 0x60, 0x66, 0x00, 0x60, 0x64, 0x00, 0x30, + 0x4C, 0x00, 0x30, 0xC8, 0x00, 0x19, 0x88, 0x00, 0x0F, 0x18, 0xF0, 0x00, 0x11, 0x98, 0x00, 0x33, + 0x0C, 0x00, 0x23, 0x0C, 0x00, 0x22, 0x04, 0x00, 0x66, 0x06, 0x00, 0x46, 0x06, 0x00, 0x46, 0x06, + 0x00, 0x86, 0x06, 0x00, 0x86, 0x06, 0x01, 0x86, 0x06, 0x01, 0x06, 0x06, 0x01, 0x06, 0x06, 0x02, + 0x02, 0x04, 0x02, 0x03, 0x0C, 0x06, 0x01, 0x98, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"%",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, 0x01, 0xF0, 0x00, 0x03, 0x38, 0x00, 0x07, 0x18, + 0x00, 0x06, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, 0x0E, 0x1C, 0x00, + 0x0E, 0x1C, 0x00, 0x0E, 0x18, 0x00, 0x0E, 0x38, 0x00, 0x0F, 0x30, 0x00, 0x07, 0x70, 0x00, 0x07, + 0x60, 0x00, 0x07, 0x80, 0x00, 0x07, 0x87, 0xF8, 0x0B, 0x80, 0xE0, 0x1B, 0xC0, 0xC0, 0x39, 0xC0, + 0xC0, 0x31, 0xE0, 0xC0, 0x31, 0xE0, 0xC0, 0x70, 0xF0, 0x80, 0x70, 0xF0, 0x80, 0x70, 0x79, 0x80, + 0x70, 0x39, 0x80, 0x70, 0x3D, 0x00, 0x70, 0x1F, 0x00, 0x78, 0x0E, 0x00, 0x38, 0x0F, 0x02, 0x3C, + 0x0F, 0x86, 0x1E, 0x1B, 0xC4, 0x0F, 0xF1, 0xFC, 0x07, 0xC0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"&",6*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, + 0x80, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"'",7*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"(",8*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*")",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, 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, 0x30, 0x38, 0x38, 0x7C, 0x38, 0x7C, 0x7E, 0x10, 0xFC, 0x3F, 0x11, 0xF8, 0x0F, + 0x93, 0xE0, 0x01, 0xD7, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x01, 0xD7, 0x00, 0x0F, 0x93, + 0xE0, 0x3F, 0x11, 0xF8, 0x7E, 0x10, 0xFC, 0x7C, 0x38, 0x7C, 0x70, 0x38, 0x1C, 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, /*"*",10*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 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, /*"+",11*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0x1F, 0x00, 0x00, 0x1F, + 0x80, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, /*",",12*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFC, 0x3F, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"-",13*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0x1F, 0x80, 0x00, 0x1F, + 0x80, 0x00, 0x1F, 0x80, 0x00, 0x1F, 0x80, 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, /*".",14*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"/",15*/ + + 0x00, 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, 0xC3, 0x80, 0x03, 0x80, + 0xC0, 0x03, 0x00, 0xE0, 0x06, 0x00, 0x60, 0x0E, 0x00, 0x70, 0x0C, 0x00, 0x30, 0x1C, 0x00, 0x38, + 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x18, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, + 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, + 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x18, 0x00, 0x18, 0x1C, 0x00, 0x38, + 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x0C, 0x00, 0x30, 0x0E, 0x00, 0x70, 0x06, 0x00, 0x60, 0x03, + 0x00, 0xE0, 0x03, 0x80, 0xC0, 0x00, 0xC3, 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, /*"0",16*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, + 0x00, 0x03, 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, 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, 0x3E, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",17*/ + + 0x00, 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, 0x01, 0x83, 0xC0, 0x06, 0x00, + 0xE0, 0x0C, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, + 0x1E, 0x00, 0x38, 0x1E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, + 0x03, 0x80, 0x00, 0x07, 0x00, 0x08, 0x06, 0x00, 0x08, 0x0C, 0x00, 0x18, 0x1C, 0x00, 0x10, 0x38, + 0x00, 0x70, 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"2",18*/ + + 0x00, 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, 0x83, 0x80, 0x02, 0x01, + 0xC0, 0x04, 0x00, 0xE0, 0x0C, 0x00, 0xE0, 0x0C, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x06, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00, + 0x01, 0x80, 0x00, 0x07, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x0C, 0x00, 0x38, 0x1E, 0x00, 0x38, 0x1E, 0x00, 0x38, 0x1E, 0x00, 0x30, 0x1C, 0x00, 0x70, 0x0C, + 0x00, 0x60, 0x06, 0x00, 0xC0, 0x03, 0x03, 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, /*"3",19*/ + + 0x00, 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, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, + 0x80, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0B, 0x80, 0x00, 0x13, 0x80, 0x00, 0x13, 0x80, + 0x00, 0x23, 0x80, 0x00, 0x63, 0x80, 0x00, 0x43, 0x80, 0x00, 0xC3, 0x80, 0x00, 0x83, 0x80, 0x01, + 0x03, 0x80, 0x03, 0x03, 0x80, 0x02, 0x03, 0x80, 0x06, 0x03, 0x80, 0x04, 0x03, 0x80, 0x0C, 0x03, + 0x80, 0x18, 0x03, 0x80, 0x18, 0x03, 0x80, 0x30, 0x03, 0x80, 0x3F, 0xFF, 0xFC, 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, 0x07, 0xC0, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"4",20*/ + + 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, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, + 0xF0, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x7F, 0x00, 0x0C, + 0xFF, 0x80, 0x0D, 0x81, 0xE0, 0x0F, 0x00, 0xE0, 0x0E, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x0C, 0x00, 0x38, + 0x1E, 0x00, 0x38, 0x1E, 0x00, 0x38, 0x1E, 0x00, 0x30, 0x1C, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x0C, + 0x00, 0xE0, 0x06, 0x00, 0xC0, 0x03, 0x83, 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, /*"5",21*/ + + 0x00, 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, 0x80, 0x00, 0xE0, 0x40, 0x01, 0x80, + 0x60, 0x03, 0x00, 0x70, 0x06, 0x00, 0x70, 0x06, 0x00, 0x70, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x3F, 0x00, 0x38, + 0xFF, 0xC0, 0x39, 0xC1, 0xE0, 0x3B, 0x00, 0x70, 0x3E, 0x00, 0x38, 0x3C, 0x00, 0x38, 0x3C, 0x00, + 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, + 0x18, 0x00, 0x1C, 0x1C, 0x00, 0x1C, 0x1C, 0x00, 0x18, 0x0C, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x07, + 0x00, 0x30, 0x03, 0x80, 0x60, 0x01, 0xC1, 0xC0, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"6",22*/ + + 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, 0x0F, 0xFF, 0xF8, 0x0F, 0xFF, + 0xF0, 0x0E, 0x00, 0x30, 0x0C, 0x00, 0x20, 0x18, 0x00, 0x40, 0x18, 0x00, 0xC0, 0x10, 0x00, 0x80, + 0x00, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",23*/ + + 0x00, 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, 0x81, 0xC0, 0x07, 0x00, + 0xE0, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, + 0x1C, 0x00, 0x38, 0x1E, 0x00, 0x38, 0x1E, 0x00, 0x30, 0x0F, 0x00, 0x70, 0x07, 0xC0, 0xE0, 0x07, + 0xE1, 0xC0, 0x01, 0xFB, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xBF, 0x00, 0x07, 0x0F, 0xC0, 0x0E, 0x03, + 0xE0, 0x0C, 0x01, 0xE0, 0x1C, 0x00, 0xF0, 0x1C, 0x00, 0x70, 0x38, 0x00, 0x78, 0x38, 0x00, 0x38, + 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x18, 0x00, 0x30, 0x1C, 0x00, 0x70, 0x0C, + 0x00, 0x60, 0x06, 0x00, 0xC0, 0x03, 0x81, 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, /*"8",24*/ + + 0x00, 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, 0x83, 0x00, 0x06, 0x01, + 0x80, 0x0E, 0x00, 0xC0, 0x1C, 0x00, 0x60, 0x1C, 0x00, 0x60, 0x18, 0x00, 0x70, 0x38, 0x00, 0x30, + 0x38, 0x00, 0x30, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, 0x00, 0x38, 0x38, + 0x00, 0x38, 0x3C, 0x00, 0x78, 0x1C, 0x00, 0xF8, 0x1C, 0x00, 0xB8, 0x1E, 0x01, 0xB8, 0x0F, 0x87, + 0x38, 0x07, 0xFE, 0x38, 0x01, 0xF8, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, + 0x03, 0x80, 0x0E, 0x07, 0x00, 0x06, 0x0E, 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, /*"9",25*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x7C, 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, 0x38, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 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, /*":",26*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*";",27*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x70, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"<",28*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFC, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0xFF, 0xFC, 0x3F, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"=",29*/ + + 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, 0x1C, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x60, 0x00, 0x00, 0xC0, 0x00, 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 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, /*">",30*/ + + 0x00, 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, 0x03, + 0xC0, 0x0C, 0x01, 0xE0, 0x18, 0x00, 0xF0, 0x10, 0x00, 0x70, 0x30, 0x00, 0x78, 0x30, 0x00, 0x78, + 0x3C, 0x00, 0x78, 0x3E, 0x00, 0x78, 0x3E, 0x00, 0x78, 0x1E, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 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, /*"?",31*/ + + 0x00, 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, 0xE0, 0xC0, 0x01, 0x80, + 0x60, 0x03, 0x00, 0x10, 0x07, 0x00, 0x18, 0x06, 0x00, 0x0C, 0x0C, 0x07, 0x6C, 0x0C, 0x0C, 0xEC, + 0x1C, 0x1C, 0xE6, 0x1C, 0x18, 0xE6, 0x18, 0x38, 0xC6, 0x38, 0x30, 0xC6, 0x38, 0x70, 0xC6, 0x38, + 0x70, 0xC6, 0x38, 0x60, 0xC6, 0x38, 0x61, 0xC6, 0x38, 0xE1, 0xC6, 0x38, 0xE1, 0x86, 0x38, 0xE1, + 0x86, 0x38, 0xE1, 0x8C, 0x38, 0xE1, 0x8C, 0x38, 0xE3, 0x8C, 0x1C, 0xE3, 0x98, 0x1C, 0x65, 0x98, + 0x1C, 0x7D, 0xF0, 0x0C, 0x38, 0xE0, 0x0E, 0x00, 0x06, 0x0E, 0x00, 0x04, 0x07, 0x00, 0x0C, 0x03, + 0x80, 0x38, 0x01, 0xE0, 0xF0, 0x00, 0xFF, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"@",32*/ + + 0x00, 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, 0x7C, + 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x4C, 0x00, 0x00, 0xCC, 0x00, 0x00, 0xCE, 0x00, + 0x00, 0x8E, 0x00, 0x00, 0x86, 0x00, 0x01, 0x86, 0x00, 0x01, 0x87, 0x00, 0x01, 0x07, 0x00, 0x01, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x80, 0x02, 0x03, 0x80, 0x02, 0x03, 0x80, 0x06, 0x01, + 0x80, 0x07, 0xFF, 0xC0, 0x04, 0x01, 0xC0, 0x04, 0x01, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xE0, + 0x08, 0x00, 0xE0, 0x08, 0x00, 0xE0, 0x18, 0x00, 0xE0, 0x18, 0x00, 0x70, 0x18, 0x00, 0x70, 0x18, + 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x78, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"A",33*/ + + 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, 0xFF, 0x00, 0x0E, 0x03, 0xC0, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, + 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, + 0x00, 0xE0, 0x0E, 0x03, 0x80, 0x0F, 0xFE, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0x60, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, + 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x38, 0x0E, + 0x00, 0x38, 0x0E, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"B",34*/ + + 0x00, 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, 0xE0, 0xF8, 0x01, 0x80, + 0x38, 0x03, 0x00, 0x18, 0x07, 0x00, 0x18, 0x06, 0x00, 0x08, 0x0E, 0x00, 0x0C, 0x0C, 0x00, 0x04, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x04, + 0x1C, 0x00, 0x04, 0x1C, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x18, 0x07, 0x00, 0x30, 0x07, + 0x80, 0x60, 0x03, 0xC0, 0xE0, 0x00, 0xFF, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"C",35*/ + + 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, 0xF8, 0x00, 0x0F, 0x07, 0x00, 0x0E, 0x01, + 0x80, 0x0E, 0x00, 0xC0, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x38, + 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, + 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, + 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x18, 0x0E, 0x00, 0x38, + 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xE0, 0x0E, + 0x01, 0xC0, 0x0E, 0x03, 0x80, 0x0E, 0x0F, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"D",36*/ + + 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, 0xFF, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x10, 0x0E, 0x00, 0x18, 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x0E, + 0x00, 0x80, 0x0E, 0x01, 0x80, 0x0F, 0xFF, 0x80, 0x0E, 0x03, 0x80, 0x0E, 0x01, 0x80, 0x0E, 0x00, + 0x80, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x80, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x04, 0x0E, 0x00, 0x04, 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x0E, + 0x00, 0x18, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0xF0, 0x7F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"E",37*/ + + 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, 0xFF, 0xF8, 0x0E, 0x00, 0x78, 0x0E, 0x00, + 0x3C, 0x0E, 0x00, 0x0C, 0x0E, 0x00, 0x04, 0x0E, 0x00, 0x06, 0x0E, 0x00, 0x02, 0x0E, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x40, 0x0E, 0x00, 0x40, 0x0E, 0x00, 0x40, 0x0E, + 0x00, 0x40, 0x0E, 0x00, 0xC0, 0x0F, 0xFF, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xC0, 0x0E, 0x00, + 0x40, 0x0E, 0x00, 0x40, 0x0E, 0x00, 0x40, 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, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"F",38*/ + + 0x00, 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, 0x20, 0x01, 0xC3, 0xE0, 0x03, 0x00, + 0xE0, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x0C, 0x00, 0x20, 0x1C, 0x00, 0x30, 0x18, 0x00, 0x30, + 0x38, 0x00, 0x10, 0x38, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x03, + 0xFE, 0x70, 0x00, 0xF8, 0x70, 0x00, 0x70, 0x70, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, + 0x38, 0x00, 0x70, 0x18, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x06, + 0x00, 0x70, 0x07, 0x00, 0xF0, 0x01, 0xC1, 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, /*"G",39*/ + + 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, 0x83, 0xFE, 0x1C, 0x00, 0x70, 0x1C, 0x00, + 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, + 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, + 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1F, 0xFF, 0xF0, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, + 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, + 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, + 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0xFF, 0x83, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"H",40*/ + + 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, 0xF0, 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, 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, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"I",41*/ + + 0x00, 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, 0xFE, 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, 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, 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, 0x00, 0x03, 0x80, 0x00, + 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x00, 0x03, 0x80, 0x18, 0x03, 0x00, 0x3C, 0x07, + 0x00, 0x3C, 0x06, 0x00, 0x3C, 0x0C, 0x00, 0x1C, 0x18, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, /*"J",42*/ + + 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, 0xC3, 0xFC, 0x0E, 0x00, 0xF0, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0xC0, 0x0E, 0x01, 0x80, 0x0E, 0x01, 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x06, 0x00, + 0x0E, 0x04, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x08, 0x00, 0x0E, 0x10, 0x00, 0x0E, 0x30, 0x00, 0x0E, + 0x38, 0x00, 0x0E, 0x78, 0x00, 0x0E, 0xF8, 0x00, 0x0E, 0x9C, 0x00, 0x0F, 0x1C, 0x00, 0x0F, 0x0E, + 0x00, 0x0E, 0x0E, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x03, 0x80, 0x0E, 0x03, 0x80, + 0x0E, 0x03, 0x80, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, + 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x78, 0x7F, 0xC1, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"K",43*/ + + 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, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x07, 0x00, 0x04, 0x07, 0x00, 0x04, 0x07, 0x00, 0x0C, 0x07, 0x00, 0x08, 0x07, + 0x00, 0x18, 0x07, 0x00, 0x38, 0x07, 0x00, 0x78, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"L",44*/ + + 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, 0x7E, 0x1C, 0x00, 0x78, 0x1C, 0x00, + 0x78, 0x1E, 0x00, 0x78, 0x1E, 0x00, 0xB8, 0x1E, 0x00, 0xB8, 0x1E, 0x00, 0xB8, 0x1E, 0x00, 0xB8, + 0x17, 0x01, 0xB8, 0x17, 0x01, 0x38, 0x17, 0x01, 0x38, 0x17, 0x01, 0x38, 0x13, 0x81, 0x38, 0x13, + 0x83, 0x38, 0x13, 0x82, 0x38, 0x13, 0x82, 0x38, 0x13, 0x82, 0x38, 0x11, 0xC6, 0x38, 0x11, 0xC4, + 0x38, 0x11, 0xC4, 0x38, 0x11, 0xC4, 0x38, 0x10, 0xEC, 0x38, 0x10, 0xEC, 0x38, 0x10, 0xE8, 0x38, + 0x10, 0xE8, 0x38, 0x10, 0xF8, 0x38, 0x10, 0x78, 0x38, 0x10, 0x70, 0x38, 0x10, 0x70, 0x38, 0x10, + 0x70, 0x38, 0x10, 0x30, 0x38, 0x10, 0x30, 0x38, 0x7C, 0x21, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"M",45*/ + + 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, 0xFE, 0x0E, 0x00, 0x10, 0x0F, 0x00, + 0x10, 0x0F, 0x00, 0x10, 0x0F, 0x80, 0x10, 0x0B, 0x80, 0x10, 0x0B, 0xC0, 0x10, 0x09, 0xC0, 0x10, + 0x09, 0xE0, 0x10, 0x08, 0xE0, 0x10, 0x08, 0xE0, 0x10, 0x08, 0x70, 0x10, 0x08, 0x70, 0x10, 0x08, + 0x38, 0x10, 0x08, 0x38, 0x10, 0x08, 0x1C, 0x10, 0x08, 0x1C, 0x10, 0x08, 0x0E, 0x10, 0x08, 0x0E, + 0x10, 0x08, 0x07, 0x10, 0x08, 0x07, 0x10, 0x08, 0x03, 0x90, 0x08, 0x03, 0x90, 0x08, 0x03, 0xD0, + 0x08, 0x01, 0xD0, 0x08, 0x01, 0xF0, 0x08, 0x00, 0xF0, 0x08, 0x00, 0xF0, 0x08, 0x00, 0x70, 0x08, + 0x00, 0x70, 0x08, 0x00, 0x30, 0x08, 0x00, 0x30, 0x7F, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"N",46*/ + + 0x00, 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, 0xC1, 0x80, 0x01, 0x80, + 0x40, 0x03, 0x00, 0x60, 0x06, 0x00, 0x30, 0x0E, 0x00, 0x38, 0x0C, 0x00, 0x18, 0x1C, 0x00, 0x18, + 0x1C, 0x00, 0x1C, 0x1C, 0x00, 0x1C, 0x18, 0x00, 0x0C, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x38, + 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x38, 0x00, + 0x0E, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x18, 0x00, 0x0C, 0x1C, 0x00, 0x0C, + 0x1C, 0x00, 0x1C, 0x0C, 0x00, 0x1C, 0x0C, 0x00, 0x18, 0x0E, 0x00, 0x38, 0x06, 0x00, 0x30, 0x03, + 0x00, 0x60, 0x01, 0x80, 0xC0, 0x00, 0xC1, 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, /*"O",47*/ + + 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, 0xFF, 0x00, 0x0E, 0x01, 0xC0, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, + 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x38, 0x0E, + 0x00, 0x30, 0x0E, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x0F, 0xFF, 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, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"P",48*/ + + 0x00, 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, 0xC3, 0x80, 0x03, 0x00, + 0xC0, 0x07, 0x00, 0x60, 0x06, 0x00, 0x60, 0x0E, 0x00, 0x30, 0x0C, 0x00, 0x30, 0x1C, 0x00, 0x38, + 0x1C, 0x00, 0x38, 0x18, 0x00, 0x18, 0x18, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, + 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, + 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x18, 0xF8, 0x18, + 0x1D, 0xFC, 0x18, 0x1D, 0x8E, 0x38, 0x0F, 0x0E, 0x38, 0x0F, 0x07, 0x30, 0x06, 0x07, 0x60, 0x07, + 0x07, 0x60, 0x03, 0x03, 0xC0, 0x01, 0xC3, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x03, 0xC8, 0x00, 0x01, + 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Q",49*/ + + 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, 0xFF, 0x00, 0x0E, 0x03, 0xC0, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x78, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, + 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, + 0x00, 0xE0, 0x0E, 0x03, 0xC0, 0x0F, 0xFF, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x0E, 0x00, 0x0E, 0x0E, + 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x03, 0x80, 0x0E, 0x03, 0x80, + 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, + 0x00, 0xF0, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x78, 0x7F, 0xC0, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"R",50*/ + + 0x00, 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, 0x03, 0xE0, 0x0E, 0x00, + 0xE0, 0x0C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x38, 0x00, 0x30, 0x38, 0x00, 0x30, 0x38, 0x00, 0x10, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, + 0xE0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x07, + 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x20, 0x00, 0x38, 0x30, 0x00, 0x38, 0x30, 0x00, 0x38, 0x10, 0x00, 0x30, 0x18, 0x00, 0x70, 0x1C, + 0x00, 0x60, 0x1E, 0x00, 0xE0, 0x1F, 0x81, 0x80, 0x10, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"S",51*/ + + 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, 0xF8, 0x38, 0x38, 0x38, 0x30, 0x38, + 0x18, 0x30, 0x38, 0x08, 0x20, 0x38, 0x08, 0x60, 0x38, 0x0C, 0x40, 0x38, 0x04, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 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, /*"T",52*/ + + 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, 0x80, 0xFE, 0x1C, 0x00, 0x10, 0x1C, 0x00, + 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, + 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, + 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, + 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, + 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x1C, 0x00, 0x10, 0x0C, 0x00, 0x20, 0x0E, + 0x00, 0x60, 0x07, 0x00, 0xC0, 0x03, 0x81, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"U",53*/ + + 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, 0xFE, 0x1E, 0x00, 0x38, 0x0E, 0x00, + 0x30, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x30, 0x0F, 0x00, 0x20, 0x07, 0x00, 0x20, 0x07, 0x00, 0x60, + 0x07, 0x00, 0x60, 0x07, 0x00, 0x40, 0x03, 0x80, 0x40, 0x03, 0x80, 0xC0, 0x03, 0x80, 0x80, 0x03, + 0x80, 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC1, 0x80, 0x01, 0xC1, 0x00, 0x01, 0xC1, 0x00, 0x00, 0xE1, + 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE2, 0x00, 0x00, 0xE2, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x76, 0x00, + 0x00, 0x74, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 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, 0x00, 0x00, /*"V",54*/ + + 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, 0x7E, 0x3F, 0x38, 0x1C, 0x0C, 0x38, 0x1C, + 0x0C, 0x38, 0x1C, 0x0C, 0x38, 0x1C, 0x08, 0x38, 0x1C, 0x08, 0x18, 0x1C, 0x08, 0x18, 0x1C, 0x08, + 0x1C, 0x1C, 0x18, 0x1C, 0x1E, 0x18, 0x1C, 0x1E, 0x10, 0x1C, 0x1E, 0x10, 0x1C, 0x3E, 0x10, 0x0C, + 0x3E, 0x10, 0x0C, 0x2E, 0x30, 0x0E, 0x26, 0x20, 0x0E, 0x27, 0x20, 0x0E, 0x67, 0x20, 0x0E, 0x67, + 0x20, 0x06, 0x47, 0x60, 0x06, 0x47, 0x60, 0x06, 0x43, 0x40, 0x07, 0xC3, 0x40, 0x07, 0xC3, 0xC0, + 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x03, 0x83, 0xC0, 0x03, 0x83, 0x80, 0x03, 0x81, 0x80, 0x03, + 0x01, 0x80, 0x03, 0x01, 0x80, 0x03, 0x01, 0x80, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"W",55*/ + + 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, 0x81, 0xFC, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x60, 0x07, 0x00, 0x60, 0x07, 0x00, 0xC0, 0x03, 0x80, 0xC0, 0x03, 0x81, 0x80, 0x01, 0xC1, 0x80, + 0x01, 0xC3, 0x00, 0x00, 0xE3, 0x00, 0x00, 0xE2, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x74, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3E, + 0x00, 0x00, 0x6E, 0x00, 0x00, 0x6E, 0x00, 0x00, 0xC7, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x83, 0x80, + 0x01, 0x83, 0x80, 0x01, 0x01, 0xC0, 0x03, 0x01, 0xC0, 0x02, 0x01, 0xE0, 0x06, 0x00, 0xE0, 0x06, + 0x00, 0xF0, 0x0C, 0x00, 0x70, 0x1C, 0x00, 0x78, 0x7F, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"X",56*/ + + 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, 0x81, 0xFC, 0x1E, 0x00, 0x70, 0x0E, 0x00, + 0x60, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x40, 0x07, 0x00, 0xC0, 0x07, 0x00, 0x80, 0x07, 0x00, 0x80, + 0x03, 0x81, 0x80, 0x03, 0x81, 0x00, 0x03, 0xC1, 0x00, 0x01, 0xC3, 0x00, 0x01, 0xC2, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0xE2, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 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, /*"Y",57*/ + + 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, 0xFC, 0x07, 0x80, 0x38, 0x0F, 0x00, + 0x78, 0x0C, 0x00, 0x70, 0x0C, 0x00, 0xF0, 0x18, 0x00, 0xE0, 0x10, 0x01, 0xE0, 0x00, 0x01, 0xC0, + 0x00, 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x00, + 0x03, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07, 0x80, 0x04, 0x07, 0x00, 0x0C, 0x0F, 0x00, 0x08, 0x0E, + 0x00, 0x18, 0x1E, 0x00, 0x38, 0x1C, 0x00, 0xF0, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"Z",58*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x7F, 0xF8, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"[",59*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"\",60*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x1F, 0xFC, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x1F, 0xFC, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"]",61*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x77, 0x00, 0x00, + 0xE1, 0x80, 0x01, 0x80, 0xC0, 0x02, 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, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"^",62*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, /*"_",63*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"`",64*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0x03, 0x80, 0x0C, + 0x01, 0xC0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x1C, 0x00, 0xE0, 0x00, 0x00, + 0xE0, 0x00, 0x0F, 0xE0, 0x00, 0xF0, 0xE0, 0x03, 0x80, 0xE0, 0x0E, 0x00, 0xE0, 0x1C, 0x00, 0xE0, + 0x1C, 0x00, 0xE0, 0x38, 0x00, 0xE0, 0x38, 0x00, 0xE0, 0x38, 0x00, 0xE0, 0x38, 0x00, 0xE2, 0x38, + 0x00, 0xE2, 0x1C, 0x03, 0xE2, 0x0E, 0x0E, 0xE4, 0x03, 0xF8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"a",65*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x7E, 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, 0x1F, 0x00, 0x0E, 0x61, 0xC0, 0x0E, + 0xC0, 0xE0, 0x0F, 0x80, 0x70, 0x0F, 0x00, 0x70, 0x0F, 0x00, 0x30, 0x0E, 0x00, 0x38, 0x0E, 0x00, + 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, + 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x30, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0F, + 0x00, 0x60, 0x0F, 0x00, 0xC0, 0x0C, 0xC1, 0x80, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"b",66*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xE0, 0xC0, 0x03, + 0x80, 0x60, 0x03, 0x00, 0x70, 0x07, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x1C, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x0E, 0x00, 0x10, 0x07, + 0x00, 0x30, 0x03, 0x80, 0x60, 0x01, 0xC0, 0xC0, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"c",67*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x03, 0xF0, 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, 0x7C, 0x70, 0x01, 0xC3, 0x70, 0x03, + 0x00, 0xF0, 0x07, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x1C, 0x00, + 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, + 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xF0, 0x06, + 0x00, 0xF0, 0x03, 0x01, 0x70, 0x01, 0x82, 0x7E, 0x00, 0xFC, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"d",68*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xC1, 0x80, 0x03, + 0x80, 0xC0, 0x07, 0x00, 0x60, 0x06, 0x00, 0x70, 0x0E, 0x00, 0x30, 0x0C, 0x00, 0x38, 0x1C, 0x00, + 0x38, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x1F, 0xFF, 0xF8, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x0E, 0x00, 0x10, 0x0E, 0x00, 0x20, 0x07, + 0x00, 0x20, 0x03, 0x80, 0x40, 0x01, 0xC1, 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, /*"e",69*/ + + 0x00, 0x00, 0x00, 0x00, 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, 0x1C, + 0x0C, 0x00, 0x30, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x3F, 0xFF, 0xE0, 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, 0xE0, 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, + 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"f",70*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0x1C, 0x01, 0x83, 0xFC, 0x03, + 0x01, 0xCC, 0x07, 0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0xE0, 0x07, 0x00, 0xC0, 0x03, 0x01, 0xC0, 0x01, 0x83, 0x80, 0x07, 0x7E, 0x00, + 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xFF, 0xC0, 0x03, + 0xFF, 0xF0, 0x0E, 0x01, 0xF0, 0x0C, 0x00, 0x78, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x1C, 0x00, + 0x38, 0x1C, 0x00, 0x30, 0x0E, 0x00, 0x70, 0x07, 0x81, 0xC0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, /*"g",71*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x7E, 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, 0x1F, 0x80, 0x0E, 0x61, 0xC0, 0x0E, + 0xC0, 0xE0, 0x0F, 0x80, 0x70, 0x0F, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, + 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x7F, 0xC3, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"h",72*/ + + 0x00, 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, 0x3E, 0x00, 0x00, 0x3E, + 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x07, 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, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"i",73*/ + + 0x00, 0x00, 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, 0xF0, 0x00, 0x01, + 0xF0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x1F, 0xE0, 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, 0xE0, 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, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x0E, 0x00, + 0xC0, 0x0E, 0x01, 0xC0, 0x0E, 0x03, 0x80, 0x07, 0x06, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, /*"j",74*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x7E, 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, 0x07, 0xF0, 0x0E, 0x01, 0x80, 0x0E, + 0x03, 0x00, 0x0E, 0x03, 0x00, 0x0E, 0x06, 0x00, 0x0E, 0x0C, 0x00, 0x0E, 0x18, 0x00, 0x0E, 0x30, + 0x00, 0x0E, 0x38, 0x00, 0x0E, 0x78, 0x00, 0x0E, 0xDC, 0x00, 0x0F, 0x9C, 0x00, 0x0F, 0x0E, 0x00, + 0x0E, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0E, 0x03, 0x80, 0x0E, 0x03, 0x80, 0x0E, 0x01, 0xC0, 0x0E, + 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xF0, 0x7F, 0xC3, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"k",75*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1C, 0x00, 0x07, 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, 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, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"l",76*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x7C, 0xF8, 0xF0, 0x1D, 0x3D, 0x38, 0x1E, + 0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"m",77*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7E, 0x1F, 0x80, 0x0E, 0x61, 0xC0, 0x0E, + 0xC0, 0xE0, 0x0F, 0x80, 0x60, 0x0F, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, + 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x7F, 0xC3, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"n",78*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xC3, 0x80, 0x03, + 0x00, 0xC0, 0x06, 0x00, 0x60, 0x0E, 0x00, 0x30, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x18, 0x00, + 0x18, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, + 0x38, 0x00, 0x1C, 0x38, 0x00, 0x1C, 0x1C, 0x00, 0x38, 0x1C, 0x00, 0x38, 0x0C, 0x00, 0x30, 0x06, + 0x00, 0x60, 0x07, 0x00, 0xC0, 0x01, 0xC1, 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, /*"o",79*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0x1F, 0x00, 0x7E, 0x60, 0xC0, 0x0E, + 0x80, 0x60, 0x0F, 0x00, 0x30, 0x0F, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x1C, 0x0E, 0x00, + 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, + 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0E, 0x00, 0x38, 0x0F, + 0x00, 0x70, 0x0F, 0x80, 0xE0, 0x0E, 0xC1, 0xC0, 0x0E, 0x3F, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, /*"p",80*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0x10, 0x01, 0x83, 0x30, 0x07, + 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x0C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x38, 0x00, + 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, + 0x38, 0x00, 0x70, 0x38, 0x00, 0x70, 0x18, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x1C, 0x00, 0x70, 0x0C, + 0x00, 0xF0, 0x06, 0x01, 0xF0, 0x03, 0x83, 0x70, 0x00, 0xFC, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, /*"q",81*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x3F, 0xC0, 0xF0, 0x01, 0xC3, 0x1C, 0x01, + 0xC6, 0x1C, 0x01, 0xC8, 0x1C, 0x01, 0xD8, 0x1C, 0x01, 0xF0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xE0, + 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, + 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, + 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x01, 0xC0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"r",82*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xC1, 0xC0, 0x03, + 0x80, 0xE0, 0x07, 0x00, 0x60, 0x07, 0x00, 0x60, 0x07, 0x00, 0x20, 0x07, 0x00, 0x00, 0x07, 0x80, + 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF8, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x07, 0xE0, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0xF0, 0x08, 0x00, 0x70, 0x08, 0x00, 0x70, 0x0C, 0x00, 0x70, 0x0C, + 0x00, 0x60, 0x0E, 0x00, 0xE0, 0x0F, 0x81, 0xC0, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"s",83*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x70, 0x00, 0x01, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 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, 0x10, 0x00, 0x70, 0x10, 0x00, + 0x70, 0x20, 0x00, 0x38, 0x20, 0x00, 0x18, 0x40, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"t",84*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x10, 0x7E, 0x03, 0xF0, 0x0E, 0x00, 0x70, 0x0E, + 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, + 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, + 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0x70, 0x0E, 0x00, 0xF0, 0x06, + 0x00, 0xF0, 0x07, 0x01, 0x70, 0x03, 0x82, 0x7E, 0x01, 0xFC, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"u",85*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0xC1, 0xFC, 0x0F, 0x00, 0x70, 0x07, + 0x00, 0x60, 0x07, 0x00, 0x60, 0x03, 0x00, 0x40, 0x03, 0x80, 0x40, 0x03, 0x80, 0xC0, 0x01, 0x80, + 0x80, 0x01, 0xC0, 0x80, 0x01, 0xC1, 0x80, 0x00, 0xC1, 0x00, 0x00, 0xE1, 0x00, 0x00, 0xE3, 0x00, + 0x00, 0xE2, 0x00, 0x00, 0x62, 0x00, 0x00, 0x76, 0x00, 0x00, 0x74, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x38, 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, /*"v",86*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0x7E, 0x3F, 0x38, 0x3C, 0x0C, 0x38, + 0x18, 0x08, 0x18, 0x18, 0x08, 0x18, 0x1C, 0x18, 0x1C, 0x1C, 0x18, 0x1C, 0x1C, 0x10, 0x1C, 0x3C, + 0x10, 0x0C, 0x2E, 0x30, 0x0E, 0x2E, 0x30, 0x0E, 0x26, 0x20, 0x0E, 0x66, 0x20, 0x06, 0x46, 0x20, + 0x07, 0x47, 0x60, 0x07, 0xC7, 0x40, 0x07, 0xC3, 0x40, 0x03, 0x83, 0x40, 0x03, 0x83, 0xC0, 0x03, + 0x83, 0x80, 0x03, 0x81, 0x80, 0x01, 0x81, 0x80, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"w",87*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0xE3, 0xF8, 0x07, 0x80, 0xE0, 0x03, + 0x80, 0xC0, 0x01, 0xC0, 0x80, 0x01, 0xC1, 0x80, 0x00, 0xE3, 0x00, 0x00, 0x72, 0x00, 0x00, 0x76, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x3E, 0x00, + 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0xC3, 0x80, 0x00, 0x83, 0x80, 0x01, 0x81, 0xC0, 0x03, + 0x00, 0xC0, 0x03, 0x00, 0xE0, 0x07, 0x00, 0xF0, 0x3F, 0x83, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"x",88*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0xC3, 0xFC, 0x0F, 0x00, 0xE0, 0x07, + 0x00, 0x60, 0x07, 0x00, 0x40, 0x03, 0x00, 0xC0, 0x03, 0x80, 0x80, 0x03, 0x80, 0x80, 0x01, 0x81, + 0x80, 0x01, 0xC1, 0x00, 0x01, 0xC1, 0x00, 0x00, 0xC3, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x62, 0x00, + 0x00, 0x66, 0x00, 0x00, 0x74, 0x00, 0x00, 0x34, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, + 0x00, 0x0C, 0x60, 0x00, 0x1E, 0x40, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, /*"y",89*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 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, 0x0E, 0x00, 0xF0, 0x1C, + 0x00, 0xE0, 0x18, 0x01, 0xC0, 0x18, 0x03, 0xC0, 0x10, 0x03, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0F, + 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, + 0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xC0, 0x08, 0x03, 0x80, 0x18, 0x07, 0x80, 0x18, 0x07, + 0x00, 0x30, 0x0E, 0x00, 0x30, 0x1E, 0x00, 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, /*"z",90*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x00, + 0x01, 0x80, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, + 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"{",91*/ + + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, /*"|",92*/ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0x00, 0x01, 0x80, + 0x00, 0x03, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"}",93*/ + + 0x03, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x08, 0x70, 0x02, 0x10, 0x38, 0x02, 0x10, 0x1C, 0x04, 0x20, + 0x0E, 0x04, 0x20, 0x07, 0x88, 0x00, 0x03, 0xF8, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"~",94*/ +}; + +const esp_painter_basic_font_t esp_painter_basic_font_48 = { + .bitmap = bitmap, + .width = 24, + .height = 48, +}; + +#endif diff --git a/components/lua_modules/esp_painter/include/esp_painter.h b/components/lua_modules/esp_painter/include/esp_painter.h new file mode 100644 index 0000000..a063481 --- /dev/null +++ b/components/lua_modules/esp_painter/include/esp_painter.h @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_err.h" +#include "esp_painter_font.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// 颜色格式定义 +typedef enum { + ESP_PAINTER_COLOR_FORMAT_RGB565, + ESP_PAINTER_COLOR_FORMAT_RGB888, + ESP_PAINTER_COLOR_FORMAT_YUV420, + ESP_PAINTER_COLOR_FORMAT_YUV422, +} esp_painter_color_format_t; + +// 通用颜色定义 +typedef enum { + ESP_PAINTER_COLOR_BLACK, + ESP_PAINTER_COLOR_NAVY, + ESP_PAINTER_COLOR_DARKGREEN, + ESP_PAINTER_COLOR_DARKCYAN, + ESP_PAINTER_COLOR_MAROON, + ESP_PAINTER_COLOR_PURPLE, + ESP_PAINTER_COLOR_OLIVE, + ESP_PAINTER_COLOR_LIGHTGREY, + ESP_PAINTER_COLOR_DARKGREY, + ESP_PAINTER_COLOR_BLUE, + ESP_PAINTER_COLOR_GREEN, + ESP_PAINTER_COLOR_CYAN, + ESP_PAINTER_COLOR_RED, + ESP_PAINTER_COLOR_MAGENTA, + ESP_PAINTER_COLOR_YELLOW, + ESP_PAINTER_COLOR_WHITE, + ESP_PAINTER_COLOR_ORANGE, + ESP_PAINTER_COLOR_GREENYELLOW, + ESP_PAINTER_COLOR_PINK, +} esp_painter_color_t; + +// Color creation macros +#define RGB565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3)) +#define RGB888(r,g,b) (((r) << 16) | ((g) << 8) | (b)) + +typedef void* esp_painter_handle_t; + +typedef struct { + struct { + uint16_t width; + uint16_t height; + } canvas; + esp_painter_color_format_t color_format; + const esp_painter_basic_font_t *default_font; + bool swap_rgb565; // Whether to swap RGB565 bytes (endianness conversion) +} esp_painter_config_t; + +esp_err_t esp_painter_init(esp_painter_config_t *config, esp_painter_handle_t *handle); + +esp_err_t esp_painter_draw_string(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + esp_painter_color_t color, const char* text); + +esp_err_t esp_painter_draw_string_rgb565(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + uint16_t color565, const char *text); + +esp_err_t esp_painter_draw_string_format(esp_painter_handle_t handle, uint8_t *buffer, uint32_t buffer_size, + uint16_t x, uint16_t y, const esp_painter_basic_font_t *font, + esp_painter_color_t color, const char* fmt, ...); + +esp_err_t esp_painter_deinit(esp_painter_handle_t handle); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/esp_painter/include/esp_painter_font.h b/components/lua_modules/esp_painter/include/esp_painter_font.h new file mode 100644 index 0000000..b49b58c --- /dev/null +++ b/components/lua_modules/esp_painter/include/esp_painter_font.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const uint8_t *bitmap; + uint16_t width; + uint16_t height; +} esp_painter_basic_font_t; + +#define esp_painter_FONT_DECLARE(font_name) extern const esp_painter_basic_font_t font_name + +#if CONFIG_ESP_PAINTER_BASIC_FONT_12 +esp_painter_FONT_DECLARE(esp_painter_basic_font_12); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_16 +esp_painter_FONT_DECLARE(esp_painter_basic_font_16); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_20 +esp_painter_FONT_DECLARE(esp_painter_basic_font_20); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_24 +esp_painter_FONT_DECLARE(esp_painter_basic_font_24); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_28 +esp_painter_FONT_DECLARE(esp_painter_basic_font_28); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_32 +esp_painter_FONT_DECLARE(esp_painter_basic_font_32); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_36 +esp_painter_FONT_DECLARE(esp_painter_basic_font_36); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_40 +esp_painter_FONT_DECLARE(esp_painter_basic_font_40); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_44 +esp_painter_FONT_DECLARE(esp_painter_basic_font_44); +#endif + +#if CONFIG_ESP_PAINTER_BASIC_FONT_48 +esp_painter_FONT_DECLARE(esp_painter_basic_font_48); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_audio/CMakeLists.txt b/components/lua_modules/lua_module_audio/CMakeLists.txt new file mode 100644 index 0000000..f610964 --- /dev/null +++ b/components/lua_modules/lua_module_audio/CMakeLists.txt @@ -0,0 +1,10 @@ +idf_component_register( + SRC_DIRS + "." + INCLUDE_DIRS + "include" + REQUIRES + cap_lua + esp_codec_dev + driver +) diff --git a/components/lua_modules/lua_module_audio/idf_component.yml b/components/lua_modules/lua_module_audio/idf_component.yml new file mode 100644 index 0000000..4b68fed --- /dev/null +++ b/components/lua_modules/lua_module_audio/idf_component.yml @@ -0,0 +1,3 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_codec_dev: "*" diff --git a/components/lua_modules/lua_module_audio/include/lua_module_audio.h b/components/lua_modules/lua_module_audio/include/lua_module_audio.h new file mode 100644 index 0000000..9a55e5a --- /dev/null +++ b/components/lua_modules/lua_module_audio/include/lua_module_audio.h @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "lua.h" +#include "esp_err.h" + +int luaopen_audio(lua_State *L); +esp_err_t lua_module_audio_register(void); diff --git a/components/lua_modules/lua_module_audio/lua_module_audio.c b/components/lua_modules/lua_module_audio/lua_module_audio.c new file mode 100644 index 0000000..35e9d3a --- /dev/null +++ b/components/lua_modules/lua_module_audio/lua_module_audio.c @@ -0,0 +1,743 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_audio.h" + +#include +#include +#include +#include +#include +#include +#include "esp_codec_dev.h" +#include "esp_err.h" +#include "esp_log.h" +#include "lauxlib.h" +#include "cap_lua.h" + +static const char *TAG = "lua_audio"; + +/* -------------------------------------------------------------------------- + * Audio constants + * -------------------------------------------------------------------------- */ +#define AUDIO_CHUNK_BYTES 512 +#define AUDIO_DEFAULT_VOL 80 +#define AUDIO_DEFAULT_GAIN_DB 30.0f +#define AUDIO_BASE_PATH "/fatfs/" +#define AUDIO_HANDLE_METATABLE "lua_audio_handle" + +typedef enum { + AUDIO_HANDLE_INPUT = 0, + AUDIO_HANDLE_OUTPUT, +} audio_handle_kind_t; + +typedef struct audio_lua_handle_t { + audio_handle_kind_t kind; + esp_codec_dev_handle_t codec_dev; + uint32_t sample_rate; + uint8_t channels; + uint8_t bits_per_sample; + uint8_t bytes_per_sample; + int out_vol; + float in_gain_db; +} audio_lua_handle_t; + +/* -------------------------------------------------------------------------- + * WAV helpers + * -------------------------------------------------------------------------- */ +typedef struct { + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint16_t bits_per_sample; + uint32_t data_offset; + uint32_t data_size; +} audio_wav_info_t; + +static void wav_write_u16(uint8_t *dst, uint16_t v) +{ + dst[0] = (uint8_t)(v & 0xFF); + dst[1] = (uint8_t)((v >> 8) & 0xFF); +} + +static void wav_write_u32(uint8_t *dst, uint32_t v) +{ + dst[0] = (uint8_t)(v & 0xFF); + dst[1] = (uint8_t)((v >> 8) & 0xFF); + dst[2] = (uint8_t)((v >> 16) & 0xFF); + dst[3] = (uint8_t)((v >> 24) & 0xFF); +} + +static uint16_t wav_read_u16(const uint8_t *src) +{ + return (uint16_t)src[0] | ((uint16_t)src[1] << 8); +} + +static uint32_t wav_read_u32(const uint8_t *src) +{ + return (uint32_t)src[0] | ((uint32_t)src[1] << 8) | + ((uint32_t)src[2] << 16) | ((uint32_t)src[3] << 24); +} + +static void wav_build_header(uint8_t *hdr, uint32_t data_size, + uint32_t sample_rate, uint16_t channels, + uint16_t bytes_per_sample, uint16_t bits_per_sample) +{ + uint32_t byte_rate = sample_rate * channels * bytes_per_sample; + uint16_t block_align = channels * bytes_per_sample; + + memcpy(hdr + 0, "RIFF", 4); + wav_write_u32(hdr + 4, data_size + 36); + memcpy(hdr + 8, "WAVE", 4); + memcpy(hdr + 12, "fmt ", 4); + wav_write_u32(hdr + 16, 16); + wav_write_u16(hdr + 20, 1); + wav_write_u16(hdr + 22, channels); + wav_write_u32(hdr + 24, sample_rate); + wav_write_u32(hdr + 28, byte_rate); + wav_write_u16(hdr + 32, block_align); + wav_write_u16(hdr + 34, bits_per_sample); + memcpy(hdr + 36, "data", 4); + wav_write_u32(hdr + 40, data_size); +} + +static esp_err_t wav_parse(FILE *f, audio_wav_info_t *info) +{ + uint8_t hdr[12]; + + memset(info, 0, sizeof(*info)); + if (fread(hdr, 1, sizeof(hdr), f) != sizeof(hdr)) { + return ESP_FAIL; + } + if (memcmp(hdr, "RIFF", 4) != 0 || memcmp(hdr + 8, "WAVE", 4) != 0) { + return ESP_ERR_INVALID_RESPONSE; + } + + while (1) { + uint8_t chunk_hdr[8]; + uint32_t chunk_size; + + if (fread(chunk_hdr, 1, sizeof(chunk_hdr), f) != sizeof(chunk_hdr)) { + break; + } + chunk_size = wav_read_u32(chunk_hdr + 4); + + if (memcmp(chunk_hdr, "fmt ", 4) == 0) { + uint8_t fmt[16]; + if (chunk_size < sizeof(fmt) || fread(fmt, 1, sizeof(fmt), f) != sizeof(fmt)) { + return ESP_FAIL; + } + info->audio_format = wav_read_u16(fmt + 0); + info->num_channels = wav_read_u16(fmt + 2); + info->sample_rate = wav_read_u32(fmt + 4); + info->bits_per_sample = wav_read_u16(fmt + 14); + if (chunk_size > sizeof(fmt)) { + fseek(f, (long)(chunk_size - sizeof(fmt)), SEEK_CUR); + } + } else if (memcmp(chunk_hdr, "data", 4) == 0) { + info->data_offset = (uint32_t)ftell(f); + info->data_size = chunk_size; + fseek(f, (long)chunk_size, SEEK_CUR); + } else { + fseek(f, (long)chunk_size, SEEK_CUR); + } + + if (chunk_size & 1U) { + fseek(f, 1, SEEK_CUR); + } + } + + if (info->data_offset == 0 || info->data_size == 0) { + return ESP_ERR_INVALID_SIZE; + } + return ESP_OK; +} + +/* -------------------------------------------------------------------------- + * Helpers + * -------------------------------------------------------------------------- */ +static bool audio_path_valid(const char *path, const char *ext) +{ + size_t base_len = strlen(AUDIO_BASE_PATH); + size_t ext_len = strlen(ext); + size_t len; + + if (!path || strstr(path, "..")) { + return false; + } + if (strncmp(path, AUDIO_BASE_PATH, base_len) != 0) { + return false; + } + len = strlen(path); + return len > ext_len && strcmp(path + len - ext_len, ext) == 0; +} + +static void *lua_audio_check_lightuserdata_arg(lua_State *L, int index, const char *name) +{ + void *ptr = lua_touserdata(L, index); + + luaL_argcheck(L, ptr != NULL, index, name); + return ptr; +} + +static uint32_t lua_audio_check_u32_arg(lua_State *L, int index, const char *name) +{ + lua_Integer value = luaL_checkinteger(L, index); + + if (value <= 0 || value > UINT32_MAX) { + luaL_error(L, "audio %s must be a positive integer", name); + return 0; + } + return (uint32_t)value; +} + +static uint8_t lua_audio_check_u8_arg(lua_State *L, int index, const char *name) +{ + lua_Integer value = luaL_checkinteger(L, index); + + if (value <= 0 || value > UINT8_MAX) { + luaL_error(L, "audio %s must be a positive integer", name); + return 0; + } + return (uint8_t)value; +} + +static esp_err_t audio_validate_sample_info(audio_lua_handle_t *handle) +{ + if (handle->sample_rate == 0 || handle->channels == 0 || handle->bits_per_sample == 0) { + return ESP_ERR_INVALID_ARG; + } + if ((handle->bits_per_sample % 8) != 0) { + return ESP_ERR_INVALID_ARG; + } + handle->bytes_per_sample = (uint8_t)(handle->bits_per_sample / 8); + if (handle->bytes_per_sample == 0) { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static esp_err_t audio_validate_handle_formats(const audio_lua_handle_t *input, + const audio_lua_handle_t *output) +{ + if (input->sample_rate != output->sample_rate || + input->channels != output->channels || + input->bits_per_sample != output->bits_per_sample) { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static esp_err_t audio_handle_activate(audio_lua_handle_t *handle) +{ + esp_codec_dev_sample_info_t fs = { + .sample_rate = handle->sample_rate, + .channel = handle->channels, + .bits_per_sample = handle->bits_per_sample, + }; + int ret; + + if (audio_validate_sample_info(handle) != ESP_OK) { + return ESP_ERR_INVALID_ARG; + } + + ret = esp_codec_dev_open(handle->codec_dev, &fs); + if (ret != ESP_CODEC_DEV_OK) { + return ESP_FAIL; + } + if (handle->kind == AUDIO_HANDLE_OUTPUT) { + ret = esp_codec_dev_set_out_vol(handle->codec_dev, handle->out_vol); + } else { + ret = esp_codec_dev_set_in_gain(handle->codec_dev, handle->in_gain_db); + } + if (ret != ESP_CODEC_DEV_OK && ret != ESP_CODEC_DEV_NOT_SUPPORT) { + esp_codec_dev_close(handle->codec_dev); + return ESP_FAIL; + } + return ESP_OK; +} + +static audio_lua_handle_t *lua_audio_check_any_handle(lua_State *L, int idx, const char *what) +{ + audio_lua_handle_t *handle = + (audio_lua_handle_t *)luaL_checkudata(L, idx, AUDIO_HANDLE_METATABLE); + + if (handle->codec_dev == NULL) { + luaL_error(L, "audio %s: invalid or closed handle", what); + return NULL; + } + return handle; +} + +static audio_lua_handle_t *lua_audio_check_handle(lua_State *L, int idx, audio_handle_kind_t kind, const char *what) +{ + audio_lua_handle_t *handle = lua_audio_check_any_handle(L, idx, what); + + if (handle->kind != kind) { + luaL_error(L, "audio %s: wrong handle type", what); + return NULL; + } + return handle; +} + +static void lua_audio_push_handle(lua_State *L, const audio_lua_handle_t *handle) +{ + audio_lua_handle_t *ud = + (audio_lua_handle_t *)lua_newuserdata(L, sizeof(*ud)); + + *ud = *handle; + luaL_getmetatable(L, AUDIO_HANDLE_METATABLE); + lua_setmetatable(L, -2); +} + +static int lua_audio_handle_gc(lua_State *L) +{ + audio_lua_handle_t *handle = + (audio_lua_handle_t *)luaL_testudata(L, 1, AUDIO_HANDLE_METATABLE); + + if (handle && handle->codec_dev != NULL) { + esp_codec_dev_close(handle->codec_dev); + handle->codec_dev = NULL; + } + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.new_input(codec_dev_handle, sample_rate, channels, bits_per_sample [, gain_db]) + * -> handle | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_audio_new_input(lua_State *L) +{ + audio_lua_handle_t handle = {0}; + + handle.kind = AUDIO_HANDLE_INPUT; + handle.codec_dev = (esp_codec_dev_handle_t)lua_audio_check_lightuserdata_arg( + L, 1, "audio codec_dev_handle lightuserdata expected"); + handle.sample_rate = lua_audio_check_u32_arg(L, 2, "sample_rate"); + handle.channels = lua_audio_check_u8_arg(L, 3, "channels"); + handle.bits_per_sample = lua_audio_check_u8_arg(L, 4, "bits_per_sample"); + handle.in_gain_db = (float)luaL_optnumber(L, 5, AUDIO_DEFAULT_GAIN_DB); + + if (audio_handle_activate(&handle) != ESP_OK) { + lua_pushnil(L); + lua_pushstring(L, "audio new_input: failed to activate input device"); + return 2; + } + lua_audio_push_handle(L, &handle); + return 1; +} + +/* -------------------------------------------------------------------------- + * audio.new_output(codec_dev_handle, sample_rate, channels, bits_per_sample [, volume]) + * -> handle | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_audio_new_output(lua_State *L) +{ + audio_lua_handle_t handle = {0}; + + handle.kind = AUDIO_HANDLE_OUTPUT; + handle.codec_dev = (esp_codec_dev_handle_t)lua_audio_check_lightuserdata_arg( + L, 1, "audio codec_dev_handle lightuserdata expected"); + handle.sample_rate = lua_audio_check_u32_arg(L, 2, "sample_rate"); + handle.channels = lua_audio_check_u8_arg(L, 3, "channels"); + handle.bits_per_sample = lua_audio_check_u8_arg(L, 4, "bits_per_sample"); + handle.out_vol = (int)luaL_optinteger(L, 5, AUDIO_DEFAULT_VOL); + + if (handle.out_vol < 0 || handle.out_vol > 100) { + lua_pushnil(L); + lua_pushstring(L, "audio new_output: volume must be 0..100"); + return 2; + } + if (audio_handle_activate(&handle) != ESP_OK) { + lua_pushnil(L); + lua_pushstring(L, "audio new_output: failed to activate output device"); + return 2; + } + lua_audio_push_handle(L, &handle); + return 1; +} + +/* -------------------------------------------------------------------------- + * audio.close(handle) -> true | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_audio_close(lua_State *L) +{ + audio_lua_handle_t *handle = lua_audio_check_any_handle(L, 1, "close"); + + esp_codec_dev_close(handle->codec_dev); + handle->codec_dev = NULL; + + lua_pushboolean(L, 1); + return 1; +} + +/* -------------------------------------------------------------------------- + * audio.play_wav(output_handle, path) -> nil + * -------------------------------------------------------------------------- */ +static int lua_audio_play_wav(lua_State *L) +{ + audio_lua_handle_t *dac = lua_audio_check_handle(L, 1, AUDIO_HANDLE_OUTPUT, "play_wav"); + const char *path = luaL_checkstring(L, 2); + FILE *f = NULL; + uint8_t *buf = NULL; + audio_wav_info_t info = {0}; + + if (!audio_path_valid(path, ".wav")) { + return luaL_error(L, "audio play_wav: path must be a .wav file under %s", AUDIO_BASE_PATH); + } + + f = fopen(path, "rb"); + if (!f) { + luaL_error(L, "audio play_wav: cannot open %s", path); + goto cleanup; + } + + if (wav_parse(f, &info) != ESP_OK) { + luaL_error(L, "audio play_wav: invalid WAV file"); + goto cleanup; + } + if (info.audio_format != 1 || + info.num_channels != dac->channels || + info.sample_rate != dac->sample_rate || + info.bits_per_sample != dac->bits_per_sample) { + luaL_error(L, "audio play_wav: WAV format does not match output handle configuration"); + goto cleanup; + } + + buf = malloc(AUDIO_CHUNK_BYTES); + if (!buf) { + luaL_error(L, "audio play_wav: out of memory"); + goto cleanup; + } + + fseek(f, (long)info.data_offset, SEEK_SET); + uint32_t remaining = info.data_size; + while (remaining > 0) { + size_t chunk = remaining < AUDIO_CHUNK_BYTES ? remaining : AUDIO_CHUNK_BYTES; + size_t read = fread(buf, 1, chunk, f); + if (read == 0) { + luaL_error(L, "audio play_wav: truncated data"); + goto cleanup; + } + if (esp_codec_dev_write(dac->codec_dev, buf, (int)read) != ESP_CODEC_DEV_OK) { + luaL_error(L, "audio play_wav: write failed"); + goto cleanup; + } + remaining -= (uint32_t)read; + } + +cleanup: + free(buf); + if (f) { + fclose(f); + } + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.record_wav(input_handle, path, duration_ms) -> { path, duration_ms, bytes } + * -------------------------------------------------------------------------- */ +static int lua_audio_record_wav(lua_State *L) +{ + audio_lua_handle_t *adc = lua_audio_check_handle(L, 1, AUDIO_HANDLE_INPUT, "record_wav"); + const char *path = luaL_checkstring(L, 2); + uint32_t duration_ms = (uint32_t)luaL_checkinteger(L, 3); + FILE *f = NULL; + uint8_t *buf = NULL; + uint32_t total_bytes = 0; + uint8_t wav_hdr[44]; + + if (!audio_path_valid(path, ".wav")) { + return luaL_error(L, "audio record_wav: path must be a .wav file under %s", AUDIO_BASE_PATH); + } + if (duration_ms == 0) { + return luaL_error(L, "audio record_wav: duration_ms must be positive"); + } + + buf = malloc(AUDIO_CHUNK_BYTES); + if (!buf) { + luaL_error(L, "audio record_wav: out of memory"); + goto cleanup; + } + + remove(path); + f = fopen(path, "wb"); + if (!f) { + luaL_error(L, "audio record_wav: cannot open %s for writing", path); + goto cleanup; + } + memset(wav_hdr, 0, sizeof(wav_hdr)); + if (fwrite(wav_hdr, 1, sizeof(wav_hdr), f) != sizeof(wav_hdr)) { + luaL_error(L, "audio record_wav: cannot write WAV header placeholder"); + goto cleanup; + } + + uint32_t total_target_bytes = + (uint32_t)((uint64_t)adc->sample_rate * duration_ms / 1000) * + adc->channels * adc->bytes_per_sample; + + while (total_bytes < total_target_bytes) { + uint32_t chunk = total_target_bytes - total_bytes; + if (chunk > AUDIO_CHUNK_BYTES) { + chunk = AUDIO_CHUNK_BYTES; + } + if (esp_codec_dev_read(adc->codec_dev, buf, (int)chunk) != ESP_CODEC_DEV_OK) { + luaL_error(L, "audio record_wav: read failed"); + goto cleanup; + } + if (fwrite(buf, 1, chunk, f) != chunk) { + luaL_error(L, "audio record_wav: write to file failed"); + goto cleanup; + } + total_bytes += chunk; + } + + wav_build_header(wav_hdr, total_bytes, adc->sample_rate, adc->channels, + adc->bytes_per_sample, adc->bits_per_sample); + fseek(f, 0, SEEK_SET); + if (fwrite(wav_hdr, 1, sizeof(wav_hdr), f) != sizeof(wav_hdr)) { + luaL_error(L, "audio record_wav: cannot finalise WAV header"); + goto cleanup; + } + fclose(f); + f = NULL; + + free(buf); + buf = NULL; + + lua_newtable(L); + lua_pushstring(L, path); + lua_setfield(L, -2, "path"); + lua_pushinteger(L, duration_ms); + lua_setfield(L, -2, "duration_ms"); + lua_pushinteger(L, total_bytes); + lua_setfield(L, -2, "bytes"); + return 1; + +cleanup: + free(buf); + if (f) { + fclose(f); + remove(path); + } + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.loopback(input_handle, output_handle [, duration_ms]) -> nil + * -------------------------------------------------------------------------- */ +static int lua_audio_loopback(lua_State *L) +{ + audio_lua_handle_t *adc = lua_audio_check_handle(L, 1, AUDIO_HANDLE_INPUT, "loopback"); + audio_lua_handle_t *dac = lua_audio_check_handle(L, 2, AUDIO_HANDLE_OUTPUT, "loopback"); + uint32_t duration_ms = (uint32_t)luaL_optinteger(L, 3, 1000); + uint8_t *buf = NULL; + + if (audio_validate_handle_formats(adc, dac) != ESP_OK) { + return luaL_error(L, "audio loopback: input/output handle formats must match"); + } + + buf = malloc(AUDIO_CHUNK_BYTES); + if (!buf) { + luaL_error(L, "audio loopback: out of memory"); + goto cleanup; + } + + uint32_t total_bytes = + (uint32_t)((uint64_t)adc->sample_rate * duration_ms / 1000) * + adc->channels * adc->bytes_per_sample; + uint32_t transferred = 0; + + ESP_LOGI(TAG, "loopback start: %" PRIu32 " ms (%" PRIu32 " bytes)", duration_ms, total_bytes); + while (transferred < total_bytes) { + uint32_t chunk = total_bytes - transferred; + if (chunk > AUDIO_CHUNK_BYTES) { + chunk = AUDIO_CHUNK_BYTES; + } + + if (esp_codec_dev_read(adc->codec_dev, buf, (int)chunk) != ESP_CODEC_DEV_OK) { + luaL_error(L, "audio loopback: input read failed"); + goto cleanup; + } + if (esp_codec_dev_write(dac->codec_dev, buf, (int)chunk) != ESP_CODEC_DEV_OK) { + luaL_error(L, "audio loopback: output write failed"); + goto cleanup; + } + transferred += chunk; + } + ESP_LOGI(TAG, "loopback done"); + +cleanup: + free(buf); + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.set_volume(output_handle, pct) -> nil + * -------------------------------------------------------------------------- */ +static int lua_audio_set_volume(lua_State *L) +{ + audio_lua_handle_t *dac = lua_audio_check_handle(L, 1, AUDIO_HANDLE_OUTPUT, "set_volume"); + int vol = (int)luaL_checkinteger(L, 2); + + if (vol < 0 || vol > 100) { + return luaL_error(L, "audio set_volume: volume must be 0..100"); + } + if (esp_codec_dev_set_out_vol(dac->codec_dev, vol) != ESP_CODEC_DEV_OK) { + return luaL_error(L, "audio set_volume: set failed"); + } + dac->out_vol = vol; + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.get_volume(output_handle) -> pct + * -------------------------------------------------------------------------- */ +static int lua_audio_get_volume(lua_State *L) +{ + audio_lua_handle_t *dac = lua_audio_check_handle(L, 1, AUDIO_HANDLE_OUTPUT, "get_volume"); + int vol = 0; + + if (esp_codec_dev_get_out_vol(dac->codec_dev, &vol) != ESP_CODEC_DEV_OK) { + return luaL_error(L, "audio get_volume: get failed"); + } + lua_pushinteger(L, vol); + return 1; +} + +/* -------------------------------------------------------------------------- + * audio.set_mute(output_handle, bool) -> nil + * -------------------------------------------------------------------------- */ +static int lua_audio_set_mute(lua_State *L) +{ + audio_lua_handle_t *dac = lua_audio_check_handle(L, 1, AUDIO_HANDLE_OUTPUT, "set_mute"); + bool mute = lua_toboolean(L, 2); + + if (esp_codec_dev_set_out_mute(dac->codec_dev, mute) != ESP_CODEC_DEV_OK) { + return luaL_error(L, "audio set_mute: set failed"); + } + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.set_gain(input_handle, db) -> nil + * -------------------------------------------------------------------------- */ +static int lua_audio_set_gain(lua_State *L) +{ + audio_lua_handle_t *adc = lua_audio_check_handle(L, 1, AUDIO_HANDLE_INPUT, "set_gain"); + float db = (float)luaL_checknumber(L, 2); + + if (esp_codec_dev_set_in_gain(adc->codec_dev, db) != ESP_CODEC_DEV_OK) { + return luaL_error(L, "audio set_gain: set failed"); + } + adc->in_gain_db = db; + return 0; +} + +/* -------------------------------------------------------------------------- + * audio.mic_read_level(input_handle [, duration_ms]) -> { rms, peak, duration_ms } + * -------------------------------------------------------------------------- */ +static int lua_audio_mic_read_level(lua_State *L) +{ + audio_lua_handle_t *adc = lua_audio_check_handle(L, 1, AUDIO_HANDLE_INPUT, "mic_read_level"); + uint32_t duration_ms = (uint32_t)luaL_optinteger(L, 2, 100); + uint8_t *buf = NULL; + uint32_t total_bytes; + int64_t sum_sq = 0; + int32_t peak = 0; + uint32_t n_samples = 0; + + if (duration_ms == 0) { + return luaL_error(L, "audio mic_read_level: duration_ms must be positive"); + } + if (adc->bits_per_sample != 16) { + return luaL_error(L, "audio mic_read_level: only 16-bit PCM input is supported"); + } + + total_bytes = + (uint32_t)((uint64_t)adc->sample_rate * duration_ms / 1000) * + adc->channels * adc->bytes_per_sample; + + buf = malloc(AUDIO_CHUNK_BYTES); + if (!buf) { + luaL_error(L, "audio mic_read_level: out of memory"); + goto cleanup; + } + + uint32_t captured = 0; + while (captured < total_bytes) { + uint32_t chunk = total_bytes - captured; + if (chunk > AUDIO_CHUNK_BYTES) { + chunk = AUDIO_CHUNK_BYTES; + } + + if (esp_codec_dev_read(adc->codec_dev, buf, (int)chunk) != ESP_CODEC_DEV_OK) { + luaL_error(L, "audio mic_read_level: read failed"); + goto cleanup; + } + + const int16_t *samples = (const int16_t *)buf; + uint32_t n = chunk / sizeof(int16_t); + for (uint32_t i = 0; i < n; i++) { + int32_t s = samples[i]; + sum_sq += (int64_t)s * s; + if (s < 0) { + s = -s; + } + if (s > peak) { + peak = s; + } + } + n_samples += n; + captured += chunk; + } + +cleanup: + free(buf); + int32_t rms = (n_samples > 0) ? (int32_t)sqrt((double)sum_sq / n_samples) : 0; + + lua_newtable(L); + lua_pushinteger(L, rms); + lua_setfield(L, -2, "rms"); + lua_pushinteger(L, peak); + lua_setfield(L, -2, "peak"); + lua_pushinteger(L, duration_ms); + lua_setfield(L, -2, "duration_ms"); + return 1; +} + +/* -------------------------------------------------------------------------- + * Module registration + * -------------------------------------------------------------------------- */ +int luaopen_audio(lua_State *L) +{ + static const luaL_Reg funcs[] = { + {"new_input", lua_audio_new_input}, + {"new_output", lua_audio_new_output}, + {"close", lua_audio_close}, + {"play_wav", lua_audio_play_wav}, + {"record_wav", lua_audio_record_wav}, + {"loopback", lua_audio_loopback}, + {"set_volume", lua_audio_set_volume}, + {"get_volume", lua_audio_get_volume}, + {"set_mute", lua_audio_set_mute}, + {"set_gain", lua_audio_set_gain}, + {"mic_read_level", lua_audio_mic_read_level}, + {NULL, NULL}, + }; + if (luaL_newmetatable(L, AUDIO_HANDLE_METATABLE)) { + lua_pushcfunction(L, lua_audio_handle_gc); + lua_setfield(L, -2, "__gc"); + } + lua_pop(L, 1); + lua_newtable(L); + luaL_setfuncs(L, funcs, 0); + return 1; +} + +esp_err_t lua_module_audio_register(void) +{ + return cap_lua_register_module("audio", luaopen_audio); +} diff --git a/components/lua_modules/lua_module_audio/skills/lua_module_audio.md b/components/lua_modules/lua_module_audio/skills/lua_module_audio.md new file mode 100644 index 0000000..77d9e0e --- /dev/null +++ b/components/lua_modules/lua_module_audio/skills/lua_module_audio.md @@ -0,0 +1,28 @@ +# Lua Audio + +This skill describes how to correctly use audio when writing Lua scripts. + +## How to call +- Import it with `local audio = require("audio")` +- Call `audio.new_input(codec_dev_handle, sample_rate, channels, bits_per_sample [, gain_db])` to create an input handle +- Call `audio.new_output(codec_dev_handle, sample_rate, channels, bits_per_sample [, volume])` to create an output handle +- Call `audio.play_wav(output_handle, path)` to play a WAV file under `/fatfs/data/` +- Call `audio.record_wav(input_handle, path, duration_ms)` to record audio to a WAV file under `/fatfs/data/` +- Call `audio.loopback(input_handle, output_handle [, duration_ms])` to route input to output for monitoring +- Call `audio.set_volume(output_handle, pct)`, `audio.get_volume(output_handle)`, `audio.set_mute(output_handle, enabled)`, or `audio.set_gain(input_handle, db)` to adjust levels +- Call `audio.mic_read_level(input_handle [, duration_ms])` to read microphone level statistics such as `rms` and `peak` +- Call `audio.close(handle)` when a created handle is no longer needed + +## Example +```lua +local audio = require("audio") +local bm = require("board_manager") + +local output_codec, rate, channels, bits = + bm.get_audio_codec_output_params("audio_dac") +local output = audio.new_output(output_codec, rate, channels, bits) + +audio.set_volume(output, 60) +audio.play_wav(output, "/fatfs/data/test.wav") +audio.close(output) +``` diff --git a/components/lua_modules/lua_module_audio/skills/skills_list.json b/components/lua_modules/lua_module_audio/skills/skills_list.json new file mode 100644 index 0000000..938bbd9 --- /dev/null +++ b/components/lua_modules/lua_module_audio/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_audio", + "file": "lua_module_audio.md", + "title": "lua_module_audio", + "summary": "How to create audio input/output handles and play, record, or inspect audio from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_board_manager/CMakeLists.txt b/components/lua_modules/lua_module_board_manager/CMakeLists.txt new file mode 100644 index 0000000..c60148f --- /dev/null +++ b/components/lua_modules/lua_module_board_manager/CMakeLists.txt @@ -0,0 +1,9 @@ +idf_component_register( + SRC_DIRS + "." + INCLUDE_DIRS + "include" + REQUIRES + cap_lua + espressif__esp_board_manager +) diff --git a/components/lua_modules/lua_module_board_manager/include/lua_module_board_manager.h b/components/lua_modules/lua_module_board_manager/include/lua_module_board_manager.h new file mode 100644 index 0000000..84316c4 --- /dev/null +++ b/components/lua_modules/lua_module_board_manager/include/lua_module_board_manager.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "lua.h" +#include "esp_err.h" + +int luaopen_board_manager(lua_State *L); +esp_err_t lua_module_board_manager_register(void); diff --git a/components/lua_modules/lua_module_board_manager/lua_module_board_manager.c b/components/lua_modules/lua_module_board_manager/lua_module_board_manager.c new file mode 100644 index 0000000..cfcedc0 --- /dev/null +++ b/components/lua_modules/lua_module_board_manager/lua_module_board_manager.c @@ -0,0 +1,464 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_board_manager.h" + +#include +#include "esp_err.h" +#include "lauxlib.h" +#include "esp_board_manager_includes.h" +#include "cap_lua.h" + +/* -------------------------------------------------------------------------- + * Helpers + * -------------------------------------------------------------------------- */ + +/** Push nil + error message string, return 2. Convenience for error paths. */ +static int push_err(lua_State *L, esp_err_t err, const char *msg) +{ + lua_pushnil(L); + if (msg) { + lua_pushfstring(L, "%s: %s", msg, esp_err_to_name(err)); + } else { + lua_pushstring(L, esp_err_to_name(err)); + } + return 2; +} + +static esp_err_t lua_module_board_manager_get_camera_paths(const char **dev_path, + const char **meta_path) +{ +#if CONFIG_ESP_BOARD_DEV_CAMERA_SUPPORT + dev_camera_handle_t *camera_handle = NULL; + esp_err_t err; + + if (dev_path == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *dev_path = NULL; + if (meta_path != NULL) { + *meta_path = NULL; + } + + err = esp_board_manager_get_device_handle(ESP_BOARD_DEVICE_NAME_CAMERA, + (void **)&camera_handle); + if (err != ESP_OK) { + return err; + } + if (camera_handle == NULL || camera_handle->dev_path == NULL) { + return ESP_ERR_NOT_FOUND; + } + + *dev_path = camera_handle->dev_path; + if (meta_path != NULL) { + *meta_path = camera_handle->meta_path; + } + return ESP_OK; +#else + if (dev_path != NULL) { + *dev_path = NULL; + } + if (meta_path != NULL) { + *meta_path = NULL; + } + return ESP_ERR_NOT_SUPPORTED; +#endif +} + +/* -------------------------------------------------------------------------- + * board_manager.get_board_info() -> table + * + * Returns a table: + * { name, chip, version, description, manufacturer } + * -------------------------------------------------------------------------- */ +static int lua_bm_get_board_info(lua_State *L) +{ + esp_board_info_t info = {0}; + esp_err_t err = esp_board_manager_get_board_info(&info); + if (err != ESP_OK) { + return push_err(L, err, "get_board_info"); + } + lua_newtable(L); + lua_pushstring(L, info.name ? info.name : ""); + lua_setfield(L, -2, "name"); + lua_pushstring(L, info.chip ? info.chip : ""); + lua_setfield(L, -2, "chip"); + lua_pushstring(L, info.version ? info.version : ""); + lua_setfield(L, -2, "version"); + lua_pushstring(L, info.description ? info.description : ""); + lua_setfield(L, -2, "description"); + lua_pushstring(L, info.manufacturer ? info.manufacturer : ""); + lua_setfield(L, -2, "manufacturer"); + return 1; +} + +/* -------------------------------------------------------------------------- + * board_manager.init_device(name) -> true | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_bm_init_device(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + esp_err_t err = esp_board_manager_init_device_by_name(name); + if (err != ESP_OK) { + return push_err(L, err, name); + } + lua_pushboolean(L, 1); + return 1; +} + +/* -------------------------------------------------------------------------- + * board_manager.deinit_device(name) -> true | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_bm_deinit_device(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + esp_err_t err = esp_board_manager_deinit_device_by_name(name); + if (err != ESP_OK) { + return push_err(L, err, name); + } + lua_pushboolean(L, 1); + return 1; +} + +/* -------------------------------------------------------------------------- + * board_manager.get_device_handle(name) -> lightuserdata | nil, errmsg + * + * Returns the raw device handle as a lightuserdata pointer. + * Useful when another C-backed Lua module needs to wrap it. + * -------------------------------------------------------------------------- */ +static int lua_bm_get_device_handle(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + void *handle = NULL; + esp_err_t err = esp_board_manager_get_device_handle(name, &handle); + if (err != ESP_OK) { + return push_err(L, err, name); + } + if (handle == NULL) { + lua_pushnil(L); + lua_pushstring(L, "device handle is NULL"); + return 2; + } + lua_pushlightuserdata(L, handle); + return 1; +} + +/* -------------------------------------------------------------------------- + * board_manager.get_device_config_handle(name) -> lightuserdata | nil, errmsg + * + * Returns the raw device config pointer as lightuserdata. + * Useful for passing board-manager-generated config structs into other modules. + * -------------------------------------------------------------------------- */ +static int lua_bm_get_device_config_handle(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + void *config = NULL; + esp_err_t err = esp_board_manager_get_device_config(name, &config); + if (err != ESP_OK) { + return push_err(L, err, name); + } + if (config == NULL) { + lua_pushnil(L); + lua_pushstring(L, "device config is NULL"); + return 2; + } + lua_pushlightuserdata(L, config); + return 1; +} + +/* -------------------------------------------------------------------------- + * board_manager.get_display_lcd_params(name) + * -> panel_handle, io_handle, lcd_width, lcd_height | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_bm_get_display_lcd_params(lua_State *L) +{ +#ifdef CONFIG_ESP_BOARD_DEV_DISPLAY_LCD_SUPPORT + const char *name = luaL_checkstring(L, 1); + void *handle = NULL; + void *config = NULL; + esp_err_t err = esp_board_manager_get_device_handle(name, &handle); + if (err != ESP_OK) { + return push_err(L, err, name); + } + err = esp_board_manager_get_device_config(name, &config); + if (err != ESP_OK) { + return push_err(L, err, name); + } + + dev_display_lcd_handles_t *lcd_handles = (dev_display_lcd_handles_t *)handle; + dev_display_lcd_config_t *lcd_cfg = (dev_display_lcd_config_t *)config; + if (lcd_handles == NULL || lcd_cfg == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "display_lcd '%s' handle/config is NULL", name); + return 2; + } + if (lcd_handles->panel_handle == NULL || lcd_handles->io_handle == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "display_lcd '%s' panel/io handle is NULL", name); + return 2; + } + + lua_pushlightuserdata(L, lcd_handles->panel_handle); + lua_pushlightuserdata(L, lcd_handles->io_handle); + lua_pushinteger(L, lcd_cfg->lcd_width); + lua_pushinteger(L, lcd_cfg->lcd_height); + return 4; +#else + lua_pushnil(L); + lua_pushstring(L, "display lcd support is disabled"); + return 2; +#endif +} + +/* -------------------------------------------------------------------------- + * board_manager.get_lcd_touch_handle(name) -> lightuserdata | nil, errmsg + * + * Returns the raw esp_lcd_touch_handle_t from the board-manager wrapper handle. + * -------------------------------------------------------------------------- */ +static int lua_bm_get_lcd_touch_handle(lua_State *L) +{ +#ifdef CONFIG_ESP_BOARD_DEV_LCD_TOUCH_I2C_SUPPORT + const char *name = luaL_checkstring(L, 1); + void *handle = NULL; + esp_err_t err = esp_board_manager_get_device_handle(name, &handle); + if (err != ESP_OK) { + return push_err(L, err, name); + } + + dev_lcd_touch_i2c_handles_t *touch_handles = (dev_lcd_touch_i2c_handles_t *)handle; + if (touch_handles == NULL || touch_handles->touch_handle == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "lcd_touch '%s' handle is NULL", name); + return 2; + } + + lua_pushlightuserdata(L, touch_handles->touch_handle); + return 1; +#else + lua_pushnil(L); + lua_pushstring(L, "lcd touch support is disabled"); + return 2; +#endif +} + +#ifdef CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT +static esp_err_t lua_bm_get_i2s_audio_format(const periph_i2s_config_t *i2s_cfg, + uint32_t *sample_rate, + uint8_t *channels, + uint8_t *bits_per_sample) +{ + if (i2s_cfg == NULL || sample_rate == NULL || channels == NULL || bits_per_sample == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (i2s_cfg->mode == I2S_COMM_MODE_STD) { + *sample_rate = i2s_cfg->i2s_cfg.std.clk_cfg.sample_rate_hz; + *channels = (i2s_cfg->i2s_cfg.std.slot_cfg.slot_mode == I2S_SLOT_MODE_STEREO) ? 2 : 1; + *bits_per_sample = (uint8_t)i2s_cfg->i2s_cfg.std.slot_cfg.data_bit_width; + return ESP_OK; + } + +#if CONFIG_SOC_I2S_SUPPORTS_TDM + if (i2s_cfg->mode == I2S_COMM_MODE_TDM) { + *sample_rate = i2s_cfg->i2s_cfg.tdm.clk_cfg.sample_rate_hz; + *channels = (uint8_t)i2s_cfg->i2s_cfg.tdm.slot_cfg.total_slot; + *bits_per_sample = (uint8_t)i2s_cfg->i2s_cfg.tdm.slot_cfg.data_bit_width; + return ESP_OK; + } +#endif + +#if CONFIG_SOC_I2S_SUPPORTS_PDM_TX + if (i2s_cfg->mode == I2S_COMM_MODE_PDM && (i2s_cfg->direction & I2S_DIR_TX)) { + *sample_rate = i2s_cfg->i2s_cfg.pdm_tx.clk_cfg.sample_rate_hz; + *channels = (i2s_cfg->i2s_cfg.pdm_tx.slot_cfg.slot_mode == I2S_SLOT_MODE_STEREO) ? 2 : 1; + *bits_per_sample = (uint8_t)i2s_cfg->i2s_cfg.pdm_tx.slot_cfg.data_bit_width; + return ESP_OK; + } +#endif + +#if CONFIG_SOC_I2S_SUPPORTS_PDM_RX + if (i2s_cfg->mode == I2S_COMM_MODE_PDM && (i2s_cfg->direction & I2S_DIR_RX)) { + *sample_rate = i2s_cfg->i2s_cfg.pdm_rx.clk_cfg.sample_rate_hz; + *channels = (i2s_cfg->i2s_cfg.pdm_rx.slot_cfg.slot_mode == I2S_SLOT_MODE_STEREO) ? 2 : 1; + *bits_per_sample = (uint8_t)i2s_cfg->i2s_cfg.pdm_rx.slot_cfg.data_bit_width; + return ESP_OK; + } +#endif + + return ESP_ERR_NOT_SUPPORTED; +} + +static esp_err_t lua_bm_get_adc_audio_format(const board_codec_adc_t *adc_cfg, + uint32_t *sample_rate, + uint8_t *channels, + uint8_t *bits_per_sample) +{ + if (adc_cfg == NULL || sample_rate == NULL || channels == NULL || bits_per_sample == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (adc_cfg->sample_rate_hz == 0 || adc_cfg->pattern_num == 0) { + return ESP_ERR_INVALID_ARG; + } + + *sample_rate = adc_cfg->sample_rate_hz; + *channels = adc_cfg->pattern_num; + *bits_per_sample = 16; + return ESP_OK; +} +#endif // CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT + +static int lua_bm_get_audio_codec_common(lua_State *L, bool for_input) +{ +#ifdef CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT + const char *name = luaL_checkstring(L, 1); + void *handle = NULL; + void *config = NULL; + void *periph_config = NULL; + esp_err_t err = esp_board_manager_get_device_handle(name, &handle); + if (err != ESP_OK) { + return push_err(L, err, name); + } + err = esp_board_manager_get_device_config(name, &config); + if (err != ESP_OK) { + return push_err(L, err, name); + } + + dev_audio_codec_handles_t *codec_handles = (dev_audio_codec_handles_t *)handle; + dev_audio_codec_config_t *codec_cfg = (dev_audio_codec_config_t *)config; + if (codec_handles == NULL || codec_cfg == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "audio_codec '%s' handle/config is NULL", name); + return 2; + } + if (codec_handles->codec_dev == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "audio_codec '%s' codec_dev handle is NULL", name); + return 2; + } + uint32_t sample_rate = 0; + uint8_t channels = 0; + uint8_t bits_per_sample = 0; + + if (codec_cfg->i2s_cfg.name != NULL) { + err = esp_board_manager_get_periph_config(codec_cfg->i2s_cfg.name, &periph_config); + if (err != ESP_OK) { + return push_err(L, err, codec_cfg->i2s_cfg.name); + } + + periph_i2s_config_t *i2s_cfg = (periph_i2s_config_t *)periph_config; + err = lua_bm_get_i2s_audio_format(i2s_cfg, &sample_rate, &channels, &bits_per_sample); + if (err != ESP_OK) { + return push_err(L, err, "audio codec i2s mode is not supported"); + } + } else if (for_input && codec_cfg->data_if_type == DEV_AUDIO_CODEC_DATA_IF_TYPE_ADC) { + err = lua_bm_get_adc_audio_format(&codec_cfg->adc_cfg, &sample_rate, &channels, &bits_per_sample); + if (err != ESP_OK) { + return push_err(L, err, "audio codec adc config is invalid"); + } + } else { + lua_pushnil(L); + lua_pushfstring(L, "audio_codec '%s' i2s config name is NULL", name); + return 2; + } + + if (for_input) { + if (!codec_cfg->adc_enabled) { + lua_pushnil(L); + lua_pushfstring(L, "audio_codec '%s' does not enable ADC input", name); + return 2; + } + lua_pushlightuserdata(L, codec_handles->codec_dev); + lua_pushinteger(L, (lua_Integer)sample_rate); + lua_pushinteger(L, (lua_Integer)channels); + lua_pushinteger(L, (lua_Integer)bits_per_sample); + lua_pushnumber(L, (lua_Number)codec_cfg->adc_init_gain); + return 5; + } + + if (!codec_cfg->dac_enabled) { + lua_pushnil(L); + lua_pushfstring(L, "audio_codec '%s' does not enable DAC output", name); + return 2; + } + lua_pushlightuserdata(L, codec_handles->codec_dev); + lua_pushinteger(L, (lua_Integer)sample_rate); + lua_pushinteger(L, (lua_Integer)channels); + lua_pushinteger(L, (lua_Integer)bits_per_sample); + return 4; +#else + (void)for_input; + lua_pushnil(L); + lua_pushstring(L, "audio codec support is disabled"); + return 2; +#endif +} + +/* -------------------------------------------------------------------------- + * board_manager.get_audio_codec_input_params(name) + * -> codec_dev_handle, sample_rate, channels, bits_per_sample, init_gain_db + * -------------------------------------------------------------------------- */ +static int lua_bm_get_audio_codec_input_params(lua_State *L) +{ + return lua_bm_get_audio_codec_common(L, true); +} + +/* -------------------------------------------------------------------------- + * board_manager.get_audio_codec_output_params(name) + * -> codec_dev_handle, sample_rate, channels, bits_per_sample + * -------------------------------------------------------------------------- */ +static int lua_bm_get_audio_codec_output_params(lua_State *L) +{ + return lua_bm_get_audio_codec_common(L, false); +} + +static int lua_bm_get_camera_paths(lua_State *L) +{ + const char *dev_path = NULL; + const char *meta_path = NULL; + esp_err_t err = lua_module_board_manager_get_camera_paths(&dev_path, &meta_path); + + if (err != ESP_OK) { + return push_err(L, err, "get_camera_paths"); + } + + lua_newtable(L); + lua_pushstring(L, dev_path); + lua_setfield(L, -2, "dev_path"); + if (meta_path != NULL) { + lua_pushstring(L, meta_path); + lua_setfield(L, -2, "meta_path"); + } + return 1; +} + +/* -------------------------------------------------------------------------- + * Module registration + * -------------------------------------------------------------------------- */ +int luaopen_board_manager(lua_State *L) +{ + static const luaL_Reg funcs[] = { + {"get_board_info", lua_bm_get_board_info}, + {"init_device", lua_bm_init_device}, + {"deinit_device", lua_bm_deinit_device}, + {"get_device_handle", lua_bm_get_device_handle}, + {"get_device_config_handle", lua_bm_get_device_config_handle}, + {"get_display_lcd_params", lua_bm_get_display_lcd_params}, + {"get_lcd_touch_handle", lua_bm_get_lcd_touch_handle}, + {"get_audio_codec_input_params", lua_bm_get_audio_codec_input_params}, + {"get_audio_codec_output_params", lua_bm_get_audio_codec_output_params}, + {"get_camera_paths", lua_bm_get_camera_paths}, + {NULL, NULL}, + }; + + lua_newtable(L); + luaL_setfuncs(L, funcs, 0); + return 1; +} + +esp_err_t lua_module_board_manager_register(void) +{ + return cap_lua_register_module("board_manager", luaopen_board_manager); +} diff --git a/components/lua_modules/lua_module_board_manager/skills/lua_module_board_manager.md b/components/lua_modules/lua_module_board_manager/skills/lua_module_board_manager.md new file mode 100644 index 0000000..fdb4a7c --- /dev/null +++ b/components/lua_modules/lua_module_board_manager/skills/lua_module_board_manager.md @@ -0,0 +1,30 @@ +# Lua Board Manager + +This skill describes how to correctly use board_manager when writing Lua scripts. + +## How to call +- Import it with `local board_manager = require("board_manager")` +- Call `board_manager.get_board_info()` to read board metadata such as `name`, `chip`, and `version` +- Call `board_manager.init_device(name)` before using a board-managed peripheral +- Call `board_manager.deinit_device(name)` when the peripheral is no longer needed +- Call `board_manager.get_device_handle(name)` or `board_manager.get_device_config_handle(name)` to resolve low-level handles +- Call `board_manager.get_display_lcd_params(name)` to get `panel_handle`, `io_handle`, `lcd_width`, and `lcd_height` +- Call `board_manager.get_lcd_touch_handle(name)` to get the raw LCD touch handle +- Call `board_manager.get_audio_codec_input_params(name)` or `board_manager.get_audio_codec_output_params(name)` to get codec handles and format parameters +- Call `board_manager.get_camera_paths()` to get camera device paths such as `dev_path` and `meta_path` + +## Example +```lua +local board_manager = require("board_manager") + +local info = board_manager.get_board_info() +print(info.name, info.chip) + +board_manager.init_device("display_lcd") +local panel_handle, io_handle, width, height = + board_manager.get_display_lcd_params("display_lcd") +print(width, height) + +local camera_paths = board_manager.get_camera_paths() +print(camera_paths.dev_path) +``` diff --git a/components/lua_modules/lua_module_board_manager/skills/skills_list.json b/components/lua_modules/lua_module_board_manager/skills/skills_list.json new file mode 100644 index 0000000..473ebaf --- /dev/null +++ b/components/lua_modules/lua_module_board_manager/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_board_manager", + "file": "lua_module_board_manager.md", + "title": "lua_module_board_manager", + "summary": "How to query board information and resolve device handles and parameters from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_button/CMakeLists.txt b/components/lua_modules/lua_module_button/CMakeLists.txt new file mode 100644 index 0000000..fca9fb7 --- /dev/null +++ b/components/lua_modules/lua_module_button/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register( + SRC_DIRS + "." + INCLUDE_DIRS + "include" + REQUIRES + cap_lua +) diff --git a/components/lua_modules/lua_module_button/idf_component.yml b/components/lua_modules/lua_module_button/idf_component.yml new file mode 100644 index 0000000..e413a0e --- /dev/null +++ b/components/lua_modules/lua_module_button/idf_component.yml @@ -0,0 +1,3 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/button: "*" diff --git a/components/lua_modules/lua_module_button/include/lua_module_button.h b/components/lua_modules/lua_module_button/include/lua_module_button.h new file mode 100644 index 0000000..fa5b2c5 --- /dev/null +++ b/components/lua_modules/lua_module_button/include/lua_module_button.h @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "lua.h" +#include "esp_err.h" + +int luaopen_button(lua_State *L); +esp_err_t lua_module_button_register(void); diff --git a/components/lua_modules/lua_module_button/lua_module_button.c b/components/lua_modules/lua_module_button/lua_module_button.c new file mode 100644 index 0000000..f8b642f --- /dev/null +++ b/components/lua_modules/lua_module_button/lua_module_button.c @@ -0,0 +1,498 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_button.h" + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "esp_err.h" +#include "esp_log.h" +#include "lauxlib.h" +#include "iot_button.h" +#include "button_gpio.h" +#include "cap_lua.h" + +static const char *TAG = "lua_button"; + +/* -------------------------------------------------------------------------- + * Constants + * -------------------------------------------------------------------------- */ +#define BTN_MAX_HANDLES 8 +#define BTN_EVENT_QUEUE_SIZE 16 +#define BTN_HANDLE_METATABLE "lua_button_handle" + +/* -------------------------------------------------------------------------- + * Internal types + * -------------------------------------------------------------------------- */ +typedef struct { + button_handle_t handle; + button_event_t event; + uint8_t repeat_count; + uint32_t pressed_time_ms; +} btn_event_item_t; + +typedef struct { + button_handle_t handle; + int lua_refs[BUTTON_EVENT_MAX]; /* LUA_NOREF if not registered */ + bool cbs_registered[BUTTON_EVENT_MAX]; +} btn_lua_reg_t; + +typedef struct { + button_handle_t handle; +} btn_lua_handle_ud_t; + +/* -------------------------------------------------------------------------- + * Module-level state + * -------------------------------------------------------------------------- */ +static btn_lua_reg_t s_regs[BTN_MAX_HANDLES]; +static int s_num_regs = 0; +static QueueHandle_t s_queue = NULL; + +/* -------------------------------------------------------------------------- + * Event name tables + * -------------------------------------------------------------------------- */ +static const char *const s_event_names[BUTTON_EVENT_MAX] = { + "press_down", + "press_up", + "press_repeat", + "press_repeat_done", + "single_click", + "double_click", + "multiple_click", + "long_press_start", + "long_press_hold", + "long_press_up", + "press_end", +}; + +static const char *btn_event_to_str(button_event_t ev) +{ + if ((unsigned)ev < BUTTON_EVENT_MAX) { + return s_event_names[ev]; + } + return "unknown"; +} + +static button_event_t btn_event_from_str(const char *s) +{ + for (int i = 0; i < BUTTON_EVENT_MAX; i++) { + if (strcmp(s, s_event_names[i]) == 0) { + return (button_event_t)i; + } + } + return BUTTON_EVENT_MAX; +} + +/* -------------------------------------------------------------------------- + * Registry helpers + * -------------------------------------------------------------------------- */ +static btn_lua_reg_t *btn_find_reg(button_handle_t handle) +{ + for (int i = 0; i < s_num_regs; i++) { + if (s_regs[i].handle == handle) { + return &s_regs[i]; + } + } + return NULL; +} + +static btn_lua_reg_t *btn_add_reg(button_handle_t handle) +{ + btn_lua_reg_t *reg = btn_find_reg(handle); + if (reg) { + return reg; + } + if (s_num_regs >= BTN_MAX_HANDLES) { + return NULL; + } + + reg = &s_regs[s_num_regs++]; + memset(reg, 0, sizeof(*reg)); + reg->handle = handle; + for (int i = 0; i < BUTTON_EVENT_MAX; i++) { + reg->lua_refs[i] = LUA_NOREF; + } + return reg; +} + +static void btn_remove_reg(lua_State *L, btn_lua_reg_t *reg) +{ + int idx = (int)(reg - s_regs); + if (idx < 0 || idx >= s_num_regs) { + return; + } + + for (int i = 0; i < BUTTON_EVENT_MAX; i++) { + if (reg->cbs_registered[i]) { + esp_err_t err = iot_button_unregister_cb(reg->handle, (button_event_t)i, NULL); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "unregister_cb failed for event %s: %s", + btn_event_to_str((button_event_t)i), esp_err_to_name(err)); + } + } + if (reg->lua_refs[i] != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, reg->lua_refs[i]); + } + } + + s_num_regs--; + if (idx != s_num_regs) { + s_regs[idx] = s_regs[s_num_regs]; + } + memset(&s_regs[s_num_regs], 0, sizeof(s_regs[s_num_regs])); +} + +static btn_lua_handle_ud_t *lua_btn_check_ud(lua_State *L, int idx) +{ + btn_lua_handle_ud_t *ud = + (btn_lua_handle_ud_t *)luaL_checkudata(L, idx, BTN_HANDLE_METATABLE); + + if (!ud || !ud->handle) { + luaL_error(L, "button handle expected"); + return NULL; + } + return ud; +} + +static button_handle_t lua_btn_check_handle(lua_State *L, int idx) +{ + return lua_btn_check_ud(L, idx)->handle; +} + +static int lua_btn_handle_gc(lua_State *L) +{ + btn_lua_handle_ud_t *ud = + (btn_lua_handle_ud_t *)luaL_testudata(L, 1, BTN_HANDLE_METATABLE); + btn_lua_reg_t *reg = NULL; + + if (!ud || !ud->handle) { + return 0; + } + + reg = btn_find_reg(ud->handle); + if (reg) { + btn_remove_reg(L, reg); + } + iot_button_delete(ud->handle); + ud->handle = NULL; + return 0; +} + +static void btn_c_event_cb(void *btn_handle, void *user_data) +{ + (void)user_data; + + if (!s_queue) { + return; + } + + button_handle_t handle = (button_handle_t)btn_handle; + btn_event_item_t item = { + .handle = handle, + .event = iot_button_get_event(handle), + .repeat_count = iot_button_get_repeat(handle), + .pressed_time_ms = iot_button_get_pressed_time(handle), + }; + + if (xQueueSend(s_queue, &item, 0) != pdTRUE) { + ESP_LOGW(TAG, "event queue full, dropped button event"); + } +} + +/* -------------------------------------------------------------------------- + * button.new(gpio_num [, active_level [, long_press_ms [, short_press_ms]]]) + * -> handle | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_btn_new(lua_State *L) +{ + int gpio_num = (int)luaL_checkinteger(L, 1); + int active_level = (int)luaL_optinteger(L, 2, 0); + int long_press_ms = (int)luaL_optinteger(L, 3, 0); + int short_press_ms = (int)luaL_optinteger(L, 4, 0); + button_handle_t btn = NULL; + + if (active_level != 0 && active_level != 1) { + lua_pushnil(L); + lua_pushstring(L, "active_level must be 0 or 1"); + return 2; + } + + button_config_t btn_cfg = { + .long_press_time = (uint16_t)long_press_ms, + .short_press_time = (uint16_t)short_press_ms, + }; + button_gpio_config_t gpio_cfg = { + .gpio_num = gpio_num, + .active_level = (uint8_t)active_level, + .enable_power_save = false, + .disable_pull = false, + }; + + esp_err_t err = iot_button_new_gpio_device(&btn_cfg, &gpio_cfg, &btn); + if (err != ESP_OK || btn == NULL) { + lua_pushnil(L); + lua_pushfstring(L, "button.new failed for gpio %d: %s", + gpio_num, esp_err_to_name(err)); + return 2; + } + + if (!btn_add_reg(btn)) { + iot_button_delete(btn); + lua_pushnil(L); + lua_pushfstring(L, "too many button handles (max %d)", BTN_MAX_HANDLES); + return 2; + } + + btn_lua_handle_ud_t *ud = + (btn_lua_handle_ud_t *)lua_newuserdata(L, sizeof(*ud)); + ud->handle = btn; + luaL_getmetatable(L, BTN_HANDLE_METATABLE); + lua_setmetatable(L, -2); + return 1; +} + +/* -------------------------------------------------------------------------- + * button.close(handle) -> true | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_btn_close(lua_State *L) +{ + btn_lua_handle_ud_t *ud = lua_btn_check_ud(L, 1); + button_handle_t handle = ud->handle; + btn_lua_reg_t *reg = btn_find_reg(handle); + esp_err_t err; + + if (!reg) { + lua_pushnil(L); + lua_pushstring(L, "invalid or closed button handle"); + return 2; + } + + btn_remove_reg(L, reg); + + err = iot_button_delete(handle); + if (err != ESP_OK) { + lua_pushnil(L); + lua_pushfstring(L, "button.close failed: %s", esp_err_to_name(err)); + return 2; + } + + ud->handle = NULL; + lua_pushboolean(L, 1); + return 1; +} + +/* -------------------------------------------------------------------------- + * button.get_key_level(handle) -> level + * -------------------------------------------------------------------------- */ +static int lua_btn_get_key_level(lua_State *L) +{ + button_handle_t handle = lua_btn_check_handle(L, 1); + btn_lua_reg_t *reg = btn_find_reg(handle); + + if (!reg) { + lua_pushnil(L); + lua_pushstring(L, "invalid or closed button handle"); + return 2; + } + + lua_pushinteger(L, iot_button_get_key_level(handle)); + return 1; +} + +/* -------------------------------------------------------------------------- + * button.on(handle, event_str, fn) -> true | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_btn_on(lua_State *L) +{ + button_handle_t handle = lua_btn_check_handle(L, 1); + const char *event_str = luaL_checkstring(L, 2); + btn_lua_reg_t *reg = btn_find_reg(handle); + + luaL_checktype(L, 3, LUA_TFUNCTION); + + if (!reg) { + lua_pushnil(L); + lua_pushstring(L, "invalid or closed button handle"); + return 2; + } + + button_event_t ev = btn_event_from_str(event_str); + if (ev == BUTTON_EVENT_MAX) { + lua_pushnil(L); + lua_pushfstring(L, "unknown event '%s'", event_str); + return 2; + } + + if (!s_queue) { + s_queue = xQueueCreate(BTN_EVENT_QUEUE_SIZE, sizeof(btn_event_item_t)); + if (!s_queue) { + lua_pushnil(L); + lua_pushstring(L, "failed to create event queue"); + return 2; + } + } + + if (reg->lua_refs[ev] != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, reg->lua_refs[ev]); + } + lua_pushvalue(L, 3); + reg->lua_refs[ev] = luaL_ref(L, LUA_REGISTRYINDEX); + + if (!reg->cbs_registered[ev]) { + esp_err_t err = iot_button_register_cb(handle, ev, NULL, btn_c_event_cb, NULL); + if (err != ESP_OK) { + luaL_unref(L, LUA_REGISTRYINDEX, reg->lua_refs[ev]); + reg->lua_refs[ev] = LUA_NOREF; + lua_pushnil(L); + lua_pushfstring(L, "register_cb failed for event '%s': %s", + event_str, esp_err_to_name(err)); + return 2; + } + reg->cbs_registered[ev] = true; + } + + lua_pushboolean(L, 1); + return 1; +} + +/* -------------------------------------------------------------------------- + * button.off(handle [, event_str]) -> true | nil, errmsg + * -------------------------------------------------------------------------- */ +static int lua_btn_off(lua_State *L) +{ + button_handle_t handle = lua_btn_check_handle(L, 1); + const char *event_str = luaL_optstring(L, 2, NULL); + btn_lua_reg_t *reg = btn_find_reg(handle); + + if (!reg) { + lua_pushnil(L); + lua_pushstring(L, "invalid or closed button handle"); + return 2; + } + + if (event_str) { + button_event_t ev = btn_event_from_str(event_str); + if (ev == BUTTON_EVENT_MAX) { + lua_pushnil(L); + lua_pushfstring(L, "unknown event '%s'", event_str); + return 2; + } + if (reg->lua_refs[ev] != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, reg->lua_refs[ev]); + reg->lua_refs[ev] = LUA_NOREF; + } + if (reg->cbs_registered[ev]) { + esp_err_t err = iot_button_unregister_cb(handle, ev, NULL); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + lua_pushnil(L); + lua_pushfstring(L, "unregister_cb failed for event '%s': %s", + event_str, esp_err_to_name(err)); + return 2; + } + reg->cbs_registered[ev] = false; + } + } else { + for (int i = 0; i < BUTTON_EVENT_MAX; i++) { + if (reg->lua_refs[i] != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, reg->lua_refs[i]); + reg->lua_refs[i] = LUA_NOREF; + } + if (reg->cbs_registered[i]) { + esp_err_t err = iot_button_unregister_cb(handle, (button_event_t)i, NULL); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + lua_pushnil(L); + lua_pushfstring(L, "unregister_cb failed for event '%s': %s", + btn_event_to_str((button_event_t)i), esp_err_to_name(err)); + return 2; + } + reg->cbs_registered[i] = false; + } + } + } + + lua_pushboolean(L, 1); + return 1; +} + +/* -------------------------------------------------------------------------- + * button.dispatch() -> count + * -------------------------------------------------------------------------- */ +static int lua_btn_dispatch(lua_State *L) +{ + int count = 0; + if (!s_queue) { + lua_pushinteger(L, 0); + return 1; + } + + btn_event_item_t item; + while (xQueueReceive(s_queue, &item, 0) == pdTRUE) { + btn_lua_reg_t *reg = btn_find_reg(item.handle); + if (!reg) { + continue; + } + + button_event_t ev = item.event; + if ((unsigned)ev >= BUTTON_EVENT_MAX) { + continue; + } + + int ref = reg->lua_refs[ev]; + if (ref == LUA_NOREF) { + continue; + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + lua_newtable(L); + lua_pushlightuserdata(L, item.handle); + lua_setfield(L, -2, "handle"); + lua_pushstring(L, btn_event_to_str(ev)); + lua_setfield(L, -2, "event"); + lua_pushinteger(L, item.repeat_count); + lua_setfield(L, -2, "repeat_count"); + lua_pushinteger(L, item.pressed_time_ms); + lua_setfield(L, -2, "pressed_time_ms"); + + if (lua_pcall(L, 1, 0, 0) != LUA_OK) { + ESP_LOGW(TAG, "button callback error: %s", lua_tostring(L, -1)); + lua_pop(L, 1); + } + count++; + } + + lua_pushinteger(L, count); + return 1; +} + +/* -------------------------------------------------------------------------- + * Module registration + * -------------------------------------------------------------------------- */ +int luaopen_button(lua_State *L) +{ + static const luaL_Reg funcs[] = { + {"new", lua_btn_new}, + {"close", lua_btn_close}, + {"get_key_level", lua_btn_get_key_level}, + {"on", lua_btn_on}, + {"off", lua_btn_off}, + {"dispatch", lua_btn_dispatch}, + {NULL, NULL}, + }; + if (luaL_newmetatable(L, BTN_HANDLE_METATABLE)) { + lua_pushcfunction(L, lua_btn_handle_gc); + lua_setfield(L, -2, "__gc"); + } + lua_pop(L, 1); + lua_newtable(L); + luaL_setfuncs(L, funcs, 0); + return 1; +} + +esp_err_t lua_module_button_register(void) +{ + return cap_lua_register_module("button", luaopen_button); +} diff --git a/components/lua_modules/lua_module_button/skills/lua_module_button.md b/components/lua_modules/lua_module_button/skills/lua_module_button.md new file mode 100644 index 0000000..d83d955 --- /dev/null +++ b/components/lua_modules/lua_module_button/skills/lua_module_button.md @@ -0,0 +1,26 @@ +# Lua Button + +This skill describes how to correctly use button when writing Lua scripts. + +## How to call +- Import it with `local button = require("button")` +- Call `local handle = button.new(gpio_num [, active_level [, long_press_ms [, short_press_ms]]])` to create a button handle +- Call `button.on(handle, event, callback)` to subscribe to a button event +- Supported event names include `press_down`, `press_up`, `single_click`, `double_click`, `multiple_click`, `long_press_start`, `long_press_hold`, and `long_press_up` +- Call `button.off(handle [, event])` to remove a subscription or clear callbacks +- Call `button.dispatch()` to poll and dispatch pending button events +- Call `button.get_key_level(handle)` to read the current key level +- Call `button.close(handle)` when the handle is no longer needed + +## Example +```lua +local button = require("button") + +local handle = button.new(0, 0) +button.on(handle, "single_click", function(evt) + print(evt.event, evt.repeat_count) +end) + +button.dispatch() +button.close(handle) +``` diff --git a/components/lua_modules/lua_module_button/skills/skills_list.json b/components/lua_modules/lua_module_button/skills/skills_list.json new file mode 100644 index 0000000..c83409d --- /dev/null +++ b/components/lua_modules/lua_module_button/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_button", + "file": "lua_module_button.md", + "title": "lua_module_button", + "summary": "How to create button handles, subscribe to events, and dispatch button state from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_camera/CMakeLists.txt b/components/lua_modules/lua_module_camera/CMakeLists.txt new file mode 100644 index 0000000..9188b1c --- /dev/null +++ b/components/lua_modules/lua_module_camera/CMakeLists.txt @@ -0,0 +1,12 @@ +idf_component_register( + SRCS + "src/lua_module_camera.c" + "src/lua_module_camera_service.c" + INCLUDE_DIRS + "include" + REQUIRES + cap_lua + esp_new_jpeg + esp_timer + freertos +) diff --git a/components/lua_modules/lua_module_camera/idf_component.yml b/components/lua_modules/lua_module_camera/idf_component.yml new file mode 100644 index 0000000..d03d96f --- /dev/null +++ b/components/lua_modules/lua_module_camera/idf_component.yml @@ -0,0 +1,4 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_new_jpeg: "^1.0.0" + espressif/esp_video: "^2.0.1" diff --git a/components/lua_modules/lua_module_camera/include/lua_module_camera.h b/components/lua_modules/lua_module_camera/include/lua_module_camera.h new file mode 100644 index 0000000..7e08eca --- /dev/null +++ b/components/lua_modules/lua_module_camera/include/lua_module_camera.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_err.h" +#include "lua.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int luaopen_camera(lua_State *L); +esp_err_t lua_module_camera_register(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_camera/skills/lua_module_camera.md b/components/lua_modules/lua_module_camera/skills/lua_module_camera.md new file mode 100644 index 0000000..a7adfc0 --- /dev/null +++ b/components/lua_modules/lua_module_camera/skills/lua_module_camera.md @@ -0,0 +1,25 @@ +# Lua Camera + +This skill describes how to correctly use camera when writing Lua scripts. + +## How to call +- Import it with `local camera = require("camera")` +- Call `camera.open(dev_path)` before reading frames +- Call `camera.info()` to get stream information such as `width`, `height`, and `pixel_format` +- Call `camera.capture(save_path [, timeout_ms])` to capture a frame to a `.jpg` or `.jpeg` path under `/fatfs/data/` +- Call `camera.close()` when the camera is no longer needed + +## Example +```lua +local camera = require("camera") +local board_manager = require("board_manager") + +local camera_paths = board_manager.get_camera_paths() +camera.open(camera_paths.dev_path) +local info = camera.info() +print(info.width, info.height, info.pixel_format) + +local frame = camera.capture("/fatfs/data/capture.jpg", 3000) +print(frame.path, frame.bytes) +camera.close() +``` diff --git a/components/lua_modules/lua_module_camera/skills/skills_list.json b/components/lua_modules/lua_module_camera/skills/skills_list.json new file mode 100644 index 0000000..7c91eea --- /dev/null +++ b/components/lua_modules/lua_module_camera/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_camera", + "file": "lua_module_camera.md", + "title": "lua_module_camera", + "summary": "How to open a camera, inspect stream info, capture frames, and close it from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_camera/src/lua_module_camera.c b/components/lua_modules/lua_module_camera/src/lua_module_camera.c new file mode 100644 index 0000000..7c08771 --- /dev/null +++ b/components/lua_modules/lua_module_camera/src/lua_module_camera.c @@ -0,0 +1,209 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_camera.h" + +#include +#include +#include +#include +#include +#include + +#include "cap_lua.h" +#include "lauxlib.h" +#include "lua_module_camera_service.h" + +#define LUA_MODULE_CAMERA_NAME "camera" +#define LUA_MODULE_CAMERA_BASE_DIR "/fatfs/data" + +static bool lua_module_camera_has_suffix(const char *path, const char *suffix) +{ + size_t path_len; + size_t suffix_len; + + if (path == NULL || suffix == NULL) { + return false; + } + + path_len = strlen(path); + suffix_len = strlen(suffix); + if (path_len < suffix_len) { + return false; + } + + path += path_len - suffix_len; + for (size_t i = 0; i < suffix_len; ++i) { + if (tolower((unsigned char)path[i]) != tolower((unsigned char)suffix[i])) { + return false; + } + } + return true; +} + +static bool lua_module_camera_save_path_is_valid(const char *path) +{ + size_t base_len; + + if (path == NULL) { + return false; + } + + base_len = strlen(LUA_MODULE_CAMERA_BASE_DIR); + if (strncmp(path, LUA_MODULE_CAMERA_BASE_DIR, base_len) != 0 || path[base_len] != '/') { + return false; + } + if (strstr(path, "..") != NULL) { + return false; + } + + return lua_module_camera_has_suffix(path, ".jpg") || + lua_module_camera_has_suffix(path, ".jpeg"); +} + +/* camera.open(dev_path) + * Opens the camera device. Must be called before info() or capture(). + * Returns true on success, or raises an error. */ +static int lua_module_camera_open(lua_State *L) +{ + const char *dev_path = luaL_checkstring(L, 1); + esp_err_t err = claw_camera_open(dev_path); + + if (err != ESP_OK) { + return luaL_error(L, "camera open failed: %s", esp_err_to_name(err)); + } + + lua_pushboolean(L, 1); + return 1; +} + +/* camera.info() + * Returns a table with stream info: width, height, pixel_format, pixel_format_raw. + * Requires the camera to be opened first. */ +static int lua_module_camera_info(lua_State *L) +{ + claw_camera_stream_info_t info = {0}; + esp_err_t err = claw_camera_get_stream_info(&info); + + if (err == ESP_ERR_INVALID_STATE) { + return luaL_error(L, "camera info failed: camera not opened, call camera.open() first"); + } + if (err != ESP_OK) { + return luaL_error(L, "camera info failed: %s", esp_err_to_name(err)); + } + + lua_newtable(L); + lua_pushinteger(L, info.width); + lua_setfield(L, -2, "width"); + lua_pushinteger(L, info.height); + lua_setfield(L, -2, "height"); + lua_pushinteger(L, (lua_Integer)info.pixel_format); + lua_setfield(L, -2, "pixel_format_raw"); + lua_pushstring(L, info.pixel_format_str); + lua_setfield(L, -2, "pixel_format"); + return 1; +} + +/* camera.capture(save_path [, timeout_ms]) + * Captures a JPEG frame and writes it to save_path. + * save_path must be a .jpg/.jpeg file under /fatfs/data/. + * Returns a table with: path, bytes, width, height, pixel_format, pixel_format_raw, + * frame_bytes, timestamp_us. */ +static int lua_module_camera_capture(lua_State *L) +{ + claw_camera_frame_info_t frame_info = {0}; + const char *path = luaL_checkstring(L, 1); + int timeout_ms = (int)luaL_optinteger(L, 2, 0); + uint8_t *jpeg_data = NULL; + size_t jpeg_bytes = 0; + FILE *file = NULL; + esp_err_t err; + + if (!lua_module_camera_save_path_is_valid(path)) { + return luaL_error(L, "save path must be a .jpg/.jpeg file under %s", + LUA_MODULE_CAMERA_BASE_DIR); + } + if (timeout_ms < 0) { + return luaL_error(L, "timeout_ms must be non-negative"); + } + + err = claw_camera_capture_jpeg(timeout_ms, &jpeg_data, &jpeg_bytes, &frame_info); + if (err == ESP_ERR_INVALID_STATE) { + return luaL_error(L, "camera capture failed: camera not opened, call camera.open() first"); + } + if (err != ESP_OK) { + return luaL_error(L, "camera capture failed: %s", esp_err_to_name(err)); + } + + file = fopen(path, "wb"); + if (file == NULL) { + claw_camera_free_buffer(jpeg_data); + return luaL_error(L, "camera capture failed: cannot open %s (errno=%d)", path, errno); + } + + if (fwrite(jpeg_data, 1, jpeg_bytes, file) != jpeg_bytes) { + fclose(file); + unlink(path); + claw_camera_free_buffer(jpeg_data); + return luaL_error(L, "camera capture failed: short write to %s", path); + } + + fclose(file); + claw_camera_free_buffer(jpeg_data); + + lua_newtable(L); + lua_pushstring(L, path); + lua_setfield(L, -2, "path"); + lua_pushinteger(L, (lua_Integer)jpeg_bytes); + lua_setfield(L, -2, "bytes"); + lua_pushinteger(L, frame_info.width); + lua_setfield(L, -2, "width"); + lua_pushinteger(L, frame_info.height); + lua_setfield(L, -2, "height"); + lua_pushinteger(L, (lua_Integer)frame_info.pixel_format); + lua_setfield(L, -2, "pixel_format_raw"); + lua_pushstring(L, frame_info.pixel_format_str); + lua_setfield(L, -2, "pixel_format"); + lua_pushinteger(L, (lua_Integer)frame_info.frame_bytes); + lua_setfield(L, -2, "frame_bytes"); + lua_pushinteger(L, (lua_Integer)frame_info.timestamp_us); + lua_setfield(L, -2, "timestamp_us"); + return 1; +} + +/* camera.close() + * Closes the camera device and releases all resources. + * Returns true on success, or raises an error. */ +static int lua_module_camera_close(lua_State *L) +{ + esp_err_t err = claw_camera_close(); + + if (err != ESP_OK) { + return luaL_error(L, "camera close failed: %s", esp_err_to_name(err)); + } + + lua_pushboolean(L, 1); + return 1; +} + +int luaopen_camera(lua_State *L) +{ + static const luaL_Reg funcs[] = { + {"open", lua_module_camera_open}, + {"info", lua_module_camera_info}, + {"capture", lua_module_camera_capture}, + {"close", lua_module_camera_close}, + {NULL, NULL}, + }; + + lua_newtable(L); + luaL_setfuncs(L, funcs, 0); + return 1; +} + +esp_err_t lua_module_camera_register(void) +{ + return cap_lua_register_module(LUA_MODULE_CAMERA_NAME, luaopen_camera); +} diff --git a/components/lua_modules/lua_module_camera/src/lua_module_camera_service.c b/components/lua_modules/lua_module_camera/src/lua_module_camera_service.c new file mode 100644 index 0000000..efdf5c0 --- /dev/null +++ b/components/lua_modules/lua_module_camera/src/lua_module_camera_service.c @@ -0,0 +1,672 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_camera_service.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "esp_jpeg_enc.h" +#include "esp_log.h" +#include "esp_timer.h" +#include "esp_video_ioctl.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "linux/videodev2.h" + +#define CLAW_CAMERA_DEFAULT_TIMEOUT_MS 5000 +#define CLAW_CAMERA_SETTLE_TIMEOUT_MS 30000 /* settle at open time, allow slow SPI sensors */ +#define CLAW_CAMERA_BUFFER_COUNT 3 +#define CLAW_CAMERA_STREAM_SETTLE_FRAMES 3 /* reduced: 3 frames enough for AE/AWB stabilize */ +#define CLAW_CAMERA_JPEG_QUALITY 80 +#define CLAW_CAMERA_MIN_JPEG_BUFFER_SIZE (64 * 1024) + +static const char *TAG = "claw_camera"; + +static esp_err_t claw_camera_settle_stream_locked(int64_t deadline_us); +static void claw_camera_fourcc_to_string(uint32_t pixel_format, char out[5]); + +typedef struct { + SemaphoreHandle_t lock; + bool opened; + bool streaming; + uint32_t settled_frames; + int fd; + uint8_t *buffers[CLAW_CAMERA_BUFFER_COUNT]; + size_t buffer_lengths[CLAW_CAMERA_BUFFER_COUNT]; + uint32_t buffer_count; + uint32_t width; + uint32_t height; + uint32_t pixel_format; + jpeg_enc_handle_t jpeg_encoder; + uint8_t *jpeg_buffer; + uint32_t jpeg_buffer_size; +} claw_camera_state_t; + +static StaticSemaphore_t s_camera_lock_buf; +static claw_camera_state_t s_camera = { + .fd = -1, +}; + +static esp_err_t claw_camera_lock(void) +{ + if (s_camera.lock == NULL) { + s_camera.lock = xSemaphoreCreateMutexStatic(&s_camera_lock_buf); + } + + if (xSemaphoreTake(s_camera.lock, pdMS_TO_TICKS(2000)) != pdTRUE) { + ESP_LOGE(TAG, "Camera mutex timeout"); + return ESP_ERR_TIMEOUT; + } + return ESP_OK; +} + +static void claw_camera_unlock(void) +{ + if (s_camera.lock != NULL) { + xSemaphoreGive(s_camera.lock); + } +} + +static int claw_camera_effective_timeout_ms(int timeout_ms) +{ + return timeout_ms > 0 ? timeout_ms : CLAW_CAMERA_DEFAULT_TIMEOUT_MS; +} + +static int claw_camera_remaining_timeout_ms(int64_t deadline_us) +{ + int64_t remaining_us = deadline_us - esp_timer_get_time(); + + if (remaining_us <= 0) { + return 0; + } + if (remaining_us > INT32_MAX * 1000LL) { + return INT32_MAX; + } + return (int)((remaining_us + 999LL) / 1000LL); +} + +static void claw_camera_fourcc_to_string(uint32_t pixel_format, char out[5]) +{ + out[0] = (char)(pixel_format & 0xff); + out[1] = (char)((pixel_format >> 8) & 0xff); + out[2] = (char)((pixel_format >> 16) & 0xff); + out[3] = (char)((pixel_format >> 24) & 0xff); + out[4] = '\0'; + + for (int i = 0; i < 4; ++i) { + if (out[i] < 32 || out[i] > 126) { + out[i] = '.'; + } + } +} + +static void claw_camera_release_encoder_locked(void) +{ + if (s_camera.jpeg_buffer != NULL) { + jpeg_free_align(s_camera.jpeg_buffer); + s_camera.jpeg_buffer = NULL; + } + if (s_camera.jpeg_encoder != NULL) { + jpeg_enc_close(s_camera.jpeg_encoder); + s_camera.jpeg_encoder = NULL; + } + s_camera.jpeg_buffer_size = 0; +} + +static void claw_camera_close_locked(void) +{ + if (s_camera.streaming && s_camera.fd >= 0) { + int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(s_camera.fd, VIDIOC_STREAMOFF, &type) != 0) { + ESP_LOGW(TAG, "VIDIOC_STREAMOFF failed (errno=%d)", errno); + } + } + + for (uint32_t i = 0; i < s_camera.buffer_count; ++i) { + if (s_camera.buffers[i] != NULL) { + munmap(s_camera.buffers[i], s_camera.buffer_lengths[i]); + s_camera.buffers[i] = NULL; + } + s_camera.buffer_lengths[i] = 0; + } + s_camera.buffer_count = 0; + + claw_camera_release_encoder_locked(); + + if (s_camera.fd >= 0) { + close(s_camera.fd); + s_camera.fd = -1; + } + + s_camera.opened = false; + s_camera.streaming = false; + s_camera.settled_frames = 0; + s_camera.width = 0; + s_camera.height = 0; + s_camera.pixel_format = 0; +} + +static esp_err_t claw_camera_prepare_encoder_locked(void) +{ + jpeg_enc_config_t config = DEFAULT_JPEG_ENC_CONFIG(); + uint64_t input_size = 0; + int jpeg_err; + + if (s_camera.pixel_format == V4L2_PIX_FMT_JPEG) { + return ESP_OK; + } + if (s_camera.jpeg_encoder != NULL && s_camera.jpeg_buffer != NULL) { + return ESP_OK; + } + + config.width = s_camera.width; + config.height = s_camera.height; + config.quality = CLAW_CAMERA_JPEG_QUALITY; + + switch (s_camera.pixel_format) { + case V4L2_PIX_FMT_UYVY: + config.src_type = JPEG_PIXEL_FORMAT_CbYCrY; + config.subsampling = JPEG_SUBSAMPLE_422; + input_size = (uint64_t)s_camera.width * s_camera.height * 2U; + break; + case V4L2_PIX_FMT_YUYV: + config.src_type = JPEG_PIXEL_FORMAT_YCbYCr; + config.subsampling = JPEG_SUBSAMPLE_422; + input_size = (uint64_t)s_camera.width * s_camera.height * 2U; + break; + case V4L2_PIX_FMT_RGB565: + config.src_type = JPEG_PIXEL_FORMAT_RGB565_LE; + config.subsampling = JPEG_SUBSAMPLE_422; + input_size = (uint64_t)s_camera.width * s_camera.height * 2U; + break; + case V4L2_PIX_FMT_RGB565X: + config.src_type = JPEG_PIXEL_FORMAT_RGB565_BE; + config.subsampling = JPEG_SUBSAMPLE_422; + input_size = (uint64_t)s_camera.width * s_camera.height * 2U; + break; + default: + ESP_LOGE(TAG, "prepare_encoder: unsupported pixel format 0x%08" PRIx32, s_camera.pixel_format); + return ESP_ERR_NOT_SUPPORTED; + } + + if (input_size == 0 || input_size > UINT32_MAX) { + return ESP_ERR_INVALID_SIZE; + } + + jpeg_err = jpeg_enc_open(&config, &s_camera.jpeg_encoder); + if (jpeg_err != JPEG_ERR_OK) { + ESP_LOGE(TAG, "jpeg_enc_open failed: %d", jpeg_err); + s_camera.jpeg_encoder = NULL; + return ESP_FAIL; + } + + s_camera.jpeg_buffer_size = (uint32_t)(input_size * 3U / 4U); + if (s_camera.jpeg_buffer_size < CLAW_CAMERA_MIN_JPEG_BUFFER_SIZE) { + s_camera.jpeg_buffer_size = CLAW_CAMERA_MIN_JPEG_BUFFER_SIZE; + } + + s_camera.jpeg_buffer = jpeg_calloc_align(s_camera.jpeg_buffer_size, 128); + if (s_camera.jpeg_buffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate JPEG output buffer"); + claw_camera_release_encoder_locked(); + return ESP_ERR_NO_MEM; + } + + return ESP_OK; +} + +static esp_err_t claw_camera_open_locked(const char *dev_path) +{ + struct v4l2_format format = {0}; + struct v4l2_requestbuffers request = {0}; + char pixel_format[5] = {0}; + esp_err_t err; + + if (s_camera.opened) { + return ESP_OK; + } + + if (dev_path == NULL) { + return ESP_ERR_INVALID_ARG; + } + + s_camera.fd = open(dev_path, O_RDWR); + if (s_camera.fd < 0) { + ESP_LOGE(TAG, "Failed to open %s (errno=%d)", dev_path, errno); + s_camera.fd = -1; + return ESP_ERR_NOT_FOUND; + } + + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(s_camera.fd, VIDIOC_G_FMT, &format) != 0) { + ESP_LOGE(TAG, "VIDIOC_G_FMT failed (errno=%d)", errno); + claw_camera_close_locked(); + return ESP_FAIL; + } + + s_camera.width = format.fmt.pix.width; + s_camera.height = format.fmt.pix.height; + s_camera.pixel_format = format.fmt.pix.pixelformat; + claw_camera_fourcc_to_string(s_camera.pixel_format, pixel_format); + + request.count = CLAW_CAMERA_BUFFER_COUNT; + request.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + request.memory = V4L2_MEMORY_MMAP; + if (ioctl(s_camera.fd, VIDIOC_REQBUFS, &request) != 0) { + ESP_LOGE(TAG, "VIDIOC_REQBUFS failed (errno=%d)", errno); + claw_camera_close_locked(); + return ESP_FAIL; + } + if (request.count == 0) { + ESP_LOGE(TAG, "Camera buffer request returned 0"); + claw_camera_close_locked(); + return ESP_ERR_NO_MEM; + } + + s_camera.buffer_count = request.count > CLAW_CAMERA_BUFFER_COUNT ? + CLAW_CAMERA_BUFFER_COUNT : request.count; + + for (uint32_t i = 0; i < s_camera.buffer_count; ++i) { + struct v4l2_buffer buffer = {0}; + + buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer.memory = V4L2_MEMORY_MMAP; + buffer.index = i; + if (ioctl(s_camera.fd, VIDIOC_QUERYBUF, &buffer) != 0) { + ESP_LOGE(TAG, "VIDIOC_QUERYBUF failed (errno=%d)", errno); + claw_camera_close_locked(); + return ESP_FAIL; + } + + s_camera.buffers[i] = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, + MAP_SHARED, s_camera.fd, buffer.m.offset); + if (s_camera.buffers[i] == MAP_FAILED) { + ESP_LOGE(TAG, "Failed to mmap camera buffer (errno=%d)", errno); + s_camera.buffers[i] = NULL; + claw_camera_close_locked(); + return ESP_ERR_NO_MEM; + } + s_camera.buffer_lengths[i] = buffer.length; + + if (ioctl(s_camera.fd, VIDIOC_QBUF, &buffer) != 0) { + ESP_LOGE(TAG, "Initial VIDIOC_QBUF failed (errno=%d)", errno); + claw_camera_close_locked(); + return ESP_FAIL; + } + } + + err = claw_camera_prepare_encoder_locked(); + if (err != ESP_OK) { + claw_camera_close_locked(); + return err; + } + + int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(s_camera.fd, VIDIOC_STREAMON, &type) != 0) { + ESP_LOGE(TAG, "VIDIOC_STREAMON failed (errno=%d)", errno); + claw_camera_close_locked(); + return ESP_FAIL; + } + + s_camera.streaming = true; + s_camera.opened = true; + s_camera.settled_frames = 0; + + ESP_LOGI(TAG, "Camera opened: path=%s size=%ux%u format=%s", + dev_path, (unsigned)s_camera.width, (unsigned)s_camera.height, + pixel_format); + + /* Settle the stream at open time with a dedicated timeout so that capture() + * calls are not penalised by the sensor warm-up delay. */ + int64_t settle_deadline_us = + esp_timer_get_time() + ((int64_t)CLAW_CAMERA_SETTLE_TIMEOUT_MS * 1000LL); + err = claw_camera_settle_stream_locked(settle_deadline_us); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Stream settle failed during open (err=0x%x)", err); + claw_camera_close_locked(); + return err; + } + + return ESP_OK; +} + +static esp_err_t claw_camera_dequeue_buffer_locked(int timeout_ms, struct v4l2_buffer *buffer) +{ + struct timeval tv = { + .tv_sec = timeout_ms / 1000, + .tv_usec = (timeout_ms % 1000) * 1000, + }; + + if (buffer == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* esp_video VFS does not implement poll(); use VIDIOC_S_DQBUF_TIMEOUT to + * set a per-call timeout and block directly in VIDIOC_DQBUF. */ + if (ioctl(s_camera.fd, VIDIOC_S_DQBUF_TIMEOUT, &tv) != 0) { + ESP_LOGW(TAG, "VIDIOC_S_DQBUF_TIMEOUT failed (errno=%d)", errno); + return ESP_FAIL; + } + + memset(buffer, 0, sizeof(*buffer)); + buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer->memory = V4L2_MEMORY_MMAP; + if (ioctl(s_camera.fd, VIDIOC_DQBUF, buffer) != 0) { + if (errno == ETIMEDOUT) { + ESP_LOGW(TAG, "VIDIOC_DQBUF timeout after %d ms", timeout_ms); + return ESP_ERR_TIMEOUT; + } + ESP_LOGW(TAG, "VIDIOC_DQBUF failed (errno=%d)", errno); + return ESP_FAIL; + } + + return ESP_OK; +} + +static esp_err_t claw_camera_requeue_buffer_locked(struct v4l2_buffer *buffer) +{ + if (buffer == NULL || buffer->index >= s_camera.buffer_count) { + return ESP_ERR_INVALID_ARG; + } + + if (ioctl(s_camera.fd, VIDIOC_QBUF, buffer) != 0) { + ESP_LOGW(TAG, "VIDIOC_QBUF failed (errno=%d)", errno); + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t claw_camera_validate_buffer_locked(const struct v4l2_buffer *buffer, + size_t *frame_bytes) +{ + if (buffer == NULL || frame_bytes == NULL) { + return ESP_ERR_INVALID_ARG; + } + if ((buffer->flags & V4L2_BUF_FLAG_DONE) == 0 || (buffer->flags & V4L2_BUF_FLAG_ERROR) != 0) { + return ESP_FAIL; + } + if (buffer->index >= s_camera.buffer_count) { + return ESP_FAIL; + } + if (s_camera.buffers[buffer->index] == NULL || s_camera.buffer_lengths[buffer->index] == 0) { + return ESP_FAIL; + } + if (buffer->bytesused > s_camera.buffer_lengths[buffer->index]) { + return ESP_ERR_INVALID_SIZE; + } + if (buffer->bytesused == 0) { + return ESP_ERR_INVALID_SIZE; + } + + *frame_bytes = buffer->bytesused; + return ESP_OK; +} + +static esp_err_t claw_camera_settle_stream_locked(int64_t deadline_us) +{ + while (s_camera.settled_frames < CLAW_CAMERA_STREAM_SETTLE_FRAMES) { + struct v4l2_buffer buffer = {0}; + size_t frame_bytes = 0; + int remaining_ms = claw_camera_remaining_timeout_ms(deadline_us); + esp_err_t err; + + if (remaining_ms <= 0) { + ESP_LOGW(TAG, "settle: timeout (settled=%" PRIu32 "/%d)", + s_camera.settled_frames, CLAW_CAMERA_STREAM_SETTLE_FRAMES); + return ESP_ERR_TIMEOUT; + } + + err = claw_camera_dequeue_buffer_locked(remaining_ms, &buffer); + if (err != ESP_OK) { + claw_camera_close_locked(); + return err; + } + + err = claw_camera_validate_buffer_locked(&buffer, &frame_bytes); + if (claw_camera_requeue_buffer_locked(&buffer) != ESP_OK) { + claw_camera_close_locked(); + return ESP_FAIL; + } + + if (err == ESP_OK && frame_bytes > 0) { + s_camera.settled_frames++; + } + } + return ESP_OK; +} + +static esp_err_t claw_camera_get_frame_locked(int timeout_ms, struct v4l2_buffer *buffer, + uint8_t **frame_data, size_t *frame_bytes, + int64_t *timestamp_us) +{ + int64_t deadline_us; + esp_err_t err; + + if (buffer == NULL || frame_data == NULL || frame_bytes == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!s_camera.opened) { + return ESP_ERR_INVALID_STATE; + } + + deadline_us = esp_timer_get_time() + ((int64_t)claw_camera_effective_timeout_ms(timeout_ms) * 1000LL); + + err = claw_camera_settle_stream_locked(deadline_us); + if (err != ESP_OK) { + return err; + } + + while (claw_camera_remaining_timeout_ms(deadline_us) > 0) { + int remaining_ms = claw_camera_remaining_timeout_ms(deadline_us); + + err = claw_camera_dequeue_buffer_locked(remaining_ms, buffer); + if (err != ESP_OK) { + claw_camera_close_locked(); + return err; + } + + err = claw_camera_validate_buffer_locked(buffer, frame_bytes); + if (err == ESP_OK) { + *frame_data = s_camera.buffers[buffer->index]; + if (timestamp_us != NULL) { + *timestamp_us = esp_timer_get_time(); + } + return ESP_OK; + } + + if (claw_camera_requeue_buffer_locked(buffer) != ESP_OK) { + claw_camera_close_locked(); + return ESP_FAIL; + } + } + + return ESP_ERR_TIMEOUT; +} + +static esp_err_t claw_camera_copy_frame_and_requeue_locked(struct v4l2_buffer *buffer, + const uint8_t *frame_data, + size_t frame_bytes, + uint8_t **out_frame_copy) +{ + uint8_t *frame_copy; + + if (buffer == NULL || frame_data == NULL || out_frame_copy == NULL) { + return ESP_ERR_INVALID_ARG; + } + + frame_copy = malloc(frame_bytes); + if (frame_copy == NULL) { + return ESP_ERR_NO_MEM; + } + + memcpy(frame_copy, frame_data, frame_bytes); + + if (claw_camera_requeue_buffer_locked(buffer) != ESP_OK) { + free(frame_copy); + claw_camera_close_locked(); + return ESP_FAIL; + } + + *out_frame_copy = frame_copy; + return ESP_OK; +} + +esp_err_t claw_camera_open(const char *dev_path) +{ + esp_err_t err = claw_camera_lock(); + + if (err != ESP_OK) { + return err; + } + + err = claw_camera_open_locked(dev_path); + claw_camera_unlock(); + return err; +} + +esp_err_t claw_camera_get_stream_info(claw_camera_stream_info_t *out_info) +{ + esp_err_t err; + + if (out_info == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(out_info, 0, sizeof(*out_info)); + + err = claw_camera_lock(); + if (err != ESP_OK) { + return err; + } + + if (!s_camera.opened) { + claw_camera_unlock(); + return ESP_ERR_INVALID_STATE; + } + + out_info->width = s_camera.width; + out_info->height = s_camera.height; + out_info->pixel_format = s_camera.pixel_format; + claw_camera_fourcc_to_string(s_camera.pixel_format, out_info->pixel_format_str); + + claw_camera_unlock(); + return ESP_OK; +} + +esp_err_t claw_camera_capture_jpeg(int timeout_ms, uint8_t **jpeg_data, size_t *jpeg_bytes, + claw_camera_frame_info_t *out_info) +{ + struct v4l2_buffer buffer = {0}; + uint8_t *frame_data = NULL; + uint8_t *frame_copy = NULL; + size_t frame_bytes = 0; + int64_t timestamp_us = 0; + uint8_t *copy = NULL; + size_t encoded_size = 0; + esp_err_t err; + + if (jpeg_data == NULL || jpeg_bytes == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *jpeg_data = NULL; + *jpeg_bytes = 0; + if (out_info != NULL) { + memset(out_info, 0, sizeof(*out_info)); + } + + err = claw_camera_lock(); + if (err != ESP_OK) { + return err; + } + + err = claw_camera_get_frame_locked(timeout_ms, &buffer, &frame_data, &frame_bytes, ×tamp_us); + if (err != ESP_OK) { + claw_camera_unlock(); + return err; + } + + err = claw_camera_copy_frame_and_requeue_locked(&buffer, frame_data, frame_bytes, &frame_copy); + if (err != ESP_OK) { + claw_camera_unlock(); + return err; + } + + if (s_camera.pixel_format == V4L2_PIX_FMT_JPEG) { + encoded_size = frame_bytes; + copy = frame_copy; + frame_copy = NULL; + } else { + int out_len = 0; + + err = claw_camera_prepare_encoder_locked(); + if (err == ESP_OK) { + if (jpeg_enc_process(s_camera.jpeg_encoder, frame_copy, (uint32_t)frame_bytes, + s_camera.jpeg_buffer, s_camera.jpeg_buffer_size, + &out_len) != JPEG_ERR_OK) { + ESP_LOGE(TAG, "jpeg_enc_process failed"); + err = ESP_FAIL; + } else if (out_len <= 0) { + err = ESP_ERR_INVALID_SIZE; + } else { + encoded_size = (size_t)out_len; + copy = malloc(encoded_size); + if (copy == NULL) { + err = ESP_ERR_NO_MEM; + } else { + memcpy(copy, s_camera.jpeg_buffer, encoded_size); + } + } + } + } + + if (err == ESP_OK) { + *jpeg_data = copy; + *jpeg_bytes = encoded_size; + if (out_info != NULL) { + out_info->width = s_camera.width; + out_info->height = s_camera.height; + out_info->pixel_format = s_camera.pixel_format; + claw_camera_fourcc_to_string(s_camera.pixel_format, out_info->pixel_format_str); + out_info->frame_bytes = frame_bytes; + out_info->timestamp_us = timestamp_us; + } + } else if (copy != NULL) { + free(copy); + } + + free(frame_copy); + claw_camera_unlock(); + return err; +} + +esp_err_t claw_camera_close(void) +{ + esp_err_t err = claw_camera_lock(); + + if (err != ESP_OK) { + return err; + } + + claw_camera_close_locked(); + claw_camera_unlock(); + return ESP_OK; +} + +void claw_camera_free_buffer(void *buffer) +{ + free(buffer); +} diff --git a/components/lua_modules/lua_module_camera/src/lua_module_camera_service.h b/components/lua_modules/lua_module_camera/src/lua_module_camera_service.h new file mode 100644 index 0000000..308daa9 --- /dev/null +++ b/components/lua_modules/lua_module_camera/src/lua_module_camera_service.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t width; + uint32_t height; + uint32_t pixel_format; + char pixel_format_str[5]; +} claw_camera_stream_info_t; + +typedef struct { + uint32_t width; + uint32_t height; + uint32_t pixel_format; + char pixel_format_str[5]; + size_t frame_bytes; + int64_t timestamp_us; +} claw_camera_frame_info_t; + +esp_err_t claw_camera_open(const char *dev_path); +esp_err_t claw_camera_get_stream_info(claw_camera_stream_info_t *out_info); +esp_err_t claw_camera_capture_jpeg(int timeout_ms, uint8_t **jpeg_data, size_t *jpeg_bytes, + claw_camera_frame_info_t *out_info); +esp_err_t claw_camera_close(void); +void claw_camera_free_buffer(void *buffer); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_display/CMakeLists.txt b/components/lua_modules/lua_module_display/CMakeLists.txt new file mode 100644 index 0000000..b595833 --- /dev/null +++ b/components/lua_modules/lua_module_display/CMakeLists.txt @@ -0,0 +1,12 @@ +idf_component_register( + SRCS + "src/display_hal.c" + "src/lua_module_display.c" + INCLUDE_DIRS + "include" + REQUIRES + cap_lua + esp_lcd + esp_painter + libpng +) diff --git a/components/lua_modules/lua_module_display/idf_component.yml b/components/lua_modules/lua_module_display/idf_component.yml new file mode 100644 index 0000000..34de3ad --- /dev/null +++ b/components/lua_modules/lua_module_display/idf_component.yml @@ -0,0 +1,3 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/libpng: "^1.6.55" diff --git a/components/lua_modules/lua_module_display/include/display_hal.h b/components/lua_modules/lua_module_display/include/display_hal.h new file mode 100644 index 0000000..64d2a40 --- /dev/null +++ b/components/lua_modules/lua_module_display/include/display_hal.h @@ -0,0 +1,136 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/* Display Hardware Abstraction Layer + * + * Declares the interface that the board/application layer must implement. + * The lua_module_display component calls these functions to perform display + * operations without depending on any specific LCD driver. + */ + +#include +#include +#include "esp_err.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_ops.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DISPLAY_HAL_TEXT_ALIGN_LEFT = 0, + DISPLAY_HAL_TEXT_ALIGN_CENTER, + DISPLAY_HAL_TEXT_ALIGN_RIGHT, +} display_hal_text_align_t; + +typedef enum { + DISPLAY_HAL_TEXT_VALIGN_TOP = 0, + DISPLAY_HAL_TEXT_VALIGN_MIDDLE, + DISPLAY_HAL_TEXT_VALIGN_BOTTOM, +} display_hal_text_valign_t; + +typedef struct { + uint8_t framebuffer_count; + bool double_buffered; + bool frame_active; + bool flush_in_flight; +} display_hal_animation_info_t; + +/* --- Lifecycle --- */ + +esp_err_t display_hal_create(esp_lcd_panel_handle_t panel_handle, + esp_lcd_panel_io_handle_t io_handle, + int lcd_width, + int lcd_height); +esp_err_t display_hal_destroy(void); + +/* --- Geometry --- */ + +int display_hal_width(void); +int display_hal_height(void); + +/* --- Frame control --- */ + +esp_err_t display_hal_begin_frame(bool clear, uint16_t color565); +esp_err_t display_hal_present(void); +esp_err_t display_hal_present_rect(int x, int y, int width, int height); +esp_err_t display_hal_end_frame(void); +bool display_hal_is_frame_active(void); +esp_err_t display_hal_get_animation_info(display_hal_animation_info_t *info); + +/* --- Drawing primitives --- */ + +esp_err_t display_hal_clear(uint16_t color565); +esp_err_t display_hal_set_clip_rect(int x, int y, int width, int height); +esp_err_t display_hal_clear_clip_rect(void); +esp_err_t display_hal_fill_rect(int x, int y, int width, int height, uint16_t color565); +esp_err_t display_hal_draw_line(int x0, int y0, int x1, int y1, uint16_t color565); +esp_err_t display_hal_draw_rect(int x, int y, int width, int height, uint16_t color565); +esp_err_t display_hal_draw_pixel(int x, int y, uint16_t color565); +esp_err_t display_hal_set_backlight(bool on); +esp_err_t display_hal_fill_circle(int cx, int cy, int r, uint16_t color565); +esp_err_t display_hal_draw_circle(int cx, int cy, int r, uint16_t color565); +esp_err_t display_hal_draw_arc(int cx, int cy, int radius, + float start_deg, float end_deg, uint16_t color565); +esp_err_t display_hal_fill_arc(int cx, int cy, int inner_radius, int outer_radius, + float start_deg, float end_deg, uint16_t color565); +esp_err_t display_hal_draw_ellipse(int cx, int cy, int radius_x, int radius_y, + uint16_t color565); +esp_err_t display_hal_fill_ellipse(int cx, int cy, int radius_x, int radius_y, + uint16_t color565); +esp_err_t display_hal_draw_round_rect(int x, int y, int width, int height, + int radius, uint16_t color565); +esp_err_t display_hal_fill_round_rect(int x, int y, int width, int height, + int radius, uint16_t color565); +esp_err_t display_hal_draw_triangle(int x1, int y1, int x2, int y2, + int x3, int y3, uint16_t color565); +esp_err_t display_hal_fill_triangle(int x1, int y1, int x2, int y2, + int x3, int y3, uint16_t color565); + +/* --- Text --- */ + +esp_err_t display_hal_measure_text(const char *text, uint8_t font_size, + uint16_t *out_width, uint16_t *out_height); +esp_err_t display_hal_draw_text(int x, int y, const char *text, uint8_t font_size, + uint16_t text_color565, bool has_bg, uint16_t bg_color565); +esp_err_t display_hal_draw_text_aligned(int x, int y, int width, int height, + const char *text, uint8_t font_size, + uint16_t text_color565, bool has_bg, uint16_t bg_color565, + display_hal_text_align_t align, + display_hal_text_valign_t valign); + +/* --- Bitmap --- */ + +/* pixels: RGB565, MSB-first byte order */ +esp_err_t display_hal_draw_bitmap(int x, int y, int w, int h, const uint16_t *pixels); +esp_err_t display_hal_draw_bitmap_crop(int x, int y, + int src_x, int src_y, + int w, int h, + int src_width, int src_height, + const uint16_t *pixels); + +/* --- JPEG --- */ + +esp_err_t display_hal_draw_jpeg(int x, int y, + const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h); +esp_err_t display_hal_draw_jpeg_crop(int x, int y, + int src_x, int src_y, + int w, int h, + const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h); +esp_err_t display_hal_jpeg_get_size(const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h); +esp_err_t display_hal_draw_jpeg_scaled(int x, int y, + const uint8_t *jpeg_data, size_t jpeg_len, + int scale_w, int scale_h, + int *out_w, int *out_h); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_display/include/lua_module_display.h b/components/lua_modules/lua_module_display/include/lua_module_display.h new file mode 100644 index 0000000..80af6ed --- /dev/null +++ b/components/lua_modules/lua_module_display/include/lua_module_display.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_err.h" +#include "lua.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Opens the "display" Lua module and pushes the table onto the stack. */ +int luaopen_display(lua_State *L); + +/* Registers the "display" module with cap_lua so Lua scripts can require it. */ +esp_err_t lua_module_display_register(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_display/skills/lua_module_display.md b/components/lua_modules/lua_module_display/skills/lua_module_display.md new file mode 100644 index 0000000..3f67c72 --- /dev/null +++ b/components/lua_modules/lua_module_display/skills/lua_module_display.md @@ -0,0 +1,433 @@ +# Lua Display + +This skill describes how to correctly use `display` when writing Lua scripts. + +`display` is a low-level drawing module. It can: +- Create and destroy the LCD drawing context +- Draw text, lines, rectangles, circles, arcs, ellipses, triangles, and round rectangles +- Draw raw RGB565 bitmaps +- Draw JPEG and PNG images from memory or files +- Manage frame-based rendering and partial screen flushes + +## Typical setup + +In this project, `display` is usually used together with `board_manager`: + +```lua +local board_manager = require("board_manager") +local display = require("display") + +local panel_handle, io_handle, width, height = + board_manager.get_display_lcd_params("display_lcd") + +display.create_screen(panel_handle, io_handle, width, height) +``` + +After `display.create_screen(...)` succeeds: +- `display.width()` returns the current screen width +- `display.height()` returns the current screen height +- Most drawing APIs can be used + +When finished: + +```lua +pcall(display.end_frame) +pcall(display.destroy_screen) +``` + +## Important rules + +- All coordinates and sizes are integer arguments unless noted otherwise. +- Colors are almost always passed as three integers: `r, g, b`. +- Text drawing only supports ASCII text. +- For Chinese or other Unicode text, render an image and draw it with `draw_png_file(...)` or `draw_jpeg_file(...)`. +- Image file paths must be absolute paths like `/fatfs/data/pic.jpg`. +- Paths containing `..` are rejected. +- Supported image file extensions are `.jpg`, `.jpeg`, and `.png`. + +## Screen lifecycle + +### `display.create_screen(panel_handle, io_handle, lcd_width, lcd_height)` + +Creates the drawing context. + +- `panel_handle`: lightuserdata, usually from `board_manager.get_display_lcd_params(...)` +- `io_handle`: lightuserdata +- `lcd_width`: integer +- `lcd_height`: integer +- Returns `true` on success +- Raises a Lua error on failure + +### `display.destroy_screen()` + +Destroys the drawing context. + +- Returns `true` on success +- Raises a Lua error on failure + +### `display.width()` + +Returns the current screen width. + +### `display.height()` + +Returns the current screen height. + +## Frame rendering + +The module supports frame-based rendering. This is the preferred mode when a script draws a full screen or updates multiple primitives together. + +### `display.begin_frame([options])` + +Starts a frame. + +`options` is an optional table: +- `clear`: boolean, default `true` +- `r`: background red, default `0` +- `g`: background green, default `0` +- `b`: background blue, default `0` + +Example: + +```lua +display.begin_frame({ clear = true, r = 12, g = 18, b = 28 }) +``` + +### `display.present()` + +Flushes the full current frame to the panel. + +### `display.present_rect(x, y, width, height)` + +Flushes only a rectangular region. This is useful for partial updates such as painting apps or small widgets. + +### `display.end_frame()` + +Ends the current frame. + +### `display.frame_active()` + +Returns a boolean indicating whether a frame is currently active. + +### `display.animation_info()` + +Returns a table with runtime rendering information: +- `framebuffer_count` +- `double_buffered` +- `frame_active` +- `flush_in_flight` + +## Backlight + +### `display.backlight(on)` + +Turns the display backlight on or off. + +- `on`: boolean + +Example: + +```lua +display.backlight(true) +``` + +## Text APIs + +### `display.draw_text(x, y, text [, options])` + +Draws ASCII text at the given position. + +`options` is an optional table: +- `r`, `g`, `b`: text color, default white +- `font_size`: integer, default `24` +- `bg_r`, `bg_g`, `bg_b`: optional background color; if any background field is given, background fill is enabled + +Example: + +```lua +display.draw_text(16, 24, "hello", { + r = 255, + g = 255, + b = 255, + font_size = 24, +}) +``` + +Restrictions: +- `text` must be ASCII +- Non-ASCII text raises an error + +### `display.measure_text(text [, options])` + +Measures text without drawing it. + +`options` currently supports: +- `font_size` + +Returns: +- `width` +- `height` + +Example: + +```lua +local tw, th = display.measure_text("hello", { font_size = 24 }) +``` + +### `display.draw_text_aligned(x, y, width, height, text [, options])` + +Draws ASCII text inside a rectangle with alignment. + +`options` supports: +- `r`, `g`, `b` +- `font_size` +- `bg_r`, `bg_g`, `bg_b` +- `align`: `"left"`, `"center"`/`"centre"`, or `"right"` +- `valign`: `"top"`, `"middle"`/`"center"`, or `"bottom"` + +Example: + +```lua +display.draw_text_aligned(0, 0, display.width(), 32, "status", { + r = 255, + g = 255, + b = 255, + font_size = 16, + align = "center", + valign = "middle", +}) +``` + +## Basic drawing primitives + +### `display.clear(r, g, b)` + +Clears the screen or current frame buffer to a solid color. + +### `display.set_clip_rect(x, y, width, height)` + +Sets a clipping rectangle. Subsequent drawing is restricted to that region until cleared. + +### `display.clear_clip_rect()` + +Removes the active clipping rectangle. + +### `display.fill_rect(x, y, width, height, r, g, b)` + +Draws a filled rectangle. + +### `display.draw_rect(x, y, width, height, r, g, b)` + +Draws a rectangle outline. + +### `display.draw_pixel(x, y, r, g, b)` + +Draws one pixel. + +### `display.draw_line(x0, y0, x1, y1, r, g, b)` + +Draws a line. + +## Shape drawing + +### `display.fill_circle(cx, cy, radius, r, g, b)` + +Draws a filled circle. + +### `display.draw_circle(cx, cy, radius, r, g, b)` + +Draws a circle outline. + +### `display.draw_arc(cx, cy, radius, start_deg, end_deg, r, g, b)` + +Draws an arc. + +- `start_deg` and `end_deg` are numeric values, not limited to integers + +### `display.fill_arc(cx, cy, inner_radius, outer_radius, start_deg, end_deg, r, g, b)` + +Draws a filled ring segment. + +### `display.draw_ellipse(cx, cy, radius_x, radius_y, r, g, b)` + +Draws an ellipse outline. + +### `display.fill_ellipse(cx, cy, radius_x, radius_y, r, g, b)` + +Draws a filled ellipse. + +### `display.draw_round_rect(x, y, width, height, radius, r, g, b)` + +Draws a rounded rectangle outline. + +### `display.fill_round_rect(x, y, width, height, radius, r, g, b)` + +Draws a filled rounded rectangle. + +### `display.draw_triangle(x1, y1, x2, y2, x3, y3, r, g, b)` + +Draws a triangle outline. + +### `display.fill_triangle(x1, y1, x2, y2, x3, y3, r, g, b)` + +Draws a filled triangle. + +## Raw bitmap APIs + +These APIs draw RGB565 pixel buffers. + +### `display.draw_bitmap(x, y, w, h, data)` + +Draws a raw RGB565 bitmap. + +- `data` is a Lua string containing exactly `w * h * 2` bytes or more +- Byte order must be RGB565, MSB-first + +If the byte string is shorter than required, the API raises an error. + +### `display.draw_bitmap_le(x, y, w, h, data)` + +Same as `draw_bitmap(...)`, but input data is little-endian RGB565. + +The module swaps bytes internally before drawing. + +Use this when your pixel buffer is generated in little-endian order. + +### `display.draw_bitmap_crop(x, y, src_x, src_y, width, height, src_width, src_height, data)` + +Draws a cropped region from a larger RGB565 source image. + +Arguments: +- `x`, `y`: destination position on screen +- `src_x`, `src_y`: top-left coordinate inside the source image +- `width`, `height`: crop size to draw +- `src_width`, `src_height`: full source image size +- `data`: source RGB565 data buffer + +Notes: +- `data` must contain the full source image, not just the crop +- Required byte size is `src_width * src_height * 2` +- This API does not have a `_le` variant, so the source buffer should already match the format expected by the HAL + +## JPEG and PNG APIs + +### `display.draw_jpeg(x, y, jpeg_data)` + +Draws a JPEG from raw bytes in memory. + +- `jpeg_data` is a Lua string containing JPEG bytes +- Returns `width, height` + +### `display.draw_jpeg_file(x, y, path)` + +Draws a JPEG from a file. + +- `path` must be an absolute `.jpg` or `.jpeg` path +- Returns `width, height` + +### `display.draw_png_file(x, y, path)` + +Draws a PNG from a file. + +- `path` must be an absolute `.png` path +- Returns `width, height` + +PNG handling details: +- The PNG is decoded inside the module +- RGBA PNG input is converted to RGB565 +- Alpha is pre-multiplied against black + +This means transparent PNG pixels are blended toward black before display, not against an arbitrary background. + +### `display.draw_jpeg_crop(x, y, src_x, src_y, width, height, jpeg_data)` + +Draws a cropped region from in-memory JPEG data. + +- Returns `width, height` + +### `display.draw_jpeg_file_crop(x, y, src_x, src_y, width, height, path)` + +Draws a cropped region from a JPEG file. + +- Returns `width, height` + +### `display.draw_jpeg_file_scaled(x, y, scale_w, scale_h, path)` + +Draws a JPEG file scaled to the requested output size. + +Restrictions from the implementation: +- `scale_w` and `scale_h` must be positive +- `scale_w` and `scale_h` must both be multiples of `8` + +Returns: +- `output_w` +- `output_h` + +### `display.draw_jpeg_file_fit(x, y, max_w, max_h, path)` + +Scales a JPEG to fit within `max_w x max_h` while preserving aspect ratio. + +Behavior: +- If the original image already fits, it is drawn at full resolution +- Otherwise the module computes a scaled size automatically +- The chosen scaled size is aligned down to multiples of `8` +- Minimum output size is clamped to `8x8` +- Maximum downscale is limited to `1/8` of the original size + +Returns: +- `output_w` +- `output_h` + +## Error behavior and constraints + +- Most APIs raise Lua errors directly when arguments are invalid or the HAL returns an error +- Integer-only APIs reject non-integer Lua values +- Path-based image APIs reject invalid or unsafe paths +- `draw_bitmap(...)` and `draw_bitmap_crop(...)` reject buffers that are too short +- `draw_text(...)` and `draw_text_aligned(...)` reject non-ASCII text + +## Recommended usage pattern + +For normal screen rendering: +1. Use `board_manager.get_display_lcd_params("display_lcd")` +2. Call `display.create_screen(...)` +3. Call `display.begin_frame(...)` +4. Draw text, shapes, or images +5. Call `display.present()` or `display.present_rect(...)` +6. Call `display.end_frame()` +7. Call `display.destroy_screen()` before exit + +## Example + +```lua +local bm = require("board_manager") +local display = require("display") + +local panel_handle, io_handle, width, height = + bm.get_display_lcd_params("display_lcd") + +display.create_screen(panel_handle, io_handle, width, height) + +display.begin_frame({ clear = true, r = 12, g = 18, b = 28 }) + +display.draw_rect(12, 12, display.width() - 24, display.height() - 24, 80, 120, 160) +display.fill_rect(20, 40, 80, 36, 72, 208, 235) +display.draw_text(24, 90, "Lua Display Demo", { + r = 245, + g = 244, + b = 238, + font_size = 24, +}) +display.draw_text_aligned(0, display.height() - 24, display.width(), 20, "frame api", { + r = 210, + g = 220, + b = 228, + font_size = 16, + align = "center", + valign = "middle", +}) + +display.present() +display.end_frame() +display.destroy_screen() +``` diff --git a/components/lua_modules/lua_module_display/skills/skills_list.json b/components/lua_modules/lua_module_display/skills/skills_list.json new file mode 100644 index 0000000..7c4992b --- /dev/null +++ b/components/lua_modules/lua_module_display/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_display", + "file": "lua_module_display.md", + "title": "lua_module_display", + "summary": "How to draw shapes, text, bitmaps, and images on the display from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_display/src/display_hal.c b/components/lua_modules/lua_module_display/src/display_hal.c new file mode 100644 index 0000000..e841d01 --- /dev/null +++ b/components/lua_modules/lua_module_display/src/display_hal.c @@ -0,0 +1,2142 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "display_hal.h" + +#include +#include +#include +#include "esp_attr.h" +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_ops.h" +#include "esp_log.h" +#include "esp_painter.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#if CONFIG_ESP_ROM_HAS_JPEG_DECODE +#include "rom/tjpgd.h" +#endif + +static const char *TAG = "display_hal"; + +#define DISPLAY_HAL_FRAMEBUFFER_COUNT_MAX 2 +#define DISPLAY_HAL_FLUSH_TIMEOUT_MS 2000 +#define DISPLAY_HAL_TEXT_CACHE_ALIGN 32 +#define DISPLAY_HAL_PI 3.14159265358979323846f +#define DISPLAY_HAL_JPEG_WORKBUF_SIZE 3100 + +typedef struct { + SemaphoreHandle_t lock; + esp_lcd_panel_handle_t panel; + esp_lcd_panel_io_handle_t io; + esp_painter_handle_t painter; + bool display_callbacks_registered; + bool clip_enabled; + int clip_x; + int clip_y; + int clip_width; + int clip_height; + int width; + int height; + size_t framebuffer_bytes; + uint16_t *framebuffers[DISPLAY_HAL_FRAMEBUFFER_COUNT_MAX]; + uint8_t framebuffer_count; + uint8_t draw_framebuffer_index; + uint8_t visible_framebuffer_index; + int8_t pending_framebuffer_index; + bool frame_active; + bool flush_in_flight; + bool framebuffer_initialized; + SemaphoreHandle_t display_flush_done; +} display_hal_state_t; + +static display_hal_state_t s_state; + +static void display_hal_clear_clip_locked(void); +static bool display_hal_flush_done_isr(esp_lcd_panel_io_handle_t panel_io, + esp_lcd_panel_io_event_data_t *edata, + void *user_ctx); +static esp_err_t display_hal_wait_flush_done_locked(TickType_t timeout_ticks); +static bool display_hal_clip_rect_to_screen_locked(int *x, int *y, int *width, int *height); + +static inline uint16_t display_hal_rgb565_to_panel(uint16_t color565) +{ + return __builtin_bswap16(color565); +} + +static esp_err_t display_hal_lock(void) +{ + if (!s_state.lock) { + s_state.lock = xSemaphoreCreateMutex(); + } + ESP_RETURN_ON_FALSE(s_state.lock != NULL, ESP_ERR_NO_MEM, TAG, "create mutex failed"); + ESP_RETURN_ON_FALSE(xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(1000)) == pdTRUE, + ESP_ERR_TIMEOUT, TAG, "mutex timeout"); + return ESP_OK; +} + +static void display_hal_unlock(void) +{ + if (s_state.lock) { + xSemaphoreGive(s_state.lock); + } +} + +static esp_err_t display_hal_require_created_locked(void) +{ + ESP_RETURN_ON_FALSE(s_state.panel != NULL && s_state.io != NULL && + s_state.width > 0 && s_state.height > 0, + ESP_ERR_INVALID_STATE, TAG, "display not created"); + return ESP_OK; +} + +static esp_err_t display_hal_ensure_display_locked(void) +{ + return display_hal_require_created_locked(); +} + +esp_err_t display_hal_create(esp_lcd_panel_handle_t panel_handle, + esp_lcd_panel_io_handle_t io_handle, + int lcd_width, + int lcd_height) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + + ESP_GOTO_ON_FALSE(panel_handle != NULL && io_handle != NULL, ESP_ERR_INVALID_ARG, + fail, TAG, "panel/io handle missing"); + ESP_GOTO_ON_FALSE(lcd_width > 0 && lcd_height > 0, ESP_ERR_INVALID_ARG, + fail, TAG, "invalid lcd size"); + + s_state.panel = panel_handle; + s_state.io = io_handle; + s_state.width = lcd_width; + s_state.height = lcd_height; + s_state.framebuffer_bytes = (size_t)s_state.width * (size_t)s_state.height * sizeof(uint16_t); + s_state.framebuffer_count = 0; + s_state.draw_framebuffer_index = 0; + s_state.visible_framebuffer_index = 0; + s_state.pending_framebuffer_index = -1; + s_state.frame_active = false; + s_state.flush_in_flight = false; + s_state.framebuffer_initialized = false; + display_hal_clear_clip_locked(); + + if (!s_state.display_flush_done) { + s_state.display_flush_done = xSemaphoreCreateBinary(); + ESP_GOTO_ON_FALSE(s_state.display_flush_done != NULL, ESP_ERR_NO_MEM, fail, TAG, + "create flush semaphore failed"); + } + if (!s_state.display_callbacks_registered) { + const esp_lcd_panel_io_callbacks_t callbacks = { + .on_color_trans_done = display_hal_flush_done_isr, + }; + ESP_GOTO_ON_ERROR(esp_lcd_panel_io_register_event_callbacks(s_state.io, &callbacks, NULL), + fail, TAG, "register flush callback failed"); + s_state.display_callbacks_registered = true; + } + +fail: + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_destroy(void) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + + if (s_state.flush_in_flight) { + ret = display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)); + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + } + + for (size_t i = 0; i < DISPLAY_HAL_FRAMEBUFFER_COUNT_MAX; ++i) { + heap_caps_free(s_state.framebuffers[i]); + s_state.framebuffers[i] = NULL; + } + if (s_state.painter) { + esp_painter_deinit(s_state.painter); + s_state.painter = NULL; + } + + s_state.panel = NULL; + s_state.io = NULL; + s_state.width = 0; + s_state.height = 0; + s_state.framebuffer_bytes = 0; + s_state.framebuffer_count = 0; + s_state.draw_framebuffer_index = 0; + s_state.visible_framebuffer_index = 0; + s_state.pending_framebuffer_index = -1; + s_state.frame_active = false; + s_state.flush_in_flight = false; + s_state.framebuffer_initialized = false; + s_state.clip_enabled = false; + s_state.clip_x = 0; + s_state.clip_y = 0; + s_state.clip_width = 0; + s_state.clip_height = 0; + + display_hal_unlock(); + return ESP_OK; +} + +static void display_hal_clear_clip_locked(void) +{ + s_state.clip_enabled = false; + s_state.clip_x = 0; + s_state.clip_y = 0; + s_state.clip_width = s_state.width; + s_state.clip_height = s_state.height; +} + +static uint16_t *display_hal_get_draw_framebuffer_locked(void) +{ + if (s_state.framebuffer_count == 0) { + return NULL; + } + return s_state.framebuffers[s_state.draw_framebuffer_index]; +} + +static uint16_t *display_hal_get_visible_framebuffer_locked(void) +{ + if (s_state.framebuffer_count == 0) { + return NULL; + } + return s_state.framebuffers[s_state.visible_framebuffer_index]; +} + +static esp_err_t display_hal_alloc_framebuffer_locked(size_t index) +{ + if (index >= DISPLAY_HAL_FRAMEBUFFER_COUNT_MAX) { + return ESP_ERR_INVALID_ARG; + } + if (s_state.framebuffers[index]) { + return ESP_OK; + } + + s_state.framebuffers[index] = heap_caps_aligned_alloc( + 16, s_state.framebuffer_bytes, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!s_state.framebuffers[index]) { + s_state.framebuffers[index] = heap_caps_aligned_alloc( + 16, s_state.framebuffer_bytes, MALLOC_CAP_DEFAULT); + } + ESP_RETURN_ON_FALSE(s_state.framebuffers[index] != NULL, ESP_ERR_NO_MEM, TAG, + "framebuffer alloc failed"); + memset(s_state.framebuffers[index], 0, s_state.framebuffer_bytes); + return ESP_OK; +} + +static esp_err_t display_hal_ensure_framebuffer_locked(void) +{ + if (s_state.framebuffer_count > 0) { + return ESP_OK; + } + + ESP_RETURN_ON_ERROR(display_hal_alloc_framebuffer_locked(0), TAG, "alloc framebuffer 0 failed"); + s_state.framebuffer_count = 1; + s_state.draw_framebuffer_index = 0; + s_state.visible_framebuffer_index = 0; + s_state.pending_framebuffer_index = -1; + + if (display_hal_alloc_framebuffer_locked(1) == ESP_OK) { + s_state.framebuffer_count = 2; + } + + s_state.framebuffer_initialized = true; + return ESP_OK; +} + +static void display_hal_fill_framebuffer_locked(uint16_t *framebuffer, uint16_t panel_color) +{ + if (!framebuffer) { + return; + } + size_t pixels = (size_t)s_state.width * (size_t)s_state.height; + for (size_t i = 0; i < pixels; ++i) { + framebuffer[i] = panel_color; + } +} + +static bool display_hal_get_clip_bounds_locked(int *left, int *top, int *right, int *bottom) +{ + int clip_left = 0; + int clip_top = 0; + int clip_right = s_state.width; + int clip_bottom = s_state.height; + + if (s_state.clip_enabled) { + clip_left = s_state.clip_x; + clip_top = s_state.clip_y; + clip_right = s_state.clip_x + s_state.clip_width; + clip_bottom = s_state.clip_y + s_state.clip_height; + + if (clip_left < 0) { + clip_left = 0; + } + if (clip_top < 0) { + clip_top = 0; + } + if (clip_right > s_state.width) { + clip_right = s_state.width; + } + if (clip_bottom > s_state.height) { + clip_bottom = s_state.height; + } + } + + if (left) { + *left = clip_left; + } + if (top) { + *top = clip_top; + } + if (right) { + *right = clip_right; + } + if (bottom) { + *bottom = clip_bottom; + } + return clip_right > clip_left && clip_bottom > clip_top; +} + +static bool display_hal_clip_rect_locked(int *x, int *y, int *width, int *height, + int *src_x, int *src_y) +{ + int clip_left = 0; + int clip_top = 0; + int clip_right = 0; + int clip_bottom = 0; + int dst_x = 0; + int dst_y = 0; + int dst_w = 0; + int dst_h = 0; + int dst_right = 0; + int dst_bottom = 0; + + if (!x || !y || !width || !height || *width <= 0 || *height <= 0) { + return false; + } + if (!display_hal_get_clip_bounds_locked(&clip_left, &clip_top, &clip_right, &clip_bottom)) { + return false; + } + + dst_x = *x; + dst_y = *y; + dst_w = *width; + dst_h = *height; + dst_right = dst_x + dst_w; + dst_bottom = dst_y + dst_h; + + if (dst_x < clip_left) { + int delta = clip_left - dst_x; + if (src_x) { + *src_x += delta; + } + dst_x = clip_left; + } + if (dst_y < clip_top) { + int delta = clip_top - dst_y; + if (src_y) { + *src_y += delta; + } + dst_y = clip_top; + } + if (dst_right > clip_right) { + dst_right = clip_right; + } + if (dst_bottom > clip_bottom) { + dst_bottom = clip_bottom; + } + + dst_w = dst_right - dst_x; + dst_h = dst_bottom - dst_y; + if (dst_w <= 0 || dst_h <= 0) { + return false; + } + + *x = dst_x; + *y = dst_y; + *width = dst_w; + *height = dst_h; + return true; +} + +static bool display_hal_clip_rect_to_screen_locked(int *x, int *y, int *width, int *height) +{ + int dst_x = 0; + int dst_y = 0; + int dst_right = 0; + int dst_bottom = 0; + + if (!x || !y || !width || !height || *width <= 0 || *height <= 0) { + return false; + } + + dst_x = *x; + dst_y = *y; + dst_right = dst_x + *width; + dst_bottom = dst_y + *height; + + if (dst_x < 0) { + dst_x = 0; + } + if (dst_y < 0) { + dst_y = 0; + } + if (dst_right > s_state.width) { + dst_right = s_state.width; + } + if (dst_bottom > s_state.height) { + dst_bottom = s_state.height; + } + + *x = dst_x; + *y = dst_y; + *width = dst_right - dst_x; + *height = dst_bottom - dst_y; + return *width > 0 && *height > 0; +} + +static float display_hal_normalize_degrees(float degrees) +{ + while (degrees < 0.0f) { + degrees += 360.0f; + } + while (degrees >= 360.0f) { + degrees -= 360.0f; + } + return degrees; +} + +static bool display_hal_arc_is_full_sweep(float start_deg, float end_deg) +{ + float sweep = end_deg - start_deg; + + if (fabsf(sweep) >= 359.999f) { + return true; + } + + return fabsf(display_hal_normalize_degrees(start_deg) - + display_hal_normalize_degrees(end_deg)) < 0.001f; +} + +static float display_hal_arc_sweep_degrees(float start_deg, float end_deg) +{ + float start = display_hal_normalize_degrees(start_deg); + float end = display_hal_normalize_degrees(end_deg); + float sweep = end - start; + + if (sweep < 0.0f) { + sweep += 360.0f; + } + return sweep; +} + +static float display_hal_point_angle_degrees(int dx, int dy) +{ + float degrees = atan2f((float)dy, (float)dx) * (180.0f / DISPLAY_HAL_PI); + + if (degrees < 0.0f) { + degrees += 360.0f; + } + return degrees; +} + +static bool display_hal_angle_in_arc(float angle_deg, float start_deg, float end_deg) +{ + float start = display_hal_normalize_degrees(start_deg); + float end = display_hal_normalize_degrees(end_deg); + float angle = display_hal_normalize_degrees(angle_deg); + + if (display_hal_arc_is_full_sweep(start_deg, end_deg)) { + return true; + } + if (start <= end) { + return angle >= start && angle <= end; + } + return angle >= start || angle <= end; +} + +static IRAM_ATTR bool display_hal_flush_done_isr(esp_lcd_panel_io_handle_t panel_io, + esp_lcd_panel_io_event_data_t *edata, + void *user_ctx) +{ + BaseType_t high_task_woken = pdFALSE; + + (void)panel_io; + (void)edata; + (void)user_ctx; + + if (s_state.display_flush_done) { + xSemaphoreGiveFromISR(s_state.display_flush_done, &high_task_woken); + } + + return high_task_woken == pdTRUE; +} + +static esp_err_t display_hal_wait_flush_done_locked(TickType_t timeout_ticks) +{ + if (!s_state.flush_in_flight) { + return ESP_OK; + } + ESP_RETURN_ON_FALSE(s_state.display_flush_done != NULL, ESP_ERR_INVALID_STATE, TAG, + "flush semaphore missing"); + + if (xSemaphoreTake(s_state.display_flush_done, timeout_ticks) != pdTRUE) { + return ESP_ERR_TIMEOUT; + } + + s_state.flush_in_flight = false; + if (s_state.pending_framebuffer_index >= 0) { + s_state.visible_framebuffer_index = (uint8_t)s_state.pending_framebuffer_index; + s_state.pending_framebuffer_index = -1; + } + return ESP_OK; +} + +static esp_err_t display_hal_submit_bitmap_locked(int x_start, int y_start, + int x_end, int y_end, + const uint16_t *pixels, + int pending_framebuffer_index, + bool wait_for_done) +{ + esp_err_t ret = display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)); + if (ret != ESP_OK) { + return ret; + } + + if (s_state.display_flush_done) { + while (xSemaphoreTake(s_state.display_flush_done, 0) == pdTRUE) { + } + } + + ret = esp_lcd_panel_draw_bitmap(s_state.panel, x_start, y_start, x_end, y_end, pixels); + if (ret != ESP_OK) { + return ret; + } + + s_state.flush_in_flight = true; + s_state.pending_framebuffer_index = (int8_t)pending_framebuffer_index; + + if (wait_for_done) { + ret = display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)); + } + return ret; +} + +static const esp_painter_basic_font_t *display_hal_get_font(uint8_t font_size) +{ + switch (font_size) { +#if CONFIG_ESP_PAINTER_BASIC_FONT_12 + case 12: + return &esp_painter_basic_font_12; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_16 + case 16: + return &esp_painter_basic_font_16; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_20 + case 20: + return &esp_painter_basic_font_20; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_24 + case 0: + case 24: + return &esp_painter_basic_font_24; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_28 + case 28: + return &esp_painter_basic_font_28; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_32 + case 32: + return &esp_painter_basic_font_32; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_36 + case 36: + return &esp_painter_basic_font_36; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_40 + case 40: + return &esp_painter_basic_font_40; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_44 + case 44: + return &esp_painter_basic_font_44; +#endif +#if CONFIG_ESP_PAINTER_BASIC_FONT_48 + case 48: + return &esp_painter_basic_font_48; +#endif + default: + break; + } + +#if CONFIG_ESP_PAINTER_BASIC_FONT_24 + return &esp_painter_basic_font_24; +#elif CONFIG_ESP_PAINTER_BASIC_FONT_20 + return &esp_painter_basic_font_20; +#elif CONFIG_ESP_PAINTER_BASIC_FONT_16 + return &esp_painter_basic_font_16; +#elif CONFIG_ESP_PAINTER_BASIC_FONT_12 + return &esp_painter_basic_font_12; +#else + return NULL; +#endif +} + +static void display_hal_measure_text_raw(const char *text, const esp_painter_basic_font_t *font, + uint16_t *out_width, uint16_t *out_height) +{ + uint16_t max_cols = 0; + uint16_t cols = 0; + uint16_t lines = 1; + + if (!text || !font) { + if (out_width) { + *out_width = 0; + } + if (out_height) { + *out_height = 0; + } + return; + } + + for (const char *p = text; *p; ++p) { + if (*p == '\n') { + if (cols > max_cols) { + max_cols = cols; + } + cols = 0; + lines++; + } else if (*p != '\r') { + cols++; + } + } + if (cols > max_cols) { + max_cols = cols; + } + + if (out_width) { + *out_width = (uint16_t)(max_cols * font->width); + } + if (out_height) { + *out_height = (uint16_t)(lines * font->height); + } +} + +static esp_err_t display_hal_ensure_painter_locked(void) +{ + esp_painter_config_t painter_cfg = { + .canvas = { + .width = (uint16_t)s_state.width, + .height = (uint16_t)s_state.height, + }, + .color_format = ESP_PAINTER_COLOR_FORMAT_RGB565, + .default_font = display_hal_get_font(24), + .swap_rgb565 = true, + }; + + if (s_state.painter) { + return ESP_OK; + } + ESP_RETURN_ON_FALSE(painter_cfg.default_font != NULL, ESP_ERR_NOT_SUPPORTED, TAG, + "no esp_painter font enabled"); + ESP_RETURN_ON_ERROR(esp_painter_init(&painter_cfg, &s_state.painter), TAG, "esp_painter_init failed"); + return ESP_OK; +} + +static esp_err_t display_hal_fill_rect_locked(int x, int y, int width, int height, uint16_t color565) +{ + uint16_t panel_color = display_hal_rgb565_to_panel(color565); + uint16_t *framebuffer = display_hal_get_draw_framebuffer_locked(); + + if (!display_hal_clip_rect_locked(&x, &y, &width, &height, NULL, NULL)) { + return ESP_OK; + } + + if (s_state.frame_active && framebuffer) { + if (s_state.flush_in_flight && + s_state.pending_framebuffer_index == (int8_t)s_state.draw_framebuffer_index) { + ESP_RETURN_ON_ERROR( + display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)), + TAG, "wait flush failed"); + } + for (int row = 0; row < height; ++row) { + uint16_t *dst = framebuffer + ((size_t)(y + row) * s_state.width) + x; + for (int col = 0; col < width; ++col) { + dst[col] = panel_color; + } + } + return ESP_OK; + } + + uint16_t *line = malloc((size_t)width * sizeof(uint16_t)); + ESP_RETURN_ON_FALSE(line != NULL, ESP_ERR_NO_MEM, TAG, "line alloc failed"); + for (int i = 0; i < width; ++i) { + line[i] = panel_color; + } + for (int row = 0; row < height; ++row) { + esp_err_t ret = display_hal_submit_bitmap_locked(x, y + row, x + width, y + row + 1, line, -1, true); + if (ret != ESP_OK) { + free(line); + return ret; + } + } + free(line); + return ESP_OK; +} + +static esp_err_t display_hal_draw_pixel_locked(int x, int y, uint16_t color565) +{ + return display_hal_fill_rect_locked(x, y, 1, 1, color565); +} + +static esp_err_t display_hal_draw_hline_locked(int x, int y, int width, uint16_t color565) +{ + return display_hal_fill_rect_locked(x, y, width, 1, color565); +} + +static esp_err_t display_hal_draw_vline_locked(int x, int y, int height, uint16_t color565) +{ + return display_hal_fill_rect_locked(x, y, 1, height, color565); +} + +static esp_err_t display_hal_draw_line_locked(int x0, int y0, int x1, int y1, uint16_t color565) +{ + if (y0 == y1) { + int x = x0 < x1 ? x0 : x1; + return display_hal_draw_hline_locked(x, y0, abs(x1 - x0) + 1, color565); + } + if (x0 == x1) { + int y = y0 < y1 ? y0 : y1; + return display_hal_draw_vline_locked(x0, y, abs(y1 - y0) + 1, color565); + } + + int dx = abs(x1 - x0); + int sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0); + int sy = y0 < y1 ? 1 : -1; + int err = dx + dy; + + while (true) { + esp_err_t ret = display_hal_draw_pixel_locked(x0, y0, color565); + if (ret != ESP_OK) { + return ret; + } + if (x0 == x1 && y0 == y1) { + break; + } + int e2 = err * 2; + if (e2 >= dy) { + err += dy; + x0 += sx; + } + if (e2 <= dx) { + err += dx; + y0 += sy; + } + } + return ESP_OK; +} + +static esp_err_t display_hal_draw_rect_locked(int x, int y, int width, int height, uint16_t color565) +{ + if (width <= 0 || height <= 0) { + return ESP_OK; + } + if (width == 1) { + return display_hal_draw_vline_locked(x, y, height, color565); + } + if (height == 1) { + return display_hal_draw_hline_locked(x, y, width, color565); + } + + ESP_RETURN_ON_ERROR(display_hal_draw_hline_locked(x, y, width, color565), TAG, "draw top failed"); + ESP_RETURN_ON_ERROR(display_hal_draw_hline_locked(x, y + height - 1, width, color565), TAG, + "draw bottom failed"); + ESP_RETURN_ON_ERROR(display_hal_draw_vline_locked(x, y + 1, height - 2, color565), TAG, + "draw left failed"); + return display_hal_draw_vline_locked(x + width - 1, y + 1, height - 2, color565); +} + +static esp_err_t display_hal_draw_bitmap_crop_locked(int x, int y, + int src_x, int src_y, + int w, int h, + int src_width, int src_height, + const uint16_t *pixels) +{ + if (!pixels || src_width <= 0 || src_height <= 0 || w <= 0 || h <= 0) { + return ESP_ERR_INVALID_ARG; + } + + if (src_x < 0) { + x -= src_x; + w += src_x; + src_x = 0; + } + if (src_y < 0) { + y -= src_y; + h += src_y; + src_y = 0; + } + if (src_x + w > src_width) { + w = src_width - src_x; + } + if (src_y + h > src_height) { + h = src_height - src_y; + } + if (w <= 0 || h <= 0) { + return ESP_OK; + } + + if (!display_hal_clip_rect_locked(&x, &y, &w, &h, &src_x, &src_y)) { + return ESP_OK; + } + + uint16_t *framebuffer = display_hal_get_draw_framebuffer_locked(); + if (s_state.frame_active && framebuffer) { + if (s_state.flush_in_flight && + s_state.pending_framebuffer_index == (int8_t)s_state.draw_framebuffer_index) { + ESP_RETURN_ON_ERROR( + display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)), + TAG, "wait flush failed"); + } + for (int row = 0; row < h; ++row) { + const uint16_t *src = pixels + ((size_t)(src_y + row) * src_width) + src_x; + uint16_t *dst = framebuffer + ((size_t)(y + row) * s_state.width) + x; + memcpy(dst, src, (size_t)w * sizeof(uint16_t)); + } + return ESP_OK; + } + + if (src_x == 0 && w == src_width) { + const uint16_t *start = pixels + ((size_t)src_y * src_width); + return display_hal_submit_bitmap_locked(x, y, x + w, y + h, start, -1, true); + } + + for (int row = 0; row < h; ++row) { + const uint16_t *row_ptr = pixels + ((size_t)(src_y + row) * src_width) + src_x; + ESP_RETURN_ON_ERROR( + display_hal_submit_bitmap_locked(x, y + row, x + w, y + row + 1, row_ptr, -1, true), + TAG, "submit bitmap row failed"); + } + return ESP_OK; +} + +static esp_err_t display_hal_draw_bitmap_locked(int x, int y, int w, int h, const uint16_t *pixels) +{ + return display_hal_draw_bitmap_crop_locked(x, y, 0, 0, w, h, w, h, pixels); +} + +static esp_err_t display_hal_present_locked(void) +{ + uint16_t *framebuffer = display_hal_get_draw_framebuffer_locked(); + + if (!framebuffer || !s_state.frame_active) { + return ESP_ERR_INVALID_STATE; + } + + ESP_RETURN_ON_ERROR( + display_hal_submit_bitmap_locked( + 0, 0, s_state.width, s_state.height, + framebuffer, (int)s_state.draw_framebuffer_index, false), + TAG, "present failed"); + + if (s_state.framebuffer_count > 1) { + s_state.draw_framebuffer_index = (uint8_t)((s_state.draw_framebuffer_index + 1) % + s_state.framebuffer_count); + } + return ESP_OK; +} + +static esp_err_t display_hal_present_rect_locked(int x, int y, int width, int height) +{ + uint16_t *draw_fb = display_hal_get_draw_framebuffer_locked(); + uint16_t *visible_fb = display_hal_get_visible_framebuffer_locked(); + + if (!draw_fb || !s_state.frame_active) { + return ESP_ERR_INVALID_STATE; + } + if (!display_hal_clip_rect_to_screen_locked(&x, &y, &width, &height)) { + return ESP_OK; + } + if (s_state.flush_in_flight) { + ESP_RETURN_ON_ERROR( + display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)), + TAG, "wait flush failed"); + } + + if (width == s_state.width) { + const uint16_t *start = draw_fb + ((size_t)y * s_state.width); + ESP_RETURN_ON_ERROR( + display_hal_submit_bitmap_locked(x, y, x + width, y + height, start, -1, true), + TAG, "present rect failed"); + } else { + for (int row = 0; row < height; ++row) { + const uint16_t *row_ptr = draw_fb + ((size_t)(y + row) * s_state.width) + x; + ESP_RETURN_ON_ERROR( + display_hal_submit_bitmap_locked( + x, y + row, x + width, y + row + 1, row_ptr, -1, true), + TAG, "present rect row failed"); + } + } + + if (visible_fb && visible_fb != draw_fb) { + for (int row = 0; row < height; ++row) { + const uint16_t *src = draw_fb + ((size_t)(y + row) * s_state.width) + x; + uint16_t *dst = visible_fb + ((size_t)(y + row) * s_state.width) + x; + memcpy(dst, src, (size_t)width * sizeof(uint16_t)); + } + } + return ESP_OK; +} + +static void display_hal_sort_vertices_by_y(int *x1, int *y1, int *x2, int *y2, int *x3, int *y3) +{ + if (*y1 > *y2) { + int tx = *x1; + int ty = *y1; + *x1 = *x2; + *y1 = *y2; + *x2 = tx; + *y2 = ty; + } + if (*y2 > *y3) { + int tx = *x2; + int ty = *y2; + *x2 = *x3; + *y2 = *y3; + *x3 = tx; + *y3 = ty; + } + if (*y1 > *y2) { + int tx = *x1; + int ty = *y1; + *x1 = *x2; + *y1 = *y2; + *x2 = tx; + *y2 = ty; + } +} + +#if CONFIG_ESP_ROM_HAS_JPEG_DECODE +typedef struct { + const uint8_t *data; + size_t len; + size_t offset; + uint16_t *pixels; + int width; + int height; +} display_hal_jpeg_ctx_t; + +static esp_err_t display_hal_jpeg_result_to_err(JRESULT result) +{ + switch (result) { + case JDR_OK: + return ESP_OK; + case JDR_PAR: + return ESP_ERR_INVALID_ARG; + case JDR_MEM1: + case JDR_MEM2: + return ESP_ERR_NO_MEM; + case JDR_FMT1: + case JDR_FMT2: + case JDR_FMT3: + return ESP_ERR_NOT_SUPPORTED; + case JDR_INTR: + case JDR_INP: + default: + return ESP_FAIL; + } +} + +static UINT display_hal_jpeg_input_cb(JDEC *decoder, BYTE *buf, UINT len) +{ + display_hal_jpeg_ctx_t *ctx = (display_hal_jpeg_ctx_t *)decoder->device; + size_t remaining = ctx->len - ctx->offset; + size_t chunk = len; + + if (chunk > remaining) { + chunk = remaining; + } + if (buf) { + memcpy(buf, ctx->data + ctx->offset, chunk); + } + ctx->offset += chunk; + return (UINT)chunk; +} + +static UINT display_hal_jpeg_output_cb(JDEC *decoder, void *bitmap, JRECT *rect) +{ + display_hal_jpeg_ctx_t *ctx = (display_hal_jpeg_ctx_t *)decoder->device; + uint8_t *src = (uint8_t *)bitmap; + + for (int y = rect->top; y <= rect->bottom; ++y) { + uint16_t *dst = ctx->pixels + ((size_t)y * (size_t)ctx->width) + rect->left; + for (int x = rect->left; x <= rect->right; ++x) { + uint16_t color = + (uint16_t)(((src[0] >> 3) << 11) | ((src[1] >> 2) << 5) | (src[2] >> 3)); + *dst++ = __builtin_bswap16(color); + src += 3; + } + } + return 1; +} + +static esp_err_t display_hal_decode_jpeg_rgb565_be(const uint8_t *jpeg_data, size_t jpeg_len, + uint16_t **pixels_out, int *out_w, int *out_h) +{ + display_hal_jpeg_ctx_t ctx = { + .data = jpeg_data, + .len = jpeg_len, + }; + JDEC decoder = {0}; + void *work = NULL; + esp_err_t ret = ESP_OK; + JRESULT result; + + if (!jpeg_data || jpeg_len == 0 || !pixels_out || !out_w || !out_h) { + return ESP_ERR_INVALID_ARG; + } + + work = calloc(1, DISPLAY_HAL_JPEG_WORKBUF_SIZE); + ESP_GOTO_ON_FALSE(work != NULL, ESP_ERR_NO_MEM, cleanup, TAG, "jpeg workspace alloc failed"); + + result = jd_prepare(&decoder, display_hal_jpeg_input_cb, work, DISPLAY_HAL_JPEG_WORKBUF_SIZE, &ctx); + ret = display_hal_jpeg_result_to_err(result); + ESP_GOTO_ON_ERROR(ret, cleanup, TAG, "jpeg header parse failed (%d)", result); + + ctx.width = (int)decoder.width; + ctx.height = (int)decoder.height; + ctx.pixels = malloc((size_t)ctx.width * (size_t)ctx.height * sizeof(uint16_t)); + ESP_GOTO_ON_FALSE(ctx.pixels != NULL, ESP_ERR_NO_MEM, cleanup, TAG, "jpeg pixel buffer alloc failed"); + + result = jd_decomp(&decoder, display_hal_jpeg_output_cb, 0); + ret = display_hal_jpeg_result_to_err(result); + ESP_GOTO_ON_ERROR(ret, cleanup, TAG, "jpeg decode failed (%d)", result); + + *pixels_out = ctx.pixels; + *out_w = ctx.width; + *out_h = ctx.height; + ctx.pixels = NULL; + +cleanup: + free(ctx.pixels); + free(work); + return ret; +} + +static esp_err_t display_hal_jpeg_get_size_internal(const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h) +{ + display_hal_jpeg_ctx_t ctx = { + .data = jpeg_data, + .len = jpeg_len, + }; + JDEC decoder = {0}; + void *work = NULL; + esp_err_t ret = ESP_OK; + JRESULT result; + + if (!jpeg_data || jpeg_len == 0 || !out_w || !out_h) { + return ESP_ERR_INVALID_ARG; + } + + work = calloc(1, DISPLAY_HAL_JPEG_WORKBUF_SIZE); + ESP_GOTO_ON_FALSE(work != NULL, ESP_ERR_NO_MEM, cleanup, TAG, "jpeg workspace alloc failed"); + + result = jd_prepare(&decoder, display_hal_jpeg_input_cb, work, DISPLAY_HAL_JPEG_WORKBUF_SIZE, &ctx); + ret = display_hal_jpeg_result_to_err(result); + ESP_GOTO_ON_ERROR(ret, cleanup, TAG, "jpeg header parse failed (%d)", result); + + *out_w = (int)decoder.width; + *out_h = (int)decoder.height; + +cleanup: + free(work); + return ret; +} +#endif + +static esp_err_t display_hal_scale_rgb565_be(const uint16_t *src, int src_w, int src_h, + int dst_w, int dst_h, uint16_t **dst_out) +{ + uint16_t *dst = NULL; + + if (!src || src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !dst_out) { + return ESP_ERR_INVALID_ARG; + } + dst = malloc((size_t)dst_w * (size_t)dst_h * sizeof(uint16_t)); + ESP_RETURN_ON_FALSE(dst != NULL, ESP_ERR_NO_MEM, TAG, "scale buffer alloc failed"); + + for (int y = 0; y < dst_h; ++y) { + int src_y = (y * src_h) / dst_h; + const uint16_t *src_row = src + ((size_t)src_y * src_w); + uint16_t *dst_row = dst + ((size_t)y * dst_w); + for (int x = 0; x < dst_w; ++x) { + int src_x = (x * src_w) / dst_w; + dst_row[x] = src_row[src_x]; + } + } + + *dst_out = dst; + return ESP_OK; +} + +int display_hal_width(void) +{ + return s_state.width; +} + +int display_hal_height(void) +{ + return s_state.height; +} + +esp_err_t display_hal_begin_frame(bool clear, uint16_t color565) +{ + esp_err_t ret = display_hal_lock(); + uint16_t *draw_fb = NULL; + uint16_t *visible_fb = NULL; + + if (ret != ESP_OK) { + return ret; + } + + ret = display_hal_ensure_display_locked(); + if (ret == ESP_OK) { + ret = display_hal_ensure_framebuffer_locked(); + } + if (ret == ESP_OK && s_state.flush_in_flight && + (!clear || s_state.pending_framebuffer_index == (int8_t)s_state.draw_framebuffer_index)) { + ret = display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)); + } + if (ret == ESP_OK) { + s_state.frame_active = true; + display_hal_clear_clip_locked(); + draw_fb = display_hal_get_draw_framebuffer_locked(); + visible_fb = display_hal_get_visible_framebuffer_locked(); + if (clear || !s_state.framebuffer_initialized) { + display_hal_fill_framebuffer_locked(draw_fb, display_hal_rgb565_to_panel(color565)); + s_state.framebuffer_initialized = true; + } else if (draw_fb && visible_fb && draw_fb != visible_fb) { + memcpy(draw_fb, visible_fb, s_state.framebuffer_bytes); + } + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_present(void) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_present_locked(); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_present_rect(int x, int y, int width, int height) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_present_rect_locked(x, y, width, height); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_end_frame(void) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (s_state.flush_in_flight) { + ret = display_hal_wait_flush_done_locked(pdMS_TO_TICKS(DISPLAY_HAL_FLUSH_TIMEOUT_MS)); + } + s_state.frame_active = false; + display_hal_clear_clip_locked(); + display_hal_unlock(); + return ret; +} + +bool display_hal_is_frame_active(void) +{ + bool active = false; + + if (display_hal_lock() == ESP_OK) { + active = s_state.frame_active; + display_hal_unlock(); + } + return active; +} + +esp_err_t display_hal_get_animation_info(display_hal_animation_info_t *info) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (!info) { + display_hal_unlock(); + return ESP_ERR_INVALID_ARG; + } + ret = display_hal_ensure_display_locked(); + if (ret == ESP_OK) { + ret = display_hal_ensure_framebuffer_locked(); + } + if (ret == ESP_OK) { + info->framebuffer_count = s_state.framebuffer_count; + info->double_buffered = s_state.framebuffer_count > 1; + info->frame_active = s_state.frame_active; + info->flush_in_flight = s_state.flush_in_flight; + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_clear(uint16_t color565) +{ + return display_hal_fill_rect(0, 0, display_hal_width(), display_hal_height(), color565); +} + +esp_err_t display_hal_set_clip_rect(int x, int y, int width, int height) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + ret = display_hal_require_created_locked(); + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + if (width <= 0 || height <= 0) { + display_hal_unlock(); + return ESP_ERR_INVALID_ARG; + } + s_state.clip_enabled = true; + s_state.clip_x = x; + s_state.clip_y = y; + s_state.clip_width = width; + s_state.clip_height = height; + display_hal_unlock(); + return ESP_OK; +} + +esp_err_t display_hal_clear_clip_rect(void) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + display_hal_clear_clip_locked(); + display_hal_unlock(); + return ESP_OK; +} + +esp_err_t display_hal_fill_rect(int x, int y, int width, int height, uint16_t color565) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_fill_rect_locked(x, y, width, height, color565); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_line(int x0, int y0, int x1, int y1, uint16_t color565) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_draw_line_locked(x0, y0, x1, y1, color565); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_rect(int x, int y, int width, int height, uint16_t color565) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_draw_rect_locked(x, y, width, height, color565); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_pixel(int x, int y, uint16_t color565) +{ + return display_hal_fill_rect(x, y, 1, 1, color565); +} + +esp_err_t display_hal_set_backlight(bool on) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = esp_lcd_panel_disp_on_off(s_state.panel, on); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_fill_circle(int cx, int cy, int r, uint16_t color565) +{ + if (r <= 0) { + return ESP_OK; + } + + uint16_t panel_color = display_hal_rgb565_to_panel(color565); + uint16_t *span = malloc((size_t)(r * 2 + 1) * sizeof(uint16_t)); + ESP_RETURN_ON_FALSE(span != NULL, ESP_ERR_NO_MEM, TAG, "circle span alloc failed"); + for (int i = 0; i < r * 2 + 1; ++i) { + span[i] = panel_color; + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + free(span); + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + for (int dy = -r; dy <= r && ret == ESP_OK; ++dy) { + int dx = (int)sqrtf((float)(r * r - dy * dy)); + ret = display_hal_draw_bitmap_locked(cx - dx, cy + dy, dx * 2 + 1, 1, span); + } + display_hal_unlock(); + free(span); + return ret; +} + +esp_err_t display_hal_draw_circle(int cx, int cy, int r, uint16_t color565) +{ + if (r <= 0) { + return display_hal_draw_pixel(cx, cy, color565); + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + int x = 0; + int y = r; + int d = 1 - r; + + while (x <= y) { + const int pts[8][2] = { + {cx + x, cy + y}, {cx - x, cy + y}, + {cx + x, cy - y}, {cx - x, cy - y}, + {cx + y, cy + x}, {cx - y, cy + x}, + {cx + y, cy - x}, {cx - y, cy - x}, + }; + for (int i = 0; i < 8 && ret == ESP_OK; ++i) { + ret = display_hal_draw_pixel_locked(pts[i][0], pts[i][1], color565); + } + if (d < 0) { + d += 2 * x + 3; + } else { + d += 2 * (x - y) + 5; + y--; + } + x++; + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_arc(int cx, int cy, int radius, + float start_deg, float end_deg, uint16_t color565) +{ + if (radius <= 0) { + return display_hal_draw_pixel(cx, cy, color565); + } + if (display_hal_arc_is_full_sweep(start_deg, end_deg)) { + return display_hal_draw_circle(cx, cy, radius, color565); + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + float start = display_hal_normalize_degrees(start_deg); + float sweep = display_hal_arc_sweep_degrees(start_deg, end_deg); + int steps = (int)ceilf(((sweep * DISPLAY_HAL_PI) / 180.0f) * (float)radius); + if (steps < 8) { + steps = 8; + } + + int prev_x = cx + (int)lroundf(cosf(start * DISPLAY_HAL_PI / 180.0f) * (float)radius); + int prev_y = cy + (int)lroundf(sinf(start * DISPLAY_HAL_PI / 180.0f) * (float)radius); + + for (int i = 1; i <= steps && ret == ESP_OK; ++i) { + float angle = start + (sweep * (float)i / (float)steps); + float rad = angle * DISPLAY_HAL_PI / 180.0f; + int x = cx + (int)lroundf(cosf(rad) * (float)radius); + int y = cy + (int)lroundf(sinf(rad) * (float)radius); + ret = display_hal_draw_line_locked(prev_x, prev_y, x, y, color565); + prev_x = x; + prev_y = y; + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_fill_arc(int cx, int cy, int inner_radius, int outer_radius, + float start_deg, float end_deg, uint16_t color565) +{ + if (outer_radius < 0) { + return ESP_ERR_INVALID_ARG; + } + if (outer_radius == 0) { + return display_hal_draw_pixel(cx, cy, color565); + } + if (inner_radius < 0) { + inner_radius = 0; + } + if (inner_radius > outer_radius) { + int tmp = inner_radius; + inner_radius = outer_radius; + outer_radius = tmp; + } + if (display_hal_arc_is_full_sweep(start_deg, end_deg) && inner_radius == 0) { + return display_hal_fill_circle(cx, cy, outer_radius, color565); + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + int clip_left = 0; + int clip_top = 0; + int clip_right = s_state.width; + int clip_bottom = s_state.height; + if (!display_hal_get_clip_bounds_locked(&clip_left, &clip_top, &clip_right, &clip_bottom)) { + display_hal_unlock(); + return ESP_OK; + } + + int outer_sq = outer_radius * outer_radius; + int inner_sq = inner_radius * inner_radius; + int y_start = cy - outer_radius; + int y_end = cy + outer_radius; + if (y_start < clip_top) { + y_start = clip_top; + } + if (y_end >= clip_bottom) { + y_end = clip_bottom - 1; + } + + for (int y = y_start; y <= y_end && ret == ESP_OK; ++y) { + int span_start = -1; + int x_start = cx - outer_radius; + int x_end = cx + outer_radius; + if (x_start < clip_left) { + x_start = clip_left; + } + if (x_end >= clip_right) { + x_end = clip_right - 1; + } + + for (int x = x_start; x <= x_end; ++x) { + int dx = x - cx; + int dy = y - cy; + int dist_sq = dx * dx + dy * dy; + bool inside = dist_sq <= outer_sq && dist_sq >= inner_sq; + + if (inside && !display_hal_arc_is_full_sweep(start_deg, end_deg)) { + inside = display_hal_angle_in_arc(display_hal_point_angle_degrees(dx, dy), start_deg, end_deg); + } + + if (inside) { + if (span_start < 0) { + span_start = x; + } + } else if (span_start >= 0) { + ret = display_hal_draw_hline_locked(span_start, y, x - span_start, color565); + span_start = -1; + } + } + + if (span_start >= 0 && ret == ESP_OK) { + ret = display_hal_draw_hline_locked(span_start, y, x_end - span_start + 1, color565); + } + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_ellipse(int cx, int cy, int radius_x, int radius_y, + uint16_t color565) +{ + if (radius_x < 0 || radius_y < 0) { + return ESP_ERR_INVALID_ARG; + } + if (radius_x == 0 && radius_y == 0) { + return display_hal_draw_pixel(cx, cy, color565); + } + if (radius_x == 0) { + return display_hal_draw_line(cx, cy - radius_y, cx, cy + radius_y, color565); + } + if (radius_y == 0) { + return display_hal_draw_line(cx - radius_x, cy, cx + radius_x, cy, color565); + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + float perimeter = DISPLAY_HAL_PI * + (3.0f * (radius_x + radius_y) - + sqrtf((float)((3 * radius_x + radius_y) * (radius_x + 3 * radius_y)))); + int steps = (int)ceilf(perimeter); + if (steps < 16) { + steps = 16; + } + + int prev_x = cx + radius_x; + int prev_y = cy; + for (int i = 1; i <= steps && ret == ESP_OK; ++i) { + float angle = ((float)i / (float)steps) * 2.0f * DISPLAY_HAL_PI; + int x = cx + (int)lroundf(cosf(angle) * (float)radius_x); + int y = cy + (int)lroundf(sinf(angle) * (float)radius_y); + ret = display_hal_draw_line_locked(prev_x, prev_y, x, y, color565); + prev_x = x; + prev_y = y; + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_fill_ellipse(int cx, int cy, int radius_x, int radius_y, + uint16_t color565) +{ + if (radius_x < 0 || radius_y < 0) { + return ESP_ERR_INVALID_ARG; + } + if (radius_x == 0 && radius_y == 0) { + return display_hal_draw_pixel(cx, cy, color565); + } + if (radius_x == 0) { + return display_hal_fill_rect(cx, cy - radius_y, 1, radius_y * 2 + 1, color565); + } + if (radius_y == 0) { + return display_hal_fill_rect(cx - radius_x, cy, radius_x * 2 + 1, 1, color565); + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + int clip_left = 0; + int clip_top = 0; + int clip_right = s_state.width; + int clip_bottom = s_state.height; + if (!display_hal_get_clip_bounds_locked(&clip_left, &clip_top, &clip_right, &clip_bottom)) { + display_hal_unlock(); + return ESP_OK; + } + + int y_start = cy - radius_y; + int y_end = cy + radius_y; + if (y_start < clip_top) { + y_start = clip_top; + } + if (y_end >= clip_bottom) { + y_end = clip_bottom - 1; + } + + for (int y = y_start; y <= y_end && ret == ESP_OK; ++y) { + float dy = (float)(y - cy) / (float)radius_y; + float dx = (float)radius_x * sqrtf(fmaxf(0.0f, 1.0f - (dy * dy))); + int span = (int)lroundf(dx); + int x0 = cx - span; + int x1 = cx + span; + + if (x0 < clip_left) { + x0 = clip_left; + } + if (x1 >= clip_right) { + x1 = clip_right - 1; + } + if (x1 >= x0) { + ret = display_hal_draw_hline_locked(x0, y, x1 - x0 + 1, color565); + } + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_round_rect(int x, int y, int width, int height, + int radius, uint16_t color565) +{ + if (width <= 0 || height <= 0) { + return ESP_OK; + } + + int max_radius = (width < height ? width : height) / 2; + if (radius <= 0 || max_radius <= 0) { + return display_hal_draw_rect(x, y, width, height, color565); + } + if (radius > max_radius) { + radius = max_radius; + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + ret = display_hal_draw_hline_locked(x + radius, y, width - (radius * 2), color565); + if (ret == ESP_OK) { + ret = display_hal_draw_hline_locked(x + radius, y + height - 1, width - (radius * 2), color565); + } + if (ret == ESP_OK) { + ret = display_hal_draw_vline_locked(x, y + radius, height - (radius * 2), color565); + } + if (ret == ESP_OK) { + ret = display_hal_draw_vline_locked(x + width - 1, y + radius, height - (radius * 2), color565); + } + + for (int row = 0; row < radius && ret == ESP_OK; ++row) { + int off = radius - row - 1; + int dx = (int)sqrtf((float)(radius * radius - off * off)); + int inset = radius - dx; + ret = display_hal_draw_pixel_locked(x + inset, y + row, color565); + if (ret == ESP_OK) { + ret = display_hal_draw_pixel_locked(x + width - 1 - inset, y + row, color565); + } + if (ret == ESP_OK) { + ret = display_hal_draw_pixel_locked(x + inset, y + height - 1 - row, color565); + } + if (ret == ESP_OK) { + ret = display_hal_draw_pixel_locked(x + width - 1 - inset, y + height - 1 - row, color565); + } + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_fill_round_rect(int x, int y, int width, int height, + int radius, uint16_t color565) +{ + if (width <= 0 || height <= 0) { + return ESP_OK; + } + + int max_radius = (width < height ? width : height) / 2; + if (radius <= 0 || max_radius <= 0) { + return display_hal_fill_rect(x, y, width, height, color565); + } + if (radius > max_radius) { + radius = max_radius; + } + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + ret = display_hal_fill_rect_locked(x + radius, y, width - (radius * 2), height, color565); + for (int row = 0; row < radius && ret == ESP_OK; ++row) { + int off = radius - row - 1; + int dx = (int)sqrtf((float)(radius * radius - off * off)); + int inset = radius - dx; + int span_w = width - (inset * 2); + ret = display_hal_draw_hline_locked(x + inset, y + row, span_w, color565); + if (ret == ESP_OK) { + ret = display_hal_draw_hline_locked(x + inset, y + height - 1 - row, span_w, color565); + } + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_triangle(int x1, int y1, int x2, int y2, + int x3, int y3, uint16_t color565) +{ + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_draw_line_locked(x1, y1, x2, y2, color565); + } + if (ret == ESP_OK) { + ret = display_hal_draw_line_locked(x2, y2, x3, y3, color565); + } + if (ret == ESP_OK) { + ret = display_hal_draw_line_locked(x3, y3, x1, y1, color565); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_fill_triangle(int x1, int y1, int x2, int y2, + int x3, int y3, uint16_t color565) +{ + display_hal_sort_vertices_by_y(&x1, &y1, &x2, &y2, &x3, &y3); + + esp_err_t ret = display_hal_lock(); + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret != ESP_OK) { + display_hal_unlock(); + return ret; + } + + if (y1 == y3) { + int min_x = x1; + int max_x = x1; + if (x2 < min_x) { + min_x = x2; + } + if (x3 < min_x) { + min_x = x3; + } + if (x2 > max_x) { + max_x = x2; + } + if (x3 > max_x) { + max_x = x3; + } + ret = display_hal_draw_hline_locked(min_x, y1, max_x - min_x + 1, color565); + display_hal_unlock(); + return ret; + } + + for (int y = y1; y <= y3 && ret == ESP_OK; ++y) { + float alpha = (y3 == y1) ? 0.0f : (float)(y - y1) / (float)(y3 - y1); + float beta = 0.0f; + int ax = x1 + (int)lroundf((x3 - x1) * alpha); + int bx = 0; + + if (y < y2) { + beta = (y2 == y1) ? 0.0f : (float)(y - y1) / (float)(y2 - y1); + bx = x1 + (int)lroundf((x2 - x1) * beta); + } else { + beta = (y3 == y2) ? 0.0f : (float)(y - y2) / (float)(y3 - y2); + bx = x2 + (int)lroundf((x3 - x2) * beta); + } + + if (ax > bx) { + int tmp = ax; + ax = bx; + bx = tmp; + } + ret = display_hal_draw_hline_locked(ax, y, bx - ax + 1, color565); + } + + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_measure_text(const char *text, uint8_t font_size, + uint16_t *out_width, uint16_t *out_height) +{ + const esp_painter_basic_font_t *font = display_hal_get_font(font_size); + + ESP_RETURN_ON_FALSE(font != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "font size %u unavailable", font_size); + display_hal_measure_text_raw(text, font, out_width, out_height); + return ESP_OK; +} + +esp_err_t display_hal_draw_text(int x, int y, const char *text, uint8_t font_size, + uint16_t text_color565, bool has_bg, uint16_t bg_color565) +{ + const esp_painter_basic_font_t *font = NULL; + uint16_t text_w = 0; + uint16_t text_h = 0; + uint16_t fill_color = 0; + uint16_t *buffer = NULL; + size_t buffer_bytes = 0; + size_t aligned_buffer_bytes = 0; + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + ESP_GOTO_ON_FALSE(text != NULL, ESP_ERR_INVALID_ARG, fail, TAG, "text is NULL"); + if (text[0] == '\0') { + ret = ESP_OK; + goto fail; + } + + ret = display_hal_ensure_display_locked(); + if (ret == ESP_OK) { + ret = display_hal_ensure_painter_locked(); + } + if (ret != ESP_OK) { + goto fail; + } + + font = display_hal_get_font(font_size); + ESP_GOTO_ON_FALSE(font != NULL, ESP_ERR_NOT_SUPPORTED, fail, TAG, "font size %u unavailable", font_size); + display_hal_measure_text_raw(text, font, &text_w, &text_h); + if (text_w == 0 || text_h == 0) { + ret = ESP_OK; + goto fail; + } + + buffer_bytes = (size_t)text_w * (size_t)text_h * sizeof(uint16_t); + aligned_buffer_bytes = (buffer_bytes + (DISPLAY_HAL_TEXT_CACHE_ALIGN - 1)) & + ~(size_t)(DISPLAY_HAL_TEXT_CACHE_ALIGN - 1); + buffer = heap_caps_aligned_alloc(DISPLAY_HAL_TEXT_CACHE_ALIGN, aligned_buffer_bytes, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!buffer) { + buffer = heap_caps_aligned_alloc(DISPLAY_HAL_TEXT_CACHE_ALIGN, aligned_buffer_bytes, MALLOC_CAP_DEFAULT); + } + ESP_GOTO_ON_FALSE(buffer != NULL, ESP_ERR_NO_MEM, fail, TAG, "text buffer alloc failed"); + + fill_color = display_hal_rgb565_to_panel(has_bg ? bg_color565 : 0x0000); + for (size_t i = 0; i < aligned_buffer_bytes / sizeof(uint16_t); ++i) { + buffer[i] = fill_color; + } + + ret = esp_painter_draw_string_rgb565(s_state.painter, (uint8_t *)buffer, (uint32_t)aligned_buffer_bytes, + 0, 0, font, text_color565, text); + if (ret == ESP_OK) { + ret = display_hal_draw_bitmap_locked(x, y, (int)text_w, (int)text_h, buffer); + } + +fail: + heap_caps_free(buffer); + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_text_aligned(int x, int y, int width, int height, + const char *text, uint8_t font_size, + uint16_t text_color565, bool has_bg, uint16_t bg_color565, + display_hal_text_align_t align, + display_hal_text_valign_t valign) +{ + uint16_t text_w = 0; + uint16_t text_h = 0; + ESP_RETURN_ON_ERROR(display_hal_measure_text(text, font_size, &text_w, &text_h), TAG, + "measure text failed"); + + int draw_x = x; + int draw_y = y; + + if (width > 0) { + if (align == DISPLAY_HAL_TEXT_ALIGN_CENTER) { + draw_x = x + (width - (int)text_w) / 2; + } else if (align == DISPLAY_HAL_TEXT_ALIGN_RIGHT) { + draw_x = x + width - (int)text_w; + } + } + if (height > 0) { + if (valign == DISPLAY_HAL_TEXT_VALIGN_MIDDLE) { + draw_y = y + (height - (int)text_h) / 2; + } else if (valign == DISPLAY_HAL_TEXT_VALIGN_BOTTOM) { + draw_y = y + height - (int)text_h; + } + } + + return display_hal_draw_text(draw_x, draw_y, text, font_size, text_color565, has_bg, bg_color565); +} + +esp_err_t display_hal_draw_bitmap(int x, int y, int w, int h, const uint16_t *pixels) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_draw_bitmap_locked(x, y, w, h, pixels); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_bitmap_crop(int x, int y, + int src_x, int src_y, + int w, int h, + int src_width, int src_height, + const uint16_t *pixels) +{ + esp_err_t ret = display_hal_lock(); + + if (ret != ESP_OK) { + return ret; + } + if (ret == ESP_OK) { + ret = display_hal_ensure_display_locked(); + } + if (ret == ESP_OK) { + ret = display_hal_draw_bitmap_crop_locked(x, y, src_x, src_y, w, h, src_width, src_height, pixels); + } + display_hal_unlock(); + return ret; +} + +esp_err_t display_hal_draw_jpeg(int x, int y, + const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h) +{ +#if !CONFIG_ESP_ROM_HAS_JPEG_DECODE + (void)x; + (void)y; + (void)jpeg_data; + (void)jpeg_len; + (void)out_w; + (void)out_h; + return ESP_ERR_NOT_SUPPORTED; +#else + uint16_t *pixels = NULL; + int width = 0; + int height = 0; + esp_err_t ret = display_hal_decode_jpeg_rgb565_be(jpeg_data, jpeg_len, &pixels, &width, &height); + + if (ret != ESP_OK) { + return ret; + } + if (out_w) { + *out_w = width; + } + if (out_h) { + *out_h = height; + } + ret = display_hal_draw_bitmap(x, y, width, height, pixels); + free(pixels); + return ret; +#endif +} + +esp_err_t display_hal_draw_jpeg_crop(int x, int y, + int src_x, int src_y, + int w, int h, + const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h) +{ +#if !CONFIG_ESP_ROM_HAS_JPEG_DECODE + (void)x; + (void)y; + (void)src_x; + (void)src_y; + (void)w; + (void)h; + (void)jpeg_data; + (void)jpeg_len; + (void)out_w; + (void)out_h; + return ESP_ERR_NOT_SUPPORTED; +#else + uint16_t *pixels = NULL; + int width = 0; + int height = 0; + esp_err_t ret = display_hal_decode_jpeg_rgb565_be(jpeg_data, jpeg_len, &pixels, &width, &height); + + if (ret != ESP_OK) { + return ret; + } + if (out_w) { + *out_w = width; + } + if (out_h) { + *out_h = height; + } + ret = display_hal_draw_bitmap_crop(x, y, src_x, src_y, w, h, width, height, pixels); + free(pixels); + return ret; +#endif +} + +esp_err_t display_hal_jpeg_get_size(const uint8_t *jpeg_data, size_t jpeg_len, + int *out_w, int *out_h) +{ +#if !CONFIG_ESP_ROM_HAS_JPEG_DECODE + (void)jpeg_data; + (void)jpeg_len; + (void)out_w; + (void)out_h; + return ESP_ERR_NOT_SUPPORTED; +#else + return display_hal_jpeg_get_size_internal(jpeg_data, jpeg_len, out_w, out_h); +#endif +} + +esp_err_t display_hal_draw_jpeg_scaled(int x, int y, + const uint8_t *jpeg_data, size_t jpeg_len, + int scale_w, int scale_h, + int *out_w, int *out_h) +{ +#if !CONFIG_ESP_ROM_HAS_JPEG_DECODE + (void)x; + (void)y; + (void)jpeg_data; + (void)jpeg_len; + (void)scale_w; + (void)scale_h; + (void)out_w; + (void)out_h; + return ESP_ERR_NOT_SUPPORTED; +#else + uint16_t *pixels = NULL; + uint16_t *scaled = NULL; + int width = 0; + int height = 0; + esp_err_t ret = ESP_OK; + + if (!jpeg_data || jpeg_len == 0 || scale_w <= 0 || scale_h <= 0) { + return ESP_ERR_INVALID_ARG; + } + + ret = display_hal_decode_jpeg_rgb565_be(jpeg_data, jpeg_len, &pixels, &width, &height); + if (ret != ESP_OK) { + return ret; + } + ret = display_hal_scale_rgb565_be(pixels, width, height, scale_w, scale_h, &scaled); + if (ret == ESP_OK) { + ret = display_hal_draw_bitmap(x, y, scale_w, scale_h, scaled); + } + if (out_w) { + *out_w = scale_w; + } + if (out_h) { + *out_h = scale_h; + } + free(pixels); + free(scaled); + return ret; +#endif +} diff --git a/components/lua_modules/lua_module_display/src/lua_module_display.c b/components/lua_modules/lua_module_display/src/lua_module_display.c new file mode 100644 index 0000000..58173d1 --- /dev/null +++ b/components/lua_modules/lua_module_display/src/lua_module_display.c @@ -0,0 +1,1288 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * Lua "display" module. + * + * Ported from esp-claw lua_module_halo_display.c. + * HAL calls are routed through display_hal.h which the board layer must + * implement. PNG decode is done here using libpng; JPEG decode is delegated + * to the HAL. + */ +#include "lua_module_display.h" + +#include "cap_lua.h" +#include "display_hal.h" +#include "esp_err.h" +#include "lauxlib.h" +#include "png.h" + +#include +#include +#include +#include + +/* ------------------------------------------------------------------------- + * Argument helpers (mirrors the reference implementation) + * ---------------------------------------------------------------------- */ + +static int lua_display_check_integer_arg(lua_State *L, int index, const char *name) +{ + if (!lua_isinteger(L, index)) { + return luaL_error(L, "display %s must be an integer", name); + } + return (int)lua_tointeger(L, index); +} + +static float lua_display_check_number_arg(lua_State *L, int index, const char *name) +{ + if (!lua_isnumber(L, index)) { + luaL_error(L, "display %s must be a number", name); + return 0.0f; + } + return (float)lua_tonumber(L, index); +} + +static bool lua_display_is_ascii_text(const char *text) +{ + if (!text) { + return false; + } + while (*text) { + unsigned char ch = (unsigned char)*text++; + if ((ch < 32 || ch > 126) && ch != '\n' && ch != '\r' && ch != '\t') { + return false; + } + } + return true; +} + +/* Pack three consecutive integer arguments into an RGB565 colour. */ +static uint16_t lua_display_color(lua_State *L, int start_index) +{ + int red = lua_display_check_integer_arg(L, start_index, "color component"); + int green = lua_display_check_integer_arg(L, start_index + 1, "color component"); + int blue = lua_display_check_integer_arg(L, start_index + 2, "color component"); + return (uint16_t)(((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3)); +} + +static uint16_t lua_display_rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue) +{ + return (uint16_t)(((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3)); +} + +static void *lua_display_check_lightuserdata_arg(lua_State *L, int index, const char *name) +{ + void *ptr = lua_touserdata(L, index); + + luaL_argcheck(L, ptr != NULL, index, name); + return ptr; +} + +/* ------------------------------------------------------------------------- + * Screen lifecycle + * ---------------------------------------------------------------------- */ + +static int lua_display_create_screen(lua_State *L) +{ + esp_lcd_panel_handle_t panel_handle = + (esp_lcd_panel_handle_t)lua_display_check_lightuserdata_arg( + L, 1, "display panel_handle lightuserdata expected"); + esp_lcd_panel_io_handle_t io_handle = + (esp_lcd_panel_io_handle_t)lua_display_check_lightuserdata_arg( + L, 2, "display io_handle lightuserdata expected"); + int lcd_width = lua_display_check_integer_arg(L, 3, "lcd_width"); + int lcd_height = lua_display_check_integer_arg(L, 4, "lcd_height"); + + esp_err_t err = display_hal_create(panel_handle, io_handle, lcd_width, lcd_height); + if (err != ESP_OK) { + return luaL_error(L, "display create_screen failed: %s", esp_err_to_name(err)); + } + + lua_pushboolean(L, 1); + return 1; +} + +static int lua_display_destroy_screen(lua_State *L) +{ + (void)L; + esp_err_t err = display_hal_destroy(); + if (err != ESP_OK) { + return luaL_error(L, "display destroy_screen failed: %s", esp_err_to_name(err)); + } + + lua_pushboolean(L, 1); + return 1; +} + +/* ------------------------------------------------------------------------- + * Text option helpers + * ---------------------------------------------------------------------- */ + +static display_hal_text_align_t lua_display_parse_align(lua_State *L, int index, + display_hal_text_align_t default_align) +{ + const char *value = lua_tostring(L, index); + if (!value || strcmp(value, "left") == 0) { + return DISPLAY_HAL_TEXT_ALIGN_LEFT; + } + if (strcmp(value, "center") == 0 || strcmp(value, "centre") == 0) { + return DISPLAY_HAL_TEXT_ALIGN_CENTER; + } + if (strcmp(value, "right") == 0) { + return DISPLAY_HAL_TEXT_ALIGN_RIGHT; + } + luaL_error(L, "display align must be left, center, or right"); + return default_align; +} + +static display_hal_text_valign_t lua_display_parse_valign(lua_State *L, int index, + display_hal_text_valign_t default_valign) +{ + const char *value = lua_tostring(L, index); + if (!value || strcmp(value, "top") == 0) { + return DISPLAY_HAL_TEXT_VALIGN_TOP; + } + if (strcmp(value, "middle") == 0 || strcmp(value, "center") == 0) { + return DISPLAY_HAL_TEXT_VALIGN_MIDDLE; + } + if (strcmp(value, "bottom") == 0) { + return DISPLAY_HAL_TEXT_VALIGN_BOTTOM; + } + luaL_error(L, "display valign must be top, middle, or bottom"); + return default_valign; +} + +/* Parse an optional table at `index` for text-rendering options. + * NULL output pointers are silently skipped. */ +static void lua_display_parse_text_options(lua_State *L, int index, + uint8_t *text_r, uint8_t *text_g, uint8_t *text_b, + uint8_t *font_size, + uint8_t *bg_r, uint8_t *bg_g, uint8_t *bg_b, + bool *has_bg, + display_hal_text_align_t *align, + display_hal_text_valign_t *valign) +{ + if (lua_isnoneornil(L, index)) { + return; + } + luaL_checktype(L, index, LUA_TTABLE); + + lua_getfield(L, index, "r"); + if (!lua_isnil(L, -1) && text_r) { + *text_r = (uint8_t)lua_display_check_integer_arg(L, -1, "text color component"); + } + lua_pop(L, 1); + + lua_getfield(L, index, "g"); + if (!lua_isnil(L, -1) && text_g) { + *text_g = (uint8_t)lua_display_check_integer_arg(L, -1, "text color component"); + } + lua_pop(L, 1); + + lua_getfield(L, index, "b"); + if (!lua_isnil(L, -1) && text_b) { + *text_b = (uint8_t)lua_display_check_integer_arg(L, -1, "text color component"); + } + lua_pop(L, 1); + + lua_getfield(L, index, "font_size"); + if (!lua_isnil(L, -1) && font_size) { + *font_size = (uint8_t)lua_display_check_integer_arg(L, -1, "font_size"); + } + lua_pop(L, 1); + + lua_getfield(L, index, "bg_r"); + if (!lua_isnil(L, -1) && bg_r) { + *bg_r = (uint8_t)lua_display_check_integer_arg(L, -1, "background color component"); + if (has_bg) { *has_bg = true; } + } + lua_pop(L, 1); + + lua_getfield(L, index, "bg_g"); + if (!lua_isnil(L, -1) && bg_g) { + *bg_g = (uint8_t)lua_display_check_integer_arg(L, -1, "background color component"); + if (has_bg) { *has_bg = true; } + } + lua_pop(L, 1); + + lua_getfield(L, index, "bg_b"); + if (!lua_isnil(L, -1) && bg_b) { + *bg_b = (uint8_t)lua_display_check_integer_arg(L, -1, "background color component"); + if (has_bg) { *has_bg = true; } + } + lua_pop(L, 1); + + lua_getfield(L, index, "align"); + if (!lua_isnil(L, -1) && align) { + *align = lua_display_parse_align(L, -1, *align); + } + lua_pop(L, 1); + + lua_getfield(L, index, "valign"); + if (!lua_isnil(L, -1) && valign) { + *valign = lua_display_parse_valign(L, -1, *valign); + } + lua_pop(L, 1); +} + +/* ------------------------------------------------------------------------- + * Text drawing + * ---------------------------------------------------------------------- */ + +static int lua_display_draw_text(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + const char *text = luaL_checkstring(L, 3); + uint8_t text_r = 255, text_g = 255, text_b = 255; + uint8_t bg_r = 0, bg_g = 0, bg_b = 0; + uint8_t font_size = 24; + bool has_bg = false; + + if (!lua_display_is_ascii_text(text)) { + return luaL_error(L, + "display draw_text only supports ASCII text; " + "use draw_png_file/draw_jpeg_file for Chinese or other Unicode text"); + } + + lua_display_parse_text_options(L, 4, + &text_r, &text_g, &text_b, &font_size, + &bg_r, &bg_g, &bg_b, &has_bg, NULL, NULL); + + esp_err_t err = display_hal_draw_text(x, y, text, font_size, + lua_display_rgb888_to_rgb565(text_r, text_g, text_b), + has_bg, + lua_display_rgb888_to_rgb565(bg_r, bg_g, bg_b)); + if (err != ESP_OK) { + return luaL_error(L, "display draw_text failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_measure_text(lua_State *L) +{ + const char *text = luaL_checkstring(L, 1); + uint8_t font_size = 24; + uint16_t width = 0, height = 0; + + lua_display_parse_text_options(L, 2, + NULL, NULL, NULL, &font_size, + NULL, NULL, NULL, NULL, NULL, NULL); + + esp_err_t err = display_hal_measure_text(text, font_size, &width, &height); + if (err != ESP_OK) { + return luaL_error(L, "display measure_text failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, width); + lua_pushinteger(L, height); + return 2; +} + +static int lua_display_draw_text_aligned(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + const char *text = luaL_checkstring(L, 5); + uint8_t text_r = 255, text_g = 255, text_b = 255; + uint8_t bg_r = 0, bg_g = 0, bg_b = 0; + uint8_t font_size = 24; + bool has_bg = false; + display_hal_text_align_t align = DISPLAY_HAL_TEXT_ALIGN_LEFT; + display_hal_text_valign_t valign = DISPLAY_HAL_TEXT_VALIGN_TOP; + + if (!lua_display_is_ascii_text(text)) { + return luaL_error(L, + "display draw_text_aligned only supports ASCII text; " + "use draw_png_file/draw_jpeg_file for Chinese or other Unicode text"); + } + + lua_display_parse_text_options(L, 6, + &text_r, &text_g, &text_b, &font_size, + &bg_r, &bg_g, &bg_b, &has_bg, &align, &valign); + + esp_err_t err = display_hal_draw_text_aligned( + x, y, width, height, text, font_size, + lua_display_rgb888_to_rgb565(text_r, text_g, text_b), + has_bg, + lua_display_rgb888_to_rgb565(bg_r, bg_g, bg_b), + align, valign); + if (err != ESP_OK) { + return luaL_error(L, "display draw_text_aligned failed: %s", esp_err_to_name(err)); + } + return 0; +} + +/* ------------------------------------------------------------------------- + * Basic drawing + * ---------------------------------------------------------------------- */ + +static int lua_display_clear(lua_State *L) +{ + uint16_t color = lua_display_color(L, 1); + esp_err_t err = display_hal_clear(color); + if (err != ESP_OK) { + return luaL_error(L, "display clear failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_set_clip_rect(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + esp_err_t err = display_hal_set_clip_rect(x, y, width, height); + if (err != ESP_OK) { + return luaL_error(L, "display set_clip_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_clear_clip_rect(lua_State *L) +{ + (void)L; + esp_err_t err = display_hal_clear_clip_rect(); + if (err != ESP_OK) { + return luaL_error(L, "display clear_clip_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_fill_rect(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + uint16_t color = lua_display_color(L, 5); + esp_err_t err = display_hal_fill_rect(x, y, width, height, color); + if (err != ESP_OK) { + return luaL_error(L, "display fill_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_pixel(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + uint16_t color = lua_display_color(L, 3); + esp_err_t err = display_hal_draw_pixel(x, y, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_pixel failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_line(lua_State *L) +{ + int x0 = lua_display_check_integer_arg(L, 1, "x0"); + int y0 = lua_display_check_integer_arg(L, 2, "y0"); + int x1 = lua_display_check_integer_arg(L, 3, "x1"); + int y1 = lua_display_check_integer_arg(L, 4, "y1"); + uint16_t color = lua_display_color(L, 5); + esp_err_t err = display_hal_draw_line(x0, y0, x1, y1, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_line failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_rect(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + uint16_t color = lua_display_color(L, 5); + esp_err_t err = display_hal_draw_rect(x, y, width, height, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_backlight(lua_State *L) +{ + int on = lua_toboolean(L, 1); + esp_err_t err = display_hal_set_backlight(on != 0); + if (err != ESP_OK) { + return luaL_error(L, "display backlight failed: %s", esp_err_to_name(err)); + } + return 0; +} + +/* ------------------------------------------------------------------------- + * Frame management + * ---------------------------------------------------------------------- */ + +static void lua_display_parse_frame_options(lua_State *L, int index, + bool *clear, uint8_t *red, + uint8_t *green, uint8_t *blue) +{ + if (clear) { *clear = true; } + if (red) { *red = 0; } + if (green) { *green = 0; } + if (blue) { *blue = 0; } + + if (lua_isnoneornil(L, index)) { + return; + } + luaL_checktype(L, index, LUA_TTABLE); + + lua_getfield(L, index, "clear"); + if (!lua_isnil(L, -1) && clear) { + *clear = lua_toboolean(L, -1); + } + lua_pop(L, 1); + + lua_getfield(L, index, "r"); + if (!lua_isnil(L, -1) && red) { + *red = (uint8_t)lua_display_check_integer_arg(L, -1, "frame color component"); + } + lua_pop(L, 1); + + lua_getfield(L, index, "g"); + if (!lua_isnil(L, -1) && green) { + *green = (uint8_t)lua_display_check_integer_arg(L, -1, "frame color component"); + } + lua_pop(L, 1); + + lua_getfield(L, index, "b"); + if (!lua_isnil(L, -1) && blue) { + *blue = (uint8_t)lua_display_check_integer_arg(L, -1, "frame color component"); + } + lua_pop(L, 1); +} + +static int lua_display_begin_frame(lua_State *L) +{ + bool clear = true; + uint8_t red = 0, green = 0, blue = 0; + lua_display_parse_frame_options(L, 1, &clear, &red, &green, &blue); + esp_err_t err = display_hal_begin_frame( + clear, lua_display_rgb888_to_rgb565(red, green, blue)); + if (err != ESP_OK) { + return luaL_error(L, "display begin_frame failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_present(lua_State *L) +{ + (void)L; + esp_err_t err = display_hal_present(); + if (err != ESP_OK) { + return luaL_error(L, "display present failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_present_rect(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + esp_err_t err = display_hal_present_rect(x, y, width, height); + if (err != ESP_OK) { + return luaL_error(L, "display present_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_end_frame(lua_State *L) +{ + (void)L; + esp_err_t err = display_hal_end_frame(); + if (err != ESP_OK) { + return luaL_error(L, "display end_frame failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_frame_active(lua_State *L) +{ + lua_pushboolean(L, display_hal_is_frame_active()); + return 1; +} + +static int lua_display_animation_info(lua_State *L) +{ + display_hal_animation_info_t info = {0}; + esp_err_t err = display_hal_get_animation_info(&info); + if (err != ESP_OK) { + return luaL_error(L, "display animation_info failed: %s", esp_err_to_name(err)); + } + lua_newtable(L); + lua_pushinteger(L, info.framebuffer_count); + lua_setfield(L, -2, "framebuffer_count"); + lua_pushboolean(L, info.double_buffered); + lua_setfield(L, -2, "double_buffered"); + lua_pushboolean(L, info.frame_active); + lua_setfield(L, -2, "frame_active"); + lua_pushboolean(L, info.flush_in_flight); + lua_setfield(L, -2, "flush_in_flight"); + return 1; +} + +static int lua_display_width(lua_State *L) +{ + lua_pushinteger(L, display_hal_width()); + return 1; +} + +static int lua_display_height(lua_State *L) +{ + lua_pushinteger(L, display_hal_height()); + return 1; +} + +/* ------------------------------------------------------------------------- + * Bitmap + * ---------------------------------------------------------------------- */ + +static int lua_display_draw_bitmap_impl(lua_State *L, bool input_is_little_endian) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + int w = (int)luaL_checkinteger(L, 3); + int h = (int)luaL_checkinteger(L, 4); + size_t data_len = 0; + const uint8_t *data = (const uint8_t *)luaL_checklstring(L, 5, &data_len); + uint8_t *swapped = NULL; + const uint16_t *pixels = NULL; + + if (w <= 0 || h <= 0) { + return luaL_error(L, "draw_bitmap: invalid size (%d x %d)", w, h); + } + + size_t expected = (size_t)w * (size_t)h * 2; + if (data_len < expected) { + return luaL_error(L, "draw_bitmap: data too short (%d bytes, need %d)", + (int)data_len, (int)expected); + } + + if (input_is_little_endian) { + swapped = malloc(expected); + if (!swapped) { + return luaL_error(L, "draw_bitmap: out of memory (%d bytes)", (int)expected); + } + /* Swap each pixel from little-endian to MSB-first order */ + for (size_t i = 0; i < expected; i += 2) { + swapped[i] = data[i + 1]; + swapped[i + 1] = data[i]; + } + pixels = (const uint16_t *)swapped; + } else { + pixels = (const uint16_t *)data; + } + + esp_err_t err = display_hal_draw_bitmap(x, y, w, h, pixels); + free(swapped); + if (err != ESP_OK) { + return luaL_error(L, "display draw_bitmap failed: %s", esp_err_to_name(err)); + } + return 0; +} + +/* + * draw_bitmap(x, y, w, h, data) + * data: raw RGB565 bytes, MSB-first (red = 0xF8 0x00). + */ +static int lua_display_draw_bitmap(lua_State *L) +{ + return lua_display_draw_bitmap_impl(L, false); +} + +/* + * draw_bitmap_le(x, y, w, h, data) + * data: RGB565 little-endian; bytes are swapped to MSB-first before sending. + */ +static int lua_display_draw_bitmap_le(lua_State *L) +{ + return lua_display_draw_bitmap_impl(L, true); +} + +static int lua_display_draw_bitmap_crop(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int src_x = lua_display_check_integer_arg(L, 3, "src_x"); + int src_y = lua_display_check_integer_arg(L, 4, "src_y"); + int w = lua_display_check_integer_arg(L, 5, "width"); + int h = lua_display_check_integer_arg(L, 6, "height"); + int src_width = lua_display_check_integer_arg(L, 7, "src_width"); + int src_height = lua_display_check_integer_arg(L, 8, "src_height"); + size_t data_len = 0; + const uint8_t *data = (const uint8_t *)luaL_checklstring(L, 9, &data_len); + + if (src_width <= 0 || src_height <= 0) { + return luaL_error(L, "draw_bitmap_crop: invalid source size (%d x %d)", + src_width, src_height); + } + + size_t expected = (size_t)src_width * (size_t)src_height * 2; + if (data_len < expected) { + return luaL_error(L, "draw_bitmap_crop: data too short (%d bytes, need %d)", + (int)data_len, (int)expected); + } + + esp_err_t err = display_hal_draw_bitmap_crop(x, y, src_x, src_y, w, h, + src_width, src_height, + (const uint16_t *)data); + if (err != ESP_OK) { + return luaL_error(L, "display draw_bitmap_crop failed: %s", esp_err_to_name(err)); + } + return 0; +} + +/* ------------------------------------------------------------------------- + * File helpers + * ---------------------------------------------------------------------- */ + +static bool lua_display_path_is_valid(const char *path) +{ + size_t len; + + if (!path || path[0] != '/') { + return false; + } + /* Reject path traversal */ + if (strstr(path, "..")) { + return false; + } + len = strlen(path); + if (len <= 4) { + return false; + } + /* Must end with a supported image extension */ + return strcmp(path + len - 4, ".jpg") == 0 || + (len > 5 && strcmp(path + len - 5, ".jpeg") == 0) || + strcmp(path + len - 4, ".png") == 0; +} + +static esp_err_t lua_display_read_file(const char *path, uint8_t **data_out, size_t *size_out) +{ + FILE *f = NULL; + long size = 0; + uint8_t *data = NULL; + + if (!data_out || !size_out || !lua_display_path_is_valid(path)) { + return ESP_ERR_INVALID_ARG; + } + *data_out = NULL; + *size_out = 0; + + f = fopen(path, "rb"); + if (!f) { + return ESP_ERR_NOT_FOUND; + } + if (fseek(f, 0, SEEK_END) != 0) { + fclose(f); + return ESP_FAIL; + } + size = ftell(f); + if (size <= 0) { + fclose(f); + return ESP_ERR_INVALID_SIZE; + } + if (fseek(f, 0, SEEK_SET) != 0) { + fclose(f); + return ESP_FAIL; + } + + data = malloc((size_t)size); + if (!data) { + fclose(f); + return ESP_ERR_NO_MEM; + } + if (fread(data, 1, (size_t)size, f) != (size_t)size) { + fclose(f); + free(data); + return ESP_FAIL; + } + fclose(f); + + *data_out = data; + *size_out = (size_t)size; + return ESP_OK; +} + +/* ------------------------------------------------------------------------- + * PNG decode (RGBA → RGB565, alpha pre-multiplied against black) + * ---------------------------------------------------------------------- */ + +static esp_err_t lua_display_decode_png(const uint8_t *png_data, size_t png_len, + uint8_t **pixels_out, + uint32_t *width_out, uint32_t *height_out) +{ + png_image image; + png_bytep rgba = NULL; + uint8_t *rgb565 = NULL; + size_t stride = 0; + + if (!png_data || png_len == 0 || !pixels_out || !width_out || !height_out) { + return ESP_ERR_INVALID_ARG; + } + + memset(&image, 0, sizeof(image)); + image.version = PNG_IMAGE_VERSION; + if (!png_image_begin_read_from_memory(&image, png_data, png_len)) { + return ESP_FAIL; + } + + image.format = PNG_FORMAT_RGBA; + stride = PNG_IMAGE_ROW_STRIDE(image); + rgba = malloc(PNG_IMAGE_SIZE(image)); + if (!rgba) { + png_image_free(&image); + return ESP_ERR_NO_MEM; + } + + if (!png_image_finish_read(&image, NULL, rgba, (png_int_32)stride, NULL)) { + free(rgba); + png_image_free(&image); + return ESP_FAIL; + } + + rgb565 = malloc((size_t)image.width * (size_t)image.height * 2); + if (!rgb565) { + free(rgba); + png_image_free(&image); + return ESP_ERR_NO_MEM; + } + + /* Convert RGBA to RGB565, alpha pre-multiplied against black */ + for (uint32_t row = 0; row < image.height; row++) { + const uint8_t *src_row = rgba + row * stride; + uint8_t *dst_row = rgb565 + (size_t)row * image.width * 2; + for (uint32_t col = 0; col < image.width; col++) { + const uint8_t *src = src_row + col * 4; + uint8_t alpha = src[3]; + uint8_t r = (uint8_t)((src[0] * alpha + 127) / 255); + uint8_t g = (uint8_t)((src[1] * alpha + 127) / 255); + uint8_t b = (uint8_t)((src[2] * alpha + 127) / 255); + uint16_t c = lua_display_rgb888_to_rgb565(r, g, b); + dst_row[col * 2] = (uint8_t)(c >> 8); + dst_row[col * 2 + 1] = (uint8_t)(c & 0xFF); + } + } + + free(rgba); + png_image_free(&image); + + *pixels_out = rgb565; + *width_out = image.width; + *height_out = image.height; + return ESP_OK; +} + +/* ------------------------------------------------------------------------- + * JPEG drawing + * ---------------------------------------------------------------------- */ + +/* + * draw_jpeg(x, y, jpeg_data) + * jpeg_data: Lua string containing raw JPEG bytes. + * Returns: width, height + */ +static int lua_display_draw_jpeg(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + size_t jpeg_len = 0; + const char *jpeg_data = luaL_checklstring(L, 3, &jpeg_len); + int img_w = 0, img_h = 0; + + esp_err_t err = display_hal_draw_jpeg(x, y, + (const uint8_t *)jpeg_data, jpeg_len, + &img_w, &img_h); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, img_w); + lua_pushinteger(L, img_h); + return 2; +} + +static int lua_display_draw_jpeg_file(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + const char *path = luaL_checkstring(L, 3); + uint8_t *jpeg_data = NULL; + size_t jpeg_len = 0; + int img_w = 0, img_h = 0; + + esp_err_t err = lua_display_read_file(path, &jpeg_data, &jpeg_len); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file failed: %s", esp_err_to_name(err)); + } + + err = display_hal_draw_jpeg(x, y, jpeg_data, jpeg_len, &img_w, &img_h); + free(jpeg_data); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, img_w); + lua_pushinteger(L, img_h); + return 2; +} + +static int lua_display_draw_png_file(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + const char *path = luaL_checkstring(L, 3); + uint8_t *png_data = NULL; + size_t png_len = 0; + uint8_t *rgb565 = NULL; + uint32_t img_w = 0, img_h = 0; + + esp_err_t err = lua_display_read_file(path, &png_data, &png_len); + if (err != ESP_OK) { + return luaL_error(L, "display draw_png_file failed: %s", esp_err_to_name(err)); + } + + err = lua_display_decode_png(png_data, png_len, &rgb565, &img_w, &img_h); + free(png_data); + if (err != ESP_OK) { + free(rgb565); + return luaL_error(L, "display draw_png_file failed: %s", esp_err_to_name(err)); + } + + err = display_hal_draw_bitmap(x, y, (int)img_w, (int)img_h, (const uint16_t *)rgb565); + free(rgb565); + if (err != ESP_OK) { + return luaL_error(L, "display draw_png_file failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, (lua_Integer)img_w); + lua_pushinteger(L, (lua_Integer)img_h); + return 2; +} + +static int lua_display_draw_jpeg_crop(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + int src_x = (int)luaL_checkinteger(L, 3); + int src_y = (int)luaL_checkinteger(L, 4); + int w = (int)luaL_checkinteger(L, 5); + int h = (int)luaL_checkinteger(L, 6); + size_t jpeg_len = 0; + const char *jpeg_data = luaL_checklstring(L, 7, &jpeg_len); + int img_w = 0, img_h = 0; + + esp_err_t err = display_hal_draw_jpeg_crop(x, y, src_x, src_y, w, h, + (const uint8_t *)jpeg_data, jpeg_len, + &img_w, &img_h); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_crop failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, img_w); + lua_pushinteger(L, img_h); + return 2; +} + +static int lua_display_draw_jpeg_file_crop(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + int src_x = (int)luaL_checkinteger(L, 3); + int src_y = (int)luaL_checkinteger(L, 4); + int w = (int)luaL_checkinteger(L, 5); + int h = (int)luaL_checkinteger(L, 6); + const char *path = luaL_checkstring(L, 7); + uint8_t *jpeg_data = NULL; + size_t jpeg_len = 0; + int img_w = 0, img_h = 0; + + esp_err_t err = lua_display_read_file(path, &jpeg_data, &jpeg_len); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_crop failed: %s", esp_err_to_name(err)); + } + + err = display_hal_draw_jpeg_crop(x, y, src_x, src_y, w, h, + jpeg_data, jpeg_len, &img_w, &img_h); + free(jpeg_data); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_crop failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, img_w); + lua_pushinteger(L, img_h); + return 2; +} + +static int lua_align_down_8(int v) { return v & ~7; } + +/* + * draw_jpeg_file_scaled(x, y, scale_w, scale_h, path) + * scale_w, scale_h must be positive multiples of 8; max downscale 1/8. + * Returns: output_w, output_h + */ +static int lua_display_draw_jpeg_file_scaled(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + int scale_w = (int)luaL_checkinteger(L, 3); + int scale_h = (int)luaL_checkinteger(L, 4); + const char *path = luaL_checkstring(L, 5); + uint8_t *jpeg_data = NULL; + size_t jpeg_len = 0; + int out_w = 0, out_h = 0; + + if ((scale_w & 7) != 0 || (scale_h & 7) != 0 || scale_w <= 0 || scale_h <= 0) { + return luaL_error(L, + "draw_jpeg_file_scaled: scale_w and scale_h must be positive multiples of 8"); + } + + esp_err_t err = lua_display_read_file(path, &jpeg_data, &jpeg_len); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_scaled failed: %s", esp_err_to_name(err)); + } + + err = display_hal_draw_jpeg_scaled(x, y, jpeg_data, jpeg_len, + scale_w, scale_h, &out_w, &out_h); + free(jpeg_data); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_scaled failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, out_w); + lua_pushinteger(L, out_h); + return 2; +} + +/* + * draw_jpeg_file_fit(x, y, max_w, max_h, path) + * Scales JPEG to fit within max_w x max_h preserving aspect ratio. + * Output size is aligned to multiples of 8 (JPEG HW decode requirement). + * Returns: output_w, output_h + */ +static int lua_display_draw_jpeg_file_fit(lua_State *L) +{ + int x = (int)luaL_checkinteger(L, 1); + int y = (int)luaL_checkinteger(L, 2); + int max_w = (int)luaL_checkinteger(L, 3); + int max_h = (int)luaL_checkinteger(L, 4); + const char *path = luaL_checkstring(L, 5); + uint8_t *jpeg_data = NULL; + size_t jpeg_len = 0; + int orig_w = 0, orig_h = 0; + int out_w = 0, out_h = 0; + + if (max_w <= 0 || max_h <= 0) { + return luaL_error(L, "draw_jpeg_file_fit: max_w and max_h must be positive"); + } + + esp_err_t err = lua_display_read_file(path, &jpeg_data, &jpeg_len); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_fit failed: %s", esp_err_to_name(err)); + } + + err = display_hal_jpeg_get_size(jpeg_data, jpeg_len, &orig_w, &orig_h); + if (err != ESP_OK) { + free(jpeg_data); + return luaL_error(L, "display draw_jpeg_file_fit: cannot read JPEG header"); + } + + if (orig_w <= max_w && orig_h <= max_h) { + /* Image already fits: draw at full resolution */ + err = display_hal_draw_jpeg(x, y, jpeg_data, jpeg_len, &out_w, &out_h); + free(jpeg_data); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_fit failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, out_w); + lua_pushinteger(L, out_h); + return 2; + } + + double ratio_w = (double)max_w / orig_w; + double ratio_h = (double)max_h / orig_h; + double ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h; + if (ratio < 0.125) { ratio = 0.125; } /* max downscale 1/8 */ + + int scale_w = lua_align_down_8((int)(orig_w * ratio)); + int scale_h = lua_align_down_8((int)(orig_h * ratio)); + if (scale_w < 8) { scale_w = 8; } + if (scale_h < 8) { scale_h = 8; } + + err = display_hal_draw_jpeg_scaled(x, y, jpeg_data, jpeg_len, + scale_w, scale_h, &out_w, &out_h); + free(jpeg_data); + if (err != ESP_OK) { + return luaL_error(L, "display draw_jpeg_file_fit failed: %s", esp_err_to_name(err)); + } + lua_pushinteger(L, out_w); + lua_pushinteger(L, out_h); + return 2; +} + +/* ------------------------------------------------------------------------- + * Shape drawing + * ---------------------------------------------------------------------- */ + +static int lua_display_fill_circle(lua_State *L) +{ + int cx = lua_display_check_integer_arg(L, 1, "cx"); + int cy = lua_display_check_integer_arg(L, 2, "cy"); + int r = lua_display_check_integer_arg(L, 3, "radius"); + uint16_t color = lua_display_color(L, 4); + esp_err_t err = display_hal_fill_circle(cx, cy, r, color); + if (err != ESP_OK) { + return luaL_error(L, "display fill_circle failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_circle(lua_State *L) +{ + int cx = lua_display_check_integer_arg(L, 1, "cx"); + int cy = lua_display_check_integer_arg(L, 2, "cy"); + int r = lua_display_check_integer_arg(L, 3, "radius"); + uint16_t color = lua_display_color(L, 4); + esp_err_t err = display_hal_draw_circle(cx, cy, r, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_circle failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_arc(lua_State *L) +{ + int cx = lua_display_check_integer_arg(L, 1, "cx"); + int cy = lua_display_check_integer_arg(L, 2, "cy"); + int radius = lua_display_check_integer_arg(L, 3, "radius"); + float start_deg = lua_display_check_number_arg(L, 4, "start_deg"); + float end_deg = lua_display_check_number_arg(L, 5, "end_deg"); + uint16_t color = lua_display_color(L, 6); + esp_err_t err = display_hal_draw_arc(cx, cy, radius, start_deg, end_deg, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_arc failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_fill_arc(lua_State *L) +{ + int cx = lua_display_check_integer_arg(L, 1, "cx"); + int cy = lua_display_check_integer_arg(L, 2, "cy"); + int inner_radius = lua_display_check_integer_arg(L, 3, "inner_radius"); + int outer_radius = lua_display_check_integer_arg(L, 4, "outer_radius"); + float start_deg = lua_display_check_number_arg(L, 5, "start_deg"); + float end_deg = lua_display_check_number_arg(L, 6, "end_deg"); + uint16_t color = lua_display_color(L, 7); + esp_err_t err = display_hal_fill_arc(cx, cy, inner_radius, outer_radius, + start_deg, end_deg, color); + if (err != ESP_OK) { + return luaL_error(L, "display fill_arc failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_ellipse(lua_State *L) +{ + int cx = lua_display_check_integer_arg(L, 1, "cx"); + int cy = lua_display_check_integer_arg(L, 2, "cy"); + int radius_x = lua_display_check_integer_arg(L, 3, "radius_x"); + int radius_y = lua_display_check_integer_arg(L, 4, "radius_y"); + uint16_t color = lua_display_color(L, 5); + esp_err_t err = display_hal_draw_ellipse(cx, cy, radius_x, radius_y, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_ellipse failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_fill_ellipse(lua_State *L) +{ + int cx = lua_display_check_integer_arg(L, 1, "cx"); + int cy = lua_display_check_integer_arg(L, 2, "cy"); + int radius_x = lua_display_check_integer_arg(L, 3, "radius_x"); + int radius_y = lua_display_check_integer_arg(L, 4, "radius_y"); + uint16_t color = lua_display_color(L, 5); + esp_err_t err = display_hal_fill_ellipse(cx, cy, radius_x, radius_y, color); + if (err != ESP_OK) { + return luaL_error(L, "display fill_ellipse failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_round_rect(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + int radius = lua_display_check_integer_arg(L, 5, "radius"); + uint16_t color = lua_display_color(L, 6); + esp_err_t err = display_hal_draw_round_rect(x, y, width, height, radius, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_round_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_fill_round_rect(lua_State *L) +{ + int x = lua_display_check_integer_arg(L, 1, "x"); + int y = lua_display_check_integer_arg(L, 2, "y"); + int width = lua_display_check_integer_arg(L, 3, "width"); + int height = lua_display_check_integer_arg(L, 4, "height"); + int radius = lua_display_check_integer_arg(L, 5, "radius"); + uint16_t color = lua_display_color(L, 6); + esp_err_t err = display_hal_fill_round_rect(x, y, width, height, radius, color); + if (err != ESP_OK) { + return luaL_error(L, "display fill_round_rect failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_draw_triangle(lua_State *L) +{ + int x1 = lua_display_check_integer_arg(L, 1, "x1"); + int y1 = lua_display_check_integer_arg(L, 2, "y1"); + int x2 = lua_display_check_integer_arg(L, 3, "x2"); + int y2 = lua_display_check_integer_arg(L, 4, "y2"); + int x3 = lua_display_check_integer_arg(L, 5, "x3"); + int y3 = lua_display_check_integer_arg(L, 6, "y3"); + uint16_t color = lua_display_color(L, 7); + esp_err_t err = display_hal_draw_triangle(x1, y1, x2, y2, x3, y3, color); + if (err != ESP_OK) { + return luaL_error(L, "display draw_triangle failed: %s", esp_err_to_name(err)); + } + return 0; +} + +static int lua_display_fill_triangle(lua_State *L) +{ + int x1 = lua_display_check_integer_arg(L, 1, "x1"); + int y1 = lua_display_check_integer_arg(L, 2, "y1"); + int x2 = lua_display_check_integer_arg(L, 3, "x2"); + int y2 = lua_display_check_integer_arg(L, 4, "y2"); + int x3 = lua_display_check_integer_arg(L, 5, "x3"); + int y3 = lua_display_check_integer_arg(L, 6, "y3"); + uint16_t color = lua_display_color(L, 7); + esp_err_t err = display_hal_fill_triangle(x1, y1, x2, y2, x3, y3, color); + if (err != ESP_OK) { + return luaL_error(L, "display fill_triangle failed: %s", esp_err_to_name(err)); + } + return 0; +} + +/* ------------------------------------------------------------------------- + * Module registration + * ---------------------------------------------------------------------- */ + +int luaopen_display(lua_State *L) +{ + lua_newtable(L); + + lua_pushcfunction(L, lua_display_create_screen); + lua_setfield(L, -2, "create_screen"); + lua_pushcfunction(L, lua_display_destroy_screen); + lua_setfield(L, -2, "destroy_screen"); + + lua_pushcfunction(L, lua_display_width); + lua_setfield(L, -2, "width"); + lua_pushcfunction(L, lua_display_height); + lua_setfield(L, -2, "height"); + + lua_pushcfunction(L, lua_display_clear); + lua_setfield(L, -2, "clear"); + lua_pushcfunction(L, lua_display_set_clip_rect); + lua_setfield(L, -2, "set_clip_rect"); + lua_pushcfunction(L, lua_display_clear_clip_rect); + lua_setfield(L, -2, "clear_clip_rect"); + + lua_pushcfunction(L, lua_display_fill_rect); + lua_setfield(L, -2, "fill_rect"); + lua_pushcfunction(L, lua_display_draw_rect); + lua_setfield(L, -2, "draw_rect"); + lua_pushcfunction(L, lua_display_draw_pixel); + lua_setfield(L, -2, "draw_pixel"); + lua_pushcfunction(L, lua_display_draw_line); + lua_setfield(L, -2, "draw_line"); + + lua_pushcfunction(L, lua_display_backlight); + lua_setfield(L, -2, "backlight"); + + lua_pushcfunction(L, lua_display_begin_frame); + lua_setfield(L, -2, "begin_frame"); + lua_pushcfunction(L, lua_display_present); + lua_setfield(L, -2, "present"); + lua_pushcfunction(L, lua_display_present_rect); + lua_setfield(L, -2, "present_rect"); + lua_pushcfunction(L, lua_display_end_frame); + lua_setfield(L, -2, "end_frame"); + lua_pushcfunction(L, lua_display_frame_active); + lua_setfield(L, -2, "frame_active"); + lua_pushcfunction(L, lua_display_animation_info); + lua_setfield(L, -2, "animation_info"); + + lua_pushcfunction(L, lua_display_measure_text); + lua_setfield(L, -2, "measure_text"); + lua_pushcfunction(L, lua_display_draw_text); + lua_setfield(L, -2, "draw_text"); + lua_pushcfunction(L, lua_display_draw_text_aligned); + lua_setfield(L, -2, "draw_text_aligned"); + + lua_pushcfunction(L, lua_display_draw_bitmap); + lua_setfield(L, -2, "draw_bitmap"); + lua_pushcfunction(L, lua_display_draw_bitmap_le); + lua_setfield(L, -2, "draw_bitmap_le"); + lua_pushcfunction(L, lua_display_draw_bitmap_crop); + lua_setfield(L, -2, "draw_bitmap_crop"); + + lua_pushcfunction(L, lua_display_draw_jpeg); + lua_setfield(L, -2, "draw_jpeg"); + lua_pushcfunction(L, lua_display_draw_jpeg_file); + lua_setfield(L, -2, "draw_jpeg_file"); + lua_pushcfunction(L, lua_display_draw_png_file); + lua_setfield(L, -2, "draw_png_file"); + lua_pushcfunction(L, lua_display_draw_jpeg_crop); + lua_setfield(L, -2, "draw_jpeg_crop"); + lua_pushcfunction(L, lua_display_draw_jpeg_file_crop); + lua_setfield(L, -2, "draw_jpeg_file_crop"); + lua_pushcfunction(L, lua_display_draw_jpeg_file_scaled); + lua_setfield(L, -2, "draw_jpeg_file_scaled"); + lua_pushcfunction(L, lua_display_draw_jpeg_file_fit); + lua_setfield(L, -2, "draw_jpeg_file_fit"); + + lua_pushcfunction(L, lua_display_fill_circle); + lua_setfield(L, -2, "fill_circle"); + lua_pushcfunction(L, lua_display_draw_circle); + lua_setfield(L, -2, "draw_circle"); + lua_pushcfunction(L, lua_display_draw_arc); + lua_setfield(L, -2, "draw_arc"); + lua_pushcfunction(L, lua_display_fill_arc); + lua_setfield(L, -2, "fill_arc"); + + lua_pushcfunction(L, lua_display_draw_ellipse); + lua_setfield(L, -2, "draw_ellipse"); + lua_pushcfunction(L, lua_display_fill_ellipse); + lua_setfield(L, -2, "fill_ellipse"); + + lua_pushcfunction(L, lua_display_draw_round_rect); + lua_setfield(L, -2, "draw_round_rect"); + lua_pushcfunction(L, lua_display_fill_round_rect); + lua_setfield(L, -2, "fill_round_rect"); + + lua_pushcfunction(L, lua_display_draw_triangle); + lua_setfield(L, -2, "draw_triangle"); + lua_pushcfunction(L, lua_display_fill_triangle); + lua_setfield(L, -2, "fill_triangle"); + + return 1; +} + +esp_err_t lua_module_display_register(void) +{ + return cap_lua_register_module("display", luaopen_display); +} diff --git a/components/lua_modules/lua_module_esp_heap/CMakeLists.txt b/components/lua_modules/lua_module_esp_heap/CMakeLists.txt new file mode 100644 index 0000000..2a58b06 --- /dev/null +++ b/components/lua_modules/lua_module_esp_heap/CMakeLists.txt @@ -0,0 +1,10 @@ +idf_component_register( + SRC_DIRS + "." + INCLUDE_DIRS + "include" + REQUIRES + cap_lua + freertos + heap +) diff --git a/components/lua_modules/lua_module_esp_heap/include/lua_module_esp_heap.h b/components/lua_modules/lua_module_esp_heap/include/lua_module_esp_heap.h new file mode 100644 index 0000000..f0826be --- /dev/null +++ b/components/lua_modules/lua_module_esp_heap/include/lua_module_esp_heap.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t lua_module_esp_heap_register(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_esp_heap/lua_module_esp_heap.c b/components/lua_modules/lua_module_esp_heap/lua_module_esp_heap.c new file mode 100644 index 0000000..af3b39a --- /dev/null +++ b/components/lua_modules/lua_module_esp_heap/lua_module_esp_heap.c @@ -0,0 +1,191 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_esp_heap.h" + +#include + +#include "cap_lua.h" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "lauxlib.h" + +#if (configUSE_TRACE_FACILITY == 1) +static const char *lua_module_esp_heap_task_state_name(eTaskState state) +{ + switch (state) { + case eRunning: + return "running"; + case eReady: + return "ready"; + case eBlocked: + return "blocked"; + case eSuspended: + return "suspended"; + case eDeleted: + return "deleted"; + case eInvalid: + default: + return "invalid"; + } +} +#endif + +static void lua_module_esp_heap_push_caps_constants(lua_State *L) +{ + lua_pushinteger(L, MALLOC_CAP_DEFAULT); + lua_setfield(L, -2, "DEFAULT"); + lua_pushinteger(L, MALLOC_CAP_INTERNAL); + lua_setfield(L, -2, "INTERNAL"); + lua_pushinteger(L, MALLOC_CAP_SPIRAM); + lua_setfield(L, -2, "SPIRAM"); + lua_pushinteger(L, MALLOC_CAP_DMA); + lua_setfield(L, -2, "DMA"); + lua_pushinteger(L, MALLOC_CAP_8BIT); + lua_setfield(L, -2, "BIT8"); + lua_pushinteger(L, MALLOC_CAP_32BIT); + lua_setfield(L, -2, "BIT32"); + lua_pushinteger(L, MALLOC_CAP_EXEC); + lua_setfield(L, -2, "EXEC"); + lua_pushinteger(L, MALLOC_CAP_IRAM_8BIT); + lua_setfield(L, -2, "IRAM_8BIT"); + lua_pushinteger(L, MALLOC_CAP_RTCRAM); + lua_setfield(L, -2, "RTCRAM"); + lua_pushinteger(L, MALLOC_CAP_RETENTION); + lua_setfield(L, -2, "RETENTION"); +} + +static int lua_module_esp_heap_caps(lua_State *L) +{ + lua_newtable(L); + lua_module_esp_heap_push_caps_constants(L); + return 1; +} + +static int lua_module_esp_heap_get_info(lua_State *L) +{ + lua_Integer caps_value = luaL_optinteger(L, 1, MALLOC_CAP_DEFAULT); + multi_heap_info_t info = {0}; + uint32_t caps = (uint32_t)caps_value; + + heap_caps_get_info(&info, caps); + + lua_newtable(L); + lua_pushinteger(L, (lua_Integer)caps); + lua_setfield(L, -2, "caps"); + lua_pushinteger(L, (lua_Integer)heap_caps_get_total_size(caps)); + lua_setfield(L, -2, "total_size"); + lua_pushinteger(L, (lua_Integer)info.total_free_bytes); + lua_setfield(L, -2, "free_size"); + lua_pushinteger(L, (lua_Integer)info.total_allocated_bytes); + lua_setfield(L, -2, "allocated_size"); + lua_pushinteger(L, (lua_Integer)info.minimum_free_bytes); + lua_setfield(L, -2, "minimum_free_size"); + lua_pushinteger(L, (lua_Integer)info.largest_free_block); + lua_setfield(L, -2, "largest_free_block"); + lua_pushinteger(L, (lua_Integer)info.allocated_blocks); + lua_setfield(L, -2, "allocated_blocks"); + lua_pushinteger(L, (lua_Integer)info.free_blocks); + lua_setfield(L, -2, "free_blocks"); + lua_pushinteger(L, (lua_Integer)info.total_blocks); + lua_setfield(L, -2, "total_blocks"); + return 1; +} + +static int lua_module_esp_heap_get_task_watermarks(lua_State *L) +{ +#if (configUSE_TRACE_FACILITY == 1) + UBaseType_t task_count = uxTaskGetNumberOfTasks(); + TaskStatus_t *tasks = NULL; + UBaseType_t count = 0; + + tasks = calloc((size_t)task_count + 4, sizeof(*tasks)); + if (!tasks) { + return luaL_error(L, "esp_heap get_task_watermarks: out of memory"); + } + + count = uxTaskGetSystemState(tasks, task_count + 4, NULL); + lua_newtable(L); + for (UBaseType_t i = 0; i < count; i++) { + lua_newtable(L); + lua_pushstring(L, tasks[i].pcTaskName ? tasks[i].pcTaskName : "(unnamed)"); + lua_setfield(L, -2, "name"); + lua_pushinteger(L, (lua_Integer)tasks[i].xTaskNumber); + lua_setfield(L, -2, "task_number"); + lua_pushstring(L, lua_module_esp_heap_task_state_name(tasks[i].eCurrentState)); + lua_setfield(L, -2, "state"); + lua_pushinteger(L, (lua_Integer)tasks[i].uxCurrentPriority); + lua_setfield(L, -2, "current_priority"); + lua_pushinteger(L, (lua_Integer)tasks[i].uxBasePriority); + lua_setfield(L, -2, "base_priority"); + lua_pushinteger(L, (lua_Integer)tasks[i].usStackHighWaterMark); + lua_setfield(L, -2, "stack_high_water_mark_words"); + lua_pushinteger(L, (lua_Integer)tasks[i].usStackHighWaterMark * (lua_Integer)sizeof(StackType_t)); + lua_setfield(L, -2, "stack_high_water_mark_bytes"); + lua_rawseti(L, -2, (lua_Integer)i + 1); + } + + free(tasks); + return 1; +#else + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + UBaseType_t words = uxTaskGetStackHighWaterMark(task); + + lua_newtable(L); + lua_newtable(L); + lua_pushstring(L, pcTaskGetName(task)); + lua_setfield(L, -2, "name"); + lua_pushinteger(L, (lua_Integer)uxTaskPriorityGet(task)); + lua_setfield(L, -2, "current_priority"); + lua_pushinteger(L, (lua_Integer)uxTaskPriorityGet(task)); + lua_setfield(L, -2, "base_priority"); + lua_pushstring(L, "running"); + lua_setfield(L, -2, "state"); + lua_pushinteger(L, (lua_Integer)words); + lua_setfield(L, -2, "stack_high_water_mark_words"); + lua_pushinteger(L, (lua_Integer)words * (lua_Integer)sizeof(StackType_t)); + lua_setfield(L, -2, "stack_high_water_mark_bytes"); + lua_rawseti(L, -2, 1); + lua_pushstring(L, "configUSE_TRACE_FACILITY=0, only current task watermark is available"); + lua_setfield(L, -2, "_warning"); + return 1; +#endif +} + +static int lua_module_esp_heap_get_current_task(lua_State *L) +{ + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + UBaseType_t words = uxTaskGetStackHighWaterMark(task); + + lua_newtable(L); + lua_pushstring(L, pcTaskGetName(task)); + lua_setfield(L, -2, "name"); + lua_pushinteger(L, (lua_Integer)words); + lua_setfield(L, -2, "stack_high_water_mark_words"); + lua_pushinteger(L, (lua_Integer)words * (lua_Integer)sizeof(StackType_t)); + lua_setfield(L, -2, "stack_high_water_mark_bytes"); + return 1; +} + +int luaopen_esp_heap(lua_State *L) +{ + static const luaL_Reg funcs[] = { + {"caps", lua_module_esp_heap_caps}, + {"get_info", lua_module_esp_heap_get_info}, + {"get_task_watermarks", lua_module_esp_heap_get_task_watermarks}, + {"get_current_task", lua_module_esp_heap_get_current_task}, + {NULL, NULL}, + }; + + lua_newtable(L); + luaL_setfuncs(L, funcs, 0); + return 1; +} + +esp_err_t lua_module_esp_heap_register(void) +{ + return cap_lua_register_module("esp_heap", luaopen_esp_heap); +} diff --git a/components/lua_modules/lua_module_esp_heap/skills/lua_module_esp_heap.md b/components/lua_modules/lua_module_esp_heap/skills/lua_module_esp_heap.md new file mode 100644 index 0000000..127094a --- /dev/null +++ b/components/lua_modules/lua_module_esp_heap/skills/lua_module_esp_heap.md @@ -0,0 +1,22 @@ +# Lua ESP Heap + +This skill describes how to correctly use esp_heap when writing Lua scripts. + +## How to call +- Import it with `local esp_heap = require("esp_heap")` +- Call `local caps = esp_heap.caps()` to get capability flags such as `caps.DEFAULT`, `caps.INTERNAL`, and `caps.SPIRAM` +- Call `esp_heap.get_info(caps)` to read heap statistics such as `free_size`, `allocated_size`, and `largest_free_block` +- Call `esp_heap.get_task_watermarks()` to inspect stack high-water marks for tasks +- Call `esp_heap.get_current_task()` to inspect the current task state + +## Example +```lua +local esp_heap = require("esp_heap") +local caps = esp_heap.caps() + +local info = esp_heap.get_info(caps.DEFAULT) +print(info.free_size, info.largest_free_block) + +local task = esp_heap.get_current_task() +print(task.name, task.stack_high_water_mark_bytes) +``` diff --git a/components/lua_modules/lua_module_esp_heap/skills/skills_list.json b/components/lua_modules/lua_module_esp_heap/skills/skills_list.json new file mode 100644 index 0000000..3336c59 --- /dev/null +++ b/components/lua_modules/lua_module_esp_heap/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_esp_heap", + "file": "lua_module_esp_heap.md", + "title": "lua_module_esp_heap", + "summary": "How to query heap capability flags, memory usage, and task watermarks from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_lcd_touch/CMakeLists.txt b/components/lua_modules/lua_module_lcd_touch/CMakeLists.txt new file mode 100644 index 0000000..16e07d9 --- /dev/null +++ b/components/lua_modules/lua_module_lcd_touch/CMakeLists.txt @@ -0,0 +1,9 @@ +idf_component_register( + SRCS + "src/lua_module_lcd_touch.c" + INCLUDE_DIRS + "include" + REQUIRES + cap_lua + esp_lcd_touch +) diff --git a/components/lua_modules/lua_module_lcd_touch/include/lua_module_lcd_touch.h b/components/lua_modules/lua_module_lcd_touch/include/lua_module_lcd_touch.h new file mode 100644 index 0000000..c362df2 --- /dev/null +++ b/components/lua_modules/lua_module_lcd_touch/include/lua_module_lcd_touch.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_err.h" +#include "lua.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int luaopen_lcd_touch(lua_State *L); +esp_err_t lua_module_lcd_touch_register(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/lua_modules/lua_module_lcd_touch/skills/lua_module_lcd_touch.md b/components/lua_modules/lua_module_lcd_touch/skills/lua_module_lcd_touch.md new file mode 100644 index 0000000..1dea9d5 --- /dev/null +++ b/components/lua_modules/lua_module_lcd_touch/skills/lua_module_lcd_touch.md @@ -0,0 +1,23 @@ +# Lua LCD Touch + +This skill describes how to correctly use lcd_touch when writing Lua scripts. + +## How to call +- Import it with `local lcd_touch = require("lcd_touch")` +- Get a touch handle first, typically from `board_manager.get_lcd_touch_handle(...)` +- Call `lcd_touch.sync(touch_handle)` to synchronize the cached touch state +- Call `lcd_touch.read(touch_handle)` to read the current touch state +- Call `lcd_touch.poll(touch_handle)` to get edge-aware touch information such as `just_pressed`, `just_released`, `x`, `y`, `dx`, `dy`, and `held_ms` + +## Example +```lua +local board_manager = require("board_manager") +local lcd_touch = require("lcd_touch") + +local touch_handle = board_manager.get_lcd_touch_handle("lcd_touch") +lcd_touch.sync(touch_handle) +local touch = lcd_touch.poll(touch_handle) +if touch.just_pressed then + print(touch.x, touch.y) +end +``` diff --git a/components/lua_modules/lua_module_lcd_touch/skills/skills_list.json b/components/lua_modules/lua_module_lcd_touch/skills/skills_list.json new file mode 100644 index 0000000..2851dae --- /dev/null +++ b/components/lua_modules/lua_module_lcd_touch/skills/skills_list.json @@ -0,0 +1,13 @@ +{ + "skills": [ + { + "id": "lua_module_lcd_touch", + "file": "lua_module_lcd_touch.md", + "title": "lua_module_lcd_touch", + "summary": "How to sync, read, and poll LCD touch state from Lua.", + "cap_groups": [ + "cap_lua" + ] + } + ] +} diff --git a/components/lua_modules/lua_module_lcd_touch/src/lua_module_lcd_touch.c b/components/lua_modules/lua_module_lcd_touch/src/lua_module_lcd_touch.c new file mode 100644 index 0000000..06bc8b6 --- /dev/null +++ b/components/lua_modules/lua_module_lcd_touch/src/lua_module_lcd_touch.c @@ -0,0 +1,290 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "lua_module_lcd_touch.h" + +#include +#include + +#include "cap_lua.h" +#include "esp_err.h" +#include "esp_lcd_touch.h" +#include "esp_timer.h" +#include "lauxlib.h" + +static const char *LUA_LCD_TOUCH_STATE_KEY = "clawgent.lcd_touch_state"; + +static esp_lcd_touch_handle_t lua_lcd_touch_check_handle(lua_State *L, int index) +{ + void *handle = lua_touserdata(L, index); + luaL_argcheck(L, handle != NULL, index, "lcd_touch handle expected"); + return (esp_lcd_touch_handle_t)handle; +} + +static esp_err_t lua_lcd_touch_read_raw(esp_lcd_touch_handle_t touch_handle, + bool *pressed, uint16_t *x, uint16_t *y) +{ + esp_lcd_touch_point_data_t points[1]; + uint8_t point_count = 0; + esp_err_t err; + + if (touch_handle == NULL || pressed == NULL || x == NULL || y == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_lcd_touch_read_data(touch_handle); + err = esp_lcd_touch_get_data(touch_handle, points, &point_count, 1); + if (err != ESP_OK) { + return err; + } + + *pressed = point_count > 0; + if (*pressed) { + *x = points[0].x; + *y = points[0].y; + } else { + *x = 0; + *y = 0; + } + + return ESP_OK; +} + +static void lua_lcd_touch_push_touch_table(lua_State *L, + bool pressed, + bool just_pressed, + bool just_released, + uint16_t x, + uint16_t y, + int dx, + int dy, + lua_Number held_ms) +{ + lua_newtable(L); + + lua_pushboolean(L, pressed); + lua_setfield(L, -2, "pressed"); + + lua_pushboolean(L, just_pressed); + lua_setfield(L, -2, "just_pressed"); + + lua_pushboolean(L, just_released); + lua_setfield(L, -2, "just_released"); + + lua_pushinteger(L, x); + lua_setfield(L, -2, "x"); + + lua_pushinteger(L, y); + lua_setfield(L, -2, "y"); + + lua_pushinteger(L, dx); + lua_setfield(L, -2, "dx"); + + lua_pushinteger(L, dy); + lua_setfield(L, -2, "dy"); + + lua_pushboolean(L, (dx != 0) || (dy != 0)); + lua_setfield(L, -2, "moved"); + + lua_pushnumber(L, held_ms); + lua_setfield(L, -2, "held_ms"); +} + +static void lua_lcd_touch_push_state_table(lua_State *L) +{ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LCD_TOUCH_STATE_KEY); + if (lua_istable(L, -1)) { + return; + } + + lua_pop(L, 1); + lua_newtable(L); + + lua_pushboolean(L, false); + lua_setfield(L, -2, "initialized"); + + lua_pushboolean(L, false); + lua_setfield(L, -2, "pressed"); + + lua_pushinteger(L, 0); + lua_setfield(L, -2, "x"); + + lua_pushinteger(L, 0); + lua_setfield(L, -2, "y"); + + lua_pushnumber(L, 0); + lua_setfield(L, -2, "press_start_ms"); + + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, LUA_LCD_TOUCH_STATE_KEY); +} + +static void lua_lcd_touch_update_state(lua_State *L, + bool initialized, + bool pressed, + uint16_t x, + uint16_t y, + lua_Number press_start_ms) +{ + lua_pushboolean(L, initialized); + lua_setfield(L, -2, "initialized"); + + lua_pushboolean(L, pressed); + lua_setfield(L, -2, "pressed"); + + lua_pushinteger(L, x); + lua_setfield(L, -2, "x"); + + lua_pushinteger(L, y); + lua_setfield(L, -2, "y"); + + lua_pushnumber(L, press_start_ms); + lua_setfield(L, -2, "press_start_ms"); +} + +static int lua_lcd_touch_sync(lua_State *L) +{ + esp_lcd_touch_handle_t touch_handle = lua_lcd_touch_check_handle(L, 1); + bool pressed = false; + uint16_t x = 0; + uint16_t y = 0; + lua_Number now_ms = (lua_Number)(esp_timer_get_time() / 1000); + esp_err_t err = lua_lcd_touch_read_raw(touch_handle, &pressed, &x, &y); + if (err != ESP_OK) { + return luaL_error(L, "lcd_touch sync failed: %s", esp_err_to_name(err)); + } + + lua_lcd_touch_push_state_table(L); + lua_lcd_touch_update_state(L, true, pressed, x, y, pressed ? now_ms : 0); + lua_pop(L, 1); + + lua_lcd_touch_push_touch_table(L, pressed, false, false, x, y, 0, 0, 0); + return 1; +} + +static int lua_lcd_touch_read(lua_State *L) +{ + esp_lcd_touch_handle_t touch_handle = lua_lcd_touch_check_handle(L, 1); + bool pressed = false; + uint16_t x = 0; + uint16_t y = 0; + esp_err_t err = lua_lcd_touch_read_raw(touch_handle, &pressed, &x, &y); + if (err != ESP_OK) { + return luaL_error(L, "lcd_touch read failed: %s", esp_err_to_name(err)); + } + + lua_newtable(L); + lua_pushboolean(L, pressed); + lua_setfield(L, -2, "pressed"); + if (pressed) { + lua_pushinteger(L, x); + lua_setfield(L, -2, "x"); + lua_pushinteger(L, y); + lua_setfield(L, -2, "y"); + } + return 1; +} + +static int lua_lcd_touch_poll(lua_State *L) +{ + esp_lcd_touch_handle_t touch_handle = lua_lcd_touch_check_handle(L, 1); + bool pressed = false; + bool prev_pressed = false; + bool initialized = false; + bool just_pressed = false; + bool just_released = false; + uint16_t x = 0; + uint16_t y = 0; + uint16_t prev_x = 0; + uint16_t prev_y = 0; + int dx = 0; + int dy = 0; + lua_Number press_start_ms = 0; + lua_Number held_ms = 0; + lua_Number now_ms = (lua_Number)(esp_timer_get_time() / 1000); + esp_err_t err = lua_lcd_touch_read_raw(touch_handle, &pressed, &x, &y); + if (err != ESP_OK) { + return luaL_error(L, "lcd_touch poll failed: %s", esp_err_to_name(err)); + } + + lua_lcd_touch_push_state_table(L); + + lua_getfield(L, -1, "initialized"); + initialized = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "pressed"); + prev_pressed = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "x"); + prev_x = (uint16_t)lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "y"); + prev_y = (uint16_t)lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "press_start_ms"); + press_start_ms = lua_tonumber(L, -1); + lua_pop(L, 1); + + if (!initialized) { + if (pressed) { + press_start_ms = now_ms; + } else { + x = 0; + y = 0; + press_start_ms = 0; + } + } else if (pressed && prev_pressed) { + dx = (int)x - (int)prev_x; + dy = (int)y - (int)prev_y; + held_ms = press_start_ms > 0 ? (now_ms - press_start_ms) : 0; + } else if (pressed && !prev_pressed) { + just_pressed = true; + press_start_ms = now_ms; + } else if (!pressed && prev_pressed) { + just_released = true; + x = prev_x; + y = prev_y; + press_start_ms = 0; + } else { + x = 0; + y = 0; + press_start_ms = 0; + } + + if (pressed && held_ms <= 0 && press_start_ms > 0) { + held_ms = now_ms - press_start_ms; + if (held_ms < 0) { + held_ms = 0; + } + } + + lua_lcd_touch_update_state(L, true, pressed, x, y, press_start_ms); + lua_pop(L, 1); + + lua_lcd_touch_push_touch_table(L, pressed, just_pressed, just_released, x, y, dx, dy, + held_ms); + return 1; +} + +int luaopen_lcd_touch(lua_State *L) +{ + lua_newtable(L); + lua_pushcfunction(L, lua_lcd_touch_read); + lua_setfield(L, -2, "read"); + lua_pushcfunction(L, lua_lcd_touch_poll); + lua_setfield(L, -2, "poll"); + lua_pushcfunction(L, lua_lcd_touch_sync); + lua_setfield(L, -2, "sync"); + return 1; +} + +esp_err_t lua_module_lcd_touch_register(void) +{ + return cap_lua_register_module("lcd_touch", luaopen_lcd_touch); +} diff --git a/components/lua_modules/lua_module_led_strip/CMakeLists.txt b/components/lua_modules/lua_module_led_strip/CMakeLists.txt index ae9c628..7c331fd 100644 --- a/components/lua_modules/lua_module_led_strip/CMakeLists.txt +++ b/components/lua_modules/lua_module_led_strip/CMakeLists.txt @@ -5,5 +5,4 @@ idf_component_register( "include" REQUIRES cap_lua - espressif__led_strip ) diff --git a/components/lua_modules/lua_module_led_strip/idf_component.yml b/components/lua_modules/lua_module_led_strip/idf_component.yml new file mode 100644 index 0000000..48d23d0 --- /dev/null +++ b/components/lua_modules/lua_module_led_strip/idf_component.yml @@ -0,0 +1,3 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/led_strip: ^3.0.3