From e8701195e66f2d27ffe17fb514eae8173795aaf7 Mon Sep 17 00:00:00 2001
From: Georgiy Bondarenko <69736697+nehilo@users.noreply.github.com>
Date: Thu, 4 Mar 2021 22:54:23 +0500
Subject: Initial commit
---
Marlin/src/lcd/extui/anycubic_chiron_lcd.cpp | 130 +
Marlin/src/lcd/extui/anycubic_i3mega_lcd.cpp | 117 +
Marlin/src/lcd/extui/dgus_lcd.cpp | 158 ++
Marlin/src/lcd/extui/example.cpp | 125 +
.../extui/lib/anycubic_chiron/FileNavigator.cpp | 164 ++
.../lcd/extui/lib/anycubic_chiron/FileNavigator.h | 56 +
Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp | 62 +
Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h | 224 ++
.../lcd/extui/lib/anycubic_chiron/chiron_tft.cpp | 885 ++++++
.../src/lcd/extui/lib/anycubic_chiron/chiron_tft.h | 77 +
.../extui/lib/anycubic_chiron/chiron_tft_defs.h | 151 +
.../lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp | 1028 +++++++
.../lib/anycubic_i3mega/anycubic_i3mega_lcd.h | 97 +
Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.cpp | 261 ++
Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h | 118 +
Marlin/src/lcd/extui/lib/dgus/DGUSDisplayDef.h | 54 +
.../src/lcd/extui/lib/dgus/DGUSScreenHandler.cpp | 1140 ++++++++
Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.h | 232 ++
Marlin/src/lcd/extui/lib/dgus/DGUSVPVariable.h | 49 +
.../lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.cpp | 486 ++++
.../src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.h | 296 ++
.../lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.cpp | 485 ++++
.../lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.h | 292 ++
.../lcd/extui/lib/dgus/origin/DGUSDisplayDef.cpp | 310 +++
.../src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.h | 282 ++
.../archim2-flash/flash_storage.cpp | 553 ++++
.../archim2-flash/flash_storage.h | 106 +
.../archim2-flash/media_file_reader.cpp | 63 +
.../archim2-flash/media_file_reader.h | 48 +
.../src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h | 53 +
.../src/lcd/extui/lib/ftdi_eve_touch_ui/config.h | 26 +
.../lib/ftdi_eve_touch_ui/ftdi_eve_lib/LICENSE.txt | 674 +++++
.../lib/ftdi_eve_touch_ui/ftdi_eve_lib/README.md | 28 +
.../ftdi_eve_touch_ui/ftdi_eve_lib/basic/boards.h | 184 ++
.../ftdi_eve_lib/basic/commands.cpp | 1194 ++++++++
.../ftdi_eve_lib/basic/commands.h | 262 ++
.../ftdi_eve_lib/basic/constants.h | 414 +++
.../ftdi_eve_lib/basic/display_list.h | 118 +
.../ftdi_eve_lib/basic/ftdi_basic.h | 40 +
.../ftdi_eve_lib/basic/registers_ft800.h | 150 +
.../ftdi_eve_lib/basic/registers_ft810.h | 187 ++
.../ftdi_eve_lib/basic/resolutions.h | 127 +
.../ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.cpp | 175 ++
.../lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.h | 136 +
.../lib/ftdi_eve_touch_ui/ftdi_eve_lib/compat.h | 278 ++
.../ftdi_eve_lib/extended/bitmap_info.h | 49 +
.../ftdi_eve_lib/extended/command_processor.cpp | 29 +
.../ftdi_eve_lib/extended/command_processor.h | 437 +++
.../ftdi_eve_lib/extended/dl_cache.cpp | 180 ++
.../ftdi_eve_lib/extended/dl_cache.h | 70 +
.../ftdi_eve_lib/extended/event_loop.cpp | 228 ++
.../ftdi_eve_lib/extended/event_loop.h | 74 +
.../ftdi_eve_lib/extended/ftdi_extended.h | 52 +
.../ftdi_eve_lib/extended/grid_layout.h | 98 +
.../ftdi_eve_lib/extended/polygon.h | 96 +
.../ftdi_eve_lib/extended/rgb_t.h | 84 +
.../ftdi_eve_lib/extended/screen_types.cpp | 105 +
.../ftdi_eve_lib/extended/screen_types.h | 241 ++
.../ftdi_eve_lib/extended/sound_list.h | 38 +
.../ftdi_eve_lib/extended/sound_player.cpp | 110 +
.../ftdi_eve_lib/extended/sound_player.h | 70 +
.../ftdi_eve_lib/extended/text_box.cpp | 129 +
.../ftdi_eve_lib/extended/text_box.h | 30 +
.../ftdi_eve_lib/extended/text_ellipsis.cpp | 91 +
.../ftdi_eve_lib/extended/text_ellipsis.h | 31 +
.../ftdi_eve_lib/extended/tiny_timer.cpp | 39 +
.../ftdi_eve_lib/extended/tiny_timer.h | 56 +
.../ftdi_eve_lib/extended/unicode/README.txt | 40 +
.../extended/unicode/cyrillic_char_set.cpp | 139 +
.../extended/unicode/cyrillic_char_set.h | 32 +
.../extended/unicode/cyrillic_char_set_bitmap_31.h | 2529 +++++++++++++++++
.../ftdi_eve_lib/extended/unicode/font_bitmaps.cpp | 58 +
.../ftdi_eve_lib/extended/unicode/font_bitmaps.h | 30 +
.../font_bitmaps/cyrillic_char_set_bitmap_31.png | Bin 0 -> 34122 bytes
.../font_bitmaps/cyrillic_char_set_bitmap_31.svg | 535 ++++
.../extended/unicode/font_bitmaps/romfont_31.pbm | Bin 0 -> 23570 bytes
.../extended/unicode/font_bitmaps/romfont_31.png | Bin 0 -> 16643 bytes
.../font_bitmaps/western_char_set_bitmap_31.png | Bin 0 -> 24548 bytes
.../font_bitmaps/western_char_set_bitmap_31.svg | 443 +++
.../ftdi_eve_lib/extended/unicode/font_size_t.cpp | 46 +
.../ftdi_eve_lib/extended/unicode/font_size_t.h | 55 +
.../extended/unicode/standard_char_set.cpp | 107 +
.../extended/unicode/standard_char_set.h | 30 +
.../ftdi_eve_lib/extended/unicode/unicode.cpp | 238 ++
.../ftdi_eve_lib/extended/unicode/unicode.h | 112 +
.../extended/unicode/western_char_set.cpp | 455 +++
.../extended/unicode/western_char_set.h | 31 +
.../extended/unicode/western_char_set_bitmap_31.h | 1315 +++++++++
.../ftdi_eve_lib/extras/bitmap2cpp.py | 108 +
.../ftdi_eve_lib/extras/circular_progress.h | 105 +
.../ftdi_eve_lib/extras/poly_ui.h | 408 +++
.../ftdi_eve_lib/extras/svg2cpp.py | 280 ++
.../ftdi_eve_touch_ui/ftdi_eve_lib/ftdi_eve_lib.h | 27 +
.../lib/ftdi_eve_touch_ui/language/language.cpp | 27 +
.../lib/ftdi_eve_touch_ui/language/language.h | 23 +
.../lib/ftdi_eve_touch_ui/language/language_en.h | 176 ++
.../extui/lib/ftdi_eve_touch_ui/marlin_events.cpp | 184 ++
.../lcd/extui/lib/ftdi_eve_touch_ui/pin_mappings.h | 144 +
.../lib/ftdi_eve_touch_ui/screens/about_screen.cpp | 116 +
.../screens/advanced_settings_menu.cpp | 156 ++
.../ftdi_eve_touch_ui/screens/alert_dialog_box.cpp | 70 +
.../screens/backlash_compensation_screen.cpp | 76 +
.../screens/base_numeric_adjustment_screen.cpp | 388 +++
.../lib/ftdi_eve_touch_ui/screens/base_screen.cpp | 90 +
.../ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp | 341 +++
.../screens/bio_advanced_settings.cpp | 137 +
.../screens/bio_confirm_home_e.cpp | 57 +
.../screens/bio_confirm_home_xyz.cpp | 56 +
.../ftdi_eve_touch_ui/screens/bio_main_menu.cpp | 88 +
.../screens/bio_printer_ui_landscape.h | 59 +
.../screens/bio_printer_ui_portrait.h | 52 +
.../screens/bio_printing_dialog_box.cpp | 151 +
.../screens/bio_status_screen.cpp | 379 +++
.../ftdi_eve_touch_ui/screens/bio_tune_menu.cpp | 79 +
.../lib/ftdi_eve_touch_ui/screens/boot_screen.cpp | 130 +
.../screens/case_light_screen.cpp | 62 +
.../screens/change_filament_screen.cpp | 330 +++
.../screens/cocoa_press_advanced_settings_menu.cpp | 102 +
.../screens/cocoa_press_load_chocolate.cpp | 101 +
.../screens/cocoa_press_main_menu.cpp | 89 +
.../screens/cocoa_press_move_e_screen.cpp | 62 +
.../screens/cocoa_press_move_xyz_screen.cpp | 53 +
.../screens/cocoa_press_preheat_menu.cpp | 113 +
.../screens/cocoa_press_preheat_screen.cpp | 172 ++
.../screens/cocoa_press_status_screen.cpp | 307 ++
.../lib/ftdi_eve_touch_ui/screens/cocoa_press_ui.h | 54 +
.../screens/cocoa_press_unload_cartridge.cpp | 101 +
.../screens/confirm_abort_print_dialog_box.cpp | 53 +
.../confirm_auto_calibration_dialog_box.cpp | 48 +
.../screens/confirm_erase_flash_dialog_box.cpp | 54 +
.../screens/confirm_start_print_dialog_box.cpp | 65 +
.../screens/confirm_user_request_alert_box.cpp | 66 +
.../screens/custom_user_menus.cpp | 215 ++
.../screens/default_acceleration_screen.cpp | 63 +
.../ftdi_eve_touch_ui/screens/developer_menu.cpp | 150 +
.../screens/dialog_box_base_class.cpp | 87 +
.../screens/display_tuning_screen.cpp | 61 +
.../screens/endstop_state_screen.cpp | 152 +
.../screens/feedrate_percent_screen.cpp | 52 +
.../ftdi_eve_touch_ui/screens/filament_menu.cpp | 85 +
.../screens/filament_runout_screen.cpp | 65 +
.../lib/ftdi_eve_touch_ui/screens/files_screen.cpp | 264 ++
.../screens/interface_settings_screen.cpp | 291 ++
.../screens/interface_sounds_screen.cpp | 160 ++
.../lib/ftdi_eve_touch_ui/screens/jerk_screen.cpp | 65 +
.../screens/junction_deviation_screen.cpp | 54 +
.../lib/ftdi_eve_touch_ui/screens/kill_screen.cpp | 62 +
.../ftdi_eve_touch_ui/screens/language_menu.cpp | 66 +
.../ftdi_eve_touch_ui/screens/leveling_menu.cpp | 121 +
.../screens/linear_advance_screen.cpp | 77 +
.../lib/ftdi_eve_touch_ui/screens/lock_screen.cpp | 205 ++
.../lib/ftdi_eve_touch_ui/screens/main_menu.cpp | 131 +
.../screens/max_acceleration_screen.cpp | 86 +
.../screens/max_velocity_screen.cpp | 90 +
.../screens/media_player_screen.cpp | 168 ++
.../ftdi_eve_touch_ui/screens/move_axis_screen.cpp | 133 +
.../screens/nozzle_offsets_screen.cpp | 73 +
.../screens/nudge_nozzle_screen.cpp | 123 +
.../screens/restore_failsafe_dialog_box.cpp | 51 +
.../screens/save_settings_dialog_box.cpp | 64 +
.../lib/ftdi_eve_touch_ui/screens/screen_data.h | 97 +
.../lib/ftdi_eve_touch_ui/screens/screens.cpp | 139 +
.../extui/lib/ftdi_eve_touch_ui/screens/screens.h | 911 ++++++
.../screens/spinner_dialog_box.cpp | 68 +
.../screens/statistics_screen.cpp | 78 +
.../ftdi_eve_touch_ui/screens/status_screen.cpp | 465 ++++
.../screens/stepper_bump_sensitivity_screen.cpp | 59 +
.../screens/stepper_current_screen.cpp | 127 +
.../lib/ftdi_eve_touch_ui/screens/steps_screen.cpp | 86 +
.../screens/stress_test_screen.cpp | 149 +
.../ftdi_eve_touch_ui/screens/string_format.cpp | 83 +
.../lib/ftdi_eve_touch_ui/screens/string_format.h | 29 +
.../screens/temperature_screen.cpp | 119 +
.../screens/touch_calibration_screen.cpp | 94 +
.../screens/touch_registers_screen.cpp | 86 +
.../lib/ftdi_eve_touch_ui/screens/tune_menu.cpp | 156 ++
.../screens/widget_demo_screen.cpp | 158 ++
.../ftdi_eve_touch_ui/screens/z_offset_screen.cpp | 54 +
.../extui/lib/ftdi_eve_touch_ui/theme/bitmaps.h | 183 ++
.../theme/bootscreen_logo_portrait.h | 42 +
.../lcd/extui/lib/ftdi_eve_touch_ui/theme/colors.h | 183 ++
.../lcd/extui/lib/ftdi_eve_touch_ui/theme/fonts.h | 80 +
.../theme/marlin_bootscreen_landscape.h | 39 +
.../theme/marlin_bootscreen_portrait.h | 39 +
.../extui/lib/ftdi_eve_touch_ui/theme/sounds.cpp | 410 +++
.../lcd/extui/lib/ftdi_eve_touch_ui/theme/sounds.h | 43 +
.../lcd/extui/lib/ftdi_eve_touch_ui/theme/theme.h | 28 +
.../src/lcd/extui/lib/mks_ui/SPIFlashStorage.cpp | 303 ++
Marlin/src/lcd/extui/lib/mks_ui/SPIFlashStorage.h | 108 +
Marlin/src/lcd/extui/lib/mks_ui/SPI_TFT.cpp | 83 +
Marlin/src/lcd/extui/lib/mks_ui/SPI_TFT.h | 43 +
Marlin/src/lcd/extui/lib/mks_ui/draw_about.cpp | 65 +
Marlin/src/lcd/extui/lib/mks_ui/draw_about.h | 33 +
.../lib/mks_ui/draw_acceleration_settings.cpp | 155 ++
.../extui/lib/mks_ui/draw_acceleration_settings.h | 33 +
.../lcd/extui/lib/mks_ui/draw_advance_settings.cpp | 96 +
.../lcd/extui/lib/mks_ui/draw_advance_settings.h | 33 +
.../lib/mks_ui/draw_auto_level_offset_settings.cpp | 90 +
.../lib/mks_ui/draw_auto_level_offset_settings.h | 33 +
.../lcd/extui/lib/mks_ui/draw_baby_stepping.cpp | 179 ++
.../src/lcd/extui/lib/mks_ui/draw_baby_stepping.h | 35 +
.../lcd/extui/lib/mks_ui/draw_bltouch_settings.cpp | 184 ++
.../lcd/extui/lib/mks_ui/draw_bltouch_settings.h | 37 +
.../src/lcd/extui/lib/mks_ui/draw_change_speed.cpp | 225 ++
.../src/lcd/extui/lib/mks_ui/draw_change_speed.h | 39 +
.../src/lcd/extui/lib/mks_ui/draw_cloud_bind.cpp | 205 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_cloud_bind.h | 37 +
Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.cpp | 574 ++++
Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.h | 91 +
.../lcd/extui/lib/mks_ui/draw_eeprom_settings.cpp | 82 +
.../lcd/extui/lib/mks_ui/draw_eeprom_settings.h | 33 +
.../lcd/extui/lib/mks_ui/draw_encoder_settings.cpp | 72 +
.../lcd/extui/lib/mks_ui/draw_encoder_settings.h | 33 +
.../lcd/extui/lib/mks_ui/draw_error_message.cpp | 46 +
.../src/lcd/extui/lib/mks_ui/draw_error_message.h | 37 +
Marlin/src/lcd/extui/lib/mks_ui/draw_extrusion.cpp | 266 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_extrusion.h | 38 +
Marlin/src/lcd/extui/lib/mks_ui/draw_fan.cpp | 117 +
Marlin/src/lcd/extui/lib/mks_ui/draw_fan.h | 34 +
.../lcd/extui/lib/mks_ui/draw_filament_change.cpp | 216 ++
.../lcd/extui/lib/mks_ui/draw_filament_change.h | 35 +
.../extui/lib/mks_ui/draw_filament_settings.cpp | 126 +
.../lcd/extui/lib/mks_ui/draw_filament_settings.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_home.cpp | 93 +
Marlin/src/lcd/extui/lib/mks_ui/draw_home.h | 33 +
.../mks_ui/draw_homing_sensitivity_settings.cpp | 104 +
.../lib/mks_ui/draw_homing_sensitivity_settings.h | 33 +
.../lcd/extui/lib/mks_ui/draw_jerk_settings.cpp | 99 +
.../src/lcd/extui/lib/mks_ui/draw_jerk_settings.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.cpp | 289 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_language.cpp | 208 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_language.h | 33 +
.../lcd/extui/lib/mks_ui/draw_level_settings.cpp | 104 +
.../src/lcd/extui/lib/mks_ui/draw_level_settings.h | 35 +
.../src/lcd/extui/lib/mks_ui/draw_machine_para.cpp | 84 +
.../src/lcd/extui/lib/mks_ui/draw_machine_para.h | 33 +
.../lcd/extui/lib/mks_ui/draw_machine_settings.cpp | 82 +
.../lcd/extui/lib/mks_ui/draw_machine_settings.h | 33 +
.../src/lcd/extui/lib/mks_ui/draw_manuaLevel.cpp | 135 +
Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.h | 33 +
.../lib/mks_ui/draw_manual_level_pos_settings.cpp | 146 +
.../lib/mks_ui/draw_manual_level_pos_settings.h | 33 +
.../lib/mks_ui/draw_max_feedrate_settings.cpp | 119 +
.../extui/lib/mks_ui/draw_max_feedrate_settings.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_more.cpp | 119 +
Marlin/src/lcd/extui/lib/mks_ui/draw_more.h | 33 +
.../lcd/extui/lib/mks_ui/draw_motor_settings.cpp | 98 +
.../src/lcd/extui/lib/mks_ui/draw_motor_settings.h | 33 +
.../src/lcd/extui/lib/mks_ui/draw_move_motor.cpp | 211 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.h | 34 +
.../src/lcd/extui/lib/mks_ui/draw_number_key.cpp | 772 ++++++
Marlin/src/lcd/extui/lib/mks_ui/draw_number_key.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_operation.cpp | 230 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_operation.h | 33 +
.../lcd/extui/lib/mks_ui/draw_pause_message.cpp | 51 +
.../src/lcd/extui/lib/mks_ui/draw_pause_message.h | 32 +
.../lcd/extui/lib/mks_ui/draw_pause_position.cpp | 85 +
.../src/lcd/extui/lib/mks_ui/draw_pause_position.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_preHeat.cpp | 297 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_preHeat.h | 36 +
.../src/lcd/extui/lib/mks_ui/draw_print_file.cpp | 552 ++++
Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.h | 64 +
Marlin/src/lcd/extui/lib/mks_ui/draw_printing.cpp | 290 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_printing.h | 53 +
.../src/lcd/extui/lib/mks_ui/draw_ready_print.cpp | 220 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.h | 40 +
Marlin/src/lcd/extui/lib/mks_ui/draw_set.cpp | 134 +
Marlin/src/lcd/extui/lib/mks_ui/draw_set.h | 33 +
.../lcd/extui/lib/mks_ui/draw_step_settings.cpp | 115 +
.../src/lcd/extui/lib/mks_ui/draw_step_settings.h | 33 +
.../extui/lib/mks_ui/draw_tmc_current_settings.cpp | 156 ++
.../extui/lib/mks_ui/draw_tmc_current_settings.h | 34 +
.../lib/mks_ui/draw_tmc_step_mode_settings.cpp | 154 ++
.../extui/lib/mks_ui/draw_tmc_step_mode_settings.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/draw_tool.cpp | 113 +
Marlin/src/lcd/extui/lib/mks_ui/draw_tool.h | 33 +
.../extui/lib/mks_ui/draw_touch_calibration.cpp | 117 +
.../lcd/extui/lib/mks_ui/draw_touch_calibration.h | 34 +
.../lcd/extui/lib/mks_ui/draw_touchmi_settings.cpp | 101 +
.../lcd/extui/lib/mks_ui/draw_touchmi_settings.h | 35 +
Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp | 1510 ++++++++++
Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h | 551 ++++
Marlin/src/lcd/extui/lib/mks_ui/draw_wifi.cpp | 166 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_wifi.h | 38 +
Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_list.cpp | 177 ++
Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_list.h | 76 +
.../lcd/extui/lib/mks_ui/draw_wifi_settings.cpp | 141 +
.../src/lcd/extui/lib/mks_ui/draw_wifi_settings.h | 36 +
Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_tips.cpp | 68 +
Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_tips.h | 51 +
Marlin/src/lcd/extui/lib/mks_ui/gb2312_puhui16.cpp | 105 +
Marlin/src/lcd/extui/lib/mks_ui/irq_overrid.cpp | 63 +
.../src/lcd/extui/lib/mks_ui/mks_hardware_test.cpp | 655 +++++
.../src/lcd/extui/lib/mks_ui/mks_hardware_test.h | 33 +
Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp | 622 +++++
Marlin/src/lcd/extui/lib/mks_ui/pic_manager.h | 168 ++
.../src/lcd/extui/lib/mks_ui/printer_operation.cpp | 250 ++
.../src/lcd/extui/lib/mks_ui/printer_operation.h | 36 +
Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h | 751 +++++
Marlin/src/lcd/extui/lib/mks_ui/tft_Language_fr.h | 268 ++
Marlin/src/lcd/extui/lib/mks_ui/tft_Language_it.h | 265 ++
Marlin/src/lcd/extui/lib/mks_ui/tft_Language_ru.h | 384 +++
.../src/lcd/extui/lib/mks_ui/tft_Language_s_cn.h | 518 ++++
Marlin/src/lcd/extui/lib/mks_ui/tft_Language_sp.h | 274 ++
.../src/lcd/extui/lib/mks_ui/tft_Language_t_cn.h | 515 ++++
.../extui/lib/mks_ui/tft_lvgl_configuration.cpp | 584 ++++
.../lcd/extui/lib/mks_ui/tft_lvgl_configuration.h | 69 +
.../lcd/extui/lib/mks_ui/tft_multi_language.cpp | 2920 ++++++++++++++++++++
.../src/lcd/extui/lib/mks_ui/tft_multi_language.h | 865 ++++++
Marlin/src/lcd/extui/lib/mks_ui/wifiSerial.cpp | 526 ++++
Marlin/src/lcd/extui/lib/mks_ui/wifiSerial.h | 145 +
Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp | 2231 +++++++++++++++
Marlin/src/lcd/extui/lib/mks_ui/wifi_module.h | 201 ++
Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.cpp | 726 +++++
Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.h | 74 +
Marlin/src/lcd/extui/malyan_lcd.cpp | 543 ++++
Marlin/src/lcd/extui/ui_api.cpp | 1074 +++++++
Marlin/src/lcd/extui/ui_api.h | 402 +++
319 files changed, 61817 insertions(+)
create mode 100644 Marlin/src/lcd/extui/anycubic_chiron_lcd.cpp
create mode 100644 Marlin/src/lcd/extui/anycubic_i3mega_lcd.cpp
create mode 100644 Marlin/src/lcd/extui/dgus_lcd.cpp
create mode 100644 Marlin/src/lcd/extui/example.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp
create mode 100644 Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.cpp
create mode 100644 Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/DGUSDisplayDef.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.cpp
create mode 100644 Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/DGUSVPVariable.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.cpp
create mode 100644 Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.cpp
create mode 100644 Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.h
create mode 100644 Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.cpp
create mode 100644 Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/config.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/LICENSE.txt
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/README.md
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/boards.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/constants.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/display_list.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/ftdi_basic.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft800.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft810.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/resolutions.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/compat.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/bitmap_info.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/ftdi_extended.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/grid_layout.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/polygon.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/rgb_t.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_list.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/README.txt
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set_bitmap_31.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.png
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.svg
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.pbm
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.png
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.png
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.svg
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set_bitmap_31.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/bitmap2cpp.py
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/circular_progress.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/poly_ui.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/svg2cpp.py
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/ftdi_eve_lib.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/language/language.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/language/language.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/language/language_en.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/marlin_events.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/pin_mappings.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/about_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/advanced_settings_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/alert_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/backlash_compensation_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/base_numeric_adjustment_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/base_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_advanced_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_confirm_home_e.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_confirm_home_xyz.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_main_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_printer_ui_landscape.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_printer_ui_portrait.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_printing_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_status_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bio_tune_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/boot_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/case_light_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/change_filament_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_advanced_settings_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_load_chocolate.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_main_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_move_e_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_move_xyz_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_preheat_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_preheat_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_status_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_ui.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/cocoa_press_unload_cartridge.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/confirm_abort_print_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/confirm_auto_calibration_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/confirm_erase_flash_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/confirm_start_print_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/confirm_user_request_alert_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/custom_user_menus.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/default_acceleration_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/developer_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/dialog_box_base_class.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/display_tuning_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/endstop_state_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/feedrate_percent_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/filament_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/filament_runout_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/files_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/interface_settings_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/interface_sounds_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/jerk_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/junction_deviation_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/kill_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/language_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/leveling_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/linear_advance_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/lock_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/max_acceleration_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/max_velocity_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/media_player_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/move_axis_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/nozzle_offsets_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/nudge_nozzle_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/restore_failsafe_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/save_settings_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screen_data.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/spinner_dialog_box.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/statistics_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/status_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stepper_bump_sensitivity_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stepper_current_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/steps_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/stress_test_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/string_format.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/string_format.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/temperature_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/touch_calibration_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/touch_registers_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/tune_menu.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/widget_demo_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/z_offset_screen.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/bitmaps.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/bootscreen_logo_portrait.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/colors.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/fonts.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/marlin_bootscreen_landscape.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/marlin_bootscreen_portrait.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/sounds.cpp
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/sounds.h
create mode 100644 Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/theme/theme.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/SPIFlashStorage.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/SPIFlashStorage.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/SPI_TFT.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/SPI_TFT.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_about.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_about.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_acceleration_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_acceleration_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_advance_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_advance_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_auto_level_offset_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_auto_level_offset_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_baby_stepping.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_baby_stepping.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_bltouch_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_bltouch_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_change_speed.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_change_speed.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_cloud_bind.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_cloud_bind.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_dialog.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_eeprom_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_eeprom_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_encoder_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_encoder_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_error_message.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_error_message.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_extrusion.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_extrusion.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_fan.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_fan.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_filament_change.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_filament_change.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_filament_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_filament_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_home.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_home.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_homing_sensitivity_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_homing_sensitivity_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_jerk_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_jerk_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_language.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_language.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_level_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_level_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_machine_para.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_machine_para.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_machine_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_machine_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_manuaLevel.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_manual_level_pos_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_manual_level_pos_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_max_feedrate_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_max_feedrate_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_more.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_more.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_motor_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_motor_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_move_motor.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_number_key.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_number_key.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_operation.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_operation.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_pause_message.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_pause_message.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_pause_position.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_pause_position.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_preHeat.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_preHeat.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_printing.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_printing.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_set.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_set.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_step_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_step_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_tmc_current_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_tmc_current_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_tmc_step_mode_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_tmc_step_mode_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_tool.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_tool.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_touch_calibration.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_touch_calibration.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_touchmi_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_touchmi_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_list.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_list.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_settings.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_settings.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_tips.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/draw_wifi_tips.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/gb2312_puhui16.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/irq_overrid.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/mks_hardware_test.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/mks_hardware_test.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/pic_manager.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/printer_operation.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/printer_operation.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_fr.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_it.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_ru.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_s_cn.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_sp.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_Language_t_cn.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/wifiSerial.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/wifiSerial.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/wifi_module.h
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.cpp
create mode 100644 Marlin/src/lcd/extui/lib/mks_ui/wifi_upload.h
create mode 100644 Marlin/src/lcd/extui/malyan_lcd.cpp
create mode 100644 Marlin/src/lcd/extui/ui_api.cpp
create mode 100644 Marlin/src/lcd/extui/ui_api.h
(limited to 'Marlin/src/lcd/extui')
diff --git a/Marlin/src/lcd/extui/anycubic_chiron_lcd.cpp b/Marlin/src/lcd/extui/anycubic_chiron_lcd.cpp
new file mode 100644
index 0000000..06baa4c
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_chiron_lcd.cpp
@@ -0,0 +1,130 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/anycubic_chiron_lcd.cpp
+ *
+ * Anycubic Chiron TFT support for Marlin
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+
+#include "ui_api.h"
+#include "lib/anycubic_chiron/chiron_tft.h"
+
+using namespace Anycubic;
+
+namespace ExtUI {
+
+ void onStartup() { Chiron.Startup(); }
+
+ void onIdle() { Chiron.IdleLoop(); }
+
+ void onPrinterKilled(PGM_P const error, PGM_P const component) {
+ Chiron.PrinterKilled(error,component);
+ }
+
+ void onMediaInserted() { Chiron.MediaEvent(AC_media_inserted); }
+ void onMediaError() { Chiron.MediaEvent(AC_media_error); }
+ void onMediaRemoved() { Chiron.MediaEvent(AC_media_removed); }
+
+ void onPlayTone(const uint16_t frequency, const uint16_t duration) {
+ #if ENABLED(SPEAKER)
+ ::tone(BEEPER_PIN, frequency, duration);
+ #endif
+ }
+
+ void onPrintTimerStarted() { Chiron.TimerEvent(AC_timer_started); }
+ void onPrintTimerPaused() { Chiron.TimerEvent(AC_timer_paused); }
+ void onPrintTimerStopped() { Chiron.TimerEvent(AC_timer_stopped); }
+ void onFilamentRunout(const extruder_t) { Chiron.FilamentRunout(); }
+ void onUserConfirmRequired(const char * const msg) { Chiron.ConfirmationRequest(msg); }
+ void onStatusChanged(const char * const msg) { Chiron.StatusChange(msg); }
+
+ void onHomingStart() {}
+ void onHomingComplete() {}
+ void onPrintFinished() {}
+
+ void onFactoryReset() {}
+
+ void onStoreSettings(char *buff) {
+ // Called when saving to EEPROM (i.e. M500). If the ExtUI needs
+ // permanent data to be stored, it can write up to eeprom_data_size bytes
+ // into buff.
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(buff, &myDataStruct, sizeof(myDataStruct));
+ }
+
+ void onLoadSettings(const char *buff) {
+ // Called while loading settings from EEPROM. If the ExtUI
+ // needs to retrieve data, it should copy up to eeprom_data_size bytes
+ // from buff
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(&myDataStruct, buff, sizeof(myDataStruct));
+ }
+
+ void onConfigurationStoreWritten(bool success) {
+ // Called after the entire EEPROM has been written,
+ // whether successful or not.
+ }
+
+ void onConfigurationStoreRead(bool success) {
+ // Called after the entire EEPROM has been read,
+ // whether successful or not.
+ }
+
+ #if HAS_MESH
+ void onMeshLevelingStart() {}
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) {
+ // Called when any mesh points are updated
+ //SERIAL_ECHOLNPAIR("onMeshUpdate() x:", xpos, " y:", ypos, " z:", zval);
+ }
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
+ // Called to indicate a special condition
+ //SERIAL_ECHOLNPAIR("onMeshUpdate() x:", xpos, " y:", ypos, " state:", state);
+ }
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ // Called on resume from power-loss
+ void onPowerLossResume() { Chiron.PowerLossRecovery(); }
+ #endif
+
+ #if HAS_PID_HEATING
+ void onPidTuning(const result_t rst) {
+ // Called for temperature PID tuning result
+ }
+ #endif
+
+ void onSteppersDisabled() {}
+ void onSteppersEnabled() {}
+}
+
+#endif // ANYCUBIC_LCD_CHIRON
diff --git a/Marlin/src/lcd/extui/anycubic_i3mega_lcd.cpp b/Marlin/src/lcd/extui/anycubic_i3mega_lcd.cpp
new file mode 100644
index 0000000..e2bd960
--- /dev/null
+++ b/Marlin/src/lcd/extui/anycubic_i3mega_lcd.cpp
@@ -0,0 +1,117 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * anycubic_i3mega_lcd.cpp
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_I3MEGA)
+
+#include "lib/anycubic_i3mega/anycubic_i3mega_lcd.h"
+#include "ui_api.h"
+
+#include // for the ::tone() call
+
+namespace ExtUI {
+
+ void onStartup() { AnycubicTFT.OnSetup(); }
+ void onIdle() { AnycubicTFT.OnCommandScan(); }
+ void onPrinterKilled(PGM_P const error, PGM_P const component) { AnycubicTFT.OnKillTFT(); }
+ void onMediaInserted() { AnycubicTFT.OnSDCardStateChange(true); }
+ void onMediaError() { AnycubicTFT.OnSDCardError(); }
+ void onMediaRemoved() { AnycubicTFT.OnSDCardStateChange(false); }
+ void onPlayTone(const uint16_t frequency, const uint16_t duration) {
+ #if ENABLED(SPEAKER)
+ ::tone(BEEPER_PIN, frequency, duration);
+ #endif
+ }
+ void onPrintTimerStarted() { AnycubicTFT.OnPrintTimerStarted(); }
+ void onPrintTimerPaused() { AnycubicTFT.OnPrintTimerPaused(); }
+ void onPrintTimerStopped() { AnycubicTFT.OnPrintTimerStopped(); }
+ void onFilamentRunout(const extruder_t extruder) { AnycubicTFT.OnFilamentRunout(); }
+ void onUserConfirmRequired(const char * const msg) { AnycubicTFT.OnUserConfirmRequired(msg); }
+ void onStatusChanged(const char * const msg) {}
+
+ void onHomingStart() {}
+ void onHomingComplete() {}
+ void onPrintFinished() {}
+
+ void onFactoryReset() {}
+
+ void onStoreSettings(char *buff) {
+ // Called when saving to EEPROM (i.e. M500). If the ExtUI needs
+ // permanent data to be stored, it can write up to eeprom_data_size bytes
+ // into buff.
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(buff, &myDataStruct, sizeof(myDataStruct));
+ }
+
+ void onLoadSettings(const char *buff) {
+ // Called while loading settings from EEPROM. If the ExtUI
+ // needs to retrieve data, it should copy up to eeprom_data_size bytes
+ // from buff
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(&myDataStruct, buff, sizeof(myDataStruct));
+ }
+
+ void onConfigurationStoreWritten(bool success) {
+ // Called after the entire EEPROM has been written,
+ // whether successful or not.
+ }
+
+ void onConfigurationStoreRead(bool success) {
+ // Called after the entire EEPROM has been read,
+ // whether successful or not.
+ }
+
+ #if HAS_MESH
+
+ void onMeshLevelingStart() {}
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) {
+ // Called when any mesh points are updated
+ }
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ void onPowerLossResume() {
+ // Called on resume from power-loss
+ }
+ #endif
+
+ #if HAS_PID_HEATING
+ void onPidTuning(const result_t rst) {
+ // Called for temperature PID tuning result
+ }
+ #endif
+
+ void onSteppersDisabled() {}
+ void onSteppersEnabled() {}
+}
+
+#endif // ANYCUBIC_LCD_I3MEGA
diff --git a/Marlin/src/lcd/extui/dgus_lcd.cpp b/Marlin/src/lcd/extui/dgus_lcd.cpp
new file mode 100644
index 0000000..9fcb6c8
--- /dev/null
+++ b/Marlin/src/lcd/extui/dgus_lcd.cpp
@@ -0,0 +1,158 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * dgus_lcd.cpp
+ *
+ * DGUS implementation for Marlin by coldtobi, Feb-May 2019
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if HAS_DGUS_LCD
+
+#include "ui_api.h"
+#include "lib/dgus/DGUSDisplay.h"
+#include "lib/dgus/DGUSDisplayDef.h"
+#include "lib/dgus/DGUSScreenHandler.h"
+
+namespace ExtUI {
+
+ void onStartup() {
+ dgusdisplay.InitDisplay();
+ ScreenHandler.UpdateScreenVPData();
+ }
+
+ void onIdle() { ScreenHandler.loop(); }
+
+ void onPrinterKilled(PGM_P const error, PGM_P const component) {
+ ScreenHandler.sendinfoscreen(GET_TEXT(MSG_HALTED), error, NUL_STR, GET_TEXT(MSG_PLEASE_RESET), true, true, true, true);
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_KILL);
+ while (!ScreenHandler.loop()); // Wait while anything is left to be sent
+ }
+
+ void onMediaInserted() { TERN_(SDSUPPORT, ScreenHandler.SDCardInserted()); }
+ void onMediaError() { TERN_(SDSUPPORT, ScreenHandler.SDCardError()); }
+ void onMediaRemoved() { TERN_(SDSUPPORT, ScreenHandler.SDCardRemoved()); }
+
+ void onPlayTone(const uint16_t frequency, const uint16_t duration) {}
+ void onPrintTimerStarted() {}
+ void onPrintTimerPaused() {}
+ void onPrintTimerStopped() {}
+ void onFilamentRunout(const extruder_t extruder) {}
+
+ void onUserConfirmRequired(const char * const msg) {
+ if (msg) {
+ ScreenHandler.sendinfoscreen(PSTR("Please confirm."), nullptr, msg, nullptr, true, true, false, true);
+ ScreenHandler.SetupConfirmAction(ExtUI::setUserConfirmed);
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_POPUP);
+ }
+ else if (ScreenHandler.getCurrentScreen() == DGUSLCD_SCREEN_POPUP ) {
+ ScreenHandler.SetupConfirmAction(nullptr);
+ ScreenHandler.PopToOldScreen();
+ }
+ }
+
+ void onStatusChanged(const char * const msg) { ScreenHandler.setstatusmessage(msg); }
+
+ void onHomingStart() {}
+ void onHomingComplete() {}
+ void onPrintFinished() {}
+
+ void onFactoryReset() {}
+
+ void onStoreSettings(char *buff) {
+ // Called when saving to EEPROM (i.e. M500). If the ExtUI needs
+ // permanent data to be stored, it can write up to eeprom_data_size bytes
+ // into buff.
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(buff, &myDataStruct, sizeof(myDataStruct));
+ }
+
+ void onLoadSettings(const char *buff) {
+ // Called while loading settings from EEPROM. If the ExtUI
+ // needs to retrieve data, it should copy up to eeprom_data_size bytes
+ // from buff
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(&myDataStruct, buff, sizeof(myDataStruct));
+ }
+
+ void onConfigurationStoreWritten(bool success) {
+ // Called after the entire EEPROM has been written,
+ // whether successful or not.
+ }
+
+ void onConfigurationStoreRead(bool success) {
+ // Called after the entire EEPROM has been read,
+ // whether successful or not.
+ }
+
+ #if HAS_MESH
+ void onMeshLevelingStart() {}
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) {
+ // Called when any mesh points are updated
+ }
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
+ // Called to indicate a special condition
+ }
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ void onPowerLossResume() {
+ // Called on resume from power-loss
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_POWER_LOSS);
+ }
+ #endif
+
+
+ #if HAS_PID_HEATING
+ void onPidTuning(const result_t rst) {
+ // Called for temperature PID tuning result
+ switch (rst) {
+ case PID_BAD_EXTRUDER_NUM:
+ ScreenHandler.setstatusmessagePGM(GET_TEXT(MSG_PID_BAD_EXTRUDER_NUM));
+ break;
+ case PID_TEMP_TOO_HIGH:
+ ScreenHandler.setstatusmessagePGM(GET_TEXT(MSG_PID_TEMP_TOO_HIGH));
+ break;
+ case PID_TUNING_TIMEOUT:
+ ScreenHandler.setstatusmessagePGM(GET_TEXT(MSG_PID_TIMEOUT));
+ break;
+ case PID_DONE:
+ ScreenHandler.setstatusmessagePGM(GET_TEXT(MSG_PID_AUTOTUNE_DONE));
+ break;
+ }
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN);
+ }
+ #endif
+
+ void onSteppersDisabled() {}
+ void onSteppersEnabled() {}
+}
+
+#endif // HAS_DGUS_LCD
diff --git a/Marlin/src/lcd/extui/example.cpp b/Marlin/src/lcd/extui/example.cpp
new file mode 100644
index 0000000..dd4b331
--- /dev/null
+++ b/Marlin/src/lcd/extui/example.cpp
@@ -0,0 +1,125 @@
+/*********************
+ * example.cpp *
+ *********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if BOTH(EXTUI_EXAMPLE, EXTENSIBLE_UI)
+
+#include "ui_api.h"
+
+// To implement a new UI, complete the functions below and
+// read or update Marlin's state using the methods in the
+// ExtUI methods in "../ui_api.h"
+//
+// Although it may be possible to access other state
+// variables from Marlin, using the API here possibly
+// helps ensure future compatibility.
+
+namespace ExtUI {
+ void onStartup() {
+ /* Initialize the display module here. The following
+ * routines are available for access to the GPIO pins:
+ *
+ * SET_OUTPUT(pin)
+ * SET_INPUT_PULLUP(pin)
+ * SET_INPUT(pin)
+ * WRITE(pin,value)
+ * READ(pin)
+ */
+ }
+ void onIdle() {}
+ void onPrinterKilled(PGM_P const error, PGM_P const component) {}
+ void onMediaInserted() {}
+ void onMediaError() {}
+ void onMediaRemoved() {}
+ void onPlayTone(const uint16_t frequency, const uint16_t duration) {}
+ void onPrintTimerStarted() {}
+ void onPrintTimerPaused() {}
+ void onPrintTimerStopped() {}
+ void onFilamentRunout(const extruder_t extruder) {}
+ void onUserConfirmRequired(const char * const msg) {}
+ void onStatusChanged(const char * const msg) {}
+
+ void onHomingStart() {}
+ void onHomingComplete() {}
+ void onPrintFinished() {}
+
+ void onFactoryReset() {}
+
+ void onStoreSettings(char *buff) {
+ // Called when saving to EEPROM (i.e. M500). If the ExtUI needs
+ // permanent data to be stored, it can write up to eeprom_data_size bytes
+ // into buff.
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(buff, &myDataStruct, sizeof(myDataStruct));
+ }
+
+ void onLoadSettings(const char *buff) {
+ // Called while loading settings from EEPROM. If the ExtUI
+ // needs to retrieve data, it should copy up to eeprom_data_size bytes
+ // from buff
+
+ // Example:
+ // static_assert(sizeof(myDataStruct) <= ExtUI::eeprom_data_size);
+ // memcpy(&myDataStruct, buff, sizeof(myDataStruct));
+ }
+
+ void onConfigurationStoreWritten(bool success) {
+ // Called after the entire EEPROM has been written,
+ // whether successful or not.
+ }
+
+ void onConfigurationStoreRead(bool success) {
+ // Called after the entire EEPROM has been read,
+ // whether successful or not.
+ }
+
+ #if HAS_MESH
+ void onMeshLevelingStart() {}
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) {
+ // Called when any mesh points are updated
+ }
+
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
+ // Called to indicate a special condition
+ }
+ #endif
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ void onPowerLossResume() {
+ // Called on resume from power-loss
+ }
+ #endif
+
+ #if HAS_PID_HEATING
+ void onPidTuning(const result_t rst) {
+ // Called for temperature PID tuning result
+ }
+ #endif
+
+ void onSteppersDisabled() {}
+ void onSteppersEnabled() {}
+}
+
+#endif // EXTUI_EXAMPLE && EXTENSIBLE_UI
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
new file mode 100644
index 0000000..19f8ec8
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
@@ -0,0 +1,164 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/lib/FileNavigator.cpp
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+/***************************************************************************
+ * The AC panel wants files in block of 4 and can only display a flat list *
+ * This library allows full folder traversal. *
+ ***************************************************************************/
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+
+#include "FileNavigator.h"
+#include "chiron_tft.h"
+
+using namespace ExtUI;
+
+namespace Anycubic {
+
+ FileNavigator filenavigator;
+
+ FileList FileNavigator::filelist; // Instance of the Marlin file API
+ char FileNavigator::currentfoldername[MAX_PATH_LEN]; // Current folder path
+ uint16_t FileNavigator::lastindex;
+ uint8_t FileNavigator::folderdepth;
+ uint16_t FileNavigator::currentindex; // override the panel request
+
+ FileNavigator::FileNavigator() { reset(); }
+
+ void FileNavigator::reset() {
+ currentfoldername[0] = '\0';
+ folderdepth = 0;
+ currentindex = 0;
+ lastindex = 0;
+ // Start at root folder
+ while (!filelist.isAtRootDir()) filelist.upDir();
+ refresh();
+ }
+
+ void FileNavigator::refresh() { filelist.refresh(); }
+
+ void FileNavigator::getFiles(uint16_t index) {
+ uint8_t files = 4;
+ if (index == 0) currentindex = 0;
+
+ // Each time we change folder we reset the file index to 0 and keep track
+ // of the current position as the TFT panel isnt aware of folders trees.
+ if (index > 0) {
+ --currentindex; // go back a file to take account off the .. we added to the root.
+ if (index > lastindex)
+ currentindex += files;
+ else
+ currentindex = currentindex < 4 ? 0 : currentindex - files;
+ }
+ lastindex = index;
+
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("index=", index, " currentindex=", currentindex);
+ #endif
+
+ if (currentindex == 0 && folderdepth > 0) { // Add a link to go up a folder
+ TFTSer.println("<<");
+ TFTSer.println("..");
+ files--;
+ }
+
+ for (uint16_t seek = currentindex; seek < currentindex + files; seek++) {
+ if (filelist.seek(seek)) {
+ sendFile();
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
+ #endif
+ }
+ }
+ }
+
+ void FileNavigator::sendFile() {
+ // send the file and folder info to the panel
+ // this info will be returned when the file is selected
+ // Permitted special characters in file name -_*#~
+ // Panel can display 22 characters per line
+ if (filelist.isDir()) {
+ //TFTSer.print(currentfoldername);
+ TFTSer.println(filelist.shortFilename());
+ TFTSer.print(filelist.shortFilename());
+ TFTSer.println("/");
+ }
+ else {
+ // Logical Name
+ TFTSer.print("/");
+ if (folderdepth > 0) TFTSer.print(currentfoldername);
+
+ TFTSer.println(filelist.shortFilename());
+
+ // Display Name
+ TFTSer.println(filelist.longFilename());
+ }
+ }
+ void FileNavigator::changeDIR(char *folder) {
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("currentfolder: ", currentfoldername, " New: ", folder);
+ #endif
+ if (folderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
+ strcat(currentfoldername, folder);
+ strcat(currentfoldername, "/");
+ filelist.changeDir(folder);
+ refresh();
+ folderdepth++;
+ currentindex = 0;
+ }
+
+ void FileNavigator::upDIR() {
+ filelist.upDir();
+ refresh();
+ folderdepth--;
+ currentindex = 0;
+ // Remove the last child folder from the stored path
+ if (folderdepth == 0) {
+ currentfoldername[0] = '\0';
+ reset();
+ }
+ else {
+ char *pos = nullptr;
+ for (uint8_t f = 0; f < folderdepth; f++)
+ pos = strchr(currentfoldername, '/');
+
+ *(pos + 1) = '\0';
+ }
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
+ #endif
+ }
+
+ char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
+}
+
+#endif // ANYCUBIC_LCD_CHIRON
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
new file mode 100644
index 0000000..8e03614
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
@@ -0,0 +1,56 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * lcd/extui/lib/FileNavigator.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#include "chiron_tft_defs.h"
+#include "../../ui_api.h"
+
+using namespace ExtUI;
+
+namespace Anycubic {
+ class FileNavigator {
+ public:
+ FileNavigator();
+ void reset();
+ void getFiles(uint16_t);
+ void upDIR();
+ void changeDIR(char *);
+ void sendFile();
+ void refresh();
+ char * getCurrentFolderName();
+ private:
+ static FileList filelist;
+ static char currentfoldername[MAX_PATH_LEN];
+ static uint16_t lastindex;
+ static uint8_t folderdepth;
+ static uint16_t currentindex;
+ };
+ extern FileNavigator filenavigator;
+}
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp
new file mode 100644
index 0000000..f09c4db
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.cpp
@@ -0,0 +1,62 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/lib/Tunes.cpp
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+/***********************************************************************
+ * A Utility to play tunes using the buzzer in the printer controller. *
+ * See Tunes.h for note and tune definitions. *
+ ***********************************************************************/
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+
+#include "Tunes.h"
+#include "../../ui_api.h"
+
+namespace Anycubic {
+
+ void PlayTune(uint8_t beeperPin, const uint16_t *tune, uint8_t speed=1) {
+ uint8_t pos = 1;
+ uint16_t wholenotelen = tune[0] / speed;
+ do {
+ uint16_t freq = tune[pos];
+ uint16_t notelen = wholenotelen / tune[pos + 1];
+
+ ::tone(beeperPin, freq, notelen);
+ ExtUI::delay_ms(notelen);
+ pos += 2;
+
+ if (pos >= MAX_TUNE_LENGTH) break;
+ } while (tune[pos] != n_END);
+ }
+
+}
+
+#endif // ANYCUBIC_LCD_CHIRON
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h
new file mode 100644
index 0000000..1bafec4
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/Tunes.h
@@ -0,0 +1,224 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * lcd/extui/lib/Tunes.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+/**************************************************************************
+ * Notes definition from https://pages.mtu.edu/~suits/NoteFreqCalcs.html *
+ * *
+ * The format of a tune is: *
+ * {,,, ,, ... } *
+ * *
+ * 1) The first value is the length of a whole note in milliseconds *
+ * 2) Then a sequence of pitch and duration pairs *
+ * 3) Finally the END marker so your tunes can be any length up to *
+ * MAX_TUNE_LEN *
+ *************************************************************************/
+
+#include
+
+#define MAX_TUNE_LENGTH 128
+
+// Special notes!
+#define n_P 0 // silence or pause
+#define n_END 10000 // end of tune marker
+
+// Note duration divisors
+#define l_T1 1
+#define l_T2 2
+#define l_T3 3
+#define l_T4 4
+#define l_T8 8
+#define l_T16 16
+
+// Note Frequency
+#define n_C0 16
+#define n_CS0 17
+#define n_D0 18
+#define n_DS0 19
+#define n_E0 21
+#define n_F0 22
+#define n_FS0 23
+#define n_G0 25
+#define n_GS0 26
+#define n_A0 28
+#define n_AS0 29
+#define n_B0 31
+#define n_C1 33
+#define n_CS1 35
+#define n_D1 37
+#define n_DS1 39
+#define n_E1 41
+#define n_F1 44
+#define n_FS1 46
+#define n_G1 49
+#define n_GS1 52
+#define n_A1 55
+#define n_AS1 58
+#define n_B1 62
+#define n_C2 65
+#define n_CS2 69
+#define n_D2 73
+#define n_DS2 78
+#define n_E2 82
+#define n_F2 87
+#define n_FS2 93
+#define n_G2 98
+#define n_GS2 104
+#define n_A2 110
+#define n_AS2 117
+#define n_B2 123
+#define n_C3 131
+#define n_CS3 139
+#define n_D3 147
+#define n_DS3 156
+#define n_E3 165
+#define n_F3 175
+#define n_FS3 185
+#define n_G3 196
+#define n_GS3 208
+#define n_A3 220
+#define n_AS3 233
+#define n_B3 247
+#define n_C4 262
+#define n_CS4 277
+#define n_D4 294
+#define n_DS4 311
+#define n_E4 330
+#define n_F4 349
+#define n_FS4 370
+#define n_G4 392
+#define n_GS4 415
+#define n_A4 440
+#define n_AS4 466
+#define n_B4 494
+#define n_C5 523
+#define n_CS5 554
+#define n_D5 587
+#define n_DS5 622
+#define n_E5 659
+#define n_F5 698
+#define n_FS5 740
+#define n_G5 784
+#define n_GS5 831
+#define n_A5 880
+#define n_AS5 932
+#define n_B5 988
+#define n_C6 1047
+#define n_CS6 1109
+#define n_D6 1175
+#define n_DS6 1245
+#define n_E6 1319
+#define n_F6 1397
+#define n_FS6 1480
+#define n_G6 1568
+#define n_GS6 1661
+#define n_A6 1760
+#define n_AS6 1865
+#define n_B6 1976
+#define n_C7 2093
+#define n_CS7 2217
+#define n_D7 2349
+#define n_DS7 2489
+#define n_E7 2637
+#define n_F7 2794
+#define n_FS7 2960
+#define n_G7 3136
+#define n_GS7 3322
+#define n_A7 3520
+#define n_AS7 3729
+#define n_B7 3951
+#define n_C8 4186
+#define n_CS8 4435
+#define n_D8 4699
+#define n_DS8 4978
+#define n_E8 5274
+#define n_F8 5587
+#define n_FS8 5920
+#define n_G8 6272
+#define n_GS8 6645
+#define n_A8 7040
+#define n_AS8 7459
+#define n_B8 7902
+
+namespace Anycubic {
+
+ void PlayTune(uint8_t beeperPin, const uint16_t *tune, uint8_t speed);
+
+ // Only uncomment the tunes you are using to save memory
+ // This will help you write tunes!
+ // https://www.apronus.com/music/flashpiano.htm
+
+ const uint16_t SOS[] = {
+ 250,
+ n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T1,
+ n_G6,l_T1, n_P,l_T3, n_G6,l_T1, n_P,l_T3, n_G6,l_T1, n_P,l_T1,
+ n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T3, n_G6,l_T3, n_P,l_T1,
+ n_END
+ };
+
+ const uint16_t BeepBeep[] = {
+ 500,
+ n_C7,l_T8, n_P,l_T16, n_C7,l_T8, n_P,l_T8,
+ n_END
+ };
+
+ const uint16_t BeepBeepBeeep[] = {
+ 1000,
+ n_G7,l_T4, n_P,l_T16, n_G7,l_T4, n_P,l_T8, n_G7,l_T2,
+ n_END
+ };
+
+ const uint16_t Anycubic_PowerOn[] = {
+ 1000,
+ n_F7,l_T8, n_P,l_T8, n_C7,l_T8, n_P,l_T8, n_D7,l_T8, n_P,l_T8,
+ n_E7,l_T8, n_P,l_T8, n_D7,l_T4, n_P,l_T4, n_G7,l_T4, n_P,l_T4,
+ n_A7,l_T2, n_P,l_T1,
+ n_END
+ };
+
+ const uint16_t GB_PowerOn[] = {
+ 500,
+ n_C6,l_T4, n_P,l_T16, n_C7,l_T2, n_P,l_T8,
+ n_END
+ };
+
+ const uint16_t Heater_Timedout[] = {
+ 1000,
+ n_C6,l_T1,
+ n_END
+ };
+
+ const uint16_t FilamentOut[] = {
+ 1000,
+ n_AS7,l_T4, n_P,l_T16, n_FS7,l_T2,
+ n_END
+ };
+
+}
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
new file mode 100644
index 0000000..61057b5
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.cpp
@@ -0,0 +1,885 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/lib/chiron_tft.cpp
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+
+#include "chiron_tft.h"
+#include "Tunes.h"
+#include "FileNavigator.h"
+
+#include "../../../../gcode/queue.h"
+#include "../../../../sd/cardreader.h"
+#include "../../../../libs/numtostr.h"
+#include "../../../../MarlinCore.h"
+
+namespace Anycubic {
+
+ printer_state_t ChironTFT::printer_state;
+ paused_state_t ChironTFT::pause_state;
+ heater_state_t ChironTFT::hotend_state;
+ heater_state_t ChironTFT::hotbed_state;
+ xy_uint8_t ChironTFT::selectedmeshpoint;
+ char ChironTFT::selectedfile[MAX_PATH_LEN];
+ char ChironTFT::panel_command[MAX_CMND_LEN];
+ uint8_t ChironTFT::command_len;
+ float ChironTFT::live_Zoffset;
+ file_menu_t ChironTFT::file_menu;
+
+ ChironTFT Chiron;
+
+ ChironTFT::ChironTFT(){}
+
+ void ChironTFT::Startup() {
+ selectedfile[0] = '\0';
+ panel_command[0] = '\0';
+ command_len = 0;
+ printer_state = AC_printer_idle;
+ pause_state = AC_paused_idle;
+ hotend_state = AC_heater_off;
+ hotbed_state = AC_heater_off;
+ live_Zoffset = 0.0;
+ file_menu = AC_menu_file;
+
+ // Setup pins for powerloss detection
+ // Two IO pins are connected on the Trigorilla Board
+ // On a power interruption the OUTAGECON_PIN goes low.
+
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ OUT_WRITE(OUTAGECON_PIN, HIGH);
+ #endif
+
+ // Filament runout is handled by Marlin settings in Configuration.h
+ // opt_set FIL_RUNOUT_STATE HIGH // Pin state indicating that filament is NOT present.
+ // opt_enable FIL_RUNOUT_PULLUP
+
+ TFTSer.begin(115200);
+
+ // Signal Board has reset
+ SendtoTFTLN(AC_msg_main_board_has_reset);
+
+ safe_delay(200);
+
+ // Enable leveling and Disable end stops during print
+ // as Z home places nozzle above the bed so we need to allow it past the end stops
+ injectCommands_P(AC_cmnd_enable_leveling);
+
+ // Startup tunes are defined in Tunes.h
+ //PlayTune(BEEPER_PIN, Anycubic_PowerOn, 1);
+ PlayTune(BEEPER_PIN, GB_PowerOn, 1);
+ #if ACDEBUGLEVEL
+ SERIAL_ECHOLNPAIR("AC Debug Level ", ACDEBUGLEVEL);
+ #endif
+ SendtoTFTLN(AC_msg_ready);
+ }
+
+ void ChironTFT::IdleLoop() {
+ if (ReadTFTCommand()) {
+ ProcessPanelRequest();
+ command_len = 0;
+ }
+ CheckHeaters();
+ }
+
+ void ChironTFT::PrinterKilled(PGM_P error,PGM_P component) {
+ SendtoTFTLN(AC_msg_kill_lcd);
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("PrinterKilled()\nerror: ", error , "\ncomponent: ", component);
+ #endif
+ }
+
+ void ChironTFT::MediaEvent(media_event_t event) {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("ProcessMediaStatus() ", event);
+ #endif
+ switch (event) {
+ case AC_media_inserted:
+ SendtoTFTLN(AC_msg_sd_card_inserted);
+ break;
+
+ case AC_media_removed:
+ SendtoTFTLN(AC_msg_sd_card_removed);
+ break;
+
+ case AC_media_error:
+ SendtoTFTLN(AC_msg_no_sd_card);
+ break;
+ }
+ }
+
+ void ChironTFT::TimerEvent(timer_event_t event) {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("TimerEvent() ", event);
+ SERIAL_ECHOLNPAIR("Printer State: ", printer_state);
+ #endif
+
+ switch (event) {
+ case AC_timer_started: {
+ live_Zoffset = 0.0; // reset print offset
+ setSoftEndstopState(false); // disable endstops to print
+ printer_state = AC_printer_printing;
+ SendtoTFTLN(AC_msg_print_from_sd_card);
+ } break;
+
+ case AC_timer_paused: {
+ printer_state = AC_printer_paused;
+ pause_state = AC_paused_idle;
+ SendtoTFTLN(AC_msg_paused);
+ } break;
+
+ case AC_timer_stopped: {
+ if (printer_state != AC_printer_idle) {
+ printer_state = AC_printer_stopping;
+ SendtoTFTLN(AC_msg_print_complete);
+ }
+ setSoftEndstopState(true); // enable endstops
+ } break;
+ }
+ }
+
+ void ChironTFT::FilamentRunout() {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("FilamentRunout() printer_state ", printer_state);
+ #endif
+ // 1 Signal filament out
+ SendtoTFTLN(isPrintingFromMedia() ? AC_msg_filament_out_alert : AC_msg_filament_out_block);
+ //printer_state = AC_printer_filament_out;
+ PlayTune(BEEPER_PIN, FilamentOut, 1);
+ }
+
+ void ChironTFT::ConfirmationRequest(const char * const msg) {
+ // M108 continue
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("ConfirmationRequest() ", msg, " printer_state:", printer_state);
+ #endif
+ switch (printer_state) {
+ case AC_printer_pausing: {
+ if (strcmp_P(msg, MARLIN_msg_print_paused) == 0 || strcmp_P(msg, MARLIN_msg_nozzle_parked) == 0) {
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ printer_state = AC_printer_paused;
+ }
+ } break;
+
+ case AC_printer_resuming_from_power_outage:
+ case AC_printer_printing:
+ case AC_printer_paused: {
+ // Heater timout, send acknowledgement
+ if (strcmp_P(msg, MARLIN_msg_heater_timeout) == 0) {
+ pause_state = AC_paused_heater_timed_out;
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ PlayTune(BEEPER_PIN,Heater_Timedout,1);
+ }
+ // Reheat finished, send acknowledgement
+ else if (strcmp_P(msg, MARLIN_msg_reheat_done) == 0) {
+ pause_state = AC_paused_idle;
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ }
+ // Filament Purging, send acknowledgement enter run mode
+ else if (strcmp_P(msg, MARLIN_msg_filament_purging) == 0) {
+ pause_state = AC_paused_purging_filament;
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+
+ void ChironTFT::StatusChange(const char * const msg) {
+ #if ACDEBUG(AC_MARLIN)
+ SERIAL_ECHOLNPAIR("StatusChange() ", msg);
+ SERIAL_ECHOLNPAIR("printer_state:", printer_state);
+ #endif
+ bool msg_matched = false;
+ // The only way to get printer status is to parse messages
+ // Use the state to minimise the work we do here.
+ switch (printer_state) {
+ case AC_printer_probing: {
+ // If probing completes ok save the mesh and park
+ // Ignore the custom machine name
+ if (strcmp_P(msg + strlen(CUSTOM_MACHINE_NAME), MARLIN_msg_ready) == 0) {
+ injectCommands_P(PSTR("M500\nG27"));
+ SendtoTFTLN(AC_msg_probing_complete);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ // If probing fails dont save the mesh raise the probe above the bad point
+ if (strcmp_P(msg, MARLIN_msg_probing_failed) == 0) {
+ PlayTune(BEEPER_PIN, BeepBeepBeeep, 1);
+ injectCommands_P(PSTR("G1 Z50 F500"));
+ SendtoTFTLN(AC_msg_probing_complete);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ } break;
+
+ case AC_printer_printing: {
+ if (strcmp_P(msg, MARLIN_msg_reheating) == 0) {
+ SendtoTFTLN(AC_msg_paused); // enable continue button
+ msg_matched = true;
+ }
+ } break;
+
+ case AC_printer_pausing: {
+ if (strcmp_P(msg, MARLIN_msg_print_paused) == 0) {
+ SendtoTFTLN(AC_msg_paused);
+ printer_state = AC_printer_paused;
+ pause_state = AC_paused_idle;
+ msg_matched = true;
+ }
+ } break;
+
+ case AC_printer_stopping: {
+ if (strcmp_P(msg, MARLIN_msg_print_aborted) == 0) {
+ SendtoTFTLN(AC_msg_stop);
+ printer_state = AC_printer_idle;
+ msg_matched = true;
+ }
+ } break;
+ default:
+ break;
+ }
+
+ // If not matched earlier see if this was a heater message
+ if (!msg_matched) {
+ if (strcmp_P(msg, MARLIN_msg_extruder_heating) == 0) {
+ SendtoTFTLN(AC_msg_nozzle_heating);
+ hotend_state = AC_heater_temp_set;
+ }
+ else if (strcmp_P(msg, MARLIN_msg_bed_heating) == 0) {
+ SendtoTFTLN(AC_msg_bed_heating);
+ hotbed_state = AC_heater_temp_set;
+ }
+ }
+ }
+
+ void ChironTFT::PowerLossRecovery() {
+ printer_state = AC_printer_resuming_from_power_outage; // Play tune to notify user we can recover.
+ PlayTune(BEEPER_PIN, SOS, 1);
+ SERIAL_ECHOLNPGM("Resuming from power outage...");
+ SERIAL_ECHOLNPGM("Select SD file then press resume");
+ }
+
+ void ChironTFT::SendtoTFT(PGM_P str) { // A helper to print PROGMEN string to the panel
+ #if ACDEBUG(AC_SOME)
+ serialprintPGM(str);
+ #endif
+ while (const char c = pgm_read_byte(str++)) TFTSer.print(c);
+ }
+
+ void ChironTFT::SendtoTFTLN(PGM_P str = nullptr) {
+ if (str) {
+ #if ACDEBUG(AC_SOME)
+ SERIAL_ECHOPGM("> ");
+ #endif
+ SendtoTFT(str);
+ #if ACDEBUG(AC_SOME)
+ SERIAL_EOL();
+ #endif
+ }
+ TFTSer.println("");
+ }
+
+ bool ChironTFT::ReadTFTCommand() {
+ bool command_ready = false;
+ while(TFTSer.available() > 0 && command_len < MAX_CMND_LEN) {
+ panel_command[command_len] = TFTSer.read();
+ if (panel_command[command_len] == '\n') {
+ command_ready = true;
+ break;
+ }
+ command_len++;
+ }
+
+ if (command_ready) {
+ panel_command[command_len] = 0x00;
+ #if ACDEBUG(AC_ALL)
+ SERIAL_ECHOLNPAIR("< ", panel_command);
+ #endif
+ #if ACDEBUG(AC_SOME)
+ // Ignore status request commands
+ uint8_t req = atoi(&panel_command[1]);
+ if (req > 7 && req != 20) {
+ SERIAL_ECHOLNPAIR("> ", panel_command);
+ SERIAL_ECHOLNPAIR("printer_state:", printer_state);
+ }
+ #endif
+ }
+ return command_ready;
+ }
+
+ int8_t ChironTFT::Findcmndpos(const char * buff, char q) {
+ int8_t pos = 0;
+ do { if (buff[pos] == q) return pos; } while(++pos < MAX_CMND_LEN);
+ return -1;
+ }
+
+ void ChironTFT::CheckHeaters() {
+ uint8_t faultDuration = 0;
+ float temp = 0;
+
+ // if the hotend temp is abnormal, confirm state before signalling panel
+ temp = getActualTemp_celsius(E0);
+ while (!WITHIN(temp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP)) {
+ faultDuration++;
+ if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
+ SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+ SERIAL_ECHOLNPAIR("Extruder temp abnormal! : ", temp);
+ break;
+ }
+ delay_ms(500);
+ temp = getActualTemp_celsius(E0);
+ }
+
+ // If the hotbed temp is abnormal, confirm state before signaling panel
+ faultDuration = 0;
+ temp = getActualTemp_celsius(BED);
+ while (!WITHIN(temp, BED_MINTEMP, BED_MAXTEMP)) {
+ faultDuration++;
+ if (faultDuration >= AC_HEATER_FAULT_VALIDATION_TIME) {
+ SendtoTFTLN(AC_msg_nozzle_temp_abnormal);
+ SERIAL_ECHOLNPAIR("Bed temp abnormal! : ", temp);
+ break;
+ }
+ delay_ms(500);
+ temp = getActualTemp_celsius(E0);
+ }
+
+ // Update panel with hotend heater status
+ if (hotend_state != AC_heater_temp_reached) {
+ if (WITHIN(getActualTemp_celsius(E0) - getTargetTemp_celsius(E0), -1, 1)) {
+ SendtoTFTLN(AC_msg_nozzle_heating_done);
+ hotend_state = AC_heater_temp_reached;
+ }
+ }
+
+ // Update panel with bed heater status
+ if (hotbed_state != AC_heater_temp_reached) {
+ if (WITHIN(getActualTemp_celsius(BED) - getTargetTemp_celsius(BED), -0.5, 0.5)) {
+ SendtoTFTLN(AC_msg_bed_heating_done);
+ hotbed_state = AC_heater_temp_reached;
+ }
+ }
+ }
+
+ void ChironTFT::SendFileList(int8_t startindex) {
+ // Respond to panel request for 4 files starting at index
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("## SendFileList ## ", startindex);
+ #endif
+ SendtoTFTLN(PSTR("FN "));
+ filenavigator.getFiles(startindex);
+ SendtoTFTLN(PSTR("END"));
+ }
+
+ void ChironTFT::SelectFile() {
+ strncpy(selectedfile, panel_command + 4, command_len - 4);
+ selectedfile[command_len - 5] = '\0';
+ #if ACDEBUG(AC_FILE)
+ SERIAL_ECHOLNPAIR_F(" Selected File: ",selectedfile);
+ #endif
+ switch (selectedfile[0]) {
+ case '/': // Valid file selected
+ SendtoTFTLN(AC_msg_sd_file_open_success);
+ break;
+
+ case '<': // .. (go up folder level)
+ filenavigator.upDIR();
+ SendtoTFTLN(AC_msg_sd_file_open_failed);
+ SendFileList( 0 );
+ break;
+ default: // enter sub folder
+ filenavigator.changeDIR(selectedfile);
+ SendtoTFTLN(AC_msg_sd_file_open_failed);
+ SendFileList( 0 );
+ break;
+ }
+ }
+
+ void ChironTFT::InjectCommandandWait(PGM_P cmd) {
+ //injectCommands_P(cmnd); queue.enqueue_now_P(cmd);
+ //SERIAL_ECHOLN(PSTR("Inject>"));
+ }
+
+ void ChironTFT::ProcessPanelRequest() {
+ // Break these up into logical blocks // as its easier to navigate than one huge switch case!
+ int8_t req = atoi(&panel_command[1]);
+
+ // Information requests A0 - A8 and A33
+ if (req <= 8 || req == 33) PanelInfo(req);
+
+ // Simple Actions A9 - A28
+ else if ( req <= 28) PanelAction(req);
+
+ // Process Initiation
+ else if (req <= 34) PanelProcess(req);
+
+ else SendtoTFTLN();
+ }
+
+ void ChironTFT::PanelInfo(uint8_t req) {
+ // information requests A0-A8 and A33
+ switch (req) {
+ case 0: // A0 Get HOTEND Temp
+ SendtoTFT(PSTR("A0V "));
+ TFTSer.println(getActualTemp_celsius(E0));
+ break;
+
+ case 1: // A1 Get HOTEND Target Temp
+ SendtoTFT(PSTR("A1V "));
+ TFTSer.println(getTargetTemp_celsius(E0));
+ break;
+
+ case 2: // A2 Get BED Temp
+ SendtoTFT(PSTR("A2V "));
+ TFTSer.println(getActualTemp_celsius(BED));
+ break;
+
+ case 3: // A3 Get BED Target Temp
+ SendtoTFT(PSTR("A3V "));
+ TFTSer.println(getTargetTemp_celsius(BED));
+ break;
+
+ case 4: // A4 Get FAN Speed
+ SendtoTFT(PSTR("A4V "));
+ TFTSer.println(getActualFan_percent(FAN0));
+ break;
+
+ case 5: // A5 Get Current Coordinates
+ SendtoTFT(PSTR("A5V X: "));
+ TFTSer.print(getAxisPosition_mm(X));
+ SendtoTFT(PSTR(" Y: "));
+ TFTSer.print(getAxisPosition_mm(Y));
+ SendtoTFT(PSTR(" Z: "));
+ TFTSer.println(getAxisPosition_mm(Z));
+ break;
+
+ case 6: // A6 Get printing progress
+ if (isPrintingFromMedia()) {
+ SendtoTFT(PSTR("A6V "));
+ TFTSer.println(ui8tostr2(getProgress_percent()));
+ }
+ else
+ SendtoTFTLN(PSTR("A6V ---"));
+ break;
+
+ case 7: { // A7 Get Printing Time
+ uint32_t time = getProgress_seconds_elapsed() / 60;
+ SendtoTFT(PSTR("A7V "));
+ TFTSer.print(ui8tostr2(time / 60));
+ SendtoTFT(PSTR(" H "));
+ TFTSer.print(ui8tostr2(time % 60));
+ SendtoTFT(PSTR(" M"));
+ #if ACDEBUG(AC_ALL)
+ SERIAL_ECHOLNPAIR("Print time ", ui8tostr2(time / 60), ":", ui8tostr2(time % 60));
+ #endif
+ } break;
+
+ case 8: // A8 Get SD Card list A8 S0
+ if (!isMediaInserted()) safe_delay(500);
+ if (!isMediaInserted()) // Make sure the card is removed
+ SendtoTFTLN(AC_msg_no_sd_card);
+ else if (panel_command[3] == 'S')
+ SendFileList( atoi( &panel_command[4] ) );
+ break;
+
+ case 33: // A33 Get firmware info
+ SendtoTFT(PSTR("J33 "));
+ SendtoTFTLN(PSTR(SHORT_BUILD_VERSION));
+ break;
+ }
+ }
+
+ void ChironTFT::PanelAction(uint8_t req) {
+ switch (req) {
+ case 9: // A9 Pause SD print
+ if (isPrintingFromMedia()) {
+ SendtoTFTLN(AC_msg_pause);
+ pausePrint();
+ printer_state = AC_printer_pausing;
+ }
+ else
+ SendtoTFTLN(AC_msg_stop);
+ break;
+
+ case 10: // A10 Resume SD Print
+ if (pause_state == AC_paused_idle || printer_state == AC_printer_resuming_from_power_outage)
+ resumePrint();
+ else
+ setUserConfirmed();
+ break;
+
+ case 11: // A11 Stop SD print
+ if (isPrintingFromMedia()) {
+ printer_state = AC_printer_stopping;
+ stopPrint();
+ }
+ else {
+ if (printer_state == AC_printer_resuming_from_power_outage)
+ injectCommands_P(PSTR("M1000 C")); // Cancel recovery
+ SendtoTFTLN(AC_msg_stop);
+ printer_state = AC_printer_idle;
+ }
+ break;
+
+ case 12: // A12 Kill printer
+ kill(); // from marlincore.h
+ break;
+
+ case 13: // A13 Select file
+ SelectFile();
+ break;
+
+ case 14: { // A14 Start Printing
+ // Allows printer to restart the job if we dont want to recover
+ if (printer_state == AC_printer_resuming_from_power_outage) {
+ injectCommands_P(PSTR("M1000 C")); // Cancel recovery
+ printer_state = AC_printer_idle;
+ }
+ #if ACDebugLevel >= 1
+ SERIAL_ECHOLNPAIR_F("Print: ", selectedfile);
+ #endif
+ // the card library needs a path starting // but the File api doesn't...
+ char file[MAX_PATH_LEN];
+ file[0] = '/';
+ strcpy(file + 1, selectedfile);
+ printFile(file);
+ SendtoTFTLN(AC_msg_print_from_sd_card);
+ } break;
+
+ case 15: // A15 Resuming from outage
+ if (printer_state == AC_printer_resuming_from_power_outage) {
+ // Need to home here to restore the Z position
+ injectCommands(AC_cmnd_power_loss_recovery);
+ injectCommands("M1000"); // home and start recovery
+ }
+ break;
+
+ case 16: { // A16 Set HotEnd temp A17 S170
+ const float set_Htemp = atof(&panel_command[5]);
+ hotend_state = set_Htemp ? AC_heater_temp_set : AC_heater_off;
+ switch ((char)panel_command[4]) {
+ // Set Temp
+ case 'S': case 'C': setTargetTemp_celsius(set_Htemp, E0);
+ }
+ } break;
+
+ case 17: { // A17 Set bed temp
+ const float set_Btemp = atof(&panel_command[5]);
+ hotbed_state = set_Btemp ? AC_heater_temp_set : AC_heater_off;
+ if (panel_command[4] == 'S')
+ setTargetTemp_celsius(set_Btemp, BED);
+ } break;
+
+ case 18: // A18 Set Fan Speed
+ if (panel_command[4] == 'S')
+ setTargetFan_percent(atof(&panel_command[5]), FAN0);
+ break;
+
+ case 19: // A19 Motors off
+ if (!isPrinting()) {
+ disable_all_steppers(); // from marlincore.h
+ SendtoTFTLN(AC_msg_ready);
+ }
+ break;
+
+ case 20: // A20 Read/write print speed
+ if (panel_command[4] == 'S')
+ setFeedrate_percent(atoi(&panel_command[5]));
+ else {
+ SendtoTFT(PSTR("A20V "));
+ TFTSer.println(getFeedrate_percent());
+ }
+ break;
+
+ case 21: // A21 Home Axis A21 X
+ if (!isPrinting()) {
+ switch ((char)panel_command[4]) {
+ case 'X': injectCommands_P(PSTR("G28X")); break;
+ case 'Y': injectCommands_P(PSTR("G28Y")); break;
+ case 'Z': injectCommands_P(PSTR("G28Z")); break;
+ case 'C': injectCommands_P(G28_STR); break;
+ }
+ }
+ break;
+
+ case 22: // A22 Move Axis A22 Y +10F3000
+ // Ignore request if printing
+ if (!isPrinting()) {
+ // setAxisPosition_mm() uses pre defined manual feedrates so ignore the feedrate from the panel
+ setSoftEndstopState(true); // enable endstops
+ float newposition = atof(&panel_command[6]);
+
+ #if ACDEBUG(AC_ACTION)
+ SERIAL_ECHOLNPAIR("Nudge ", panel_command[4], " axis ", newposition);
+ #endif
+
+ switch (panel_command[4]) {
+ case 'X': setAxisPosition_mm(getAxisPosition_mm(X) + newposition, X); break;
+ case 'Y': setAxisPosition_mm(getAxisPosition_mm(Y) + newposition, Y); break;
+ case 'Z': setAxisPosition_mm(getAxisPosition_mm(Z) + newposition, Z); break;
+ case 'E': // The only time we get this command is from the filament load/unload menu
+ // the standard movement is too slow so we will use the load unlod GCode to speed it up a bit
+ if (canMove(E0) && !commandsInQueue())
+ injectCommands_P(newposition > 0 ? AC_cmnd_manual_load_filament : AC_cmnd_manual_unload_filament);
+ break;
+ }
+ }
+ break;
+
+ case 23: // A23 Preheat PLA
+ // Ignore request if printing
+ if (!isPrinting()) {
+ // Temps defined in configuration.h
+ setTargetTemp_celsius(PREHEAT_1_TEMP_BED, BED);
+ setTargetTemp_celsius(PREHEAT_1_TEMP_HOTEND, E0);
+ SendtoTFTLN();
+ hotbed_state = AC_heater_temp_set;
+ hotend_state = AC_heater_temp_set;
+ }
+ break;
+
+ case 24: // A24 Preheat ABS
+ // Ignore request if printing
+ if (!isPrinting()) {
+ setTargetTemp_celsius(PREHEAT_2_TEMP_BED, BED);
+ setTargetTemp_celsius(PREHEAT_2_TEMP_HOTEND, E0);
+ SendtoTFTLN();
+ hotbed_state = AC_heater_temp_set;
+ hotend_state = AC_heater_temp_set;
+ }
+ break;
+
+ case 25: // A25 Cool Down
+ // Ignore request if printing
+ if (!isPrinting()) {
+ setTargetTemp_celsius(0, E0);
+ setTargetTemp_celsius(0, BED);
+ SendtoTFTLN(AC_msg_ready);
+ hotbed_state = AC_heater_off;
+ hotend_state = AC_heater_off;
+ }
+ break;
+
+ case 26: // A26 Refresh SD
+ // M22 M21 maybe needed here to reset sd card
+ filenavigator.reset();
+ break;
+
+ case 27: // A27 Servo Angles adjust
+ break;
+
+ case 28: // A28 Filament set A28 O/C
+ // Ignore request if printing
+ if (isPrinting()) break;
+ SendtoTFTLN();
+ break;
+ }
+ }
+
+ void ChironTFT::PanelProcess(uint8_t req) {
+ switch (req) {
+ case 29: { // A29 Read Mesh Point A29 X1 Y1
+ xy_uint8_t pos;
+ float pos_z;
+ pos.x = atoi(&panel_command[5]);
+ pos.y = atoi(&panel_command[8]);
+ pos_z = getMeshPoint(pos);
+
+ SendtoTFT(PSTR("A29V "));
+ TFTSer.println(pos_z * 100);
+ if (!isPrinting()) {
+ setSoftEndstopState(true); // disable endstops
+ // If the same meshpoint is selected twice in a row, move the head to that ready for adjustment
+ if ((selectedmeshpoint.x == pos.x) && (selectedmeshpoint.y == pos.y)) {
+ if (!isPositionKnown())
+ injectCommands_P(G28_STR); // home
+
+ if (isPositionKnown()) {
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Moving to mesh point at x: ", pos.x, " y: ", pos.y, " z: ", pos_z);
+ #endif
+ // Go up before moving
+ setAxisPosition_mm(3.0,Z);
+
+ setAxisPosition_mm(17 + (93 * pos.x), X);
+ setAxisPosition_mm(20 + (93 * pos.y), Y);
+ setAxisPosition_mm(0.0, Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Current Z: ", getAxisPosition_mm(Z));
+ #endif
+ }
+ }
+ selectedmeshpoint.x = pos.x;
+ selectedmeshpoint.y = pos.y;
+ }
+ } break;
+
+ case 30: { // A30 Auto leveling
+ if (panel_command[3] == 'S') { // Start probing
+ // Ignore request if printing
+ if (isPrinting())
+ SendtoTFTLN(AC_msg_probing_not_allowed); // forbid auto leveling
+ else {
+ injectCommands_P(PSTR("G28O\nG29"));
+ printer_state = AC_printer_probing;
+ SendtoTFTLN(AC_msg_start_probing);
+ }
+ }
+ else SendtoTFTLN(AC_msg_start_probing);
+ } break;
+
+ case 31: { // A31 Adjust all Probe Points
+ switch (panel_command[3]) {
+ case 'C': // Restore and apply original offsets
+ if (!isPrinting()) {
+ injectCommands_P(PSTR("M501\nM420 S1"));
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ }
+ break;
+ case 'D': // Save Z Offset tables and restore leveling state
+ if (!isPrinting()) {
+ setAxisPosition_mm(1.0,Z);
+ injectCommands_P(PSTR("M500"));
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ }
+ break;
+ case 'G': // Get current offset
+ SendtoTFT(PSTR("A31V "));
+ // When printing use the live z Offset position
+ // we will use babystepping to move the print head
+ if (isPrinting())
+ TFTSer.println(live_Zoffset);
+ else {
+ TFTSer.println(getZOffset_mm());
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ }
+ break;
+ case 'S': { // Set offset (adjusts all points by value)
+ float Zshift = atof(&panel_command[4]);
+ setSoftEndstopState(false); // disable endstops
+ // Allow temporary Z position nudging during print
+ // From the leveling panel use the all points UI to adjust the print pos.
+ if (isPrinting()) {
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Change Zoffset from:", live_Zoffset, " to ", live_Zoffset + Zshift);
+ #endif
+ if (isAxisPositionKnown(Z)) {
+ #if ACDEBUG(AC_INFO)
+ const float currZpos = getAxisPosition_mm(Z);
+ SERIAL_ECHOLNPAIR("Nudge Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
+ #endif
+ // Use babystepping to adjust the head position
+ int16_t steps = mmToWholeSteps(constrain(Zshift,-0.05,0.05), Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Steps to move Z: ", steps);
+ #endif
+ babystepAxis_steps(steps, Z);
+ live_Zoffset += Zshift;
+ }
+ SendtoTFT(PSTR("A31V "));
+ TFTSer.println(live_Zoffset);
+ }
+ else {
+ GRID_LOOP(x, y) {
+ const xy_uint8_t pos { x, y };
+ const float currval = getMeshPoint(pos);
+ setMeshPoint(pos, constrain(currval + Zshift, AC_LOWEST_MESHPOINT_VAL, 2));
+ }
+ const float currZOffset = getZOffset_mm();
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Change probe offset from ", currZOffset, " to ", currZOffset + Zshift);
+ #endif
+
+ setZOffset_mm(currZOffset + Zshift);
+ SendtoTFT(PSTR("A31V "));
+ TFTSer.println(getZOffset_mm());
+
+ if (isAxisPositionKnown(Z)) {
+ // Move Z axis
+ const float currZpos = getAxisPosition_mm(Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Move Z pos from ", currZpos, " to ", currZpos + constrain(Zshift, -0.05, 0.05));
+ #endif
+ setAxisPosition_mm(currZpos+constrain(Zshift,-0.05,0.05),Z);
+ }
+ }
+ } break;
+ } // end switch
+ } break;
+
+ case 32: { // A32 clean leveling beep flag
+ // Ignore request if printing
+ //if (isPrinting()) break;
+ //injectCommands_P(PSTR("M500\nM420 S1\nG1 Z10 F240\nG1 X0 Y0 F6000"));
+ //TFTSer.println("");
+ } break;
+
+ // A33 firmware info request seet PanelInfo()
+
+ case 34: { // A34 Adjust single mesh point A34 C/S X1 Y1 V123
+ if (panel_command[3] == 'C') { // Restore original offsets
+ injectCommands_P(PSTR("M501\nM420 S1"));
+ selectedmeshpoint.x = selectedmeshpoint.y = 99;
+ //printer_state = AC_printer_idle;
+ }
+ else {
+ xy_uint8_t pos;
+ pos.x = atoi(&panel_command[5]);
+ pos.y = atoi(&panel_command[8]);
+
+ float currmesh = getMeshPoint(pos);
+ float newval = atof(&panel_command[11])/100;
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Change mesh point x:", pos.x, " y:", pos.y);
+ SERIAL_ECHOLNPAIR("from ", currmesh, " to ", newval);
+ #endif
+ // Update Meshpoint
+ setMeshPoint(pos,newval);
+ if (printer_state == AC_printer_idle || printer_state == AC_printer_probing /*!isPrinting()*/) {
+ // if we are at the current mesh point indicated on the panel Move Z pos +/- 0.05mm
+ // (The panel changes the mesh value by +/- 0.05mm on each button press)
+ if (selectedmeshpoint.x == pos.x && selectedmeshpoint.y == pos.y) {
+ setSoftEndstopState(false);
+ float currZpos = getAxisPosition_mm(Z);
+ #if ACDEBUG(AC_INFO)
+ SERIAL_ECHOLNPAIR("Move Z pos from ", currZpos, " to ", currZpos + constrain(newval - currmesh, -0.05, 0.05));
+ #endif
+ setAxisPosition_mm(currZpos + constrain(newval - currmesh, -0.05, 0.05), Z);
+ }
+ }
+ }
+ } break;
+ }
+ }
+} // namespace
+
+#endif // ANYCUBIC_LCD_CHIRON
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
new file mode 100644
index 0000000..267f2fe
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft.h
@@ -0,0 +1,77 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/**
+ * lcd/extui/lib/chiron_tft.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#include "chiron_tft_defs.h"
+#include "../../../../inc/MarlinConfigPre.h"
+#include "../../ui_api.h"
+namespace Anycubic {
+
+ class ChironTFT {
+ static printer_state_t printer_state;
+ static paused_state_t pause_state;
+ static heater_state_t hotend_state;
+ static heater_state_t hotbed_state;
+ static xy_uint8_t selectedmeshpoint;
+ static char panel_command[MAX_CMND_LEN];
+ static uint8_t command_len;
+ static char selectedfile[MAX_PATH_LEN];
+ static float live_Zoffset;
+ static file_menu_t file_menu;
+ public:
+ ChironTFT();
+ void Startup();
+ void IdleLoop();
+ void PrinterKilled(PGM_P,PGM_P);
+ void MediaEvent(media_event_t);
+ void TimerEvent(timer_event_t);
+ void FilamentRunout();
+ void ConfirmationRequest(const char * const );
+ void StatusChange(const char * const );
+ void PowerLossRecovery();
+
+ private:
+ void SendtoTFT(PGM_P);
+ void SendtoTFTLN(PGM_P);
+ bool ReadTFTCommand();
+ int8_t Findcmndpos(const char *, char);
+ void CheckHeaters();
+ void SendFileList(int8_t);
+ void SelectFile();
+ void InjectCommandandWait(PGM_P);
+ void ProcessPanelRequest();
+ void PanelInfo(uint8_t);
+ void PanelAction(uint8_t);
+ void PanelProcess(uint8_t);
+ };
+
+ extern ChironTFT Chiron;
+
+}
diff --git a/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
new file mode 100644
index 0000000..7012e98
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_chiron/chiron_tft_defs.h
@@ -0,0 +1,151 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * lcd/extui/lib/chiron_defs.h
+ *
+ * Extensible_UI implementation for Anycubic Chiron
+ * Written By Nick Wells, 2020 [https://github.com/SwiftNick]
+ * (not affiliated with Anycubic, Ltd.)
+ */
+
+#pragma once
+#include "../../../../inc/MarlinConfigPre.h"
+//#define ACDEBUGLEVEL 255
+
+#if ACDEBUGLEVEL
+ // Bit-masks for selective debug:
+ enum ACDebugMask : uint8_t {
+ AC_INFO = 1,
+ AC_ACTION = 2,
+ AC_FILE = 4,
+ AC_PANEL = 8,
+ AC_MARLIN = 16,
+ AC_SOME = 32,
+ AC_ALL = 64
+ };
+ #define ACDEBUG(mask) ( ((mask) & ACDEBUGLEVEL) == mask ) // Debug flag macro
+#else
+ #define ACDEBUG(mask) false
+#endif
+
+#define TFTSer LCD_SERIAL // Serial interface for TFT panel now uses marlinserial
+#define MAX_FOLDER_DEPTH 4 // Limit folder depth TFT has a limit for the file path
+#define MAX_CMND_LEN 16 * MAX_FOLDER_DEPTH // Maximum Length for a Panel command
+#define MAX_PATH_LEN 16 * MAX_FOLDER_DEPTH // Maximum number of characters in a SD file path
+
+#define AC_HEATER_FAULT_VALIDATION_TIME 5 // number of 1/2 second loops before signalling a heater fault
+#define AC_LOWEST_MESHPOINT_VAL Z_PROBE_LOW_POINT // The lowest value you can set for a single mesh point offset
+
+ // TFT panel commands
+#define AC_msg_sd_card_inserted PSTR("J00")
+#define AC_msg_sd_card_removed PSTR("J01")
+#define AC_msg_no_sd_card PSTR("J02")
+#define AC_msg_usb_connected PSTR("J03")
+#define AC_msg_print_from_sd_card PSTR("J04")
+#define AC_msg_pause PSTR("J05")
+#define AC_msg_nozzle_heating PSTR("J06")
+#define AC_msg_nozzle_heating_done PSTR("J07")
+#define AC_msg_bed_heating PSTR("J08")
+#define AC_msg_bed_heating_done PSTR("J09")
+#define AC_msg_nozzle_temp_abnormal PSTR("J10")
+#define AC_msg_kill_lcd PSTR("J11")
+#define AC_msg_ready PSTR("J12")
+#define AC_msg_low_nozzle_temp PSTR("J13")
+#define AC_msg_print_complete PSTR("J14")
+#define AC_msg_filament_out_alert PSTR("J15")
+#define AC_msg_stop PSTR("J16")
+#define AC_msg_main_board_has_reset PSTR("J17")
+#define AC_msg_paused PSTR("J18")
+#define AC_msg_j19_unknown PSTR("J19")
+#define AC_msg_sd_file_open_success PSTR("J20")
+#define AC_msg_sd_file_open_failed PSTR("J21")
+#define AC_msg_level_monitor_finished PSTR("J22")
+#define AC_msg_filament_out_block PSTR("J23")
+#define AC_msg_probing_not_allowed PSTR("J24")
+#define AC_msg_probing_complete PSTR("J25")
+#define AC_msg_start_probing PSTR("J26")
+#define AC_msg_version PSTR("J27")
+
+#define MARLIN_msg_start_probing PSTR("Probing Point 1/25")
+#define MARLIN_msg_probing_failed PSTR("Probing Failed")
+#define MARLIN_msg_ready PSTR(" Ready.")
+#define MARLIN_msg_print_paused PSTR("Print Paused")
+#define MARLIN_msg_print_aborted PSTR("Print Aborted")
+#define MARLIN_msg_extruder_heating PSTR("E Heating...")
+#define MARLIN_msg_bed_heating PSTR("Bed Heating...")
+
+#define MARLIN_msg_nozzle_parked PSTR("Nozzle Parked")
+#define MARLIN_msg_heater_timeout PSTR("Heater Timeout")
+#define MARLIN_msg_reheating PSTR("Reheating...")
+#define MARLIN_msg_reheat_done PSTR("Reheat finished.")
+#define MARLIN_msg_filament_purging PSTR("Filament Purging...")
+#define MARLIN_msg_special_pause PSTR("PB")
+#define AC_cmnd_auto_unload_filament PSTR("M701") // Use Marlin unload routine
+#define AC_cmnd_auto_load_filament PSTR("M702 M0 PB") // Use Marlin load routing then pause for user to clean nozzle
+
+#define AC_cmnd_manual_load_filament PSTR("M83\nG1 E50 F700\nM82") // replace the manual panel commands with something a little faster
+#define AC_cmnd_manual_unload_filament PSTR("M83\nG1 E-50 F1200\nM82")
+#define AC_cmnd_enable_leveling PSTR("M420SV")
+#define AC_cmnd_power_loss_recovery PSTR("G28XYR5\nG28Z") // Lift, home X and Y then home Z when in 'safe' position
+
+namespace Anycubic {
+ enum heater_state_t : uint8_t {
+ AC_heater_off,
+ AC_heater_temp_set,
+ AC_heater_temp_reached
+ };
+
+ enum paused_state_t : uint8_t {
+ AC_paused_heater_timed_out,
+ AC_paused_purging_filament,
+ AC_paused_idle
+ };
+
+ enum printer_state_t : uint8_t {
+ AC_printer_idle,
+ AC_printer_probing,
+ AC_printer_printing,
+ AC_printer_pausing,
+ AC_printer_paused,
+ AC_printer_stopping,
+ AC_printer_resuming_from_power_outage
+ };
+
+ enum timer_event_t : uint8_t {
+ AC_timer_started,
+ AC_timer_paused,
+ AC_timer_stopped
+ };
+
+ enum media_event_t : uint8_t {
+ AC_media_inserted,
+ AC_media_removed,
+ AC_media_error
+ };
+ enum file_menu_t : uint8_t {
+ AC_menu_file,
+ AC_menu_command,
+ AC_menu_change_to_file,
+ AC_menu_change_to_command
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp
new file mode 100644
index 0000000..1508dc0
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.cpp
@@ -0,0 +1,1028 @@
+/**
+ * anycubic_i3mega_lcd.cpp --- Support for Anycubic i3 Mega TFT
+ * Created by Christian Hopp on 09.12.17.
+ * Improved by David Ramiro
+ * Converted to ext_iu by John BouAntoun 21 June 2020
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(ANYCUBIC_LCD_I3MEGA)
+
+#include "anycubic_i3mega_lcd.h"
+#include "../../ui_api.h"
+
+#include "../../../../libs/numtostr.h"
+#include "../../../../module/motion.h" // for quickstop_stepper, A20 read printing speed, feedrate_percentage
+#include "../../../../MarlinCore.h" // for disable_steppers
+#include "../../../../inc/MarlinConfig.h"
+
+// command sending macro's with debugging capability
+#define SEND_PGM(x) send_P(PSTR(x))
+#define SENDLINE_PGM(x) sendLine_P(PSTR(x))
+#define SEND_PGM_VAL(x,y) (send_P(PSTR(x)), sendLine(i16tostr3rj(y)))
+#define SEND(x) send(x)
+#define SENDLINE(x) sendLine(x)
+#if ENABLED(ANYCUBIC_LCD_DEBUG)
+ #define SENDLINE_DBG_PGM(x,y) (sendLine_P(PSTR(x)), SERIAL_ECHOLNPGM(y))
+ #define SENDLINE_DBG_PGM_VAL(x,y,z) (sendLine_P(PSTR(x)), SERIAL_ECHOPGM(y), SERIAL_ECHOLN(z))
+#else
+ #define SENDLINE_DBG_PGM(x,y) sendLine_P(PSTR(x))
+ #define SENDLINE_DBG_PGM_VAL(x,y,z) sendLine_P(PSTR(x))
+#endif
+
+AnycubicTFTClass AnycubicTFT;
+
+static void sendNewLine(void) {
+ LCD_SERIAL.write('\r');
+ LCD_SERIAL.write('\n');
+}
+
+static void send(const char *str) {
+ LCD_SERIAL.print(str);
+}
+
+static void sendLine(const char *str) {
+ send(str);
+ sendNewLine();
+}
+
+static void send_P(PGM_P str) {
+ while (const char c = pgm_read_byte(str++))
+ LCD_SERIAL.write(c);
+}
+
+static void sendLine_P(PGM_P str) {
+ send_P(str);
+ sendNewLine();
+}
+
+AnycubicTFTClass::AnycubicTFTClass() {}
+
+void AnycubicTFTClass::OnSetup() {
+ #ifndef LCD_BAUDRATE
+ #define LCD_BAUDRATE 115200
+ #endif
+ LCD_SERIAL.begin(LCD_BAUDRATE);
+
+ SENDLINE_DBG_PGM("J17", "TFT Serial Debug: Main board reset... J17"); // J17 Main board reset
+ ExtUI::delay_ms(10);
+
+ // initialise the state of the key pins running on the tft
+ #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
+ SET_INPUT_PULLUP(SD_DETECT_PIN);
+ #endif
+ #if ENABLED(FILAMENT_RUNOUT_SENSOR)
+ SET_INPUT_PULLUP(FIL_RUNOUT1_PIN);
+ #endif
+
+ mediaPrintingState = AMPRINTSTATE_NOT_PRINTING;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+
+ // DoSDCardStateCheck();
+ SENDLINE_DBG_PGM("J12", "TFT Serial Debug: Ready... J12"); // J12 Ready
+ ExtUI::delay_ms(10);
+
+ DoFilamentRunoutCheck();
+ SelectedFile[0] = 0;
+
+ #if ENABLED(STARTUP_CHIME)
+ ExtUI::injectCommands_P(PSTR("M300 P250 S554\nM300 P250 S554\nM300 P250 S740\nM300 P250 S554\nM300 P250 S740\nM300 P250 S554\nM300 P500 S831"));
+ #endif
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOLNPGM("TFT Serial Debug: Finished startup");
+ #endif
+}
+
+void AnycubicTFTClass::OnCommandScan() {
+ static millis_t nextStopCheck = 0; // used to slow the stopped print check down to reasonable times
+ const millis_t ms = millis();
+ if (ELAPSED(ms, nextStopCheck)) {
+ nextStopCheck = ms + 1000UL;
+ if (mediaPrintingState == AMPRINTSTATE_STOP_REQUESTED && IsNozzleHomed()) {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOLNPGM("TFT Serial Debug: Finished stopping print, releasing motors ...");
+ #endif
+ mediaPrintingState = AMPRINTSTATE_NOT_PRINTING;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+ ExtUI::injectCommands_P(PSTR("M84\nM27")); // disable stepper motors and force report of SD status
+ ExtUI::delay_ms(200);
+ // tell printer to release resources of print to indicate it is done
+ SENDLINE_DBG_PGM("J14", "TFT Serial Debug: SD Print Stopped... J14");
+ }
+ }
+
+ if (TFTbuflen < (TFTBUFSIZE - 1))
+ GetCommandFromTFT();
+
+ if (TFTbuflen) {
+ TFTbuflen = (TFTbuflen - 1);
+ TFTbufindr = (TFTbufindr + 1) % TFTBUFSIZE;
+ }
+}
+
+void AnycubicTFTClass::OnKillTFT() {
+ SENDLINE_DBG_PGM("J11", "TFT Serial Debug: Kill command... J11");
+}
+
+void AnycubicTFTClass::OnSDCardStateChange(bool isInserted) {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOPGM("TFT Serial Debug: OnSDCardStateChange event triggered...");
+ SERIAL_ECHO(ui8tostr2(isInserted));
+ SERIAL_EOL();
+ #endif
+ DoSDCardStateCheck();
+}
+
+void AnycubicTFTClass::OnSDCardError() {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOLNPGM("TFT Serial Debug: OnSDCardError event triggered...");
+ #endif
+ SENDLINE_DBG_PGM("J21", "TFT Serial Debug: On SD Card Error ... J21");
+}
+
+void AnycubicTFTClass::OnFilamentRunout() {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOLNPGM("TFT Serial Debug: FilamentRunout triggered...");
+ #endif
+ DoFilamentRunoutCheck();
+}
+
+void AnycubicTFTClass::OnUserConfirmRequired(const char * const msg) {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOPGM("TFT Serial Debug: OnUserConfirmRequired triggered... ");
+ SERIAL_ECHOLN(msg);
+ #endif
+
+ #if ENABLED(SDSUPPORT)
+ /**
+ * Need to handle the process of following states
+ * "Nozzle Parked"
+ * "Load Filament"
+ * "Filament Purging..."
+ * "HeaterTimeout"
+ * "Reheat finished."
+ *
+ * NOTE: The only way to handle these states is strcmp_P with the msg unfortunately (very expensive)
+ */
+ if (strcmp_P(msg, PSTR("Nozzle Parked")) == 0) {
+ mediaPrintingState = AMPRINTSTATE_PAUSED;
+ mediaPauseState = AMPAUSESTATE_PARKED;
+ // enable continue button
+ SENDLINE_DBG_PGM("J18", "TFT Serial Debug: UserConfirm SD print paused done... J18");
+ }
+ else if (strcmp_P(msg, PSTR("Load Filament")) == 0) {
+ mediaPrintingState = AMPRINTSTATE_PAUSED;
+ mediaPauseState = AMPAUSESTATE_FILAMENT_OUT;
+ // enable continue button
+ SENDLINE_DBG_PGM("J18", "TFT Serial Debug: UserConfirm Filament is out... J18");
+ SENDLINE_DBG_PGM("J23", "TFT Serial Debug: UserConfirm Blocking filament prompt... J23");
+ }
+ else if (strcmp_P(msg, PSTR("Filament Purging...")) == 0) {
+ mediaPrintingState = AMPRINTSTATE_PAUSED;
+ mediaPauseState = AMPAUSESTATE_PARKING;
+ // TODO: JBA I don't think J05 just disables the continue button, i think it injects a rogue M25. So taking this out
+ // disable continue button
+ // SENDLINE_DBG_PGM("J05", "TFT Serial Debug: UserConfirm SD Filament Purging... J05"); // J05 printing pause
+
+ // enable continue button
+ SENDLINE_DBG_PGM("J18", "TFT Serial Debug: UserConfirm Filament is purging... J18");
+ }
+ else if (strcmp_P(msg, PSTR("HeaterTimeout")) == 0) {
+ mediaPrintingState = AMPRINTSTATE_PAUSED;
+ mediaPauseState = AMPAUSESTATE_HEATER_TIMEOUT;
+ // enable continue button
+ SENDLINE_DBG_PGM("J18", "TFT Serial Debug: UserConfirm SD Heater timeout... J18");
+ }
+ else if (strcmp_P(msg, PSTR("Reheat finished.")) == 0) {
+ mediaPrintingState = AMPRINTSTATE_PAUSED;
+ mediaPauseState = AMPAUSESTATE_REHEAT_FINISHED;
+ // enable continue button
+ SENDLINE_DBG_PGM("J18", "TFT Serial Debug: UserConfirm SD Reheat done... J18");
+ }
+ #endif
+}
+
+float AnycubicTFTClass::CodeValue() {
+ return (strtod(&TFTcmdbuffer[TFTbufindr][TFTstrchr_pointer - TFTcmdbuffer[TFTbufindr] + 1], nullptr));
+}
+
+bool AnycubicTFTClass::CodeSeen(char code) {
+ TFTstrchr_pointer = strchr(TFTcmdbuffer[TFTbufindr], code);
+ return !!TFTstrchr_pointer; // Return True if a character was found
+}
+
+bool AnycubicTFTClass::IsNozzleHomed() {
+ const float xPosition = ExtUI::getAxisPosition_mm((ExtUI::axis_t) ExtUI::X);
+ const float yPosition = ExtUI::getAxisPosition_mm((ExtUI::axis_t) ExtUI::Y);
+ return WITHIN(xPosition, X_MIN_POS - 0.1, X_MIN_POS + 0.1) &&
+ WITHIN(yPosition, Y_MIN_POS - 0.1, Y_MIN_POS + 0.1);
+}
+
+void AnycubicTFTClass::HandleSpecialMenu() {
+ /**
+ * NOTE: that the file selection command actual lowercases the entire selected file/foldername, so charracter comparisons need to be lowercase.
+ */
+ if (SelectedDirectory[0] == '<') {
+ switch (SelectedDirectory[1]) {
+ case 'e': // ""
+ SpecialMenu = false;
+ return;
+ break;
+
+ #if ENABLED(PROBE_MANUALLY)
+ case '0':
+ switch (SelectedDirectory[2]) {
+ case '1': // "<01ZUp0.1>"
+ SERIAL_ECHOLNPGM("Special Menu: Z Up 0.1");
+ ExtUI::injectCommands_P(PSTR("G91\nG1 Z+0.1\nG90"));
+ break;
+
+ case '2': // "<02ZUp0.02>"
+ SERIAL_ECHOLNPGM("Special Menu: Z Up 0.02");
+ ExtUI::injectCommands_P(PSTR("G91\nG1 Z+0.02\nG90"));
+ break;
+
+ case '3': // "<03ZDn0.02>"
+ SERIAL_ECHOLNPGM("Special Menu: Z Down 0.02");
+ ExtUI::injectCommands_P(PSTR("G91\nG1 Z-0.02\nG90"));
+ break;
+
+ case '4': // "<04ZDn0.1>"
+ SERIAL_ECHOLNPGM("Special Menu: Z Down 0.1");
+ ExtUI::injectCommands_P(PSTR("G91\nG1 Z-0.1\nG90"));
+ break;
+
+ case '5': // "<05PrehtBed>"
+ SERIAL_ECHOLNPGM("Special Menu: Preheat Bed");
+ ExtUI::injectCommands_P(PSTR("M140 S65"));
+ break;
+
+ case '6': // "<06SMeshLvl>"
+ SERIAL_ECHOLNPGM("Special Menu: Start Mesh Leveling");
+ ExtUI::injectCommands_P(PSTR("G29S1"));
+ break;
+
+ case '7': // "<07MeshNPnt>"
+ SERIAL_ECHOLNPGM("Special Menu: Next Mesh Point");
+ ExtUI::injectCommands_P(PSTR("G29S2"));
+ break;
+
+ case '8': // "<08HtEndPID>"
+ SERIAL_ECHOLNPGM("Special Menu: Auto Tune Hotend PID");
+ // need to dwell for half a second to give the fan a chance to start before the pid tuning starts
+ ExtUI::injectCommands_P(PSTR("M106 S204\nG4 P500\nM303 E0 S215 C15 U1"));
+ break;
+
+ case '9': // "<09HtBedPID>"
+ SERIAL_ECHOLNPGM("Special Menu: Auto Tune Hotbed Pid");
+ ExtUI::injectCommands_P(PSTR("M303 E-1 S65 C6 U1"));
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case '1':
+ switch (SelectedDirectory[2]) {
+ case '0': // "<10FWDeflts>"
+ SERIAL_ECHOLNPGM("Special Menu: Load FW Defaults");
+ ExtUI::injectCommands_P(PSTR("M502\nM300 P105 S1661\nM300 P210 S1108"));
+ break;
+
+ case '1': // "<11SvEEPROM>"
+ SERIAL_ECHOLNPGM("Special Menu: Save EEPROM");
+ ExtUI::injectCommands_P(PSTR("M500\nM300 P105 S1108\nM300 P210 S1661"));
+ break;
+
+ default:
+ break;
+ }
+ break;
+ #else // if ENABLED(PROBE_MANUALLY)
+ case '0':
+ switch (SelectedDirectory[2]) {
+ case '1': // "<01PrehtBed>"
+ SERIAL_ECHOLNPGM("Special Menu: Preheat Bed");
+ ExtUI::injectCommands_P(PSTR("M140 S65"));
+ break;
+
+ case '2': // "<02ABL>"
+ SERIAL_ECHOLNPGM("Special Menu: Auto Bed Leveling");
+ ExtUI::injectCommands_P(PSTR("G29N"));
+ break;
+
+ case '3': // "<03HtendPID>"
+ SERIAL_ECHOLNPGM("Special Menu: Auto Tune Hotend PID");
+ // need to dwell for half a second to give the fan a chance to start before the pid tuning starts
+ ExtUI::injectCommands_P(PSTR("M106 S204\nG4 P500\nM303 E0 S215 C15 U1"));
+ break;
+
+ case '4': // "<04HtbedPID>"
+ SERIAL_ECHOLNPGM("Special Menu: Auto Tune Hotbed Pid");
+ ExtUI::injectCommands_P(PSTR("M303 E-1 S65 C6 U1"));
+ break;
+
+ case '5': // "<05FWDeflts>"
+ SERIAL_ECHOLNPGM("Special Menu: Load FW Defaults");
+ ExtUI::injectCommands_P(PSTR("M502\nM300 P105 S1661\nM300 P210 S1108"));
+ break;
+
+ case '6': // "<06SvEEPROM>"
+ SERIAL_ECHOLNPGM("Special Menu: Save EEPROM");
+ ExtUI::injectCommands_P(PSTR("M500\nM300 P105 S1108\nM300 P210 S1661"));
+ break;
+
+ case '7': // <07SendM108>
+ SERIAL_ECHOLNPGM("Special Menu: Send User Confirmation");
+ ExtUI::injectCommands_P(PSTR("M108"));
+ break;
+
+ default:
+ break;
+ }
+ break;
+ #endif // PROBE_MANUALLY
+
+ default:
+ break;
+ }
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ }
+ else {
+ SERIAL_ECHOPGM("TFT Serial Debug: Attempted to HandleSpecialMenu on non-special menu... ");
+ SERIAL_ECHOLN(SelectedDirectory);
+ #endif
+ }
+}
+
+void AnycubicTFTClass::RenderCurrentFileList() {
+ #if ENABLED(SDSUPPORT)
+ uint16_t selectedNumber = 0;
+ SelectedDirectory[0] = 0;
+ SelectedFile[0] = 0;
+ ExtUI::FileList currentFileList;
+
+ SENDLINE_PGM("FN "); // Filelist start
+
+ if (!ExtUI::isMediaInserted() && !SpecialMenu) {
+ SENDLINE_DBG_PGM("J02", "TFT Serial Debug: No SD Card mounted to render Current File List... J02");
+
+ SENDLINE_PGM("");
+ SENDLINE_PGM("");
+ }
+ else {
+ if (CodeSeen('S'))
+ selectedNumber = CodeValue();
+
+ if (SpecialMenu)
+ RenderSpecialMenu(selectedNumber);
+ else if (selectedNumber <= currentFileList.count())
+ RenderCurrentFolder(selectedNumber);
+ }
+ SENDLINE_PGM("END"); // Filelist stop
+ #endif // SDSUPPORT
+}
+
+void AnycubicTFTClass::RenderSpecialMenu(uint16_t selectedNumber) {
+ switch (selectedNumber) {
+ #if ENABLED(PROBE_MANUALLY)
+ case 0: // First Page
+ SENDLINE_PGM("<01ZUp0.1>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<02ZUp0.02>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<03ZDn0.02>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<04ZDn0.1>");
+ SENDLINE_PGM("");
+ break;
+
+ case 4: // Second Page
+ SENDLINE_PGM("<05PrehtBed>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<06SMeshLvl>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<07MeshNPnt>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<08HtEndPID>");
+ SENDLINE_PGM("");
+ break;
+
+ case 8: // Third Page
+ SENDLINE_PGM("<09HtBedPID>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<10FWDeflts>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<11SvEEPROM>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("");
+ break;
+ #else
+ case 0: // First Page
+ SENDLINE_PGM("<01PrehtBed>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<02ABL>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<03HtEndPID>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<04HtBedPID>");
+ SENDLINE_PGM("");
+ break;
+
+ case 4: // Second Page
+ SENDLINE_PGM("<05FWDeflts>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<06SvEEPROM>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("<07SendM108>");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("");
+ SENDLINE_PGM("");
+ break;
+
+ #endif // PROBE_MANUALLY
+
+ default:
+ break;
+ }
+}
+
+void AnycubicTFTClass::RenderCurrentFolder(uint16_t selectedNumber) {
+ ExtUI::FileList currentFileList;
+ uint16_t cnt = selectedNumber;
+ uint16_t max_files;
+ uint16_t dir_files = currentFileList.count();
+
+ if ((dir_files - selectedNumber) < 4)
+ max_files = dir_files;
+ else
+ max_files = selectedNumber + 3;
+
+ for (cnt = selectedNumber; cnt <= max_files; cnt++) {
+ if (cnt == 0) { // Special Entry
+ if (currentFileList.isAtRootDir()) {
+ SENDLINE_PGM("");
+ SENDLINE_PGM("");
+ }
+ else {
+ SENDLINE_PGM("/..");
+ SENDLINE_PGM("/..");
+ }
+ }
+ else {
+ currentFileList.seek(cnt - 1, false);
+
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOLN(currentFileList.filename());
+ #endif
+ if (currentFileList.isDir()) {
+ SEND_PGM("/");
+ SENDLINE(currentFileList.shortFilename());
+ SEND_PGM("/");
+ SENDLINE(currentFileList.filename());
+
+ }
+ else {
+ SENDLINE(currentFileList.shortFilename());
+ SENDLINE(currentFileList.filename());
+ }
+ }
+ }
+}
+
+void AnycubicTFTClass::OnPrintTimerStarted() {
+ #if ENABLED(SDSUPPORT)
+ if (mediaPrintingState == AMPRINTSTATE_PRINTING)
+ SENDLINE_DBG_PGM("J04", "TFT Serial Debug: Starting SD Print... J04"); // J04 Starting Print
+
+ #endif
+}
+
+void AnycubicTFTClass::OnPrintTimerPaused() {
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isPrintingFromMedia()) {
+ mediaPrintingState = AMPRINTSTATE_PAUSED;
+ mediaPauseState = AMPAUSESTATE_PARKING;
+ }
+ #endif
+}
+
+void AnycubicTFTClass::OnPrintTimerStopped() {
+ #if ENABLED(SDSUPPORT)
+ if (mediaPrintingState == AMPRINTSTATE_PRINTING) {
+ mediaPrintingState = AMPRINTSTATE_NOT_PRINTING;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+ SENDLINE_DBG_PGM("J14", "TFT Serial Debug: SD Print Completed... J14");
+ }
+ // otherwise it was stopped by the printer so don't send print completed signal to TFT
+ #endif
+}
+
+void AnycubicTFTClass::GetCommandFromTFT() {
+ char *starpos = nullptr;
+ while (LCD_SERIAL.available() > 0 && TFTbuflen < TFTBUFSIZE) {
+ serial3_char = LCD_SERIAL.read();
+ if (serial3_char == '\n' ||
+ serial3_char == '\r' ||
+ serial3_char == ':' ||
+ serial3_count >= (TFT_MAX_CMD_SIZE - 1)
+ ) {
+
+ if (!serial3_count) return; // if empty line
+
+ TFTcmdbuffer[TFTbufindw][serial3_count] = 0; // terminate string
+
+ if ((strchr(TFTcmdbuffer[TFTbufindw], 'A') != nullptr)) {
+ int16_t a_command;
+ TFTstrchr_pointer = strchr(TFTcmdbuffer[TFTbufindw], 'A');
+ a_command = ((int)((strtod(&TFTcmdbuffer[TFTbufindw][TFTstrchr_pointer - TFTcmdbuffer[TFTbufindw] + 1], nullptr))));
+
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ if ((a_command > 7) && (a_command != 20)) { // No debugging of status polls, please!
+ SERIAL_ECHOPGM("TFT Serial Command: ");
+ SERIAL_ECHOLN(TFTcmdbuffer[TFTbufindw]);
+ }
+ #endif
+
+ switch (a_command) {
+ case 0: { // A0 GET HOTEND TEMP
+ float hotendActualTemp = ExtUI::getActualTemp_celsius((ExtUI::extruder_t) (ExtUI::extruder_t) ExtUI::E0);
+ SEND_PGM_VAL("A0V ", int(hotendActualTemp + 0.5));
+ }
+ break;
+
+ case 1: { // A1 GET HOTEND TARGET TEMP
+ float hotendTargetTemp = ExtUI::getTargetTemp_celsius((ExtUI::extruder_t) (ExtUI::extruder_t) ExtUI::E0);
+ SEND_PGM_VAL("A1V ", int(hotendTargetTemp + 0.5));
+ }
+ break;
+
+ case 2: { // A2 GET HOTBED TEMP
+ float heatedBedActualTemp = ExtUI::getActualTemp_celsius((ExtUI::heater_t) ExtUI::BED);
+ SEND_PGM_VAL("A2V ", int(heatedBedActualTemp + 0.5));
+ }
+ break;
+
+ case 3: { // A3 GET HOTBED TARGET TEMP
+ float heatedBedTargetTemp = ExtUI::getTargetTemp_celsius((ExtUI::heater_t) ExtUI::BED);
+ SEND_PGM_VAL("A3V ", int(heatedBedTargetTemp + 0.5));
+ } break;
+
+ case 4: { // A4 GET FAN SPEED
+ float fanPercent = ExtUI::getActualFan_percent(ExtUI::FAN0);
+ fanPercent = constrain(fanPercent, 0, 100);
+ SEND_PGM_VAL("A4V ", int(fanPercent));
+ } break;
+
+ case 5: { // A5 GET CURRENT COORDINATE
+ const float xPosition = ExtUI::getAxisPosition_mm(ExtUI::X),
+ yPosition = ExtUI::getAxisPosition_mm(ExtUI::Y),
+ zPosition = ExtUI::getAxisPosition_mm(ExtUI::Z);
+ SEND_PGM("A5V X: "); LCD_SERIAL.print(xPosition);
+ SEND_PGM( " Y: "); LCD_SERIAL.print(yPosition);
+ SEND_PGM( " Z: "); LCD_SERIAL.print(zPosition);
+ SENDLINE_PGM("");
+ } break;
+
+ case 6: // A6 GET SD CARD PRINTING STATUS
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isPrintingFromMedia()) {
+ SEND_PGM("A6V ");
+ if (ExtUI::isMediaInserted())
+ SENDLINE(ui8tostr3rj(ExtUI::getProgress_percent()));
+ else
+ SENDLINE_DBG_PGM("J02", "TFT Serial Debug: No SD Card mounted to return printing status... J02");
+ }
+ else
+ SENDLINE_PGM("A6V ---");
+ #endif
+ break;
+
+ case 7: { // A7 GET PRINTING TIME
+ const uint32_t elapsedSeconds = ExtUI::getProgress_seconds_elapsed();
+ SEND_PGM("A7V ");
+ if (elapsedSeconds != 0) { // print time
+ const uint32_t elapsedMinutes = elapsedSeconds / 60;
+ SEND(ui8tostr2(elapsedMinutes / 60));
+ SEND_PGM(" H ");
+ SEND(ui8tostr2(elapsedMinutes % 60));
+ SENDLINE_PGM(" M");
+ }
+ else
+ SENDLINE_PGM(" 999:999");
+ }
+ break;
+
+ case 8: // A8 GET SD LIST
+ #if ENABLED(SDSUPPORT)
+ SelectedFile[0] = 0;
+ RenderCurrentFileList();
+ #endif
+ break;
+
+ case 9: // A9 pause sd print
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isPrintingFromMedia())
+ PausePrint();
+ #endif
+ break;
+
+ case 10: // A10 resume sd print
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isPrintingFromMediaPaused())
+ ResumePrint();
+ #endif
+ break;
+
+ case 11: // A11 STOP SD PRINT
+ TERN_(SDSUPPORT, StopPrint());
+ break;
+
+ case 12: // A12 kill
+ kill(PSTR(STR_ERR_KILLED));
+ break;
+
+ case 13: // A13 SELECTION FILE
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isMediaInserted()) {
+ starpos = (strchr(TFTstrchr_pointer + 4, '*'));
+ if (TFTstrchr_pointer[4] == '/') {
+ strcpy(SelectedDirectory, TFTstrchr_pointer + 5);
+ SelectedFile[0] = 0;
+ SENDLINE_DBG_PGM("J21", "TFT Serial Debug: Clear file selection... J21 "); // J21 Not File Selected
+ SENDLINE_PGM("");
+ }
+ else if (TFTstrchr_pointer[4] == '<') {
+ strcpy(SelectedDirectory, TFTstrchr_pointer + 4);
+ SpecialMenu = true;
+ SelectedFile[0] = 0;
+ SENDLINE_DBG_PGM("J21", "TFT Serial Debug: Clear file selection... J21 "); // J21 Not File Selected
+ SENDLINE_PGM("");
+ }
+ else {
+ SelectedDirectory[0] = 0;
+
+ if (starpos) *(starpos - 1) = '\0';
+
+ strcpy(SelectedFile, TFTstrchr_pointer + 4);
+ SENDLINE_DBG_PGM_VAL("J20", "TFT Serial Debug: File Selected... J20 ", SelectedFile); // J20 File Selected
+ }
+ }
+ #endif
+ break;
+
+ case 14: // A14 START PRINTING
+ #if ENABLED(SDSUPPORT)
+ if (!ExtUI::isPrinting() && strlen(SelectedFile) > 0)
+ StartPrint();
+ #endif
+ break;
+
+ case 15: // A15 RESUMING FROM OUTAGE
+ // TODO: JBA implement resume form outage
+ break;
+
+ case 16: { // A16 set hotend temp
+ unsigned int tempvalue;
+ if (CodeSeen('S')) {
+ tempvalue = constrain(CodeValue(), 0, 275);
+ ExtUI::setTargetTemp_celsius(tempvalue, (ExtUI::extruder_t) ExtUI::E0);
+ }
+ else if (CodeSeen('C') && !ExtUI::isPrinting()) {
+ if (ExtUI::getAxisPosition_mm(ExtUI::Z) < 10)
+ ExtUI::injectCommands_P(PSTR("G1 Z10")); // RASE Z AXIS
+ tempvalue = constrain(CodeValue(), 0, 275);
+ ExtUI::setTargetTemp_celsius(tempvalue, (ExtUI::extruder_t) ExtUI::E0);
+ }
+ }
+ break;
+
+ case 17: { // A17 set heated bed temp
+ unsigned int tempbed;
+ if (CodeSeen('S')) {
+ tempbed = constrain(CodeValue(), 0, 100);
+ ExtUI::setTargetTemp_celsius(tempbed, (ExtUI::heater_t)ExtUI::BED);
+ }
+ }
+ break;
+
+ case 18: { // A18 set fan speed
+ float fanPercent;
+ if (CodeSeen('S')) {
+ fanPercent = CodeValue();
+ fanPercent = constrain(fanPercent, 0, 100);
+ ExtUI::setTargetFan_percent(fanPercent, ExtUI::FAN0);
+ }
+ else
+ fanPercent = 100;
+
+ ExtUI::setTargetFan_percent(fanPercent, ExtUI::FAN0);
+ SENDLINE_PGM("");
+ }
+ break;
+
+ case 19: // A19 stop stepper drivers - sent on stop extrude command and on turn motors off command
+ if (!ExtUI::isPrinting()) {
+ quickstop_stepper();
+ disable_all_steppers();
+ }
+
+ SENDLINE_PGM("");
+ break;
+
+ case 20: // A20 read printing speed
+ if (CodeSeen('S'))
+ feedrate_percentage = constrain(CodeValue(), 40, 999);
+ else
+ SEND_PGM_VAL("A20V ", feedrate_percentage);
+ break;
+
+ case 21: // A21 all home
+ if (!ExtUI::isPrinting() && !ExtUI::isPrintingFromMediaPaused()) {
+ if (CodeSeen('X') || CodeSeen('Y') || CodeSeen('Z')) {
+ if (CodeSeen('X'))
+ ExtUI::injectCommands_P(PSTR("G28X"));
+ if (CodeSeen('Y'))
+ ExtUI::injectCommands_P(PSTR("G28Y"));
+ if (CodeSeen('Z'))
+ ExtUI::injectCommands_P(PSTR("G28Z"));
+ }
+ else if (CodeSeen('C')) {
+ ExtUI::injectCommands_P(G28_STR);
+ }
+ }
+ break;
+
+ case 22: // A22 move X/Y/Z or extrude
+ if (!ExtUI::isPrinting()) {
+ float coorvalue;
+ unsigned int movespeed = 0;
+ char commandStr[30];
+ char fullCommandStr[38];
+
+ commandStr[0] = 0; // empty string
+ if (CodeSeen('F')) // Set feedrate
+ movespeed = CodeValue();
+
+ if (CodeSeen('X')) { // Move in X direction
+ coorvalue = CodeValue();
+ if ((coorvalue <= 0.2) && coorvalue > 0)
+ sprintf_P(commandStr, PSTR("G1 X0.1F%i"), movespeed);
+ else if ((coorvalue <= -0.1) && coorvalue > -1)
+ sprintf_P(commandStr, PSTR("G1 X-0.1F%i"), movespeed);
+ else
+ sprintf_P(commandStr, PSTR("G1 X%iF%i"), int(coorvalue), movespeed);
+ }
+ else if (CodeSeen('Y')) { // Move in Y direction
+ coorvalue = CodeValue();
+ if ((coorvalue <= 0.2) && coorvalue > 0)
+ sprintf_P(commandStr, PSTR("G1 Y0.1F%i"), movespeed);
+ else if ((coorvalue <= -0.1) && coorvalue > -1)
+ sprintf_P(commandStr, PSTR("G1 Y-0.1F%i"), movespeed);
+ else
+ sprintf_P(commandStr, PSTR("G1 Y%iF%i"), int(coorvalue), movespeed);
+ }
+ else if (CodeSeen('Z')) { // Move in Z direction
+ coorvalue = CodeValue();
+ if ((coorvalue <= 0.2) && coorvalue > 0)
+ sprintf_P(commandStr, PSTR("G1 Z0.1F%i"), movespeed);
+ else if ((coorvalue <= -0.1) && coorvalue > -1)
+ sprintf_P(commandStr, PSTR("G1 Z-0.1F%i"), movespeed);
+ else
+ sprintf_P(commandStr, PSTR("G1 Z%iF%i"), int(coorvalue), movespeed);
+ }
+ else if (CodeSeen('E')) { // Extrude
+ coorvalue = CodeValue();
+ if ((coorvalue <= 0.2) && coorvalue > 0)
+ sprintf_P(commandStr, PSTR("G1 E0.1F%i"), movespeed);
+ else if ((coorvalue <= -0.1) && coorvalue > -1)
+ sprintf_P(commandStr, PSTR("G1 E-0.1F%i"), movespeed);
+ else
+ sprintf_P(commandStr, PSTR("G1 E%iF500"), int(coorvalue));
+ }
+
+ if (strlen(commandStr) > 0) {
+ sprintf_P(fullCommandStr, PSTR("G91\n%s\nG90"), commandStr);
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOPGM("TFT Serial Debug: A22 Move final request with gcode... ");
+ SERIAL_ECHOLN(fullCommandStr);
+ #endif
+ ExtUI::injectCommands(fullCommandStr);
+ }
+ }
+ SENDLINE_PGM("");
+ break;
+
+ case 23: // A23 preheat pla
+ if (!ExtUI::isPrinting()) {
+ if (ExtUI::getAxisPosition_mm(ExtUI::Z) < 10)
+ ExtUI::injectCommands_P(PSTR("G1 Z10")); // RASE Z AXIS
+
+ ExtUI::setTargetTemp_celsius(PREHEAT_1_TEMP_BED, (ExtUI::heater_t) ExtUI::BED);
+ ExtUI::setTargetTemp_celsius(PREHEAT_1_TEMP_HOTEND, (ExtUI::extruder_t) ExtUI::E0);
+ SENDLINE_PGM("OK");
+ }
+ break;
+
+ case 24:// A24 preheat abs
+ if (!ExtUI::isPrinting()) {
+ if (ExtUI::getAxisPosition_mm(ExtUI::Z) < 10)
+ ExtUI::injectCommands_P(PSTR("G1 Z10")); // RASE Z AXIS
+
+ ExtUI::setTargetTemp_celsius(PREHEAT_2_TEMP_BED, (ExtUI::heater_t) ExtUI::BED);
+ ExtUI::setTargetTemp_celsius(PREHEAT_2_TEMP_HOTEND, (ExtUI::extruder_t) ExtUI::E0);
+ SENDLINE_PGM("OK");
+ }
+ break;
+
+ case 25: // A25 cool down
+ if (!ExtUI::isPrinting()) {
+ ExtUI::setTargetTemp_celsius(0, (ExtUI::heater_t) ExtUI::BED);
+ ExtUI::setTargetTemp_celsius(0, (ExtUI::extruder_t) ExtUI::E0);
+
+ SENDLINE_DBG_PGM("J12", "TFT Serial Debug: Cooling down... J12"); // J12 cool down
+ }
+ break;
+
+ case 26: // A26 refresh SD
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isMediaInserted()) {
+ if (strlen(SelectedDirectory) > 0) {
+ ExtUI::FileList currentFileList;
+ if ((SelectedDirectory[0] == '.') && (SelectedDirectory[1] == '.')) {
+ currentFileList.upDir();
+ }
+ else {
+ if (SelectedDirectory[0] == '<')
+ HandleSpecialMenu();
+ else
+ currentFileList.changeDir(SelectedDirectory);
+ }
+ }
+ }
+ else {
+ SENDLINE_DBG_PGM("J02", "TFT Serial Debug: No SD Card mounted to refresh SD A26... J02");
+ }
+
+ SelectedDirectory[0] = 0;
+ #endif
+ break;
+
+ #if ENABLED(SERVO_ENDSTOPS)
+ case 27: break; // A27 servos angles adjust
+ #endif
+
+ case 28: // A28 filament test
+ if (CodeSeen('O'))
+ NOOP;
+ else if (CodeSeen('C'))
+ NOOP;
+ SENDLINE_PGM("");
+ break;
+
+ case 33: // A33 get version info
+ SEND_PGM("J33 ");
+ SENDLINE_PGM(DETAILED_BUILD_VERSION);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ TFTbufindw = (TFTbufindw + 1) % TFTBUFSIZE;
+ TFTbuflen += 1;
+ serial3_count = 0; // clear buffer
+ }
+ else {
+ TFTcmdbuffer[TFTbufindw][serial3_count++] = serial3_char;
+ }
+ }
+}
+
+void AnycubicTFTClass::DoSDCardStateCheck() {
+ #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
+ bool isInserted = ExtUI::isMediaInserted();
+ if (isInserted)
+ SENDLINE_DBG_PGM("J00", "TFT Serial Debug: SD card state changed... isInserted");
+ else
+ SENDLINE_DBG_PGM("J01", "TFT Serial Debug: SD card state changed... !isInserted");
+
+ #endif
+}
+
+void AnycubicTFTClass::DoFilamentRunoutCheck() {
+ #if ENABLED(FILAMENT_RUNOUT_SENSOR)
+ // NOTE: ExtUI::getFilamentRunoutState() only returns the runout state if the job is printing
+ // we want to actually check the status of the pin here, regardless of printstate
+ if (READ(FIL_RUNOUT1_PIN)) {
+ if (mediaPrintingState == AMPRINTSTATE_PRINTING || mediaPrintingState == AMPRINTSTATE_PAUSED || mediaPrintingState == AMPRINTSTATE_PAUSE_REQUESTED) {
+ // play tone to indicate filament is out
+ ExtUI::injectCommands_P(PSTR("\nM300 P200 S1567\nM300 P200 S1174\nM300 P200 S1567\nM300 P200 S1174\nM300 P2000 S1567"));
+
+ // tell the user that the filament has run out and wait
+ SENDLINE_DBG_PGM("J23", "TFT Serial Debug: Blocking filament prompt... J23");
+ }
+ else {
+ SENDLINE_DBG_PGM("J15", "TFT Serial Debug: Non blocking filament runout... J15");
+ }
+ }
+ #endif // FILAMENT_RUNOUT_SENSOR
+}
+
+void AnycubicTFTClass::StartPrint() {
+ #if ENABLED(SDSUPPORT)
+ if (!ExtUI::isPrinting() && strlen(SelectedFile) > 0) {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOPGM("TFT Serial Debug: About to print file ... ");
+ SERIAL_ECHO(ExtUI::isPrinting());
+ SERIAL_ECHOPGM(" ");
+ SERIAL_ECHOLN(SelectedFile);
+ #endif
+ mediaPrintingState = AMPRINTSTATE_PRINTING;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+ ExtUI::printFile(SelectedFile);
+ }
+ #endif // SDUPPORT
+}
+
+void AnycubicTFTClass::PausePrint() {
+ #if ENABLED(SDSUPPORT)
+ if (ExtUI::isPrintingFromMedia() && mediaPrintingState != AMPRINTSTATE_STOP_REQUESTED && mediaPauseState == AMPAUSESTATE_NOT_PAUSED) {
+ mediaPrintingState = AMPRINTSTATE_PAUSE_REQUESTED;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED; // need the userconfirm method to update pause state
+ SENDLINE_DBG_PGM("J05", "TFT Serial Debug: SD print pause started... J05"); // J05 printing pause
+
+ // for some reason pausing the print doesn't retract the extruder so force a manual one here
+ ExtUI::injectCommands_P(PSTR("G91\nG1 E-2 F1800\nG90"));
+ ExtUI::pausePrint();
+ }
+ #endif
+}
+
+void AnycubicTFTClass::ResumePrint() {
+ #if ENABLED(SDSUPPORT)
+ #if ENABLED(FILAMENT_RUNOUT_SENSOR)
+ if (READ(FIL_RUNOUT1_PIN)) {
+ #if ENABLED(ANYCUBIC_LCD_DEBUG)
+ SERIAL_ECHOLNPGM("TFT Serial Debug: Resume Print with filament sensor still tripped... ");
+ #endif
+
+ // trigger the user message box
+ DoFilamentRunoutCheck();
+
+ // re-enable the continue button
+ SENDLINE_DBG_PGM("J18", "TFT Serial Debug: Resume Print with filament sensor still tripped... J18");
+ return;
+ }
+ #endif
+
+ if (mediaPauseState == AMPAUSESTATE_HEATER_TIMEOUT) {
+ mediaPauseState = AMPAUSESTATE_REHEATING;
+ // TODO: JBA I don't think J05 just disables the continue button, i think it injects a rogue M25. So taking this out
+ // // disable the continue button
+ // SENDLINE_DBG_PGM("J05", "TFT Serial Debug: Resume called with heater timeout... J05"); // J05 printing pause
+
+ // reheat the nozzle
+ ExtUI::setUserConfirmed();
+ }
+ else {
+ mediaPrintingState = AMPRINTSTATE_PRINTING;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+
+ SENDLINE_DBG_PGM("J04", "TFT Serial Debug: SD print resumed... J04"); // J04 printing form sd card now
+ ExtUI::resumePrint();
+ }
+ #endif
+}
+
+void AnycubicTFTClass::StopPrint() {
+ #if ENABLED(SDSUPPORT)
+ mediaPrintingState = AMPRINTSTATE_STOP_REQUESTED;
+ mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+ SENDLINE_DBG_PGM("J16", "TFT Serial Debug: SD print stop called... J16");
+
+ // for some reason stopping the print doesn't retract the extruder so force a manual one here
+ ExtUI::injectCommands_P(PSTR("G91\nG1 E-2 F1800\nG90"));
+ ExtUI::stopPrint();
+ #endif
+}
+
+#endif // ANYCUBIC_LCD_I3MEGA
diff --git a/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h
new file mode 100644
index 0000000..59050ac
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/anycubic_i3mega/anycubic_i3mega_lcd.h
@@ -0,0 +1,97 @@
+/**
+ * anycubic_i3mega_lcd.h --- Support for Anycubic i3 Mega TFT
+ * Created by Christian Hopp on 09.12.17.
+ * Improved by David Ramiro
+ * Converted to ext_iu by John BouAntoun 21 June 2020
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#pragma once
+
+#include "../../../../inc/MarlinConfigPre.h"
+#include "../../../../sd/SdFatConfig.h" // for the FILENAME_LENGTH macro
+
+#define TFTBUFSIZE 4
+#define TFT_MAX_CMD_SIZE 96
+
+enum AnycubicMediaPrintState {
+ AMPRINTSTATE_NOT_PRINTING,
+ AMPRINTSTATE_PRINTING,
+ AMPRINTSTATE_PAUSE_REQUESTED,
+ AMPRINTSTATE_PAUSED,
+ AMPRINTSTATE_STOP_REQUESTED
+};
+
+enum AnycubicMediaPauseState {
+ AMPAUSESTATE_NOT_PAUSED,
+ AMPAUSESTATE_PARKING,
+ AMPAUSESTATE_PARKED,
+ AMPAUSESTATE_FILAMENT_OUT,
+ AMPAUSESTATE_FIAMENT_PRUGING,
+ AMPAUSESTATE_HEATER_TIMEOUT,
+ AMPAUSESTATE_REHEATING,
+ AMPAUSESTATE_REHEAT_FINISHED
+};
+
+class AnycubicTFTClass {
+public:
+ AnycubicTFTClass();
+ void OnSetup();
+ void OnCommandScan();
+ void OnKillTFT();
+ void OnSDCardStateChange(bool);
+ void OnSDCardError();
+ void OnFilamentRunout();
+ void OnUserConfirmRequired(const char *);
+ void OnPrintTimerStarted();
+ void OnPrintTimerPaused();
+ void OnPrintTimerStopped();
+
+private:
+ char TFTcmdbuffer[TFTBUFSIZE][TFT_MAX_CMD_SIZE];
+ int TFTbuflen=0;
+ int TFTbufindr = 0;
+ int TFTbufindw = 0;
+ char serial3_char;
+ int serial3_count = 0;
+ char *TFTstrchr_pointer;
+ uint8_t SpecialMenu = false;
+ AnycubicMediaPrintState mediaPrintingState = AMPRINTSTATE_NOT_PRINTING;
+ AnycubicMediaPauseState mediaPauseState = AMPAUSESTATE_NOT_PAUSED;
+
+ float CodeValue();
+ bool CodeSeen(char);
+ bool IsNozzleHomed();
+ void RenderCurrentFileList();
+ void RenderSpecialMenu(uint16_t);
+ void RenderCurrentFolder(uint16_t);
+ void GetCommandFromTFT();
+ void CheckSDCardChange();
+ void CheckPauseState();
+ void CheckPrintCompletion();
+ void HandleSpecialMenu();
+ void DoSDCardStateCheck();
+ void DoFilamentRunoutCheck();
+ void StartPrint();
+ void PausePrint();
+ void ResumePrint();
+ void StopPrint();
+
+ char SelectedDirectory[30];
+ char SelectedFile[FILENAME_LENGTH];
+};
+
+extern AnycubicTFTClass AnycubicTFT;
+extern const char G28_STR[];
diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.cpp b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.cpp
new file mode 100644
index 0000000..c7cd767
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.cpp
@@ -0,0 +1,261 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/* DGUS implementation written by coldtobi in 2019 for Marlin */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if HAS_DGUS_LCD
+
+#if HOTENDS > 2
+ #error "More than 2 hotends not implemented on the Display UI design."
+#endif
+
+#include "../../ui_api.h"
+
+#include "../../../../MarlinCore.h"
+#include "../../../../module/motion.h"
+#include "../../../../gcode/queue.h"
+#include "../../../../module/planner.h"
+#include "../../../../libs/duration_t.h"
+#include "../../../../module/printcounter.h"
+#if ENABLED(POWER_LOSS_RECOVERY)
+ #include "../../../../feature/powerloss.h"
+#endif
+
+#include "DGUSDisplay.h"
+#include "DGUSVPVariable.h"
+#include "DGUSDisplayDef.h"
+
+// Preamble... 2 Bytes, usually 0x5A 0xA5, but configurable
+constexpr uint8_t DGUS_HEADER1 = 0x5A;
+constexpr uint8_t DGUS_HEADER2 = 0xA5;
+
+constexpr uint8_t DGUS_CMD_WRITEVAR = 0x82;
+constexpr uint8_t DGUS_CMD_READVAR = 0x83;
+
+#if ENABLED(DEBUG_DGUSLCD)
+ bool dguslcd_local_debug; // = false;
+#endif
+
+void DGUSDisplay::InitDisplay() {
+ #ifndef LCD_BAUDRATE
+ #define LCD_BAUDRATE 115200
+ #endif
+ LCD_SERIAL.begin(LCD_BAUDRATE);
+ if (TERN1(POWER_LOSS_RECOVERY, !recovery.valid()))
+ RequestScreen(TERN(SHOW_BOOTSCREEN, DGUSLCD_SCREEN_BOOT, DGUSLCD_SCREEN_MAIN));
+}
+
+void DGUSDisplay::WriteVariable(uint16_t adr, const void* values, uint8_t valueslen, bool isstr) {
+ const char* myvalues = static_cast(values);
+ bool strend = !myvalues;
+ WriteHeader(adr, DGUS_CMD_WRITEVAR, valueslen);
+ while (valueslen--) {
+ char x;
+ if (!strend) x = *myvalues++;
+ if ((isstr && !x) || strend) {
+ strend = true;
+ x = ' ';
+ }
+ LCD_SERIAL.write(x);
+ }
+}
+
+void DGUSDisplay::WriteVariable(uint16_t adr, uint16_t value) {
+ value = (value & 0xffU) << 8U | (value >> 8U);
+ WriteVariable(adr, static_cast(&value), sizeof(uint16_t));
+}
+
+void DGUSDisplay::WriteVariable(uint16_t adr, int16_t value) {
+ value = (value & 0xffU) << 8U | (value >> 8U);
+ WriteVariable(adr, static_cast(&value), sizeof(uint16_t));
+}
+
+void DGUSDisplay::WriteVariable(uint16_t adr, uint8_t value) {
+ WriteVariable(adr, static_cast(&value), sizeof(uint8_t));
+}
+
+void DGUSDisplay::WriteVariable(uint16_t adr, int8_t value) {
+ WriteVariable(adr, static_cast(&value), sizeof(int8_t));
+}
+
+void DGUSDisplay::WriteVariable(uint16_t adr, long value) {
+ union { long l; char lb[4]; } endian;
+ char tmp[4];
+ endian.l = value;
+ tmp[0] = endian.lb[3];
+ tmp[1] = endian.lb[2];
+ tmp[2] = endian.lb[1];
+ tmp[3] = endian.lb[0];
+ WriteVariable(adr, static_cast(&tmp), sizeof(long));
+}
+
+void DGUSDisplay::WriteVariablePGM(uint16_t adr, const void* values, uint8_t valueslen, bool isstr) {
+ const char* myvalues = static_cast(values);
+ bool strend = !myvalues;
+ WriteHeader(adr, DGUS_CMD_WRITEVAR, valueslen);
+ while (valueslen--) {
+ char x;
+ if (!strend) x = pgm_read_byte(myvalues++);
+ if ((isstr && !x) || strend) {
+ strend = true;
+ x = ' ';
+ }
+ LCD_SERIAL.write(x);
+ }
+}
+
+void DGUSDisplay::ProcessRx() {
+
+ #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
+ if (!LCD_SERIAL.available() && LCD_SERIAL.buffer_overruns()) {
+ // Overrun, but reset the flag only when the buffer is empty
+ // We want to extract as many as valid datagrams possible...
+ DEBUG_ECHOPGM("OVFL");
+ rx_datagram_state = DGUS_IDLE;
+ //LCD_SERIAL.reset_rx_overun();
+ LCD_SERIAL.flush();
+ }
+ #endif
+
+ uint8_t receivedbyte;
+ while (LCD_SERIAL.available()) {
+ switch (rx_datagram_state) {
+
+ case DGUS_IDLE: // Waiting for the first header byte
+ receivedbyte = LCD_SERIAL.read();
+ //DEBUG_ECHOPAIR("< ",x);
+ if (DGUS_HEADER1 == receivedbyte) rx_datagram_state = DGUS_HEADER1_SEEN;
+ break;
+
+ case DGUS_HEADER1_SEEN: // Waiting for the second header byte
+ receivedbyte = LCD_SERIAL.read();
+ //DEBUG_ECHOPAIR(" ",x);
+ rx_datagram_state = (DGUS_HEADER2 == receivedbyte) ? DGUS_HEADER2_SEEN : DGUS_IDLE;
+ break;
+
+ case DGUS_HEADER2_SEEN: // Waiting for the length byte
+ rx_datagram_len = LCD_SERIAL.read();
+ DEBUG_ECHOPAIR(" (", rx_datagram_len, ") ");
+
+ // Telegram min len is 3 (command and one word of payload)
+ rx_datagram_state = WITHIN(rx_datagram_len, 3, DGUS_RX_BUFFER_SIZE) ? DGUS_WAIT_TELEGRAM : DGUS_IDLE;
+ break;
+
+ case DGUS_WAIT_TELEGRAM: // wait for complete datagram to arrive.
+ if (LCD_SERIAL.available() < rx_datagram_len) return;
+
+ Initialized = true; // We've talked to it, so we defined it as initialized.
+ uint8_t command = LCD_SERIAL.read();
+
+ DEBUG_ECHOPAIR("# ", command);
+
+ uint8_t readlen = rx_datagram_len - 1; // command is part of len.
+ unsigned char tmp[rx_datagram_len - 1];
+ unsigned char *ptmp = tmp;
+ while (readlen--) {
+ receivedbyte = LCD_SERIAL.read();
+ DEBUG_ECHOPAIR(" ", receivedbyte);
+ *ptmp++ = receivedbyte;
+ }
+ DEBUG_ECHOPGM(" # ");
+ // mostly we'll get this: 5A A5 03 82 4F 4B -- ACK on 0x82, so discard it.
+ if (command == DGUS_CMD_WRITEVAR && 'O' == tmp[0] && 'K' == tmp[1]) {
+ DEBUG_ECHOLNPGM(">");
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ /* AutoUpload, (and answer to) Command 0x83 :
+ | tmp[0 1 2 3 4 ... ]
+ | Example 5A A5 06 83 20 01 01 78 01 ……
+ | / / | | \ / | \ \
+ | Header | | | | \_____\_ DATA (Words!)
+ | DatagramLen / VPAdr |
+ | Command DataLen (in Words) */
+ if (command == DGUS_CMD_READVAR) {
+ const uint16_t vp = tmp[0] << 8 | tmp[1];
+ //const uint8_t dlen = tmp[2] << 1; // Convert to Bytes. (Display works with words)
+ //DEBUG_ECHOPAIR(" vp=", vp, " dlen=", dlen);
+ DGUS_VP_Variable ramcopy;
+ if (populate_VPVar(vp, &ramcopy)) {
+ if (ramcopy.set_by_display_handler)
+ ramcopy.set_by_display_handler(ramcopy, &tmp[3]);
+ else
+ DEBUG_ECHOLNPGM(" VPVar found, no handler.");
+ }
+ else
+ DEBUG_ECHOLNPAIR(" VPVar not found:", vp);
+
+ rx_datagram_state = DGUS_IDLE;
+ break;
+ }
+
+ // discard anything else
+ rx_datagram_state = DGUS_IDLE;
+ }
+ }
+}
+
+size_t DGUSDisplay::GetFreeTxBuffer() { return SERIAL_GET_TX_BUFFER_FREE(); }
+
+void DGUSDisplay::WriteHeader(uint16_t adr, uint8_t cmd, uint8_t payloadlen) {
+ LCD_SERIAL.write(DGUS_HEADER1);
+ LCD_SERIAL.write(DGUS_HEADER2);
+ LCD_SERIAL.write(payloadlen + 3);
+ LCD_SERIAL.write(cmd);
+ LCD_SERIAL.write(adr >> 8);
+ LCD_SERIAL.write(adr & 0xFF);
+}
+
+void DGUSDisplay::WritePGM(const char str[], uint8_t len) {
+ while (len--) LCD_SERIAL.write(pgm_read_byte(str++));
+}
+
+void DGUSDisplay::loop() {
+ // protect against recursion… ProcessRx() may indirectly call idle() when injecting gcode commands.
+ if (!no_reentrance) {
+ no_reentrance = true;
+ ProcessRx();
+ no_reentrance = false;
+ }
+}
+
+rx_datagram_state_t DGUSDisplay::rx_datagram_state = DGUS_IDLE;
+uint8_t DGUSDisplay::rx_datagram_len = 0;
+bool DGUSDisplay::Initialized = false;
+bool DGUSDisplay::no_reentrance = false;
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() asm volatile("": : :"memory");
+
+bool populate_VPVar(const uint16_t VP, DGUS_VP_Variable * const ramcopy) {
+ // DEBUG_ECHOPAIR("populate_VPVar ", VP);
+ const DGUS_VP_Variable *pvp = DGUSLCD_FindVPVar(VP);
+ // DEBUG_ECHOLNPAIR(" pvp ", (uint16_t )pvp);
+ if (!pvp) return false;
+ memcpy_P(ramcopy, pvp, sizeof(DGUS_VP_Variable));
+ return true;
+}
+
+#endif // HAS_DGUS_LCD
diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h
new file mode 100644
index 0000000..88c1195
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplay.h
@@ -0,0 +1,118 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/* DGUS implementation written by coldtobi in 2019 for Marlin */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#include // size_t
+
+#if HAS_BED_PROBE
+ #include "../../../../module/probe.h"
+#endif
+#include "DGUSVPVariable.h"
+
+enum DGUSLCD_Screens : uint8_t;
+
+#define DEBUG_OUT ENABLED(DEBUG_DGUSLCD)
+#include "../../../../core/debug_out.h"
+
+typedef enum : uint8_t {
+ DGUS_IDLE, //< waiting for DGUS_HEADER1.
+ DGUS_HEADER1_SEEN, //< DGUS_HEADER1 received
+ DGUS_HEADER2_SEEN, //< DGUS_HEADER2 received
+ DGUS_WAIT_TELEGRAM, //< LEN received, Waiting for to receive all bytes.
+} rx_datagram_state_t;
+
+// Low-Level access to the display.
+class DGUSDisplay {
+public:
+
+ DGUSDisplay() = default;
+
+ static void InitDisplay();
+
+ // Variable access.
+ static void WriteVariable(uint16_t adr, const void* values, uint8_t valueslen, bool isstr=false);
+ static void WriteVariablePGM(uint16_t adr, const void* values, uint8_t valueslen, bool isstr=false);
+ static void WriteVariable(uint16_t adr, int16_t value);
+ static void WriteVariable(uint16_t adr, uint16_t value);
+ static void WriteVariable(uint16_t adr, uint8_t value);
+ static void WriteVariable(uint16_t adr, int8_t value);
+ static void WriteVariable(uint16_t adr, long value);
+
+ // Utility functions for bridging ui_api and dbus
+ template
+ static void SetVariable(DGUS_VP_Variable &var) {
+ WriteVariable(var.VP, (WireType)Getter(selector));
+ }
+
+ template
+ static void GetVariable(DGUS_VP_Variable &var, void *val_ptr) {
+ uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
+ Setter(newvalue, selector);
+ }
+
+ // Until now I did not need to actively read from the display. That's why there is no ReadVariable
+ // (I extensively use the auto upload of the display)
+
+ // Force display into another screen.
+ // (And trigger update of containing VPs)
+ // (to implement a pop up message, which may not be nested)
+ static void RequestScreen(DGUSLCD_Screens screen);
+
+ // Periodic tasks, eg. Rx-Queue handling.
+ static void loop();
+
+public:
+ // Helper for users of this class to estimate if an interaction would be blocking.
+ static size_t GetFreeTxBuffer();
+
+ // Checks two things: Can we confirm the presence of the display and has we initiliazed it.
+ // (both boils down that the display answered to our chatting)
+ static inline bool isInitialized() { return Initialized; }
+
+private:
+ static void WriteHeader(uint16_t adr, uint8_t cmd, uint8_t payloadlen);
+ static void WritePGM(const char str[], uint8_t len);
+ static void ProcessRx();
+
+ static inline uint16_t swap16(const uint16_t value) { return (value & 0xFFU) << 8U | (value >> 8U); }
+ static rx_datagram_state_t rx_datagram_state;
+ static uint8_t rx_datagram_len;
+ static bool Initialized, no_reentrance;
+};
+
+#define GET_VARIABLE(f, t, V...) (&DGUSDisplay::GetVariable)
+#define SET_VARIABLE(f, t, V...) (&DGUSDisplay::SetVariable)
+
+extern DGUSDisplay dgusdisplay;
+
+// compile-time x^y
+constexpr float cpow(const float x, const int y) { return y == 0 ? 1.0 : x * cpow(x, y - 1); }
+
+/// Find the flash address of a DGUS_VP_Variable for the VP.
+extern const DGUS_VP_Variable* DGUSLCD_FindVPVar(const uint16_t vp);
+
+/// Helper to populate a DGUS_VP_Variable for a given VP. Return false if not found.
+extern bool populate_VPVar(const uint16_t VP, DGUS_VP_Variable * const ramcopy);
diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSDisplayDef.h b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplayDef.h
new file mode 100644
index 0000000..b34a048
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/DGUSDisplayDef.h
@@ -0,0 +1,54 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+/* DGUS implementation written by coldtobi in 2019 for Marlin */
+
+#include "DGUSVPVariable.h"
+
+#include
+
+// This file defines the interaction between Marlin and the display firmware.
+
+// information on which screen which VP is displayed
+// As this is a sparse table, two arrays are needed:
+// one to list the VPs of one screen and one to map screens to the lists.
+// (Strictly this would not be necessary, but allows to only send data the display needs and reducing load on Marlin)
+struct VPMapping {
+ const uint8_t screen;
+ const uint16_t *VPList; // The list is null-terminated.
+};
+
+extern const struct VPMapping VPMap[];
+
+// List of VPs handled by Marlin / The Display.
+extern const struct DGUS_VP_Variable ListOfVP[];
+
+#include "../../../../inc/MarlinConfig.h"
+
+#if ENABLED(DGUS_LCD_UI_ORIGIN)
+ #include "origin/DGUSDisplayDef.h"
+#elif ENABLED(DGUS_LCD_UI_FYSETC)
+ #include "fysetc/DGUSDisplayDef.h"
+#elif ENABLED(DGUS_LCD_UI_HIPRECY)
+ #include "hiprecy/DGUSDisplayDef.h"
+#endif
diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.cpp b/Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.cpp
new file mode 100644
index 0000000..77feacf
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.cpp
@@ -0,0 +1,1140 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../../../inc/MarlinConfigPre.h"
+
+#if HAS_DGUS_LCD
+
+#include "DGUSScreenHandler.h"
+#include "DGUSDisplay.h"
+#include "DGUSVPVariable.h"
+#include "DGUSDisplayDef.h"
+
+#include "../../ui_api.h"
+#include "../../../../MarlinCore.h"
+#include "../../../../module/temperature.h"
+#include "../../../../module/motion.h"
+#include "../../../../gcode/queue.h"
+#include "../../../../module/planner.h"
+#include "../../../../sd/cardreader.h"
+#include "../../../../libs/duration_t.h"
+#include "../../../../module/printcounter.h"
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+ #include "../../../../feature/powerloss.h"
+#endif
+
+uint16_t DGUSScreenHandler::ConfirmVP;
+
+#if ENABLED(SDSUPPORT)
+ int16_t DGUSScreenHandler::top_file = 0;
+ int16_t DGUSScreenHandler::file_to_print = 0;
+ static ExtUI::FileList filelist;
+#endif
+
+void (*DGUSScreenHandler::confirm_action_cb)() = nullptr;
+
+//DGUSScreenHandler ScreenHandler;
+
+DGUSLCD_Screens DGUSScreenHandler::current_screen;
+DGUSLCD_Screens DGUSScreenHandler::past_screens[NUM_PAST_SCREENS];
+uint8_t DGUSScreenHandler::update_ptr;
+uint16_t DGUSScreenHandler::skipVP;
+bool DGUSScreenHandler::ScreenComplete;
+
+//DGUSDisplay dgusdisplay;
+
+// endianness swap
+uint16_t swap16(const uint16_t value) { return (value & 0xffU) << 8U | (value >> 8U); }
+
+void DGUSScreenHandler::sendinfoscreen(const char* line1, const char* line2, const char* line3, const char* line4, bool l1inflash, bool l2inflash, bool l3inflash, bool l4inflash) {
+ DGUS_VP_Variable ramcopy;
+ if (populate_VPVar(VP_MSGSTR1, &ramcopy)) {
+ ramcopy.memadr = (void*) line1;
+ l1inflash ? DGUSScreenHandler::DGUSLCD_SendStringToDisplayPGM(ramcopy) : DGUSScreenHandler::DGUSLCD_SendStringToDisplay(ramcopy);
+ }
+ if (populate_VPVar(VP_MSGSTR2, &ramcopy)) {
+ ramcopy.memadr = (void*) line2;
+ l2inflash ? DGUSScreenHandler::DGUSLCD_SendStringToDisplayPGM(ramcopy) : DGUSScreenHandler::DGUSLCD_SendStringToDisplay(ramcopy);
+ }
+ if (populate_VPVar(VP_MSGSTR3, &ramcopy)) {
+ ramcopy.memadr = (void*) line3;
+ l3inflash ? DGUSScreenHandler::DGUSLCD_SendStringToDisplayPGM(ramcopy) : DGUSScreenHandler::DGUSLCD_SendStringToDisplay(ramcopy);
+ }
+ if (populate_VPVar(VP_MSGSTR4, &ramcopy)) {
+ ramcopy.memadr = (void*) line4;
+ l4inflash ? DGUSScreenHandler::DGUSLCD_SendStringToDisplayPGM(ramcopy) : DGUSScreenHandler::DGUSLCD_SendStringToDisplay(ramcopy);
+ }
+}
+
+void DGUSScreenHandler::HandleUserConfirmationPopUp(uint16_t VP, const char* line1, const char* line2, const char* line3, const char* line4, bool l1, bool l2, bool l3, bool l4) {
+ if (current_screen == DGUSLCD_SCREEN_CONFIRM) {
+ // Already showing a pop up, so we need to cancel that first.
+ PopToOldScreen();
+ }
+
+ ConfirmVP = VP;
+ sendinfoscreen(line1, line2, line3, line4, l1, l2, l3, l4);
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_CONFIRM);
+}
+
+void DGUSScreenHandler::setstatusmessage(const char *msg) {
+ DGUS_VP_Variable ramcopy;
+ if (populate_VPVar(VP_M117, &ramcopy)) {
+ ramcopy.memadr = (void*) msg;
+ DGUSLCD_SendStringToDisplay(ramcopy);
+ }
+}
+
+void DGUSScreenHandler::setstatusmessagePGM(PGM_P const msg) {
+ DGUS_VP_Variable ramcopy;
+ if (populate_VPVar(VP_M117, &ramcopy)) {
+ ramcopy.memadr = (void*) msg;
+ DGUSLCD_SendStringToDisplayPGM(ramcopy);
+ }
+}
+
+// Send an 8 bit or 16 bit value to the display.
+void DGUSScreenHandler::DGUSLCD_SendWordValueToDisplay(DGUS_VP_Variable &var) {
+ if (var.memadr) {
+ //DEBUG_ECHOPAIR(" DGUS_LCD_SendWordValueToDisplay ", var.VP);
+ //DEBUG_ECHOLNPAIR(" data ", *(uint16_t *)var.memadr);
+ if (var.size > 1)
+ dgusdisplay.WriteVariable(var.VP, *(int16_t*)var.memadr);
+ else
+ dgusdisplay.WriteVariable(var.VP, *(int8_t*)var.memadr);
+ }
+}
+
+// Send an uint8_t between 0 and 255 to the display, but scale to a percentage (0..100)
+void DGUSScreenHandler::DGUSLCD_SendPercentageToDisplay(DGUS_VP_Variable &var) {
+ if (var.memadr) {
+ //DEBUG_ECHOPAIR(" DGUS_LCD_SendWordValueToDisplay ", var.VP);
+ //DEBUG_ECHOLNPAIR(" data ", *(uint16_t *)var.memadr);
+ uint16_t tmp = *(uint8_t *) var.memadr +1 ; // +1 -> avoid rounding issues for the display.
+ tmp = map(tmp, 0, 255, 0, 100);
+ dgusdisplay.WriteVariable(var.VP, tmp);
+ }
+}
+
+// Send the current print progress to the display.
+void DGUSScreenHandler::DGUSLCD_SendPrintProgressToDisplay(DGUS_VP_Variable &var) {
+ //DEBUG_ECHOPAIR(" DGUSLCD_SendPrintProgressToDisplay ", var.VP);
+ uint16_t tmp = ExtUI::getProgress_percent();
+ //DEBUG_ECHOLNPAIR(" data ", tmp);
+ dgusdisplay.WriteVariable(var.VP, tmp);
+}
+
+// Send the current print time to the display.
+// It is using a hex display for that: It expects BSD coded data in the format xxyyzz
+void DGUSScreenHandler::DGUSLCD_SendPrintTimeToDisplay(DGUS_VP_Variable &var) {
+ duration_t elapsed = print_job_timer.duration();
+ char buf[32];
+ elapsed.toString(buf);
+ dgusdisplay.WriteVariable(VP_PrintTime, buf, var.size, true);
+}
+
+// Send an uint8_t between 0 and 100 to a variable scale to 0..255
+void DGUSScreenHandler::DGUSLCD_PercentageToUint8(DGUS_VP_Variable &var, void *val_ptr) {
+ if (var.memadr) {
+ uint16_t value = swap16(*(uint16_t*)val_ptr);
+ *(uint8_t*)var.memadr = map(constrain(value, 0, 100), 0, 100, 0, 255);
+ }
+}
+
+// Sends a (RAM located) string to the DGUS Display
+// (Note: The DGUS Display does not clear after the \0, you have to
+// overwrite the remainings with spaces.// var.size has the display buffer size!
+void DGUSScreenHandler::DGUSLCD_SendStringToDisplay(DGUS_VP_Variable &var) {
+ char *tmp = (char*) var.memadr;
+ dgusdisplay.WriteVariable(var.VP, tmp, var.size, true);
+}
+
+// Sends a (flash located) string to the DGUS Display
+// (Note: The DGUS Display does not clear after the \0, you have to
+// overwrite the remainings with spaces.// var.size has the display buffer size!
+void DGUSScreenHandler::DGUSLCD_SendStringToDisplayPGM(DGUS_VP_Variable &var) {
+ char *tmp = (char*) var.memadr;
+ dgusdisplay.WriteVariablePGM(var.VP, tmp, var.size, true);
+}
+
+#if HAS_PID_HEATING
+ void DGUSScreenHandler::DGUSLCD_SendTemperaturePID(DGUS_VP_Variable &var) {
+ float value = *(float *)var.memadr;
+ float valuesend = 0;
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_E0_PID_P: valuesend = value; break;
+ case VP_E0_PID_I: valuesend = unscalePID_i(value); break;
+ case VP_E0_PID_D: valuesend = unscalePID_d(value); break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_E1_PID_P: valuesend = value; break;
+ case VP_E1_PID_I: valuesend = unscalePID_i(value); break;
+ case VP_E1_PID_D: valuesend = unscalePID_d(value); break;
+ #endif
+ #if HAS_HEATED_BED
+ case VP_BED_PID_P: valuesend = value; break;
+ case VP_BED_PID_I: valuesend = unscalePID_i(value); break;
+ case VP_BED_PID_D: valuesend = unscalePID_d(value); break;
+ #endif
+ }
+
+ valuesend *= cpow(10, 1);
+ union { int16_t i; char lb[2]; } endian;
+
+ char tmp[2];
+ endian.i = valuesend;
+ tmp[0] = endian.lb[1];
+ tmp[1] = endian.lb[0];
+ dgusdisplay.WriteVariable(var.VP, tmp, 2);
+ }
+#endif
+
+#if ENABLED(PRINTCOUNTER)
+
+ // Send the accumulate print time to the display.
+ // It is using a hex display for that: It expects BSD coded data in the format xxyyzz
+ void DGUSScreenHandler::DGUSLCD_SendPrintAccTimeToDisplay(DGUS_VP_Variable &var) {
+ printStatistics state = print_job_timer.getStats();
+ char buf[22];
+ duration_t elapsed = state.printTime;
+ elapsed.toString(buf);
+ dgusdisplay.WriteVariable(VP_PrintAccTime, buf, var.size, true);
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SendPrintsTotalToDisplay(DGUS_VP_Variable &var) {
+ printStatistics state = print_job_timer.getStats();
+ char buf[10];
+ sprintf_P(buf, PSTR("%u"), state.totalPrints);
+ dgusdisplay.WriteVariable(VP_PrintsTotal, buf, var.size, true);
+ }
+
+#endif
+
+// Send fan status value to the display.
+#if HAS_FAN
+ void DGUSScreenHandler::DGUSLCD_SendFanStatusToDisplay(DGUS_VP_Variable &var) {
+ if (var.memadr) {
+ DEBUG_ECHOPAIR(" DGUSLCD_SendFanStatusToDisplay ", var.VP);
+ DEBUG_ECHOLNPAIR(" data ", *(uint8_t *)var.memadr);
+ uint16_t data_to_send = 0;
+ if (*(uint8_t *) var.memadr) data_to_send = 1;
+ dgusdisplay.WriteVariable(var.VP, data_to_send);
+ }
+ }
+#endif
+
+// Send heater status value to the display.
+void DGUSScreenHandler::DGUSLCD_SendHeaterStatusToDisplay(DGUS_VP_Variable &var) {
+ if (var.memadr) {
+ DEBUG_ECHOPAIR(" DGUSLCD_SendHeaterStatusToDisplay ", var.VP);
+ DEBUG_ECHOLNPAIR(" data ", *(int16_t *)var.memadr);
+ uint16_t data_to_send = 0;
+ if (*(int16_t *) var.memadr) data_to_send = 1;
+ dgusdisplay.WriteVariable(var.VP, data_to_send);
+ }
+}
+
+#if ENABLED(DGUS_UI_WAITING)
+ void DGUSScreenHandler::DGUSLCD_SendWaitingStatusToDisplay(DGUS_VP_Variable &var) {
+ // In FYSETC UI design there are 10 statuses to loop
+ static uint16_t period = 0;
+ static uint16_t index = 0;
+ //DEBUG_ECHOPAIR(" DGUSLCD_SendWaitingStatusToDisplay ", var.VP);
+ //DEBUG_ECHOLNPAIR(" data ", swap16(index));
+ if (period++ > DGUS_UI_WAITING_STATUS_PERIOD) {
+ dgusdisplay.WriteVariable(var.VP, index);
+ //DEBUG_ECHOLNPAIR(" data ", swap16(index));
+ if (++index >= DGUS_UI_WAITING_STATUS) index = 0;
+ period = 0;
+ }
+ }
+#endif
+
+#if ENABLED(SDSUPPORT)
+
+ void DGUSScreenHandler::ScreenChangeHookIfSD(DGUS_VP_Variable &var, void *val_ptr) {
+ // default action executed when there is a SD card, but not printing
+ if (ExtUI::isMediaInserted() && !ExtUI::isPrintingFromMedia()) {
+ ScreenChangeHook(var, val_ptr);
+ dgusdisplay.RequestScreen(current_screen);
+ return;
+ }
+
+ // if we are printing, we jump to two screens after the requested one.
+ // This should host e.g a print pause / print abort / print resume dialog.
+ // This concept allows to recycle this hook for other file
+ if (ExtUI::isPrintingFromMedia() && !card.flag.abort_sd_printing) {
+ GotoScreen(DGUSLCD_SCREEN_SDPRINTMANIPULATION);
+ return;
+ }
+
+ // Don't let the user in the dark why there is no reaction.
+ if (!ExtUI::isMediaInserted()) {
+ setstatusmessagePGM(GET_TEXT(MSG_NO_MEDIA));
+ return;
+ }
+ if (card.flag.abort_sd_printing) {
+ setstatusmessagePGM(GET_TEXT(MSG_MEDIA_ABORTING));
+ return;
+ }
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_ScrollFilelist(DGUS_VP_Variable& var, void *val_ptr) {
+ auto old_top = top_file;
+ const int16_t scroll = (int16_t)swap16(*(uint16_t*)val_ptr);
+ if (scroll) {
+ top_file += scroll;
+ DEBUG_ECHOPAIR("new topfile calculated:", top_file);
+ if (top_file < 0) {
+ top_file = 0;
+ DEBUG_ECHOLNPGM("Top of filelist reached");
+ }
+ else {
+ int16_t max_top = filelist.count() - DGUS_SD_FILESPERSCREEN;
+ NOLESS(max_top, 0);
+ NOMORE(top_file, max_top);
+ }
+ DEBUG_ECHOPAIR("new topfile adjusted:", top_file);
+ }
+ else if (!filelist.isAtRootDir()) {
+ filelist.upDir();
+ top_file = 0;
+ ForceCompleteUpdate();
+ }
+
+ if (old_top != top_file) ForceCompleteUpdate();
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_FileSelected(DGUS_VP_Variable &var, void *val_ptr) {
+ uint16_t touched_nr = (int16_t)swap16(*(uint16_t*)val_ptr) + top_file;
+ if (touched_nr > filelist.count()) return;
+ if (!filelist.seek(touched_nr)) return;
+ if (filelist.isDir()) {
+ filelist.changeDir(filelist.filename());
+ top_file = 0;
+ ForceCompleteUpdate();
+ return;
+ }
+
+ #if ENABLED(DGUS_PRINT_FILENAME)
+ // Send print filename
+ dgusdisplay.WriteVariable(VP_SD_Print_Filename, filelist.filename(), VP_SD_FileName_LEN, true);
+ #endif
+
+ // Setup Confirmation screen
+ file_to_print = touched_nr;
+ HandleUserConfirmationPopUp(VP_SD_FileSelectConfirm, nullptr, PSTR("Print file"), filelist.filename(), PSTR("from SD Card?"), true, true, false, true);
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_StartPrint(DGUS_VP_Variable &var, void *val_ptr) {
+ if (!filelist.seek(file_to_print)) return;
+ ExtUI::printFile(filelist.shortFilename());
+ ScreenHandler.GotoScreen(
+ #if ENABLED(DGUS_LCD_UI_ORIGIN)
+ DGUSLCD_SCREEN_STATUS
+ #else
+ DGUSLCD_SCREEN_SDPRINTMANIPULATION
+ #endif
+ );
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_ResumePauseAbort(DGUS_VP_Variable &var, void *val_ptr) {
+ if (!ExtUI::isPrintingFromMedia()) return; // avoid race condition when user stays in this menu and printer finishes.
+ switch (swap16(*(uint16_t*)val_ptr)) {
+ case 0: // Resume
+ if (ExtUI::isPrintingFromMediaPaused()) ExtUI::resumePrint();
+ break;
+ case 1: // Pause
+ if (!ExtUI::isPrintingFromMediaPaused()) ExtUI::pausePrint();
+ break;
+ case 2: // Abort
+ ScreenHandler.HandleUserConfirmationPopUp(VP_SD_AbortPrintConfirmed, nullptr, PSTR("Abort printing"), filelist.filename(), PSTR("?"), true, true, false, true);
+ break;
+ }
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_ReallyAbort(DGUS_VP_Variable &var, void *val_ptr) {
+ ExtUI::stopPrint();
+ GotoScreen(DGUSLCD_SCREEN_MAIN);
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_PrintTune(DGUS_VP_Variable &var, void *val_ptr) {
+ if (!ExtUI::isPrintingFromMedia()) return; // avoid race condition when user stays in this menu and printer finishes.
+ GotoScreen(DGUSLCD_SCREEN_SDPRINTTUNE);
+ }
+
+ void DGUSScreenHandler::DGUSLCD_SD_SendFilename(DGUS_VP_Variable& var) {
+ uint16_t target_line = (var.VP - VP_SD_FileName0) / VP_SD_FileName_LEN;
+ if (target_line > DGUS_SD_FILESPERSCREEN) return;
+ char tmpfilename[VP_SD_FileName_LEN + 1] = "";
+ var.memadr = (void*)tmpfilename;
+ if (filelist.seek(top_file + target_line))
+ snprintf_P(tmpfilename, VP_SD_FileName_LEN, PSTR("%s%c"), filelist.filename(), filelist.isDir() ? '/' : 0);
+ DGUSLCD_SendStringToDisplay(var);
+ }
+
+ void DGUSScreenHandler::SDCardInserted() {
+ top_file = 0;
+ filelist.refresh();
+ auto cs = ScreenHandler.getCurrentScreen();
+ if (cs == DGUSLCD_SCREEN_MAIN || cs == DGUSLCD_SCREEN_STATUS)
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_SDFILELIST);
+ }
+
+ void DGUSScreenHandler::SDCardRemoved() {
+ if (current_screen == DGUSLCD_SCREEN_SDFILELIST
+ || (current_screen == DGUSLCD_SCREEN_CONFIRM && (ConfirmVP == VP_SD_AbortPrintConfirmed || ConfirmVP == VP_SD_FileSelectConfirm))
+ || current_screen == DGUSLCD_SCREEN_SDPRINTMANIPULATION
+ ) ScreenHandler.GotoScreen(DGUSLCD_SCREEN_MAIN);
+ }
+
+ void DGUSScreenHandler::SDCardError() {
+ DGUSScreenHandler::SDCardRemoved();
+ ScreenHandler.sendinfoscreen(PSTR("NOTICE"), nullptr, PSTR("SD card error"), nullptr, true, true, true, true);
+ ScreenHandler.SetupConfirmAction(nullptr);
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_POPUP);
+ }
+
+#endif // SDSUPPORT
+
+void DGUSScreenHandler::ScreenConfirmedOK(DGUS_VP_Variable &var, void *val_ptr) {
+ DGUS_VP_Variable ramcopy;
+ if (!populate_VPVar(ConfirmVP, &ramcopy)) return;
+ if (ramcopy.set_by_display_handler) ramcopy.set_by_display_handler(ramcopy, val_ptr);
+}
+
+const uint16_t* DGUSLCD_FindScreenVPMapList(uint8_t screen) {
+ const uint16_t *ret;
+ const struct VPMapping *map = VPMap;
+ while (ret = (uint16_t*) pgm_read_ptr(&(map->VPList))) {
+ if (pgm_read_byte(&(map->screen)) == screen) return ret;
+ map++;
+ }
+ return nullptr;
+}
+
+const DGUS_VP_Variable* DGUSLCD_FindVPVar(const uint16_t vp) {
+ const DGUS_VP_Variable *ret = ListOfVP;
+ do {
+ const uint16_t vpcheck = pgm_read_word(&(ret->VP));
+ if (vpcheck == 0) break;
+ if (vpcheck == vp) return ret;
+ ++ret;
+ } while (1);
+
+ DEBUG_ECHOLNPAIR("FindVPVar NOT FOUND ", vp);
+ return nullptr;
+}
+
+void DGUSScreenHandler::ScreenChangeHookIfIdle(DGUS_VP_Variable &var, void *val_ptr) {
+ if (!ExtUI::isPrinting()) {
+ ScreenChangeHook(var, val_ptr);
+ dgusdisplay.RequestScreen(current_screen);
+ }
+}
+
+void DGUSScreenHandler::ScreenChangeHook(DGUS_VP_Variable &var, void *val_ptr) {
+ uint8_t *tmp = (uint8_t*)val_ptr;
+
+ // The keycode in target is coded as , so 0x0100A means
+ // from screen 1 (main) to 10 (temperature). DGUSLCD_SCREEN_POPUP is special,
+ // meaning "return to previous screen"
+ DGUSLCD_Screens target = (DGUSLCD_Screens)tmp[1];
+
+ if (target == DGUSLCD_SCREEN_POPUP) {
+ // special handling for popup is to return to previous menu
+ if (current_screen == DGUSLCD_SCREEN_POPUP && confirm_action_cb) confirm_action_cb();
+ PopToOldScreen();
+ return;
+ }
+
+ UpdateNewScreen(target);
+
+ #ifdef DEBUG_DGUSLCD
+ if (!DGUSLCD_FindScreenVPMapList(target)) DEBUG_ECHOLNPAIR("WARNING: No screen Mapping found for ", target);
+ #endif
+}
+
+void DGUSScreenHandler::HandleAllHeatersOff(DGUS_VP_Variable &var, void *val_ptr) {
+ thermalManager.disable_all_heaters();
+ ScreenHandler.ForceCompleteUpdate(); // hint to send all data.
+}
+
+void DGUSScreenHandler::HandleTemperatureChanged(DGUS_VP_Variable &var, void *val_ptr) {
+ uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
+ uint16_t acceptedvalue;
+
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_T_E0_Set:
+ thermalManager.setTargetHotend(newvalue, 0);
+ acceptedvalue = thermalManager.temp_hotend[0].target;
+ break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_T_E1_Set:
+ thermalManager.setTargetHotend(newvalue, 1);
+ acceptedvalue = thermalManager.temp_hotend[1].target;
+ break;
+ #endif
+ #if HAS_HEATED_BED
+ case VP_T_Bed_Set:
+ thermalManager.setTargetBed(newvalue);
+ acceptedvalue = thermalManager.temp_bed.target;
+ break;
+ #endif
+ }
+
+ // reply to display the new value to update the view if the new value was rejected by the Thermal Manager.
+ if (newvalue != acceptedvalue && var.send_to_display_handler) var.send_to_display_handler(var);
+ ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
+}
+
+void DGUSScreenHandler::HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr) {
+ #if EXTRUDERS
+ uint16_t newvalue = swap16(*(uint16_t*)val_ptr);
+ uint8_t target_extruder;
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_Flowrate_E0: target_extruder = 0; break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_Flowrate_E1: target_extruder = 1; break;
+ #endif
+ }
+
+ planner.set_flow(target_extruder, newvalue);
+ ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
+ #else
+ UNUSED(var); UNUSED(val_ptr);
+ #endif
+}
+
+void DGUSScreenHandler::HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleManualExtrude");
+
+ int16_t movevalue = swap16(*(uint16_t*)val_ptr);
+ float target = movevalue * 0.01f;
+ ExtUI::extruder_t target_extruder;
+
+ switch (var.VP) {
+ #if HOTENDS >= 1
+ case VP_MOVE_E0: target_extruder = ExtUI::extruder_t::E0; break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_MOVE_E1: target_extruder = ExtUI::extruder_t::E1; break;
+ #endif
+ default: return;
+ }
+
+ target += ExtUI::getAxisPosition_mm(target_extruder);
+ ExtUI::setAxisPosition_mm(target, target_extruder);
+ skipVP = var.VP;
+}
+
+#if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ void DGUSScreenHandler::HandleManualMoveOption(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleManualMoveOption");
+ *(uint16_t*)var.memadr = swap16(*(uint16_t*)val_ptr);
+ }
+#endif
+
+void DGUSScreenHandler::HandleManualMove(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleManualMove");
+
+ int16_t movevalue = swap16(*(uint16_t*)val_ptr);
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ if (movevalue) {
+ const uint16_t choice = *(uint16_t*)var.memadr;
+ movevalue = movevalue < 0 ? -choice : choice;
+ }
+ #endif
+ char axiscode;
+ unsigned int speed = 1500; //FIXME: get default feedrate for manual moves, dont hardcode.
+
+ switch (var.VP) {
+ default: return;
+
+ case VP_MOVE_X:
+ axiscode = 'X';
+ if (!ExtUI::canMove(ExtUI::axis_t::X)) goto cannotmove;
+ break;
+
+ case VP_MOVE_Y:
+ axiscode = 'Y';
+ if (!ExtUI::canMove(ExtUI::axis_t::Y)) goto cannotmove;
+ break;
+
+ case VP_MOVE_Z:
+ axiscode = 'Z';
+ speed = 300; // default to 5mm/s
+ if (!ExtUI::canMove(ExtUI::axis_t::Z)) goto cannotmove;
+ break;
+
+ case VP_HOME_ALL: // only used for homing
+ axiscode = '\0';
+ movevalue = 0; // ignore value sent from display, this VP is _ONLY_ for homing.
+ break;
+ }
+
+ if (!movevalue) {
+ // homing
+ DEBUG_ECHOPAIR(" homing ", axiscode);
+ char buf[6] = "G28 X";
+ buf[4] = axiscode;
+ //DEBUG_ECHOPAIR(" ", buf);
+ queue.enqueue_one_now(buf);
+ //DEBUG_ECHOLNPGM(" ✓");
+ ScreenHandler.ForceCompleteUpdate();
+ return;
+ }
+ else {
+ //movement
+ DEBUG_ECHOPAIR(" move ", axiscode);
+ bool old_relative_mode = relative_mode;
+ if (!relative_mode) {
+ //DEBUG_ECHOPGM(" G91");
+ queue.enqueue_now_P(PSTR("G91"));
+ //DEBUG_ECHOPGM(" ✓ ");
+ }
+ char buf[32]; // G1 X9999.99 F12345
+ unsigned int backup_speed = MMS_TO_MMM(feedrate_mm_s);
+ char sign[]="\0";
+ int16_t value = movevalue / 100;
+ if (movevalue < 0) { value = -value; sign[0] = '-'; }
+ int16_t fraction = ABS(movevalue) % 100;
+ snprintf_P(buf, 32, PSTR("G0 %c%s%d.%02d F%d"), axiscode, sign, value, fraction, speed);
+ //DEBUG_ECHOPAIR(" ", buf);
+ queue.enqueue_one_now(buf);
+ //DEBUG_ECHOLNPGM(" ✓ ");
+ if (backup_speed != speed) {
+ snprintf_P(buf, 32, PSTR("G0 F%d"), backup_speed);
+ queue.enqueue_one_now(buf);
+ //DEBUG_ECHOPAIR(" ", buf);
+ }
+ //while (!enqueue_and_echo_command(buf)) idle();
+ //DEBUG_ECHOLNPGM(" ✓ ");
+ if (!old_relative_mode) {
+ //DEBUG_ECHOPGM("G90");
+ queue.enqueue_now_P(PSTR("G90"));
+ //DEBUG_ECHOPGM(" ✓ ");
+ }
+ }
+
+ ScreenHandler.ForceCompleteUpdate();
+ DEBUG_ECHOLNPGM("manmv done.");
+ return;
+
+ cannotmove:
+ DEBUG_ECHOLNPAIR(" cannot move ", axiscode);
+ return;
+}
+
+void DGUSScreenHandler::HandleMotorLockUnlock(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleMotorLockUnlock");
+
+ char buf[4];
+ const int16_t lock = swap16(*(uint16_t*)val_ptr);
+ strcpy_P(buf, lock ? PSTR("M18") : PSTR("M17"));
+
+ //DEBUG_ECHOPAIR(" ", buf);
+ queue.enqueue_one_now(buf);
+}
+
+#if ENABLED(POWER_LOSS_RECOVERY)
+
+ void DGUSScreenHandler::HandlePowerLossRecovery(DGUS_VP_Variable &var, void *val_ptr) {
+ uint16_t value = swap16(*(uint16_t*)val_ptr);
+ if (value) {
+ queue.inject_P(PSTR("M1000"));
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_SDPRINTMANIPULATION);
+ }
+ else {
+ recovery.cancel();
+ ScreenHandler.GotoScreen(DGUSLCD_SCREEN_STATUS);
+ }
+ }
+
+#endif
+
+void DGUSScreenHandler::HandleSettings(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleSettings");
+ uint16_t value = swap16(*(uint16_t*)val_ptr);
+ switch (value) {
+ default: break;
+ case 1:
+ TERN_(PRINTCOUNTER, print_job_timer.initStats());
+ queue.inject_P(PSTR("M502\nM500"));
+ break;
+ case 2: queue.inject_P(PSTR("M501")); break;
+ case 3: queue.inject_P(PSTR("M500")); break;
+ }
+}
+
+void DGUSScreenHandler::HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleStepPerMMChanged");
+
+ uint16_t value_raw = swap16(*(uint16_t*)val_ptr);
+ DEBUG_ECHOLNPAIR("value_raw:", value_raw);
+ float value = (float)value_raw/10;
+ ExtUI::axis_t axis;
+ switch (var.VP) {
+ case VP_X_STEP_PER_MM: axis = ExtUI::axis_t::X; break;
+ case VP_Y_STEP_PER_MM: axis = ExtUI::axis_t::Y; break;
+ case VP_Z_STEP_PER_MM: axis = ExtUI::axis_t::Z; break;
+ default: return;
+ }
+ DEBUG_ECHOLNPAIR_F("value:", value);
+ ExtUI::setAxisSteps_per_mm(value, axis);
+ DEBUG_ECHOLNPAIR_F("value_set:", ExtUI::getAxisSteps_per_mm(axis));
+ ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
+ return;
+}
+
+void DGUSScreenHandler::HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleStepPerMMExtruderChanged");
+
+ uint16_t value_raw = swap16(*(uint16_t*)val_ptr);
+ DEBUG_ECHOLNPAIR("value_raw:", value_raw);
+ float value = (float)value_raw/10;
+ ExtUI::extruder_t extruder;
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_E0_STEP_PER_MM: extruder = ExtUI::extruder_t::E0; break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_E1_STEP_PER_MM: extruder = ExtUI::extruder_t::E1; break;
+ #endif
+ }
+ DEBUG_ECHOLNPAIR_F("value:", value);
+ ExtUI::setAxisSteps_per_mm(value,extruder);
+ DEBUG_ECHOLNPAIR_F("value_set:", ExtUI::getAxisSteps_per_mm(extruder));
+ ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
+ return;
+}
+
+#if HAS_PID_HEATING
+ void DGUSScreenHandler::HandleTemperaturePIDChanged(DGUS_VP_Variable &var, void *val_ptr) {
+ uint16_t rawvalue = swap16(*(uint16_t*)val_ptr);
+ DEBUG_ECHOLNPAIR("V1:", rawvalue);
+ float value = (float)rawvalue / 10;
+ DEBUG_ECHOLNPAIR("V2:", value);
+ float newvalue = 0;
+
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_E0_PID_P: newvalue = value; break;
+ case VP_E0_PID_I: newvalue = scalePID_i(value); break;
+ case VP_E0_PID_D: newvalue = scalePID_d(value); break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_E1_PID_P: newvalue = value; break;
+ case VP_E1_PID_I: newvalue = scalePID_i(value); break;
+ case VP_E1_PID_D: newvalue = scalePID_d(value); break;
+ #endif
+ #if HAS_HEATED_BED
+ case VP_BED_PID_P: newvalue = value; break;
+ case VP_BED_PID_I: newvalue = scalePID_i(value); break;
+ case VP_BED_PID_D: newvalue = scalePID_d(value); break;
+ #endif
+ }
+
+ DEBUG_ECHOLNPAIR_F("V3:", newvalue);
+ *(float *)var.memadr = newvalue;
+ ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
+ }
+
+ void DGUSScreenHandler::HandlePIDAutotune(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandlePIDAutotune");
+
+ char buf[32] = {0};
+
+ switch (var.VP) {
+ default: break;
+ #if ENABLED(PIDTEMP)
+ #if HOTENDS >= 1
+ case VP_PID_AUTOTUNE_E0: // Autotune Extruder 0
+ sprintf(buf, "M303 E%d C5 S210 U1", ExtUI::extruder_t::E0);
+ break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_PID_AUTOTUNE_E1:
+ sprintf(buf, "M303 E%d C5 S210 U1", ExtUI::extruder_t::E1);
+ break;
+ #endif
+ #endif
+ #if ENABLED(PIDTEMPBED)
+ case VP_PID_AUTOTUNE_BED:
+ sprintf(buf, "M303 E-1 C5 S70 U1");
+ break;
+ #endif
+ }
+
+ if (buf[0]) queue.enqueue_one_now(buf);
+
+ #if ENABLED(DGUS_UI_WAITING)
+ sendinfoscreen(PSTR("PID is autotuning"), PSTR("please wait"), NUL_STR, NUL_STR, true, true, true, true);
+ GotoScreen(DGUSLCD_SCREEN_WAITING);
+ #endif
+ }
+#endif
+
+#if HAS_BED_PROBE
+ void DGUSScreenHandler::HandleProbeOffsetZChanged(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleProbeOffsetZChanged");
+
+ const float offset = float(int16_t(swap16(*(uint16_t*)val_ptr))) / 100.0f;
+ ExtUI::setZOffset_mm(offset);
+ ScreenHandler.skipVP = var.VP; // don't overwrite value the next update time as the display might autoincrement in parallel
+ return;
+ }
+#endif
+
+#if ENABLED(BABYSTEPPING)
+ void DGUSScreenHandler::HandleLiveAdjustZ(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleLiveAdjustZ");
+
+ int16_t flag = swap16(*(uint16_t*)val_ptr);
+ int16_t steps = flag ? -20 : 20;
+ ExtUI::smartAdjustAxis_steps(steps, ExtUI::axis_t::Z, true);
+ ScreenHandler.ForceCompleteUpdate();
+ return;
+ }
+#endif
+
+#if HAS_FAN
+ void DGUSScreenHandler::HandleFanControl(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleFanControl");
+ *(uint8_t*)var.memadr = *(uint8_t*)var.memadr > 0 ? 0 : 255;
+ }
+#endif
+
+void DGUSScreenHandler::HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleHeaterControl");
+
+ uint8_t preheat_temp = 0;
+ switch (var.VP) {
+ #if HOTENDS >= 1
+ case VP_E0_CONTROL:
+ #endif
+ #if HOTENDS >= 2
+ case VP_E1_CONTROL:
+ #endif
+ #if HOTENDS >= 3
+ case VP_E2_CONTROL:
+ #endif
+ preheat_temp = PREHEAT_1_TEMP_HOTEND;
+ break;
+
+ case VP_BED_CONTROL:
+ preheat_temp = PREHEAT_1_TEMP_BED;
+ break;
+ }
+
+ *(int16_t*)var.memadr = *(int16_t*)var.memadr > 0 ? 0 : preheat_temp;
+}
+
+#if ENABLED(DGUS_PREHEAT_UI)
+
+ void DGUSScreenHandler::HandlePreheat(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandlePreheat");
+
+ uint8_t e_temp = 0;
+ TERN_(HAS_HEATED_BED, uint8_t bed_temp = 0);
+ const uint16_t preheat_option = swap16(*(uint16_t*)val_ptr);
+ switch (preheat_option) {
+ default:
+ case 0: // Preheat PLA
+ #if defined(PREHEAT_1_TEMP_HOTEND) && defined(PREHEAT_1_TEMP_BED)
+ e_temp = PREHEAT_1_TEMP_HOTEND;
+ TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_1_TEMP_BED);
+ #endif
+ break;
+ case 1: // Preheat ABS
+ #if defined(PREHEAT_2_TEMP_HOTEND) && defined(PREHEAT_2_TEMP_BED)
+ e_temp = PREHEAT_2_TEMP_HOTEND;
+ TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_2_TEMP_BED);
+ #endif
+ break;
+ case 2: // Preheat PET
+ #if defined(PREHEAT_3_TEMP_HOTEND) && defined(PREHEAT_3_TEMP_BED)
+ e_temp = PREHEAT_3_TEMP_HOTEND;
+ TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_3_TEMP_BED);
+ #endif
+ break;
+ case 3: // Preheat FLEX
+ #if defined(PREHEAT_4_TEMP_HOTEND) && defined(PREHEAT_4_TEMP_BED)
+ e_temp = PREHEAT_4_TEMP_HOTEND;
+ TERN_(HAS_HEATED_BED, bed_temp = PREHEAT_4_TEMP_BED);
+ #endif
+ break;
+ case 7: break; // Custom preheat
+ case 9: break; // Cool down
+ }
+
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_E0_BED_PREHEAT:
+ thermalManager.setTargetHotend(e_temp, 0);
+ TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(bed_temp));
+ break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_E1_BED_PREHEAT:
+ thermalManager.setTargetHotend(e_temp, 1);
+ TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(bed_temp));
+ break;
+ #endif
+ }
+
+ // Go to the preheat screen to show the heating progress
+ GotoScreen(DGUSLCD_SCREEN_PREHEAT);
+ }
+
+#endif
+
+#if ENABLED(DGUS_FILAMENT_LOADUNLOAD)
+
+ typedef struct {
+ ExtUI::extruder_t extruder; // which extruder to operate
+ uint8_t action; // load or unload
+ bool heated; // heating done ?
+ float purge_length; // the length to extrude before unload, prevent filament jam
+ } filament_data_t;
+
+ static filament_data_t filament_data;
+
+ void DGUSScreenHandler::HandleFilamentOption(DGUS_VP_Variable &var, void *val_ptr) {
+ DEBUG_ECHOLNPGM("HandleFilamentOption");
+
+ uint8_t e_temp = 0;
+ filament_data.heated = false;
+ uint16_t preheat_option = swap16(*(uint16_t*)val_ptr);
+ if (preheat_option <= 8) // Load filament type
+ filament_data.action = 1;
+ else if (preheat_option >= 10) { // Unload filament type
+ preheat_option -= 10;
+ filament_data.action = 2;
+ filament_data.purge_length = DGUS_FILAMENT_PURGE_LENGTH;
+ }
+ else // Cancel filament operation
+ filament_data.action = 0;
+
+ switch (preheat_option) {
+ case 0: // Load PLA
+ #ifdef PREHEAT_1_TEMP_HOTEND
+ e_temp = PREHEAT_1_TEMP_HOTEND;
+ #endif
+ break;
+ case 1: // Load ABS
+ TERN_(PREHEAT_2_TEMP_HOTEND, e_temp = PREHEAT_2_TEMP_HOTEND);
+ break;
+ case 2: // Load PET
+ #ifdef PREHEAT_3_TEMP_HOTEND
+ e_temp = PREHEAT_3_TEMP_HOTEND;
+ #endif
+ break;
+ case 3: // Load FLEX
+ #ifdef PREHEAT_4_TEMP_HOTEND
+ e_temp = PREHEAT_4_TEMP_HOTEND;
+ #endif
+ break;
+ case 9: // Cool down
+ default:
+ e_temp = 0;
+ break;
+ }
+
+ if (filament_data.action == 0) { // Go back to utility screen
+ #if HOTENDS >= 1
+ thermalManager.setTargetHotend(e_temp, ExtUI::extruder_t::E0);
+ #endif
+ #if HOTENDS >= 2
+ thermalManager.setTargetHotend(e_temp, ExtUI::extruder_t::E1);
+ #endif
+ GotoScreen(DGUSLCD_SCREEN_UTILITY);
+ }
+ else { // Go to the preheat screen to show the heating progress
+ switch (var.VP) {
+ default: return;
+ #if HOTENDS >= 1
+ case VP_E0_FILAMENT_LOAD_UNLOAD:
+ filament_data.extruder = ExtUI::extruder_t::E0;
+ thermalManager.setTargetHotend(e_temp, filament_data.extruder);
+ break;
+ #endif
+ #if HOTENDS >= 2
+ case VP_E1_FILAMENT_LOAD_UNLOAD:
+ filament_data.extruder = ExtUI::extruder_t::E1;
+ thermalManager.setTargetHotend(e_temp, filament_data.extruder);
+ break;
+ #endif
+ }
+ GotoScreen(DGUSLCD_SCREEN_FILAMENT_HEATING);
+ }
+ }
+
+ void DGUSScreenHandler::HandleFilamentLoadUnload(DGUS_VP_Variable &var) {
+ DEBUG_ECHOLNPGM("HandleFilamentLoadUnload");
+ if (filament_data.action <= 0) return;
+
+ // If we close to the target temperature, we can start load or unload the filament
+ if (thermalManager.hotEnoughToExtrude(filament_data.extruder) && \
+ thermalManager.targetHotEnoughToExtrude(filament_data.extruder)) {
+ float movevalue = DGUS_FILAMENT_LOAD_LENGTH_PER_TIME;
+
+ if (filament_data.action == 1) { // load filament
+ if (!filament_data.heated) {
+ GotoScreen(DGUSLCD_SCREEN_FILAMENT_LOADING);
+ filament_data.heated = true;
+ }
+ movevalue = ExtUI::getAxisPosition_mm(filament_data.extruder)+movevalue;
+ }
+ else { // unload filament
+ if (!filament_data.heated) {
+ GotoScreen(DGUSLCD_SCREEN_FILAMENT_UNLOADING);
+ filament_data.heated = true;
+ }
+ // Before unloading extrude to prevent jamming
+ if (filament_data.purge_length >= 0) {
+ movevalue = ExtUI::getAxisPosition_mm(filament_data.extruder) + movevalue;
+ filament_data.purge_length -= movevalue;
+ }
+ else
+ movevalue = ExtUI::getAxisPosition_mm(filament_data.extruder) - movevalue;
+ }
+ ExtUI::setAxisPosition_mm(movevalue, filament_data.extruder);
+ }
+ }
+#endif
+
+void DGUSScreenHandler::UpdateNewScreen(DGUSLCD_Screens newscreen, bool popup) {
+ DEBUG_ECHOLNPAIR("SetNewScreen: ", newscreen);
+
+ if (!popup) {
+ memmove(&past_screens[1], &past_screens[0], sizeof(past_screens) - 1);
+ past_screens[0] = current_screen;
+ }
+
+ current_screen = newscreen;
+ skipVP = 0;
+ ForceCompleteUpdate();
+}
+
+void DGUSScreenHandler::PopToOldScreen() {
+ DEBUG_ECHOLNPAIR("PopToOldScreen s=", past_screens[0]);
+ GotoScreen(past_screens[0], true);
+ memmove(&past_screens[0], &past_screens[1], sizeof(past_screens) - 1);
+ past_screens[sizeof(past_screens) - 1] = DGUSLCD_SCREEN_MAIN;
+}
+
+void DGUSScreenHandler::UpdateScreenVPData() {
+ DEBUG_ECHOPAIR(" UpdateScreenVPData Screen: ", current_screen);
+
+ const uint16_t *VPList = DGUSLCD_FindScreenVPMapList(current_screen);
+ if (!VPList) {
+ DEBUG_ECHOLNPAIR(" NO SCREEN FOR: ", current_screen);
+ ScreenComplete = true;
+ return; // nothing to do, likely a bug or boring screen.
+ }
+
+ // Round-robin updating of all VPs.
+ VPList += update_ptr;
+
+ bool sent_one = false;
+ do {
+ uint16_t VP = pgm_read_word(VPList);
+ DEBUG_ECHOPAIR(" VP: ", VP);
+ if (!VP) {
+ update_ptr = 0;
+ DEBUG_ECHOLNPGM(" UpdateScreenVPData done");
+ ScreenComplete = true;
+ return; // Screen completed.
+ }
+
+ if (VP == skipVP) { skipVP = 0; continue; }
+
+ DGUS_VP_Variable rcpy;
+ if (populate_VPVar(VP, &rcpy)) {
+ uint8_t expected_tx = 6 + rcpy.size; // expected overhead is 6 bytes + payload.
+ // Send the VP to the display, but try to avoid overrunning the Tx Buffer.
+ // But send at least one VP, to avoid getting stalled.
+ if (rcpy.send_to_display_handler && (!sent_one || expected_tx <= dgusdisplay.GetFreeTxBuffer())) {
+ //DEBUG_ECHOPAIR(" calling handler for ", rcpy.VP);
+ sent_one = true;
+ rcpy.send_to_display_handler(rcpy);
+ }
+ else {
+ //auto x=dgusdisplay.GetFreeTxBuffer();
+ //DEBUG_ECHOLNPAIR(" tx almost full: ", x);
+ //DEBUG_ECHOPAIR(" update_ptr ", update_ptr);
+ ScreenComplete = false;
+ return; // please call again!
+ }
+ }
+
+ } while (++update_ptr, ++VPList, true);
+}
+
+void DGUSScreenHandler::GotoScreen(DGUSLCD_Screens screen, bool ispopup) {
+ dgusdisplay.RequestScreen(screen);
+ UpdateNewScreen(screen, ispopup);
+}
+
+bool DGUSScreenHandler::loop() {
+ dgusdisplay.loop();
+
+ const millis_t ms = millis();
+ static millis_t next_event_ms = 0;
+
+ if (!IsScreenComplete() || ELAPSED(ms, next_event_ms)) {
+ next_event_ms = ms + DGUS_UPDATE_INTERVAL_MS;
+ UpdateScreenVPData();
+ }
+
+ #if ENABLED(SHOW_BOOTSCREEN)
+ static bool booted = false;
+ if (!booted && TERN0(POWER_LOSS_RECOVERY, recovery.valid()))
+ booted = true;
+ if (!booted && ELAPSED(ms, BOOTSCREEN_TIMEOUT)) {
+ booted = true;
+ GotoScreen(DGUSLCD_SCREEN_MAIN);
+ }
+ #endif
+ return IsScreenComplete();
+}
+
+void DGUSDisplay::RequestScreen(DGUSLCD_Screens screen) {
+ DEBUG_ECHOLNPAIR("GotoScreen ", screen);
+ const unsigned char gotoscreen[] = { 0x5A, 0x01, (unsigned char) (screen >> 8U), (unsigned char) (screen & 0xFFU) };
+ WriteVariable(0x84, gotoscreen, sizeof(gotoscreen));
+}
+
+#endif // HAS_DGUS_LCD
diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.h b/Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.h
new file mode 100644
index 0000000..df738db
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/DGUSScreenHandler.h
@@ -0,0 +1,232 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "DGUSDisplay.h"
+#include "DGUSVPVariable.h"
+
+#include "../../../../inc/MarlinConfig.h"
+
+enum DGUSLCD_Screens : uint8_t;
+
+class DGUSScreenHandler {
+public:
+ DGUSScreenHandler() = default;
+
+ static bool loop();
+
+ /// Send all 4 strings that are displayed on the infoscreen, confirmation screen and kill screen
+ /// The bools specifing whether the strings are in RAM or FLASH.
+ static void sendinfoscreen(const char* line1, const char* line2, const char* line3, const char* line4, bool l1inflash, bool l2inflash, bool l3inflash, bool liinflash);
+
+ static void HandleUserConfirmationPopUp(uint16_t ConfirmVP, const char* line1, const char* line2, const char* line3, const char* line4, bool l1inflash, bool l2inflash, bool l3inflash, bool liinflash);
+
+ /// "M117" Message -- msg is a RAM ptr.
+ static void setstatusmessage(const char* msg);
+ /// The same for messages from Flash
+ static void setstatusmessagePGM(PGM_P const msg);
+ // Callback for VP "Display wants to change screen on idle printer"
+ static void ScreenChangeHookIfIdle(DGUS_VP_Variable &var, void *val_ptr);
+ // Callback for VP "Screen has been changed"
+ static void ScreenChangeHook(DGUS_VP_Variable &var, void *val_ptr);
+ // Callback for VP "All Heaters Off"
+ static void HandleAllHeatersOff(DGUS_VP_Variable &var, void *val_ptr);
+ // Hook for "Change this temperature"
+ static void HandleTemperatureChanged(DGUS_VP_Variable &var, void *val_ptr);
+ // Hook for "Change Flowrate"
+ static void HandleFlowRateChanged(DGUS_VP_Variable &var, void *val_ptr);
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ // Hook for manual move option
+ static void HandleManualMoveOption(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ // Hook for manual move.
+ static void HandleManualMove(DGUS_VP_Variable &var, void *val_ptr);
+ // Hook for manual extrude.
+ static void HandleManualExtrude(DGUS_VP_Variable &var, void *val_ptr);
+ // Hook for motor lock and unlook
+ static void HandleMotorLockUnlock(DGUS_VP_Variable &var, void *val_ptr);
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ // Hook for power loss recovery.
+ static void HandlePowerLossRecovery(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ // Hook for settings
+ static void HandleSettings(DGUS_VP_Variable &var, void *val_ptr);
+ static void HandleStepPerMMChanged(DGUS_VP_Variable &var, void *val_ptr);
+ static void HandleStepPerMMExtruderChanged(DGUS_VP_Variable &var, void *val_ptr);
+ #if HAS_PID_HEATING
+ // Hook for "Change this temperature PID para"
+ static void HandleTemperaturePIDChanged(DGUS_VP_Variable &var, void *val_ptr);
+ // Hook for PID autotune
+ static void HandlePIDAutotune(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ #if HAS_BED_PROBE
+ // Hook for "Change probe offset z"
+ static void HandleProbeOffsetZChanged(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ #if ENABLED(BABYSTEPPING)
+ // Hook for live z adjust action
+ static void HandleLiveAdjustZ(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ #if HAS_FAN
+ // Hook for fan control
+ static void HandleFanControl(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ // Hook for heater control
+ static void HandleHeaterControl(DGUS_VP_Variable &var, void *val_ptr);
+ #if ENABLED(DGUS_PREHEAT_UI)
+ // Hook for preheat
+ static void HandlePreheat(DGUS_VP_Variable &var, void *val_ptr);
+ #endif
+ #if ENABLED(DGUS_FILAMENT_LOADUNLOAD)
+ // Hook for filament load and unload filament option
+ static void HandleFilamentOption(DGUS_VP_Variable &var, void *val_ptr);
+ // Hook for filament load and unload
+ static void HandleFilamentLoadUnload(DGUS_VP_Variable &var);
+ #endif
+
+ #if ENABLED(SDSUPPORT)
+ // Callback for VP "Display wants to change screen when there is a SD card"
+ static void ScreenChangeHookIfSD(DGUS_VP_Variable &var, void *val_ptr);
+ /// Scroll buttons on the file listing screen.
+ static void DGUSLCD_SD_ScrollFilelist(DGUS_VP_Variable &var, void *val_ptr);
+ /// File touched.
+ static void DGUSLCD_SD_FileSelected(DGUS_VP_Variable &var, void *val_ptr);
+ /// start print after confirmation received.
+ static void DGUSLCD_SD_StartPrint(DGUS_VP_Variable &var, void *val_ptr);
+ /// User hit the pause, resume or abort button.
+ static void DGUSLCD_SD_ResumePauseAbort(DGUS_VP_Variable &var, void *val_ptr);
+ /// User confirmed the abort action
+ static void DGUSLCD_SD_ReallyAbort(DGUS_VP_Variable &var, void *val_ptr);
+ /// User hit the tune button
+ static void DGUSLCD_SD_PrintTune(DGUS_VP_Variable &var, void *val_ptr);
+ /// Send a single filename to the display.
+ static void DGUSLCD_SD_SendFilename(DGUS_VP_Variable &var);
+ /// Marlin informed us that a new SD has been inserted.
+ static void SDCardInserted();
+ /// Marlin informed us that the SD Card has been removed().
+ static void SDCardRemoved();
+ /// Marlin informed us about a bad SD Card.
+ static void SDCardError();
+ #endif
+
+ // OK Button the Confirm screen.
+ static void ScreenConfirmedOK(DGUS_VP_Variable &var, void *val_ptr);
+
+ // Update data after went to new screen (by display or by GotoScreen)
+ // remember: store the last-displayed screen, so it can get returned to.
+ // (e.g for pop up messages)
+ static void UpdateNewScreen(DGUSLCD_Screens newscreen, bool popup=false);
+
+ // Recall the remembered screen.
+ static void PopToOldScreen();
+
+ // Make the display show the screen and update all VPs in it.
+ static void GotoScreen(DGUSLCD_Screens screen, bool ispopup = false);
+
+ static void UpdateScreenVPData();
+
+ // Helpers to convert and transfer data to the display.
+ static void DGUSLCD_SendWordValueToDisplay(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendStringToDisplay(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendStringToDisplayPGM(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendTemperaturePID(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendPercentageToDisplay(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendPrintProgressToDisplay(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendPrintTimeToDisplay(DGUS_VP_Variable &var);
+ #if ENABLED(PRINTCOUNTER)
+ static void DGUSLCD_SendPrintAccTimeToDisplay(DGUS_VP_Variable &var);
+ static void DGUSLCD_SendPrintsTotalToDisplay(DGUS_VP_Variable &var);
+ #endif
+ #if HAS_FAN
+ static void DGUSLCD_SendFanStatusToDisplay(DGUS_VP_Variable &var);
+ #endif
+ static void DGUSLCD_SendHeaterStatusToDisplay(DGUS_VP_Variable &var);
+ #if ENABLED(DGUS_UI_WAITING)
+ static void DGUSLCD_SendWaitingStatusToDisplay(DGUS_VP_Variable &var);
+ #endif
+
+ /// Send a value from 0..100 to a variable with a range from 0..255
+ static void DGUSLCD_PercentageToUint8(DGUS_VP_Variable &var, void *val_ptr);
+
+ template
+ static void DGUSLCD_SetValueDirectly(DGUS_VP_Variable &var, void *val_ptr) {
+ if (!var.memadr) return;
+ union { unsigned char tmp[sizeof(T)]; T t; } x;
+ unsigned char *ptr = (unsigned char*)val_ptr;
+ LOOP_L_N(i, sizeof(T)) x.tmp[i] = ptr[sizeof(T) - i - 1];
+ *(T*)var.memadr = x.t;
+ }
+
+ /// Send a float value to the display.
+ /// Display will get a 4-byte integer scaled to the number of digits:
+ /// Tell the display the number of digits and it cheats by displaying a dot between...
+ template
+ static void DGUSLCD_SendFloatAsLongValueToDisplay(DGUS_VP_Variable &var) {
+ if (var.memadr) {
+ float f = *(float *)var.memadr;
+ f *= cpow(10, decimals);
+ dgusdisplay.WriteVariable(var.VP, (long)f);
+ }
+ }
+
+ /// Send a float value to the display.
+ /// Display will get a 2-byte integer scaled to the number of digits:
+ /// Tell the display the number of digits and it cheats by displaying a dot between...
+ template
+ static void DGUSLCD_SendFloatAsIntValueToDisplay(DGUS_VP_Variable &var) {
+ if (var.memadr) {
+ float f = *(float *)var.memadr;
+ DEBUG_ECHOLNPAIR_F(" >> ", f, 6);
+ f *= cpow(10, decimals);
+ dgusdisplay.WriteVariable(var.VP, (int16_t)f);
+ }
+ }
+
+ /// Force an update of all VP on the current screen.
+ static inline void ForceCompleteUpdate() { update_ptr = 0; ScreenComplete = false; }
+ /// Has all VPs sent to the screen
+ static inline bool IsScreenComplete() { return ScreenComplete; }
+
+ static inline DGUSLCD_Screens getCurrentScreen() { return current_screen; }
+
+ static inline void SetupConfirmAction( void (*f)()) { confirm_action_cb = f; }
+
+private:
+ static DGUSLCD_Screens current_screen; ///< currently on screen
+ static constexpr uint8_t NUM_PAST_SCREENS = 4;
+ static DGUSLCD_Screens past_screens[NUM_PAST_SCREENS]; ///< LIFO with past screens for the "back" button.
+
+ static uint8_t update_ptr; ///< Last sent entry in the VPList for the actual screen.
+ static uint16_t skipVP; ///< When updating the screen data, skip this one, because the user is interacting with it.
+ static bool ScreenComplete; ///< All VPs sent to screen?
+
+ static uint16_t ConfirmVP; ///< context for confirm screen (VP that will be emulated-sent on "OK").
+
+ #if ENABLED(SDSUPPORT)
+ static int16_t top_file; ///< file on top of file chooser
+ static int16_t file_to_print; ///< touched file to be confirmed
+ #endif
+
+ static void (*confirm_action_cb)();
+};
+
+extern DGUSScreenHandler ScreenHandler;
diff --git a/Marlin/src/lcd/extui/lib/dgus/DGUSVPVariable.h b/Marlin/src/lcd/extui/lib/dgus/DGUSVPVariable.h
new file mode 100644
index 0000000..8c193c7
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/DGUSVPVariable.h
@@ -0,0 +1,49 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+/**
+ * DGUSVPVariable.h
+ *
+ * Created on: Feb 9, 2019
+ * Author: tobi
+ */
+
+struct DGUS_VP_Variable {
+ uint16_t VP;
+ void* memadr; // If nullptr, the value cannot be uploaded to the display.
+ uint8_t size;
+
+ // Callback that will be called if the display modified the value.
+ // nullptr makes it readonly for the display.
+ void (*set_by_display_handler)(DGUS_VP_Variable &var, void *val_ptr);
+ void (*send_to_display_handler)(DGUS_VP_Variable &var);
+
+ template
+ DGUS_VP_Variable& operator =(T &o) {
+ *(T*)memadr = o; // warning this is not typesafe.
+ // TODO: Call out the display or mark as dirty for the next update.
+ return *this;
+ }
+};
diff --git a/Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.cpp
new file mode 100644
index 0000000..467444c
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.cpp
@@ -0,0 +1,486 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/* DGUS VPs changed by George Fu in 2019 for Marlin */
+
+#include "../../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_FYSETC)
+
+#include "DGUSDisplayDef.h"
+#include "../DGUSDisplay.h"
+#include "../DGUSScreenHandler.h"
+
+#include "../../../../../module/temperature.h"
+#include "../../../../../module/motion.h"
+#include "../../../../../module/planner.h"
+
+#include "../../../ui_api.h"
+#include "../../../../marlinui.h"
+
+#if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ uint16_t distanceToMove = 10;
+#endif
+
+const uint16_t VPList_Boot[] PROGMEM = {
+ VP_MARLIN_VERSION,
+ 0x0000
+};
+
+const uint16_t VPList_Main[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded. */
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set, VP_E0_STATUS,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set, VP_BED_STATUS,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage, VP_FAN0_STATUS,
+ #endif
+ VP_XPos, VP_YPos, VP_ZPos,
+ VP_Fan0_Percentage,
+ VP_Feedrate_Percentage,
+ #if ENABLED(LCD_SET_PROGRESS_MANUALLY)
+ VP_PrintProgress_Percentage,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Temp[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Status[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded */
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage,
+ #endif
+ VP_XPos, VP_YPos, VP_ZPos,
+ VP_Fan0_Percentage,
+ VP_Feedrate_Percentage,
+ VP_PrintProgress_Percentage,
+ 0x0000
+};
+
+const uint16_t VPList_Status2[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded */
+ #if HOTENDS >= 1
+ VP_Flowrate_E0,
+ #endif
+ #if HOTENDS >= 2
+ VP_Flowrate_E1,
+ #endif
+ VP_PrintProgress_Percentage,
+ VP_PrintTime,
+ 0x0000
+};
+
+const uint16_t VPList_Preheat[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_ManualMove[] PROGMEM = {
+ VP_XPos, VP_YPos, VP_ZPos,
+ 0x0000
+};
+
+const uint16_t VPList_ManualExtrude[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ VP_EPos,
+ 0x0000
+};
+
+const uint16_t VPList_FanAndFeedrate[] PROGMEM = {
+ VP_Feedrate_Percentage, VP_Fan0_Percentage,
+ 0x0000
+};
+
+const uint16_t VPList_SD_FlowRates[] PROGMEM = {
+ VP_Flowrate_E0, VP_Flowrate_E1,
+ 0x0000
+};
+
+const uint16_t VPList_Filament_heating[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ VP_E0_FILAMENT_LOAD_UNLOAD,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ VP_E1_FILAMENT_LOAD_UNLOAD,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Filament_load_unload[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_E0_FILAMENT_LOAD_UNLOAD,
+ #endif
+ #if HOTENDS >= 2
+ VP_E1_FILAMENT_LOAD_UNLOAD,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_SDFileList[] PROGMEM = {
+ VP_SD_FileName0, VP_SD_FileName1, VP_SD_FileName2, VP_SD_FileName3, VP_SD_FileName4,
+ 0x0000
+};
+
+const uint16_t VPList_SD_PrintManipulation[] PROGMEM = {
+ VP_PrintProgress_Percentage, VP_PrintTime,
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage,
+ #if FAN_COUNT > 1
+ VP_Fan1_Percentage,
+ #endif
+ #endif
+ VP_Flowrate_E0,
+ 0x0000
+};
+
+const uint16_t VPList_SDPrintTune[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set, VP_Flowrate_E0,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set, VP_Flowrate_E1,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ VP_Feedrate_Percentage,
+ VP_SD_Print_ProbeOffsetZ,
+ 0x0000
+};
+
+const uint16_t VPList_StepPerMM[] PROGMEM = {
+ VP_X_STEP_PER_MM,
+ VP_Y_STEP_PER_MM,
+ VP_Z_STEP_PER_MM,
+ #if HOTENDS >= 1
+ VP_E0_STEP_PER_MM,
+ #endif
+ #if HOTENDS >= 2
+ VP_E1_STEP_PER_MM,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_PIDE0[] PROGMEM = {
+ #if ENABLED(PIDTEMP)
+ VP_E0_PID_P,
+ VP_E0_PID_I,
+ VP_E0_PID_D,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_PIDBED[] PROGMEM = {
+ #if ENABLED(PIDTEMP)
+ VP_BED_PID_P,
+ VP_BED_PID_I,
+ VP_BED_PID_D,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Infos[] PROGMEM = {
+ VP_MARLIN_VERSION,
+ VP_PrintTime,
+ #if ENABLED(PRINTCOUNTER)
+ VP_PrintAccTime,
+ VP_PrintsTotal,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_PIDTuningWaiting[] PROGMEM = {
+ VP_WAITING_STATUS,
+ 0x0000
+};
+
+const uint16_t VPList_FLCPreheat[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_FLCPrinting[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_SD_Print_ProbeOffsetZ,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Z_Offset[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_SD_Print_ProbeOffsetZ,
+ #endif
+ 0x0000
+};
+
+const struct VPMapping VPMap[] PROGMEM = {
+ { DGUSLCD_SCREEN_BOOT, VPList_Boot },
+ { DGUSLCD_SCREEN_MAIN, VPList_Main },
+ { DGUSLCD_SCREEN_TEMPERATURE, VPList_Temp },
+ { DGUSLCD_SCREEN_STATUS, VPList_Status },
+ { DGUSLCD_SCREEN_STATUS2, VPList_Status2 },
+ { DGUSLCD_SCREEN_PREHEAT, VPList_Preheat },
+ { DGUSLCD_SCREEN_MANUALMOVE, VPList_ManualMove },
+ { DGUSLCD_SCREEN_MANUALEXTRUDE, VPList_ManualExtrude },
+ { DGUSLCD_SCREEN_FILAMENT_HEATING, VPList_Filament_heating },
+ { DGUSLCD_SCREEN_FILAMENT_LOADING, VPList_Filament_load_unload },
+ { DGUSLCD_SCREEN_FILAMENT_UNLOADING, VPList_Filament_load_unload },
+ { DGUSLCD_SCREEN_SDPRINTMANIPULATION, VPList_SD_PrintManipulation },
+ { DGUSLCD_SCREEN_SDFILELIST, VPList_SDFileList },
+ { DGUSLCD_SCREEN_SDPRINTTUNE, VPList_SDPrintTune },
+ { DGUSLCD_SCREEN_WAITING, VPList_PIDTuningWaiting },
+ { DGUSLCD_SCREEN_FLC_PREHEAT, VPList_FLCPreheat },
+ { DGUSLCD_SCREEN_FLC_PRINTING, VPList_FLCPrinting },
+ { DGUSLCD_SCREEN_Z_OFFSET, VPList_Z_Offset },
+ { DGUSLCD_SCREEN_STEPPERMM, VPList_StepPerMM },
+ { DGUSLCD_SCREEN_PID_E, VPList_PIDE0 },
+ { DGUSLCD_SCREEN_PID_BED, VPList_PIDBED },
+ { DGUSLCD_SCREEN_INFOS, VPList_Infos },
+ { 0 , nullptr } // List is terminated with an nullptr as table entry.
+};
+
+const char MarlinVersion[] PROGMEM = SHORT_BUILD_VERSION;
+
+// Helper to define a DGUS_VP_Variable for common use cases.
+#define VPHELPER(VPADR, VPADRVAR, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=sizeof(VPADRVAR), \
+ .set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
+
+// Helper to define a DGUS_VP_Variable when the sizeo of the var cannot be determined automaticalyl (eg. a string)
+#define VPHELPER_STR(VPADR, VPADRVAR, STRLEN, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=STRLEN, \
+ .set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
+
+const struct DGUS_VP_Variable ListOfVP[] PROGMEM = {
+ // Helper to detect touch events
+ VPHELPER(VP_SCREENCHANGE, nullptr, ScreenHandler.ScreenChangeHook, nullptr),
+ VPHELPER(VP_SCREENCHANGE_ASK, nullptr, ScreenHandler.ScreenChangeHookIfIdle, nullptr),
+ #if ENABLED(SDSUPPORT)
+ VPHELPER(VP_SCREENCHANGE_WHENSD, nullptr, ScreenHandler.ScreenChangeHookIfSD, nullptr),
+ #endif
+ VPHELPER(VP_CONFIRMED, nullptr, ScreenHandler.ScreenConfirmedOK, nullptr),
+
+ VPHELPER(VP_TEMP_ALL_OFF, nullptr, &ScreenHandler.HandleAllHeatersOff, nullptr),
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ VPHELPER(VP_MOVE_OPTION, &distanceToMove, &ScreenHandler.HandleManualMoveOption, nullptr),
+ #endif
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ VPHELPER(VP_MOVE_X, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Y, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Z, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_HOME_ALL, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ #else
+ VPHELPER(VP_MOVE_X, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Y, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Z, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_HOME_ALL, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ #endif
+ VPHELPER(VP_MOTOR_LOCK_UNLOK, nullptr, &ScreenHandler.HandleMotorLockUnlock, nullptr),
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ VPHELPER(VP_POWER_LOSS_RECOVERY, nullptr, &ScreenHandler.HandlePowerLossRecovery, nullptr),
+ #endif
+ VPHELPER(VP_SETTINGS, nullptr, &ScreenHandler.HandleSettings, nullptr),
+ #if ENABLED(SINGLE_Z_CALIBRATION)
+ VPHELPER(VP_Z_CALIBRATE, nullptr, &ScreenHandler.HandleZCalibration, nullptr),
+ #endif
+
+ #if ENABLED(FIRST_LAYER_CAL)
+ VPHELPER(VP_Z_FIRST_LAYER_CAL, nullptr, &ScreenHandler.HandleFirstLayerCal, nullptr),
+ #endif
+
+ { .VP = VP_MARLIN_VERSION, .memadr = (void*)MarlinVersion, .size = VP_MARLIN_VERSION_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ // M117 LCD String (We don't need the string in memory but "just" push it to the display on demand, hence the nullptr
+ { .VP = VP_M117, .memadr = nullptr, .size = VP_M117_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplay },
+
+ // Temperature Data
+ #if HOTENDS >= 1
+ VPHELPER(VP_T_E0_Is, &thermalManager.temp_hotend[0].celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_E0_Set, &thermalManager.temp_hotend[0].target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_Flowrate_E0, &planner.flow_percentage[ExtUI::extruder_t::E0], ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_EPos, &destination.e, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_MOVE_E0, nullptr, &ScreenHandler.HandleManualExtrude, nullptr),
+ VPHELPER(VP_E0_CONTROL, &thermalManager.temp_hotend[0].target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_E0_STATUS, &thermalManager.temp_hotend[0].target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(DGUS_PREHEAT_UI)
+ VPHELPER(VP_E0_BED_PREHEAT, nullptr, &ScreenHandler.HandlePreheat, nullptr),
+ #endif
+ #if ENABLED(PIDTEMP)
+ VPHELPER(VP_E0_PID_P, &thermalManager.temp_hotend[0].pid.Kp, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_E0_PID_I, &thermalManager.temp_hotend[0].pid.Ki, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_E0_PID_D, &thermalManager.temp_hotend[0].pid.Kd, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_PID_AUTOTUNE_E0, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ #if ENABLED(DGUS_FILAMENT_LOADUNLOAD)
+ VPHELPER(VP_E0_FILAMENT_LOAD_UNLOAD, nullptr, &ScreenHandler.HandleFilamentOption, &ScreenHandler.HandleFilamentLoadUnload),
+ #endif
+ #endif
+ #if HOTENDS >= 2
+ VPHELPER(VP_T_E1_Is, &thermalManager.temp_hotend[1].celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_E1_Set, &thermalManager.temp_hotend[1].target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_Flowrate_E1, &planner.flow_percentage[ExtUI::extruder_t::E1], ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_MOVE_E1, nullptr, &ScreenHandler.HandleManualExtrude, nullptr),
+ VPHELPER(VP_E1_CONTROL, &thermalManager.temp_hotend[1].target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_E1_STATUS, &thermalManager.temp_hotend[1].target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(PIDTEMP)
+ VPHELPER(VP_PID_AUTOTUNE_E1, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ VPHELPER(VP_E1_FILAMENT_LOAD_UNLOAD, nullptr, &ScreenHandler.HandleFilamentOption, &ScreenHandler.HandleFilamentLoadUnload),
+ #endif
+ #if HAS_HEATED_BED
+ VPHELPER(VP_T_Bed_Is, &thermalManager.temp_bed.celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_Bed_Set, &thermalManager.temp_bed.target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_BED_CONTROL, &thermalManager.temp_bed.target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_BED_STATUS, &thermalManager.temp_bed.target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(PIDTEMPBED)
+ VPHELPER(VP_BED_PID_P, &thermalManager.temp_bed.pid.Kp, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_BED_PID_I, &thermalManager.temp_bed.pid.Ki, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_BED_PID_D, &thermalManager.temp_bed.pid.Kd, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_PID_AUTOTUNE_BED, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ #endif
+
+ // Fan Data
+ #if HAS_FAN
+ #define FAN_VPHELPER(N) \
+ VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], ScreenHandler.DGUSLCD_PercentageToUint8, &ScreenHandler.DGUSLCD_SendPercentageToDisplay), \
+ VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], &ScreenHandler.HandleFanControl, nullptr), \
+ VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, &ScreenHandler.DGUSLCD_SendFanStatusToDisplay),
+ REPEAT(FAN_COUNT, FAN_VPHELPER)
+ #endif
+
+ // Feedrate
+ VPHELPER(VP_Feedrate_Percentage, &feedrate_percentage, ScreenHandler.DGUSLCD_SetValueDirectly, &ScreenHandler.DGUSLCD_SendWordValueToDisplay ),
+
+ // Position Data
+ VPHELPER(VP_XPos, ¤t_position.x, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_YPos, ¤t_position.y, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_ZPos, ¤t_position.z, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+
+ // Print Progress
+ VPHELPER(VP_PrintProgress_Percentage, nullptr, nullptr, ScreenHandler.DGUSLCD_SendPrintProgressToDisplay ),
+
+ // Print Time
+ VPHELPER_STR(VP_PrintTime, nullptr, VP_PrintTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintTimeToDisplay),
+ #if ENABLED(PRINTCOUNTER)
+ VPHELPER_STR(VP_PrintAccTime, nullptr, VP_PrintAccTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintAccTimeToDisplay),
+ VPHELPER_STR(VP_PrintsTotal, nullptr, VP_PrintsTotal_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintsTotalToDisplay),
+ #endif
+
+ VPHELPER(VP_X_STEP_PER_MM, &planner.settings.axis_steps_per_mm[X_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ VPHELPER(VP_Y_STEP_PER_MM, &planner.settings.axis_steps_per_mm[Y_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ VPHELPER(VP_Z_STEP_PER_MM, &planner.settings.axis_steps_per_mm[Z_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #if HOTENDS >= 1
+ VPHELPER(VP_E0_STEP_PER_MM, &planner.settings.axis_steps_per_mm[E_AXIS_N(0)], ScreenHandler.HandleStepPerMMExtruderChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #endif
+ #if HOTENDS >= 2
+ VPHELPER(VP_E1_STEP_PER_MM, &planner.settings.axis_steps_per_mm[E_AXIS_N(1)], ScreenHandler.HandleStepPerMMExtruderChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #endif
+
+ // SDCard File listing.
+ #if ENABLED(SDSUPPORT)
+ VPHELPER(VP_SD_ScrollEvent, nullptr, ScreenHandler.DGUSLCD_SD_ScrollFilelist, nullptr),
+ VPHELPER(VP_SD_FileSelected, nullptr, ScreenHandler.DGUSLCD_SD_FileSelected, nullptr),
+ VPHELPER(VP_SD_FileSelectConfirm, nullptr, ScreenHandler.DGUSLCD_SD_StartPrint, nullptr),
+ VPHELPER_STR(VP_SD_FileName0, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
+ VPHELPER_STR(VP_SD_FileName1, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
+ VPHELPER_STR(VP_SD_FileName2, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
+ VPHELPER_STR(VP_SD_FileName3, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
+ VPHELPER_STR(VP_SD_FileName4, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename),
+ VPHELPER(VP_SD_ResumePauseAbort, nullptr, ScreenHandler.DGUSLCD_SD_ResumePauseAbort, nullptr),
+ VPHELPER(VP_SD_AbortPrintConfirmed, nullptr, ScreenHandler.DGUSLCD_SD_ReallyAbort, nullptr),
+ VPHELPER(VP_SD_Print_Setting, nullptr, ScreenHandler.DGUSLCD_SD_PrintTune, nullptr),
+ #if HAS_BED_PROBE
+ VPHELPER(VP_SD_Print_ProbeOffsetZ, &probe.offset.z, ScreenHandler.HandleProbeOffsetZChanged, &ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<2>),
+ #if ENABLED(BABYSTEPPING)
+ VPHELPER(VP_SD_Print_LiveAdjustZ, nullptr, ScreenHandler.HandleLiveAdjustZ, nullptr),
+ #endif
+ #endif
+ #endif
+
+ #if ENABLED(DGUS_UI_WAITING)
+ VPHELPER(VP_WAITING_STATUS, nullptr, nullptr, ScreenHandler.DGUSLCD_SendWaitingStatusToDisplay),
+ #endif
+
+ // Messages for the User, shared by the popup and the kill screen. They cant be autouploaded as we do not buffer content.
+ { .VP = VP_MSGSTR1, .memadr = nullptr, .size = VP_MSGSTR1_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR2, .memadr = nullptr, .size = VP_MSGSTR2_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR3, .memadr = nullptr, .size = VP_MSGSTR3_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR4, .memadr = nullptr, .size = VP_MSGSTR4_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+
+ VPHELPER(0, 0, 0, 0) // must be last entry.
+};
+
+#endif // DGUS_LCD_UI_FYSETC
diff --git a/Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.h b/Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.h
new file mode 100644
index 0000000..910f5f7
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/fysetc/DGUSDisplayDef.h
@@ -0,0 +1,296 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../DGUSDisplayDef.h"
+
+enum DGUSLCD_Screens : uint8_t {
+ DGUSLCD_SCREEN_BOOT = 0,
+ DGUSLCD_SCREEN_MAIN = 1,
+ DGUSLCD_SCREEN_STATUS = 1,
+ DGUSLCD_SCREEN_STATUS2 = 1,
+ DGUSLCD_SCREEN_TEMPERATURE = 10,
+ DGUSLCD_SCREEN_PREHEAT = 18,
+ DGUSLCD_SCREEN_POWER_LOSS = 100,
+ DGUSLCD_SCREEN_MANUALMOVE = 192,
+ DGUSLCD_SCREEN_UTILITY = 120,
+ DGUSLCD_SCREEN_FILAMENT_HEATING = 146,
+ DGUSLCD_SCREEN_FILAMENT_LOADING = 148,
+ DGUSLCD_SCREEN_FILAMENT_UNLOADING = 158,
+ DGUSLCD_SCREEN_MANUALEXTRUDE = 160,
+ DGUSLCD_SCREEN_SDFILELIST = 71,
+ DGUSLCD_SCREEN_SDPRINTMANIPULATION = 73,
+ DGUSLCD_SCREEN_SDPRINTTUNE = 75,
+ DGUSLCD_SCREEN_FLC_PREHEAT = 94,
+ DGUSLCD_SCREEN_FLC_PRINTING = 96,
+ DGUSLCD_SCREEN_STEPPERMM = 212,
+ DGUSLCD_SCREEN_PID_E = 214,
+ DGUSLCD_SCREEN_PID_BED = 218,
+ DGUSLCD_SCREEN_Z_OFFSET = 222,
+ DGUSLCD_SCREEN_INFOS = 36,
+ DGUSLCD_SCREEN_CONFIRM = 240,
+ DGUSLCD_SCREEN_KILL = 250, ///< Kill Screen. Must always be 250 (to be able to display "Error wrong LCD Version")
+ DGUSLCD_SCREEN_WAITING = 251,
+ DGUSLCD_SCREEN_POPUP = 252, ///< special target, popup screen will also return this code to say "return to previous screen"
+ DGUSLDC_SCREEN_UNUSED = 255
+};
+
+// Display Memory layout used (T5UID)
+// Except system variables this is arbitrary, just to organize stuff....
+
+// 0x0000 .. 0x0FFF -- System variables and reserved by the display
+// 0x1000 .. 0x1FFF -- Variables to never change location, regardless of UI Version
+// 0x2000 .. 0x2FFF -- Controls (VPs that will trigger some action)
+// 0x3000 .. 0x4FFF -- Marlin Data to be displayed
+// 0x5000 .. -- SPs (if we want to modify display elements, e.g change color or like) -- currently unused
+
+// As there is plenty of space (at least most displays have >8k RAM), we do not pack them too tight,
+// so that we can keep variables nicely together in the address space.
+
+// UI Version always on 0x1000...0x1002 so that the firmware can check this and bail out.
+constexpr uint16_t VP_UI_VERSION_MAJOR = 0x1000; // Major -- incremented when incompatible
+constexpr uint16_t VP_UI_VERSION_MINOR = 0x1001; // Minor -- incremented on new features, but compatible
+constexpr uint16_t VP_UI_VERSION_PATCH = 0x1002; // Patch -- fixed which do not change functionality.
+constexpr uint16_t VP_UI_FLAVOUR = 0x1010; // lets reserve 16 bytes here to determine if UI is suitable for this Marlin. tbd.
+
+// Storage space for the Killscreen messages. 0x1100 - 0x1200 . Reused for the popup.
+constexpr uint16_t VP_MSGSTR1 = 0x1100;
+constexpr uint8_t VP_MSGSTR1_LEN = 0x20; // might be more place for it...
+constexpr uint16_t VP_MSGSTR2 = 0x1140;
+constexpr uint8_t VP_MSGSTR2_LEN = 0x20;
+constexpr uint16_t VP_MSGSTR3 = 0x1180;
+constexpr uint8_t VP_MSGSTR3_LEN = 0x20;
+constexpr uint16_t VP_MSGSTR4 = 0x11C0;
+constexpr uint8_t VP_MSGSTR4_LEN = 0x20;
+
+// Screenchange request for screens that only make sense when printer is idle.
+// e.g movement is only allowed if printer is not printing.
+// Marlin must confirm by setting the screen manually.
+constexpr uint16_t VP_SCREENCHANGE_ASK = 0x2000;
+constexpr uint16_t VP_SCREENCHANGE = 0x2001; // Key-Return button to new menu pressed. Data contains target screen in low byte and info in high byte.
+constexpr uint16_t VP_TEMP_ALL_OFF = 0x2002; // Turn all heaters off. Value arbitrary ;)=
+constexpr uint16_t VP_SCREENCHANGE_WHENSD = 0x2003; // "Print" Button touched -- go only there if there is an SD Card.
+
+constexpr uint16_t VP_CONFIRMED = 0x2010; // OK on confirm screen.
+
+// Buttons on the SD-Card File listing.
+constexpr uint16_t VP_SD_ScrollEvent = 0x2020; // Data: 0 for "up a directory", numbers are the amount to scroll, e.g -1 one up, 1 one down
+constexpr uint16_t VP_SD_FileSelected = 0x2022; // Number of file field selected.
+constexpr uint16_t VP_SD_FileSelectConfirm = 0x2024; // (This is a virtual VP and emulated by the Confirm Screen when a file has been confirmed)
+
+constexpr uint16_t VP_SD_ResumePauseAbort = 0x2026; // Resume(Data=0), Pause(Data=1), Abort(Data=2) SD Card prints
+constexpr uint16_t VP_SD_AbortPrintConfirmed = 0x2028; // Abort print confirmation (virtual, will be injected by the confirm dialog)
+constexpr uint16_t VP_SD_Print_Setting = 0x2040;
+constexpr uint16_t VP_SD_Print_LiveAdjustZ = 0x2050; // Data: 0 down, 1 up
+
+// Controls for movement (we can't use the incremental / decremental feature of the display at this feature works only with 16 bit values
+// (which would limit us to 655.35mm, which is likely not a problem for common setups, but i don't want to rule out hangprinters support)
+// A word about the coding: The VP will be per axis and the return code will be an signed 16 bit value in 0.01 mm resolution, telling us
+// the relative travel amount t he user wants to do. So eg. if the display sends us VP=2100 with value 100, the user wants us to move X by +1 mm.
+constexpr uint16_t VP_MOVE_X = 0x2100;
+constexpr uint16_t VP_MOVE_Y = 0x2102;
+constexpr uint16_t VP_MOVE_Z = 0x2104;
+constexpr uint16_t VP_MOVE_E0 = 0x2110;
+constexpr uint16_t VP_MOVE_E1 = 0x2112;
+//constexpr uint16_t VP_MOVE_E2 = 0x2114;
+//constexpr uint16_t VP_MOVE_E3 = 0x2116;
+//constexpr uint16_t VP_MOVE_E4 = 0x2118;
+//constexpr uint16_t VP_MOVE_E5 = 0x211A;
+constexpr uint16_t VP_HOME_ALL = 0x2120;
+constexpr uint16_t VP_MOTOR_LOCK_UNLOK = 0x2130;
+
+// Power loss recovery
+constexpr uint16_t VP_POWER_LOSS_RECOVERY = 0x2180;
+
+// Fan Control Buttons , switch between "off" and "on"
+constexpr uint16_t VP_FAN0_CONTROL = 0x2200;
+constexpr uint16_t VP_FAN1_CONTROL = 0x2202;
+constexpr uint16_t VP_FAN2_CONTROL = 0x2204;
+constexpr uint16_t VP_FAN3_CONTROL = 0x2206;
+
+// Heater Control Buttons , triged between "cool down" and "heat PLA" state
+constexpr uint16_t VP_E0_CONTROL = 0x2210;
+constexpr uint16_t VP_E1_CONTROL = 0x2212;
+//constexpr uint16_t VP_E2_CONTROL = 0x2214;
+//constexpr uint16_t VP_E3_CONTROL = 0x2216;
+//constexpr uint16_t VP_E4_CONTROL = 0x2218;
+//constexpr uint16_t VP_E5_CONTROL = 0x221A;
+constexpr uint16_t VP_BED_CONTROL = 0x221C;
+
+// Preheat
+constexpr uint16_t VP_E0_BED_PREHEAT = 0x2220;
+constexpr uint16_t VP_E1_BED_PREHEAT = 0x2222;
+//constexpr uint16_t VP_E2_BED_PREHEAT = 0x2224;
+//constexpr uint16_t VP_E3_BED_PREHEAT = 0x2226;
+//constexpr uint16_t VP_E4_BED_PREHEAT = 0x2228;
+//constexpr uint16_t VP_E5_BED_PREHEAT = 0x222A;
+
+// Filament load and unload
+constexpr uint16_t VP_E0_FILAMENT_LOAD_UNLOAD = 0x2300;
+constexpr uint16_t VP_E1_FILAMENT_LOAD_UNLOAD = 0x2302;
+
+// Settings store , reset
+constexpr uint16_t VP_SETTINGS = 0x2400;
+
+// PID autotune
+constexpr uint16_t VP_PID_AUTOTUNE_E0 = 0x2410;
+constexpr uint16_t VP_PID_AUTOTUNE_E1 = 0x2412;
+//constexpr uint16_t VP_PID_AUTOTUNE_E2 = 0x2414;
+//constexpr uint16_t VP_PID_AUTOTUNE_E3 = 0x2416;
+//constexpr uint16_t VP_PID_AUTOTUNE_E4 = 0x2418;
+//constexpr uint16_t VP_PID_AUTOTUNE_E5 = 0x241A;
+constexpr uint16_t VP_PID_AUTOTUNE_BED = 0x2420;
+
+// Calibrate Z
+constexpr uint16_t VP_Z_CALIBRATE = 0x2430;
+
+// First layer cal
+constexpr uint16_t VP_Z_FIRST_LAYER_CAL = 0x2500; // Data: 0 - Cancel first layer cal progress, >0 filament type have loaded
+
+// Firmware version on the boot screen.
+constexpr uint16_t VP_MARLIN_VERSION = 0x3000;
+constexpr uint8_t VP_MARLIN_VERSION_LEN = 16; // there is more space on the display, if needed.
+
+// Place for status messages.
+constexpr uint16_t VP_M117 = 0x3020;
+constexpr uint8_t VP_M117_LEN = 0x20;
+
+// Temperatures.
+constexpr uint16_t VP_T_E0_Is = 0x3060; // 4 Byte Integer
+constexpr uint16_t VP_T_E0_Set = 0x3062; // 2 Byte Integer
+constexpr uint16_t VP_T_E1_Is = 0x3064; // 4 Byte Integer
+
+// reserved to support up to 6 Extruders:
+constexpr uint16_t VP_T_E1_Set = 0x3066; // 2 Byte Integer
+//constexpr uint16_t VP_T_E2_Is = 0x3068; // 4 Byte Integer
+//constexpr uint16_t VP_T_E2_Set = 0x306A; // 2 Byte Integer
+//constexpr uint16_t VP_T_E3_Is = 0x306C; // 4 Byte Integer
+//constexpr uint16_t VP_T_E3_Set = 0x306E; // 2 Byte Integer
+//constexpr uint16_t VP_T_E4_Is = 0x3070; // 4 Byte Integer
+//constexpr uint16_t VP_T_E4_Set = 0x3072; // 2 Byte Integer
+//constexpr uint16_t VP_T_E4_Is = 0x3074; // 4 Byte Integer
+//constexpr uint16_t VP_T_E4_Set = 0x3076; // 2 Byte Integer
+//constexpr uint16_t VP_T_E5_Is = 0x3078; // 4 Byte Integer
+//constexpr uint16_t VP_T_E5_Set = 0x307A; // 2 Byte Integer
+
+constexpr uint16_t VP_T_Bed_Is = 0x3080; // 4 Byte Integer
+constexpr uint16_t VP_T_Bed_Set = 0x3082; // 2 Byte Integer
+
+constexpr uint16_t VP_Flowrate_E0 = 0x3090; // 2 Byte Integer
+constexpr uint16_t VP_Flowrate_E1 = 0x3092; // 2 Byte Integer
+
+// reserved for up to 6 Extruders:
+//constexpr uint16_t VP_Flowrate_E2 = 0x3094;
+//constexpr uint16_t VP_Flowrate_E3 = 0x3096;
+//constexpr uint16_t VP_Flowrate_E4 = 0x3098;
+//constexpr uint16_t VP_Flowrate_E5 = 0x309A;
+
+constexpr uint16_t VP_Fan0_Percentage = 0x3100; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan1_Percentage = 0x3102; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan2_Percentage = 0x3104; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan3_Percentage = 0x3106; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Feedrate_Percentage = 0x3108; // 2 Byte Integer (0..100)
+
+// Actual Position
+constexpr uint16_t VP_XPos = 0x3110; // 4 Byte Fixed point number; format xxx.yy
+constexpr uint16_t VP_YPos = 0x3112; // 4 Byte Fixed point number; format xxx.yy
+constexpr uint16_t VP_ZPos = 0x3114; // 4 Byte Fixed point number; format xxx.yy
+
+constexpr uint16_t VP_EPos = 0x3120; // 4 Byte Fixed point number; format xxx.yy
+
+constexpr uint16_t VP_PrintProgress_Percentage = 0x3130; // 2 Byte Integer (0..100)
+
+constexpr uint16_t VP_PrintTime = 0x3140;
+constexpr uint16_t VP_PrintTime_LEN = 32;
+
+constexpr uint16_t VP_PrintAccTime = 0x3160;
+constexpr uint16_t VP_PrintAccTime_LEN = 32;
+
+constexpr uint16_t VP_PrintsTotal = 0x3180;
+constexpr uint16_t VP_PrintsTotal_LEN = 16;
+
+// SDCard File Listing
+constexpr uint16_t VP_SD_FileName_LEN = 32; // LEN is shared for all entries.
+constexpr uint16_t DGUS_SD_FILESPERSCREEN = 5; // FIXME move that info to the display and read it from there.
+constexpr uint16_t VP_SD_FileName0 = 0x3200;
+constexpr uint16_t VP_SD_FileName1 = 0x3220;
+constexpr uint16_t VP_SD_FileName2 = 0x3240;
+constexpr uint16_t VP_SD_FileName3 = 0x3260;
+constexpr uint16_t VP_SD_FileName4 = 0x3280;
+
+constexpr uint16_t VP_SD_Print_ProbeOffsetZ = 0x32A0; //
+constexpr uint16_t VP_SD_Print_Filename = 0x32C0;
+
+// Fan status
+constexpr uint16_t VP_FAN0_STATUS = 0x3300;
+constexpr uint16_t VP_FAN1_STATUS = 0x3302;
+constexpr uint16_t VP_FAN2_STATUS = 0x3304;
+constexpr uint16_t VP_FAN3_STATUS = 0x3306;
+
+// Heater status
+constexpr uint16_t VP_E0_STATUS = 0x3310;
+constexpr uint16_t VP_E1_STATUS = 0x3312;
+//constexpr uint16_t VP_E2_STATUS = 0x3314;
+//constexpr uint16_t VP_E3_STATUS = 0x3316;
+//constexpr uint16_t VP_E4_STATUS = 0x3318;
+//constexpr uint16_t VP_E5_STATUS = 0x331A;
+constexpr uint16_t VP_BED_STATUS = 0x331C;
+
+constexpr uint16_t VP_MOVE_OPTION = 0x3400;
+
+// Step per mm
+constexpr uint16_t VP_X_STEP_PER_MM = 0x3600; // at the moment , 2 byte unsigned int , 0~1638.4
+//constexpr uint16_t VP_X2_STEP_PER_MM = 0x3602;
+constexpr uint16_t VP_Y_STEP_PER_MM = 0x3604;
+//constexpr uint16_t VP_Y2_STEP_PER_MM = 0x3606;
+constexpr uint16_t VP_Z_STEP_PER_MM = 0x3608;
+//constexpr uint16_t VP_Z2_STEP_PER_MM = 0x360A;
+constexpr uint16_t VP_E0_STEP_PER_MM = 0x3610;
+constexpr uint16_t VP_E1_STEP_PER_MM = 0x3612;
+//constexpr uint16_t VP_E2_STEP_PER_MM = 0x3614;
+//constexpr uint16_t VP_E3_STEP_PER_MM = 0x3616;
+//constexpr uint16_t VP_E4_STEP_PER_MM = 0x3618;
+//constexpr uint16_t VP_E5_STEP_PER_MM = 0x361A;
+
+// PIDs
+constexpr uint16_t VP_E0_PID_P = 0x3700; // at the moment , 2 byte unsigned int , 0~1638.4
+constexpr uint16_t VP_E0_PID_I = 0x3702;
+constexpr uint16_t VP_E0_PID_D = 0x3704;
+constexpr uint16_t VP_E1_PID_P = 0x3706; // at the moment , 2 byte unsigned int , 0~1638.4
+constexpr uint16_t VP_E1_PID_I = 0x3708;
+constexpr uint16_t VP_E1_PID_D = 0x370A;
+constexpr uint16_t VP_BED_PID_P = 0x3710;
+constexpr uint16_t VP_BED_PID_I = 0x3712;
+constexpr uint16_t VP_BED_PID_D = 0x3714;
+
+// Wating screen status
+constexpr uint16_t VP_WAITING_STATUS = 0x3800;
+
+// SPs for certain variables...
+// located at 0x5000 and up
+// Not used yet!
+// This can be used e.g to make controls / data display invisible
+constexpr uint16_t SP_T_E0_Is = 0x5000;
+constexpr uint16_t SP_T_E0_Set = 0x5010;
+constexpr uint16_t SP_T_E1_Is = 0x5020;
+constexpr uint16_t SP_T_Bed_Is = 0x5030;
+constexpr uint16_t SP_T_Bed_Set = 0x5040;
diff --git a/Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.cpp
new file mode 100644
index 0000000..536640e
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.cpp
@@ -0,0 +1,485 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/* DGUS VPs changed by George Fu in 2019 for Marlin */
+
+#include "../../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_HIPRECY)
+
+#include "DGUSDisplayDef.h"
+#include "../DGUSDisplay.h"
+#include "../DGUSScreenHandler.h"
+
+#include "../../../../../module/temperature.h"
+#include "../../../../../module/motion.h"
+#include "../../../../../module/planner.h"
+
+#include "../../../ui_api.h"
+#include "../../../../marlinui.h"
+
+#if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ uint16_t distanceToMove = 10;
+#endif
+
+const uint16_t VPList_Boot[] PROGMEM = {
+ VP_MARLIN_VERSION,
+ 0x0000
+};
+
+const uint16_t VPList_Main[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded. */
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set, VP_E0_STATUS,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set, VP_BED_STATUS,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage, VP_FAN0_STATUS,
+ #endif
+ VP_XPos, VP_YPos, VP_ZPos,
+ VP_Fan0_Percentage,
+ VP_Feedrate_Percentage,
+ #if ENABLED(LCD_SET_PROGRESS_MANUALLY)
+ VP_PrintProgress_Percentage,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Temp[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Status[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded */
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage,
+ #endif
+ VP_XPos, VP_YPos, VP_ZPos,
+ VP_Fan0_Percentage,
+ VP_Feedrate_Percentage,
+ VP_PrintProgress_Percentage,
+ 0x0000
+};
+
+const uint16_t VPList_Status2[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded */
+ #if HOTENDS >= 1
+ VP_Flowrate_E0,
+ #endif
+ #if HOTENDS >= 2
+ VP_Flowrate_E1,
+ #endif
+ VP_PrintProgress_Percentage,
+ VP_PrintTime,
+ 0x0000
+};
+
+const uint16_t VPList_Preheat[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_ManualMove[] PROGMEM = {
+ VP_XPos, VP_YPos, VP_ZPos,
+ 0x0000
+};
+
+const uint16_t VPList_ManualExtrude[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ VP_EPos,
+ 0x0000
+};
+
+const uint16_t VPList_FanAndFeedrate[] PROGMEM = {
+ VP_Feedrate_Percentage, VP_Fan0_Percentage,
+ 0x0000
+};
+
+const uint16_t VPList_SD_FlowRates[] PROGMEM = {
+ VP_Flowrate_E0, VP_Flowrate_E1,
+ 0x0000
+};
+
+const uint16_t VPList_Filament_heating[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ VP_E0_FILAMENT_LOAD_UNLOAD,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Filament_load_unload[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_E0_FILAMENT_LOAD_UNLOAD,
+ #endif
+ #if HOTENDS >= 2
+ VP_E1_FILAMENT_LOAD_UNLOAD,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_SDFileList[] PROGMEM = {
+ VP_SD_FileName0, VP_SD_FileName1, VP_SD_FileName2, VP_SD_FileName3, VP_SD_FileName4,
+ 0x0000
+};
+
+const uint16_t VPList_SD_PrintManipulation[] PROGMEM = {
+ VP_PrintProgress_Percentage, VP_PrintTime,
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage,
+ #if FAN_COUNT > 1
+ VP_Fan1_Percentage,
+ #endif
+ #endif
+ VP_Flowrate_E0,
+ 0x0000
+};
+
+const uint16_t VPList_SDPrintTune[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ VP_Feedrate_Percentage,
+ #if HAS_FAN
+ VP_Fan0_Percentage,
+ #endif
+ VP_Flowrate_E0,
+ VP_SD_Print_ProbeOffsetZ,
+ 0x0000
+};
+
+const uint16_t VPList_StepPerMM[] PROGMEM = {
+ VP_X_STEP_PER_MM,
+ VP_Y_STEP_PER_MM,
+ VP_Z_STEP_PER_MM,
+ #if HOTENDS >= 1
+ VP_E0_STEP_PER_MM,
+ #endif
+ #if HOTENDS >= 2
+ VP_E1_STEP_PER_MM,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_PIDE0[] PROGMEM = {
+ #if ENABLED(PIDTEMP)
+ VP_E0_PID_P,
+ VP_E0_PID_I,
+ VP_E0_PID_D,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_PIDBED[] PROGMEM = {
+ #if ENABLED(PIDTEMP)
+ VP_BED_PID_P,
+ VP_BED_PID_I,
+ VP_BED_PID_D,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Infos[] PROGMEM = {
+ VP_MARLIN_VERSION,
+ VP_PrintTime,
+ #if ENABLED(PRINTCOUNTER)
+ VP_PrintAccTime,
+ VP_PrintsTotal,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_PIDTuningWaiting[] PROGMEM = {
+ VP_WAITING_STATUS,
+ 0x0000
+};
+
+const uint16_t VPList_FLCPreheat[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_FLCPrinting[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_SD_Print_ProbeOffsetZ,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Z_Offset[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_SD_Print_ProbeOffsetZ,
+ #endif
+ 0x0000
+};
+
+const struct VPMapping VPMap[] PROGMEM = {
+ { DGUSLCD_SCREEN_BOOT, VPList_Boot },
+ { DGUSLCD_SCREEN_MAIN, VPList_Main },
+ { DGUSLCD_SCREEN_TEMPERATURE, VPList_Temp },
+ { DGUSLCD_SCREEN_STATUS, VPList_Status },
+ { DGUSLCD_SCREEN_STATUS2, VPList_Status2 },
+ { DGUSLCD_SCREEN_PREHEAT, VPList_Preheat },
+ { DGUSLCD_SCREEN_MANUALMOVE, VPList_ManualMove },
+ { DGUSLCD_SCREEN_Z_OFFSET, VPList_Z_Offset },
+ { DGUSLCD_SCREEN_MANUALEXTRUDE, VPList_ManualExtrude },
+ { DGUSLCD_SCREEN_FILAMENT_HEATING, VPList_Filament_heating },
+ { DGUSLCD_SCREEN_FILAMENT_LOADING, VPList_Filament_load_unload },
+ { DGUSLCD_SCREEN_FILAMENT_UNLOADING, VPList_Filament_load_unload },
+ { DGUSLCD_SCREEN_SDPRINTMANIPULATION, VPList_SD_PrintManipulation },
+ { DGUSLCD_SCREEN_SDFILELIST, VPList_SDFileList },
+ { DGUSLCD_SCREEN_SDPRINTTUNE, VPList_SDPrintTune },
+ { DGUSLCD_SCREEN_WAITING, VPList_PIDTuningWaiting },
+ { DGUSLCD_SCREEN_FLC_PREHEAT, VPList_FLCPreheat },
+ { DGUSLCD_SCREEN_FLC_PRINTING, VPList_FLCPrinting },
+ { DGUSLCD_SCREEN_STEPPERMM, VPList_StepPerMM },
+ { DGUSLCD_SCREEN_PID_E, VPList_PIDE0 },
+ { DGUSLCD_SCREEN_PID_BED, VPList_PIDBED },
+ { DGUSLCD_SCREEN_INFOS, VPList_Infos },
+ { 0 , nullptr } // List is terminated with an nullptr as table entry.
+};
+
+const char MarlinVersion[] PROGMEM = SHORT_BUILD_VERSION;
+
+// Helper to define a DGUS_VP_Variable for common use cases.
+#define VPHELPER(VPADR, VPADRVAR, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=sizeof(VPADRVAR), \
+ .set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
+
+// Helper to define a DGUS_VP_Variable when the sizeo of the var cannot be determined automaticalyl (eg. a string)
+#define VPHELPER_STR(VPADR, VPADRVAR, STRLEN, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=STRLEN, \
+ .set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
+
+const struct DGUS_VP_Variable ListOfVP[] PROGMEM = {
+ // Helper to detect touch events
+ VPHELPER(VP_SCREENCHANGE, nullptr, ScreenHandler.ScreenChangeHook, nullptr),
+ VPHELPER(VP_SCREENCHANGE_ASK, nullptr, ScreenHandler.ScreenChangeHookIfIdle, nullptr),
+ #if ENABLED(SDSUPPORT)
+ VPHELPER(VP_SCREENCHANGE_WHENSD, nullptr, ScreenHandler.ScreenChangeHookIfSD, nullptr),
+ #endif
+ VPHELPER(VP_CONFIRMED, nullptr, ScreenHandler.ScreenConfirmedOK, nullptr),
+
+ VPHELPER(VP_TEMP_ALL_OFF, nullptr, &ScreenHandler.HandleAllHeatersOff, nullptr),
+
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ VPHELPER(VP_MOVE_OPTION, &distanceToMove, &ScreenHandler.HandleManualMoveOption, nullptr),
+ #endif
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ VPHELPER(VP_MOVE_X, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Y, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Z, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_HOME_ALL, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ #else
+ VPHELPER(VP_MOVE_X, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Y, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Z, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_HOME_ALL, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ #endif
+ VPHELPER(VP_MOTOR_LOCK_UNLOK, nullptr, &ScreenHandler.HandleMotorLockUnlock, nullptr),
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ VPHELPER(VP_POWER_LOSS_RECOVERY, nullptr, &ScreenHandler.HandlePowerLossRecovery, nullptr),
+ #endif
+ VPHELPER(VP_SETTINGS, nullptr, &ScreenHandler.HandleSettings, nullptr),
+ #if ENABLED(SINGLE_Z_CALIBRATION)
+ VPHELPER(VP_Z_CALIBRATE, nullptr, &ScreenHandler.HandleZCalibration, nullptr),
+ #endif
+ #if ENABLED(FIRST_LAYER_CAL)
+ VPHELPER(VP_Z_FIRST_LAYER_CAL, nullptr, &ScreenHandler.HandleFirstLayerCal, nullptr),
+ #endif
+
+ { .VP = VP_MARLIN_VERSION, .memadr = (void*)MarlinVersion, .size = VP_MARLIN_VERSION_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ // M117 LCD String (We don't need the string in memory but "just" push it to the display on demand, hence the nullptr
+ { .VP = VP_M117, .memadr = nullptr, .size = VP_M117_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplay },
+
+ // Temperature Data
+ #if HOTENDS >= 1
+ VPHELPER(VP_T_E0_Is, &thermalManager.temp_hotend[0].celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_E0_Set, &thermalManager.temp_hotend[0].target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_Flowrate_E0, &planner.flow_percentage[ExtUI::extruder_t::E0], ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_EPos, &destination.e, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_MOVE_E0, nullptr, &ScreenHandler.HandleManualExtrude, nullptr),
+ VPHELPER(VP_E0_CONTROL, &thermalManager.temp_hotend[0].target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_E0_STATUS, &thermalManager.temp_hotend[0].target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(DGUS_PREHEAT_UI)
+ VPHELPER(VP_E0_BED_PREHEAT, nullptr, &ScreenHandler.HandlePreheat, nullptr),
+ #endif
+ #if ENABLED(DGUS_FILAMENT_LOADUNLOAD)
+ VPHELPER(VP_E0_FILAMENT_LOAD_UNLOAD, nullptr, &ScreenHandler.HandleFilamentOption, &ScreenHandler.HandleFilamentLoadUnload),
+ #endif
+ #if ENABLED(PIDTEMP)
+ VPHELPER(VP_E0_PID_P, &thermalManager.temp_hotend[0].pid.Kp, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_E0_PID_I, &thermalManager.temp_hotend[0].pid.Ki, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_E0_PID_D, &thermalManager.temp_hotend[0].pid.Kd, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_PID_AUTOTUNE_E0, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ #endif
+ #if HOTENDS >= 2
+ VPHELPER(VP_T_E1_Is, &thermalManager.temp_hotend[1].celsius, nullptr, DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_E1_Set, &thermalManager.temp_hotend[1].target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_Flowrate_E1, nullptr, ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_MOVE_E1, nullptr, &ScreenHandler.HandleManualExtrude, nullptr),
+ VPHELPER(VP_E1_CONTROL, &thermalManager.temp_hotend[1].target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_E1_STATUS, &thermalManager.temp_hotend[1].target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #endif
+ #if HAS_HEATED_BED
+ VPHELPER(VP_T_Bed_Is, &thermalManager.temp_bed.celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_Bed_Set, &thermalManager.temp_bed.target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_BED_CONTROL, &thermalManager.temp_bed.target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_BED_STATUS, &thermalManager.temp_bed.target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(PIDTEMP)
+ VPHELPER(VP_BED_PID_P, &thermalManager.temp_bed.pid.Kp, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_BED_PID_I, &thermalManager.temp_bed.pid.Ki, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_BED_PID_D, &thermalManager.temp_bed.pid.Kd, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_PID_AUTOTUNE_BED, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ #endif
+
+ // Fan Data
+ #if HAS_FAN
+ #define FAN_VPHELPER(N) \
+ VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], ScreenHandler.DGUSLCD_PercentageToUint8, &ScreenHandler.DGUSLCD_SendPercentageToDisplay), \
+ VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], &ScreenHandler.HandleFanControl, nullptr), \
+ VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, &ScreenHandler.DGUSLCD_SendFanStatusToDisplay),
+ REPEAT(FAN_COUNT, FAN_VPHELPER)
+ #endif
+
+ // Feedrate
+ VPHELPER(VP_Feedrate_Percentage, &feedrate_percentage, ScreenHandler.DGUSLCD_SetValueDirectly, &ScreenHandler.DGUSLCD_SendWordValueToDisplay ),
+
+ // Position Data
+ VPHELPER(VP_XPos, ¤t_position.x, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_YPos, ¤t_position.y, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_ZPos, ¤t_position.z, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+
+ // Print Progress
+ VPHELPER(VP_PrintProgress_Percentage, nullptr, nullptr, ScreenHandler.DGUSLCD_SendPrintProgressToDisplay ),
+
+ // Print Time
+ VPHELPER_STR(VP_PrintTime, nullptr, VP_PrintTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintTimeToDisplay ),
+ #if ENABLED(PRINTCOUNTER)
+ VPHELPER_STR(VP_PrintAccTime, nullptr, VP_PrintAccTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintAccTimeToDisplay ),
+ VPHELPER_STR(VP_PrintsTotal, nullptr, VP_PrintsTotal_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintsTotalToDisplay ),
+ #endif
+
+ VPHELPER(VP_X_STEP_PER_MM, &planner.settings.axis_steps_per_mm[X_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ VPHELPER(VP_Y_STEP_PER_MM, &planner.settings.axis_steps_per_mm[Y_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ VPHELPER(VP_Z_STEP_PER_MM, &planner.settings.axis_steps_per_mm[Z_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #if HOTENDS >= 1
+ VPHELPER(VP_E0_STEP_PER_MM, &planner.settings.axis_steps_per_mm[E_AXIS_N(0)], ScreenHandler.HandleStepPerMMExtruderChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #endif
+ #if HOTENDS >= 2
+ VPHELPER(VP_E1_STEP_PER_MM, &planner.settings.axis_steps_per_mm[E_AXIS_N(1)], ScreenHandler.HandleStepPerMMExtruderChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #endif
+
+ // SDCard File listing.
+ #if ENABLED(SDSUPPORT)
+ VPHELPER(VP_SD_ScrollEvent, nullptr, ScreenHandler.DGUSLCD_SD_ScrollFilelist, nullptr),
+ VPHELPER(VP_SD_FileSelected, nullptr, ScreenHandler.DGUSLCD_SD_FileSelected, nullptr),
+ VPHELPER(VP_SD_FileSelectConfirm, nullptr, ScreenHandler.DGUSLCD_SD_StartPrint, nullptr),
+ VPHELPER_STR(VP_SD_FileName0, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName1, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName2, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName3, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName4, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER(VP_SD_ResumePauseAbort, nullptr, ScreenHandler.DGUSLCD_SD_ResumePauseAbort, nullptr),
+ VPHELPER(VP_SD_AbortPrintConfirmed, nullptr, ScreenHandler.DGUSLCD_SD_ReallyAbort, nullptr),
+ VPHELPER(VP_SD_Print_Setting, nullptr, ScreenHandler.DGUSLCD_SD_PrintTune, nullptr),
+ #if HAS_BED_PROBE
+ VPHELPER(VP_SD_Print_ProbeOffsetZ, &probe.offset.z, ScreenHandler.HandleProbeOffsetZChanged, &ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<2>),
+ #if ENABLED(BABYSTEPPING)
+ VPHELPER(VP_SD_Print_LiveAdjustZ, nullptr, ScreenHandler.HandleLiveAdjustZ, nullptr),
+ #endif
+ #endif
+ #endif
+
+ #if ENABLED(DGUS_UI_WAITING)
+ VPHELPER(VP_WAITING_STATUS, nullptr, nullptr, ScreenHandler.DGUSLCD_SendWaitingStatusToDisplay),
+ #endif
+
+ // Messages for the User, shared by the popup and the kill screen. They cant be autouploaded as we do not buffer content.
+ { .VP = VP_MSGSTR1, .memadr = nullptr, .size = VP_MSGSTR1_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR2, .memadr = nullptr, .size = VP_MSGSTR2_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR3, .memadr = nullptr, .size = VP_MSGSTR3_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR4, .memadr = nullptr, .size = VP_MSGSTR4_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+
+ VPHELPER(0, 0, 0, 0) // must be last entry.
+};
+
+#endif // DGUS_LCD_UI_HIPRECY
diff --git a/Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.h b/Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.h
new file mode 100644
index 0000000..d18989a
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/hiprecy/DGUSDisplayDef.h
@@ -0,0 +1,292 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../DGUSDisplayDef.h"
+
+enum DGUSLCD_Screens : uint8_t {
+ DGUSLCD_SCREEN_BOOT = 160,
+ DGUSLCD_SCREEN_MAIN = 1,
+ DGUSLCD_SCREEN_STATUS = 1,
+ DGUSLCD_SCREEN_STATUS2 = 1,
+ DGUSLCD_SCREEN_POWER_LOSS = 17,
+ DGUSLCD_SCREEN_TEMPERATURE = 40,
+ DGUSLCD_SCREEN_MANUALMOVE = 86,
+ DGUSLCD_SCREEN_PREHEAT = 48,
+ DGUSLCD_SCREEN_UTILITY = 70,
+ DGUSLCD_SCREEN_FILAMENT_HEATING = 80,
+ DGUSLCD_SCREEN_FILAMENT_LOADING = 76,
+ DGUSLCD_SCREEN_FILAMENT_UNLOADING = 82,
+ DGUSLCD_SCREEN_MANUALEXTRUDE = 84,
+ DGUSLCD_SCREEN_Z_OFFSET = 88,
+ DGUSLCD_SCREEN_SDFILELIST = 3,
+ DGUSLCD_SCREEN_SDPRINTMANIPULATION = 7,
+ DGUSLCD_SCREEN_SDPRINTTUNE = 9,
+ DGUSLCD_SCREEN_FLC_PREHEAT = 94,
+ DGUSLCD_SCREEN_FLC_PRINTING = 96,
+ DGUSLCD_SCREEN_STEPPERMM = 122,
+ DGUSLCD_SCREEN_PID_E = 126,
+ DGUSLCD_SCREEN_PID_BED = 128,
+ DGUSLCD_SCREEN_INFOS = 131,
+ DGUSLCD_SCREEN_CONFIRM = 240,
+ DGUSLCD_SCREEN_KILL = 250, ///< Kill Screen. Must always be 250 (to be able to display "Error wrong LCD Version")
+ DGUSLCD_SCREEN_WAITING = 251,
+ DGUSLCD_SCREEN_POPUP = 252, ///< special target, popup screen will also return this code to say "return to previous screen"
+ DGUSLDC_SCREEN_UNUSED = 255
+};
+
+// Display Memory layout used (T5UID)
+// Except system variables this is arbitrary, just to organize stuff....
+
+// 0x0000 .. 0x0FFF -- System variables and reserved by the display
+// 0x1000 .. 0x1FFF -- Variables to never change location, regardless of UI Version
+// 0x2000 .. 0x2FFF -- Controls (VPs that will trigger some action)
+// 0x3000 .. 0x4FFF -- Marlin Data to be displayed
+// 0x5000 .. -- SPs (if we want to modify display elements, e.g change color or like) -- currently unused
+
+// As there is plenty of space (at least most displays have >8k RAM), we do not pack them too tight,
+// so that we can keep variables nicely together in the address space.
+
+// UI Version always on 0x1000...0x1002 so that the firmware can check this and bail out.
+constexpr uint16_t VP_UI_VERSION_MAJOR = 0x1000; // Major -- incremented when incompatible
+constexpr uint16_t VP_UI_VERSION_MINOR = 0x1001; // Minor -- incremented on new features, but compatible
+constexpr uint16_t VP_UI_VERSION_PATCH = 0x1002; // Patch -- fixed which do not change functionality.
+constexpr uint16_t VP_UI_FLAVOUR = 0x1010; // lets reserve 16 bytes here to determine if UI is suitable for this Marlin. tbd.
+
+// Storage space for the Killscreen messages. 0x1100 - 0x1200 . Reused for the popup.
+constexpr uint16_t VP_MSGSTR1 = 0x1100;
+constexpr uint8_t VP_MSGSTR1_LEN = 0x20; // might be more place for it...
+constexpr uint16_t VP_MSGSTR2 = 0x1140;
+constexpr uint8_t VP_MSGSTR2_LEN = 0x20;
+constexpr uint16_t VP_MSGSTR3 = 0x1180;
+constexpr uint8_t VP_MSGSTR3_LEN = 0x20;
+constexpr uint16_t VP_MSGSTR4 = 0x11C0;
+constexpr uint8_t VP_MSGSTR4_LEN = 0x20;
+
+// Screenchange request for screens that only make sense when printer is idle.
+// e.g movement is only allowed if printer is not printing.
+// Marlin must confirm by setting the screen manually.
+constexpr uint16_t VP_SCREENCHANGE_ASK = 0x2000;
+constexpr uint16_t VP_SCREENCHANGE = 0x2001; // Key-Return button to new menu pressed. Data contains target screen in low byte and info in high byte.
+constexpr uint16_t VP_TEMP_ALL_OFF = 0x2002; // Turn all heaters off. Value arbitrary ;)=
+constexpr uint16_t VP_SCREENCHANGE_WHENSD = 0x2003; // "Print" Button touched -- go only there if there is an SD Card.
+
+constexpr uint16_t VP_CONFIRMED = 0x2010; // OK on confirm screen.
+
+// Buttons on the SD-Card File listing.
+constexpr uint16_t VP_SD_ScrollEvent = 0x2020; // Data: 0 for "up a directory", numbers are the amount to scroll, e.g -1 one up, 1 one down
+constexpr uint16_t VP_SD_FileSelected = 0x2022; // Number of file field selected.
+constexpr uint16_t VP_SD_FileSelectConfirm = 0x2024; // (This is a virtual VP and emulated by the Confirm Screen when a file has been confirmed)
+
+constexpr uint16_t VP_SD_ResumePauseAbort = 0x2026; // Resume(Data=0), Pause(Data=1), Abort(Data=2) SD Card prints
+constexpr uint16_t VP_SD_AbortPrintConfirmed = 0x2028; // Abort print confirmation (virtual, will be injected by the confirm dialog)
+constexpr uint16_t VP_SD_Print_Setting = 0x2040;
+constexpr uint16_t VP_SD_Print_LiveAdjustZ = 0x2050; // Data: 0 down, 1 up
+
+// Controls for movement (we can't use the incremental / decremental feature of the display at this feature works only with 16 bit values
+// (which would limit us to 655.35mm, which is likely not a problem for common setups, but i don't want to rule out hangprinters support)
+// A word about the coding: The VP will be per axis and the return code will be an signed 16 bit value in 0.01 mm resolution, telling us
+// the relative travel amount t he user wants to do. So eg. if the display sends us VP=2100 with value 100, the user wants us to move X by +1 mm.
+constexpr uint16_t VP_MOVE_X = 0x2100;
+constexpr uint16_t VP_MOVE_Y = 0x2102;
+constexpr uint16_t VP_MOVE_Z = 0x2104;
+constexpr uint16_t VP_MOVE_E0 = 0x2110;
+constexpr uint16_t VP_MOVE_E1 = 0x2112;
+//constexpr uint16_t VP_MOVE_E2 = 0x2114;
+//constexpr uint16_t VP_MOVE_E3 = 0x2116;
+//constexpr uint16_t VP_MOVE_E4 = 0x2118;
+//constexpr uint16_t VP_MOVE_E5 = 0x211A;
+constexpr uint16_t VP_HOME_ALL = 0x2120;
+constexpr uint16_t VP_MOTOR_LOCK_UNLOK = 0x2130;
+
+// Power loss recovery
+constexpr uint16_t VP_POWER_LOSS_RECOVERY = 0x2180;
+
+// Fan Control Buttons , switch between "off" and "on"
+constexpr uint16_t VP_FAN0_CONTROL = 0x2200;
+constexpr uint16_t VP_FAN1_CONTROL = 0x2202;
+//constexpr uint16_t VP_FAN2_CONTROL = 0x2204;
+//constexpr uint16_t VP_FAN3_CONTROL = 0x2206;
+
+// Heater Control Buttons , triged between "cool down" and "heat PLA" state
+constexpr uint16_t VP_E0_CONTROL = 0x2210;
+constexpr uint16_t VP_E1_CONTROL = 0x2212;
+//constexpr uint16_t VP_E2_CONTROL = 0x2214;
+//constexpr uint16_t VP_E3_CONTROL = 0x2216;
+//constexpr uint16_t VP_E4_CONTROL = 0x2218;
+//constexpr uint16_t VP_E5_CONTROL = 0x221A;
+constexpr uint16_t VP_BED_CONTROL = 0x221C;
+
+// Preheat
+constexpr uint16_t VP_E0_BED_PREHEAT = 0x2220;
+//constexpr uint16_t VP_E1_BED_PREHEAT = 0x2222;
+//constexpr uint16_t VP_E2_BED_PREHEAT = 0x2224;
+//constexpr uint16_t VP_E3_BED_PREHEAT = 0x2226;
+//constexpr uint16_t VP_E4_BED_PREHEAT = 0x2228;
+//constexpr uint16_t VP_E5_BED_PREHEAT = 0x222A;
+
+// Filament load and unload
+constexpr uint16_t VP_E0_FILAMENT_LOAD_UNLOAD = 0x2300;
+
+// Settings store , reset
+constexpr uint16_t VP_SETTINGS = 0x2400;
+
+// PID autotune
+constexpr uint16_t VP_PID_AUTOTUNE_E0 = 0x2410;
+//constexpr uint16_t VP_PID_AUTOTUNE_E1 = 0x2412;
+//constexpr uint16_t VP_PID_AUTOTUNE_E2 = 0x2414;
+//constexpr uint16_t VP_PID_AUTOTUNE_E3 = 0x2416;
+//constexpr uint16_t VP_PID_AUTOTUNE_E4 = 0x2418;
+//constexpr uint16_t VP_PID_AUTOTUNE_E5 = 0x241A;
+constexpr uint16_t VP_PID_AUTOTUNE_BED = 0x2420;
+
+// Calibrate Z
+constexpr uint16_t VP_Z_CALIBRATE = 0x2430;
+
+// First layer cal
+constexpr uint16_t VP_Z_FIRST_LAYER_CAL = 0x2500; // Data: 0 - Cancel first layer cal progress, >0 filament type have loaded
+
+// Firmware version on the boot screen.
+constexpr uint16_t VP_MARLIN_VERSION = 0x3000;
+constexpr uint8_t VP_MARLIN_VERSION_LEN = 16; // there is more space on the display, if needed.
+
+// Place for status messages.
+constexpr uint16_t VP_M117 = 0x3020;
+constexpr uint8_t VP_M117_LEN = 0x20;
+
+// Temperatures.
+constexpr uint16_t VP_T_E0_Is = 0x3060; // 4 Byte Integer
+constexpr uint16_t VP_T_E0_Set = 0x3062; // 2 Byte Integer
+constexpr uint16_t VP_T_E1_Is = 0x3064; // 4 Byte Integer
+
+// reserved to support up to 6 Extruders:
+//constexpr uint16_t VP_T_E1_Set = 0x3066; // 2 Byte Integer
+//constexpr uint16_t VP_T_E2_Is = 0x3068; // 4 Byte Integer
+//constexpr uint16_t VP_T_E2_Set = 0x306A; // 2 Byte Integer
+//constexpr uint16_t VP_T_E3_Is = 0x306C; // 4 Byte Integer
+//constexpr uint16_t VP_T_E3_Set = 0x306E; // 2 Byte Integer
+//constexpr uint16_t VP_T_E4_Is = 0x3070; // 4 Byte Integer
+//constexpr uint16_t VP_T_E4_Set = 0x3072; // 2 Byte Integer
+//constexpr uint16_t VP_T_E4_Is = 0x3074; // 4 Byte Integer
+//constexpr uint16_t VP_T_E4_Set = 0x3076; // 2 Byte Integer
+//constexpr uint16_t VP_T_E5_Is = 0x3078; // 4 Byte Integer
+//constexpr uint16_t VP_T_E5_Set = 0x307A; // 2 Byte Integer
+
+constexpr uint16_t VP_T_Bed_Is = 0x3080; // 4 Byte Integer
+constexpr uint16_t VP_T_Bed_Set = 0x3082; // 2 Byte Integer
+
+constexpr uint16_t VP_Flowrate_E0 = 0x3090; // 2 Byte Integer
+constexpr uint16_t VP_Flowrate_E1 = 0x3092; // 2 Byte Integer
+
+// reserved for up to 6 Extruders:
+//constexpr uint16_t VP_Flowrate_E2 = 0x3094;
+//constexpr uint16_t VP_Flowrate_E3 = 0x3096;
+//constexpr uint16_t VP_Flowrate_E4 = 0x3098;
+//constexpr uint16_t VP_Flowrate_E5 = 0x309A;
+
+constexpr uint16_t VP_Fan0_Percentage = 0x3100; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan1_Percentage = 0x3102; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan2_Percentage = 0x3104; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan3_Percentage = 0x3106; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Feedrate_Percentage = 0x3108; // 2 Byte Integer (0..100)
+
+// Actual Position
+constexpr uint16_t VP_XPos = 0x3110; // 4 Byte Fixed point number; format xxx.yy
+constexpr uint16_t VP_YPos = 0x3112; // 4 Byte Fixed point number; format xxx.yy
+constexpr uint16_t VP_ZPos = 0x3114; // 4 Byte Fixed point number; format xxx.yy
+
+constexpr uint16_t VP_EPos = 0x3120; // 4 Byte Fixed point number; format xxx.yy
+
+constexpr uint16_t VP_PrintProgress_Percentage = 0x3130; // 2 Byte Integer (0..100)
+
+constexpr uint16_t VP_PrintTime = 0x3140;
+constexpr uint16_t VP_PrintTime_LEN = 32;
+
+constexpr uint16_t VP_PrintAccTime = 0x3160;
+constexpr uint16_t VP_PrintAccTime_LEN = 32;
+
+constexpr uint16_t VP_PrintsTotal = 0x3180;
+constexpr uint16_t VP_PrintsTotal_LEN = 16;
+
+// SDCard File Listing
+constexpr uint16_t VP_SD_FileName_LEN = 32; // LEN is shared for all entries.
+constexpr uint16_t DGUS_SD_FILESPERSCREEN = 5; // FIXME move that info to the display and read it from there.
+constexpr uint16_t VP_SD_FileName0 = 0x3200;
+constexpr uint16_t VP_SD_FileName1 = 0x3220;
+constexpr uint16_t VP_SD_FileName2 = 0x3240;
+constexpr uint16_t VP_SD_FileName3 = 0x3260;
+constexpr uint16_t VP_SD_FileName4 = 0x3280;
+
+constexpr uint16_t VP_SD_Print_ProbeOffsetZ = 0x32A0; //
+
+constexpr uint16_t VP_SD_Print_Filename = 0x32C0; //
+// Fan status
+constexpr uint16_t VP_FAN0_STATUS = 0x3300;
+constexpr uint16_t VP_FAN1_STATUS = 0x3302;
+//constexpr uint16_t VP_FAN2_STATUS = 0x3304;
+//constexpr uint16_t VP_FAN3_STATUS = 0x3306;
+
+// Heater status
+constexpr uint16_t VP_E0_STATUS = 0x3310;
+//constexpr uint16_t VP_E1_STATUS = 0x3312;
+//constexpr uint16_t VP_E2_STATUS = 0x3314;
+//constexpr uint16_t VP_E3_STATUS = 0x3316;
+//constexpr uint16_t VP_E4_STATUS = 0x3318;
+//constexpr uint16_t VP_E5_STATUS = 0x331A;
+constexpr uint16_t VP_BED_STATUS = 0x331C;
+
+constexpr uint16_t VP_MOVE_OPTION = 0x3400;
+
+// Step per mm
+constexpr uint16_t VP_X_STEP_PER_MM = 0x3600; // at the moment , 2 byte unsigned int , 0~1638.4
+//constexpr uint16_t VP_X2_STEP_PER_MM = 0x3602;
+constexpr uint16_t VP_Y_STEP_PER_MM = 0x3604;
+//constexpr uint16_t VP_Y2_STEP_PER_MM = 0x3606;
+constexpr uint16_t VP_Z_STEP_PER_MM = 0x3608;
+//constexpr uint16_t VP_Z2_STEP_PER_MM = 0x360A;
+constexpr uint16_t VP_E0_STEP_PER_MM = 0x3610;
+//constexpr uint16_t VP_E1_STEP_PER_MM = 0x3612;
+//constexpr uint16_t VP_E2_STEP_PER_MM = 0x3614;
+//constexpr uint16_t VP_E3_STEP_PER_MM = 0x3616;
+//constexpr uint16_t VP_E4_STEP_PER_MM = 0x3618;
+//constexpr uint16_t VP_E5_STEP_PER_MM = 0x361A;
+
+// PIDs
+constexpr uint16_t VP_E0_PID_P = 0x3700; // at the moment , 2 byte unsigned int , 0~1638.4
+constexpr uint16_t VP_E0_PID_I = 0x3702;
+constexpr uint16_t VP_E0_PID_D = 0x3704;
+constexpr uint16_t VP_BED_PID_P = 0x3710;
+constexpr uint16_t VP_BED_PID_I = 0x3712;
+constexpr uint16_t VP_BED_PID_D = 0x3714;
+
+// Wating screen status
+constexpr uint16_t VP_WAITING_STATUS = 0x3800;
+
+// SPs for certain variables...
+// located at 0x5000 and up
+// Not used yet!
+// This can be used e.g to make controls / data display invisible
+constexpr uint16_t SP_T_E0_Is = 0x5000;
+constexpr uint16_t SP_T_E0_Set = 0x5010;
+constexpr uint16_t SP_T_E1_Is = 0x5020;
+constexpr uint16_t SP_T_Bed_Is = 0x5030;
+constexpr uint16_t SP_T_Bed_Set = 0x5040;
diff --git a/Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.cpp
new file mode 100644
index 0000000..28e66e5
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.cpp
@@ -0,0 +1,310 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/* DGUS implementation written by coldtobi in 2019 for Marlin */
+
+#include "../../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(DGUS_LCD_UI_ORIGIN)
+
+#include "DGUSDisplayDef.h"
+#include "../DGUSDisplay.h"
+#include "../DGUSScreenHandler.h"
+
+#include "../../../../../module/temperature.h"
+#include "../../../../../module/motion.h"
+#include "../../../../../module/planner.h"
+
+#include "../../../../marlinui.h"
+#include "../../../ui_api.h"
+
+#if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ uint16_t distanceToMove = 10;
+#endif
+using namespace ExtUI;
+
+const uint16_t VPList_Boot[] PROGMEM = {
+ VP_MARLIN_VERSION,
+ 0x0000
+};
+
+const uint16_t VPList_Main[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded. */
+ 0x0000
+};
+
+const uint16_t VPList_Temp[] PROGMEM = {
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ 0x0000
+};
+
+const uint16_t VPList_Status[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded */
+ #if HOTENDS >= 1
+ VP_T_E0_Is, VP_T_E0_Set,
+ #endif
+ #if HOTENDS >= 2
+ VP_T_E1_Is, VP_T_E1_Set,
+ #endif
+ #if HAS_HEATED_BED
+ VP_T_Bed_Is, VP_T_Bed_Set,
+ #endif
+ #if HAS_FAN
+ VP_Fan0_Percentage,
+ #endif
+ VP_XPos, VP_YPos, VP_ZPos,
+ VP_Fan0_Percentage,
+ VP_Feedrate_Percentage,
+ VP_PrintProgress_Percentage,
+ 0x0000
+};
+
+const uint16_t VPList_Status2[] PROGMEM = {
+ /* VP_M117, for completeness, but it cannot be auto-uploaded */
+ #if HOTENDS >= 1
+ VP_Flowrate_E0,
+ #endif
+ #if HOTENDS >= 2
+ VP_Flowrate_E1,
+ #endif
+ VP_PrintProgress_Percentage,
+ VP_PrintTime,
+ 0x0000
+};
+
+const uint16_t VPList_ManualMove[] PROGMEM = {
+ VP_XPos, VP_YPos, VP_ZPos,
+ 0x0000
+};
+
+const uint16_t VPList_ManualExtrude[] PROGMEM = {
+ VP_EPos,
+ 0x0000
+};
+
+const uint16_t VPList_FanAndFeedrate[] PROGMEM = {
+ VP_Feedrate_Percentage, VP_Fan0_Percentage,
+ 0x0000
+};
+
+const uint16_t VPList_SD_FlowRates[] PROGMEM = {
+ VP_Flowrate_E0, VP_Flowrate_E1,
+ 0x0000
+};
+
+const uint16_t VPList_SDFileList[] PROGMEM = {
+ VP_SD_FileName0, VP_SD_FileName1, VP_SD_FileName2, VP_SD_FileName3, VP_SD_FileName4,
+ 0x0000
+};
+
+const uint16_t VPList_SD_PrintManipulation[] PROGMEM = {
+ VP_PrintProgress_Percentage, VP_PrintTime,
+ 0x0000
+};
+
+const struct VPMapping VPMap[] PROGMEM = {
+ { DGUSLCD_SCREEN_BOOT, VPList_Boot },
+ { DGUSLCD_SCREEN_MAIN, VPList_Main },
+ { DGUSLCD_SCREEN_TEMPERATURE, VPList_Temp },
+ { DGUSLCD_SCREEN_STATUS, VPList_Status },
+ { DGUSLCD_SCREEN_STATUS2, VPList_Status2 },
+ { DGUSLCD_SCREEN_MANUALMOVE, VPList_ManualMove },
+ { DGUSLCD_SCREEN_MANUALEXTRUDE, VPList_ManualExtrude },
+ { DGUSLCD_SCREEN_FANANDFEEDRATE, VPList_FanAndFeedrate },
+ { DGUSLCD_SCREEN_FLOWRATES, VPList_SD_FlowRates },
+ { DGUSLCD_SCREEN_SDPRINTMANIPULATION, VPList_SD_PrintManipulation },
+ { DGUSLCD_SCREEN_SDFILELIST, VPList_SDFileList },
+ { 0 , nullptr } // List is terminated with an nullptr as table entry.
+};
+
+const char MarlinVersion[] PROGMEM = SHORT_BUILD_VERSION;
+
+// Helper to define a DGUS_VP_Variable for common use cases.
+#define VPHELPER(VPADR, VPADRVAR, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=sizeof(VPADRVAR), \
+ .set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
+
+// Helper to define a DGUS_VP_Variable when the sizeo of the var cannot be determined automaticalyl (eg. a string)
+#define VPHELPER_STR(VPADR, VPADRVAR, STRLEN, RXFPTR, TXFPTR ) { .VP=VPADR, .memadr=VPADRVAR, .size=STRLEN, \
+ .set_by_display_handler = RXFPTR, .send_to_display_handler = TXFPTR }
+
+const struct DGUS_VP_Variable ListOfVP[] PROGMEM = {
+ // Helper to detect touch events
+ VPHELPER(VP_SCREENCHANGE, nullptr, ScreenHandler.ScreenChangeHook, nullptr),
+ VPHELPER(VP_SCREENCHANGE_ASK, nullptr, ScreenHandler.ScreenChangeHookIfIdle, nullptr),
+ #if ENABLED(SDSUPPORT)
+ VPHELPER(VP_SCREENCHANGE_WHENSD, nullptr, ScreenHandler.ScreenChangeHookIfSD, nullptr),
+ #endif
+ VPHELPER(VP_CONFIRMED, nullptr, ScreenHandler.ScreenConfirmedOK, nullptr),
+
+ VPHELPER(VP_TEMP_ALL_OFF, nullptr, &ScreenHandler.HandleAllHeatersOff, nullptr),
+
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ VPHELPER(VP_MOVE_OPTION, &distanceToMove, &ScreenHandler.HandleManualMoveOption, nullptr),
+ #endif
+ #if ENABLED(DGUS_UI_MOVE_DIS_OPTION)
+ VPHELPER(VP_MOVE_X, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Y, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Z, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_HOME_ALL, &distanceToMove, &ScreenHandler.HandleManualMove, nullptr),
+ #else
+ VPHELPER(VP_MOVE_X, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Y, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_MOVE_Z, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ VPHELPER(VP_HOME_ALL, nullptr, &ScreenHandler.HandleManualMove, nullptr),
+ #endif
+
+ VPHELPER(VP_MOTOR_LOCK_UNLOK, nullptr, &ScreenHandler.HandleMotorLockUnlock, nullptr),
+ #if ENABLED(POWER_LOSS_RECOVERY)
+ VPHELPER(VP_POWER_LOSS_RECOVERY, nullptr, &ScreenHandler.HandlePowerLossRecovery, nullptr),
+ #endif
+ VPHELPER(VP_SETTINGS, nullptr, &ScreenHandler.HandleSettings, nullptr),
+
+ { .VP = VP_MARLIN_VERSION, .memadr = (void*)MarlinVersion, .size = VP_MARLIN_VERSION_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ // M117 LCD String (We don't need the string in memory but "just" push it to the display on demand, hence the nullptr
+ { .VP = VP_M117, .memadr = nullptr, .size = VP_M117_LEN, .set_by_display_handler = nullptr, .send_to_display_handler =&ScreenHandler.DGUSLCD_SendStringToDisplay },
+
+ // Temperature Data
+ #if HOTENDS >= 1
+ VPHELPER(VP_T_E0_Is, nullptr, nullptr, SET_VARIABLE(getActualTemp_celsius, E0, long)),
+ VPHELPER(VP_T_E0_Set, nullptr, GET_VARIABLE(setTargetTemp_celsius, E0),
+ SET_VARIABLE(getTargetTemp_celsius, E0)),
+ VPHELPER(VP_Flowrate_E0, nullptr, ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_EPos, &destination.e, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_MOVE_E0, nullptr, &ScreenHandler.HandleManualExtrude, nullptr),
+ VPHELPER(VP_E0_CONTROL, &thermalManager.temp_hotend[0].target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_E0_STATUS, &thermalManager.temp_hotend[0].target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(DGUS_PREHEAT_UI)
+ VPHELPER(VP_E0_BED_PREHEAT, nullptr, &ScreenHandler.HandlePreheat, nullptr),
+ #endif
+ #if ENABLED(PIDTEMP)
+ VPHELPER(VP_E0_PID_P, &thermalManager.temp_hotend[0].pid.Kp, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_E0_PID_I, &thermalManager.temp_hotend[0].pid.Ki, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_E0_PID_D, &thermalManager.temp_hotend[0].pid.Kd, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_PID_AUTOTUNE_E0, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ #if ENABLED(DGUS_FILAMENT_LOADUNLOAD)
+ VPHELPER(VP_E0_FILAMENT_LOAD_UNLOAD, nullptr, &ScreenHandler.HandleFilamentOption, &ScreenHandler.HandleFilamentLoadUnload),
+ #endif
+ #endif
+ #if HOTENDS >= 2
+ VPHELPER(VP_T_E1_Is, &thermalManager.temp_hotend[1].celsius, nullptr, DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_E1_Set, &thermalManager.temp_hotend[1].target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_Flowrate_E1, nullptr, ScreenHandler.HandleFlowRateChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_MOVE_E1, nullptr, &ScreenHandler.HandleManualExtrude, nullptr),
+ VPHELPER(VP_E1_CONTROL, &thermalManager.temp_hotend[1].target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_E1_STATUS, &thermalManager.temp_hotend[1].target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(PIDTEMP)
+ VPHELPER(VP_PID_AUTOTUNE_E1, nullptr, &ScreenHandler.HandlePIDAutotune, nullptr),
+ #endif
+ #endif
+ #if HAS_HEATED_BED
+ VPHELPER(VP_T_Bed_Is, &thermalManager.temp_bed.celsius, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<0>),
+ VPHELPER(VP_T_Bed_Set, &thermalManager.temp_bed.target, ScreenHandler.HandleTemperatureChanged, &ScreenHandler.DGUSLCD_SendWordValueToDisplay),
+ VPHELPER(VP_BED_CONTROL, &thermalManager.temp_bed.target, &ScreenHandler.HandleHeaterControl, nullptr),
+ VPHELPER(VP_BED_STATUS, &thermalManager.temp_bed.target, nullptr, &ScreenHandler.DGUSLCD_SendHeaterStatusToDisplay),
+ #if ENABLED(PIDTEMPBED)
+ VPHELPER(VP_BED_PID_P, &thermalManager.temp_bed.pid.Kp, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_BED_PID_I, &thermalManager.temp_bed.pid.Ki, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ VPHELPER(VP_BED_PID_D, &thermalManager.temp_bed.pid.Kd, ScreenHandler.HandleTemperaturePIDChanged, ScreenHandler.DGUSLCD_SendTemperaturePID),
+ #endif
+ #endif
+
+ // Fan Data
+ #if HAS_FAN
+ #define FAN_VPHELPER(N) \
+ VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], ScreenHandler.DGUSLCD_PercentageToUint8, &ScreenHandler.DGUSLCD_SendPercentageToDisplay), \
+ VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], &ScreenHandler.HandleFanControl, nullptr), \
+ VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, &ScreenHandler.DGUSLCD_SendFanStatusToDisplay),
+ REPEAT(FAN_COUNT, FAN_VPHELPER)
+ #endif
+
+ // Feedrate
+ VPHELPER(VP_Feedrate_Percentage, &feedrate_percentage, ScreenHandler.DGUSLCD_SetValueDirectly, &ScreenHandler.DGUSLCD_SendWordValueToDisplay ),
+
+ // Position Data
+ VPHELPER(VP_XPos, ¤t_position.x, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_YPos, ¤t_position.y, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+ VPHELPER(VP_ZPos, ¤t_position.z, nullptr, ScreenHandler.DGUSLCD_SendFloatAsLongValueToDisplay<2>),
+
+ // Print Progress
+ VPHELPER(VP_PrintProgress_Percentage, nullptr, nullptr, ScreenHandler.DGUSLCD_SendPrintProgressToDisplay ),
+
+ // Print Time
+ VPHELPER_STR(VP_PrintTime, nullptr, VP_PrintTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintTimeToDisplay ),
+ #if ENABLED(PRINTCOUNTER)
+ VPHELPER_STR(VP_PrintAccTime, nullptr, VP_PrintAccTime_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintAccTimeToDisplay ),
+ VPHELPER_STR(VP_PrintsTotal, nullptr, VP_PrintsTotal_LEN, nullptr, ScreenHandler.DGUSLCD_SendPrintsTotalToDisplay ),
+ #endif
+
+ VPHELPER(VP_X_STEP_PER_MM, &planner.settings.axis_steps_per_mm[X_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ VPHELPER(VP_Y_STEP_PER_MM, &planner.settings.axis_steps_per_mm[Y_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ VPHELPER(VP_Z_STEP_PER_MM, &planner.settings.axis_steps_per_mm[Z_AXIS], ScreenHandler.HandleStepPerMMChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #if HOTENDS >= 1
+ VPHELPER(VP_E0_STEP_PER_MM, &planner.settings.axis_steps_per_mm[E_AXIS_N(0)], ScreenHandler.HandleStepPerMMExtruderChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #endif
+ #if HOTENDS >= 2
+ VPHELPER(VP_E1_STEP_PER_MM, &planner.settings.axis_steps_per_mm[E_AXIS_N(1)], ScreenHandler.HandleStepPerMMExtruderChanged, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<1>),
+ #endif
+
+ // SDCard File listing.
+ #if ENABLED(SDSUPPORT)
+ VPHELPER(VP_SD_ScrollEvent, nullptr, ScreenHandler.DGUSLCD_SD_ScrollFilelist, nullptr),
+ VPHELPER(VP_SD_FileSelected, nullptr, ScreenHandler.DGUSLCD_SD_FileSelected, nullptr),
+ VPHELPER(VP_SD_FileSelectConfirm, nullptr, ScreenHandler.DGUSLCD_SD_StartPrint, nullptr),
+ VPHELPER_STR(VP_SD_FileName0, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName1, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName2, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName3, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER_STR(VP_SD_FileName4, nullptr, VP_SD_FileName_LEN, nullptr, ScreenHandler.DGUSLCD_SD_SendFilename ),
+ VPHELPER(VP_SD_ResumePauseAbort, nullptr, ScreenHandler.DGUSLCD_SD_ResumePauseAbort, nullptr),
+ VPHELPER(VP_SD_AbortPrintConfirmed, nullptr, ScreenHandler.DGUSLCD_SD_ReallyAbort, nullptr),
+ VPHELPER(VP_SD_Print_Setting, nullptr, ScreenHandler.DGUSLCD_SD_PrintTune, nullptr),
+ #if HAS_BED_PROBE
+ VPHELPER(VP_SD_Print_ProbeOffsetZ, &probe.offset.z, ScreenHandler.HandleProbeOffsetZChanged, &ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<2>),
+ #if ENABLED(BABYSTEPPING)
+ VPHELPER(VP_SD_Print_LiveAdjustZ, nullptr, ScreenHandler.HandleLiveAdjustZ, nullptr),
+ #endif
+ #endif
+ #endif
+
+ #if ENABLED(DGUS_UI_WAITING)
+ VPHELPER(VP_WAITING_STATUS, nullptr, nullptr, ScreenHandler.DGUSLCD_SendWaitingStatusToDisplay),
+ #endif
+
+ // Messages for the User, shared by the popup and the kill screen. They cant be autouploaded as we do not buffer content.
+ { .VP = VP_MSGSTR1, .memadr = nullptr, .size = VP_MSGSTR1_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR2, .memadr = nullptr, .size = VP_MSGSTR2_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR3, .memadr = nullptr, .size = VP_MSGSTR3_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+ { .VP = VP_MSGSTR4, .memadr = nullptr, .size = VP_MSGSTR4_LEN, .set_by_display_handler = nullptr, .send_to_display_handler = &ScreenHandler.DGUSLCD_SendStringToDisplayPGM },
+
+ VPHELPER(0, 0, 0, 0) // must be last entry.
+};
+
+#endif // DGUS_LCD_UI_ORIGIN
diff --git a/Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.h b/Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.h
new file mode 100644
index 0000000..5c5a315
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/dgus/origin/DGUSDisplayDef.h
@@ -0,0 +1,282 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include "../DGUSDisplayDef.h"
+
+enum DGUSLCD_Screens : uint8_t {
+ DGUSLCD_SCREEN_BOOT = 0,
+ DGUSLCD_SCREEN_MAIN = 10,
+ DGUSLCD_SCREEN_TEMPERATURE = 20,
+ DGUSLCD_SCREEN_STATUS = 30,
+ DGUSLCD_SCREEN_STATUS2 = 32,
+ DGUSLCD_SCREEN_MANUALMOVE = 40,
+ DGUSLCD_SCREEN_MANUALEXTRUDE=42,
+ DGUSLCD_SCREEN_FANANDFEEDRATE = 44,
+ DGUSLCD_SCREEN_FLOWRATES = 46,
+ DGUSLCD_SCREEN_SDFILELIST = 50,
+ DGUSLCD_SCREEN_SDPRINTMANIPULATION = 52,
+ DGUSLCD_SCREEN_POWER_LOSS = 100,
+ DGUSLCD_SCREEN_PREHEAT=120,
+ DGUSLCD_SCREEN_UTILITY=110,
+ DGUSLCD_SCREEN_FILAMENT_HEATING=146,
+ DGUSLCD_SCREEN_FILAMENT_LOADING=148,
+ DGUSLCD_SCREEN_FILAMENT_UNLOADING=158,
+ DGUSLCD_SCREEN_SDPRINTTUNE = 170,
+ DGUSLCD_SCREEN_CONFIRM = 240,
+ DGUSLCD_SCREEN_KILL = 250, ///< Kill Screen. Must always be 250 (to be able to display "Error wrong LCD Version")
+ DGUSLCD_SCREEN_WAITING = 251,
+ DGUSLCD_SCREEN_POPUP = 252, ///< special target, popup screen will also return this code to say "return to previous screen"
+ DGUSLDC_SCREEN_UNUSED = 255
+};
+
+// Display Memory layout used (T5UID)
+// Except system variables this is arbitrary, just to organize stuff....
+
+// 0x0000 .. 0x0FFF -- System variables and reserved by the display
+// 0x1000 .. 0x1FFF -- Variables to never change location, regardless of UI Version
+// 0x2000 .. 0x2FFF -- Controls (VPs that will trigger some action)
+// 0x3000 .. 0x4FFF -- Marlin Data to be displayed
+// 0x5000 .. -- SPs (if we want to modify display elements, e.g change color or like) -- currently unused
+
+// As there is plenty of space (at least most displays have >8k RAM), we do not pack them too tight,
+// so that we can keep variables nicely together in the address space.
+
+// UI Version always on 0x1000...0x1002 so that the firmware can check this and bail out.
+constexpr uint16_t VP_UI_VERSION_MAJOR = 0x1000; // Major -- incremented when incompatible
+constexpr uint16_t VP_UI_VERSION_MINOR = 0x1001; // Minor -- incremented on new features, but compatible
+constexpr uint16_t VP_UI_VERSION_PATCH = 0x1002; // Patch -- fixed which do not change functionality.
+constexpr uint16_t VP_UI_FLAVOUR = 0x1010; // lets reserve 16 bytes here to determine if UI is suitable for this Marlin. tbd.
+
+// Storage space for the Killscreen messages. 0x1100 - 0x1200 . Reused for the popup.
+constexpr uint16_t VP_MSGSTR1 = 0x1100;
+constexpr uint8_t VP_MSGSTR1_LEN = 0x20; // might be more place for it...
+constexpr uint16_t VP_MSGSTR2 = 0x1140;
+constexpr uint8_t VP_MSGSTR2_LEN = 0x20;
+constexpr uint16_t VP_MSGSTR3 = 0x1180;
+constexpr uint8_t VP_MSGSTR3_LEN = 0x20;
+constexpr uint16_t VP_MSGSTR4 = 0x11C0;
+constexpr uint8_t VP_MSGSTR4_LEN = 0x20;
+
+// Screenchange request for screens that only make sense when printer is idle.
+// e.g movement is only allowed if printer is not printing.
+// Marlin must confirm by setting the screen manually.
+constexpr uint16_t VP_SCREENCHANGE_ASK = 0x2000;
+constexpr uint16_t VP_SCREENCHANGE = 0x2001; // Key-Return button to new menu pressed. Data contains target screen in low byte and info in high byte.
+constexpr uint16_t VP_TEMP_ALL_OFF = 0x2002; // Turn all heaters off. Value arbitrary ;)=
+constexpr uint16_t VP_SCREENCHANGE_WHENSD = 0x2003; // "Print" Button touched -- go only there if there is an SD Card.
+
+constexpr uint16_t VP_CONFIRMED = 0x2010; // OK on confirm screen.
+
+// Buttons on the SD-Card File listing.
+constexpr uint16_t VP_SD_ScrollEvent = 0x2020; // Data: 0 for "up a directory", numbers are the amount to scroll, e.g -1 one up, 1 one down
+constexpr uint16_t VP_SD_FileSelected = 0x2022; // Number of file field selected.
+constexpr uint16_t VP_SD_FileSelectConfirm = 0x2024; // (This is a virtual VP and emulated by the Confirm Screen when a file has been confirmed)
+
+constexpr uint16_t VP_SD_ResumePauseAbort = 0x2026; // Resume(Data=0), Pause(Data=1), Abort(Data=2) SD Card prints
+constexpr uint16_t VP_SD_AbortPrintConfirmed = 0x2028; // Abort print confirmation (virtual, will be injected by the confirm dialog)
+constexpr uint16_t VP_SD_Print_Setting = 0x2040;
+constexpr uint16_t VP_SD_Print_LiveAdjustZ = 0x2050; // Data: 0 down, 1 up
+
+// Controls for movement (we can't use the incremental / decremental feature of the display at this feature works only with 16 bit values
+// (which would limit us to 655.35mm, which is likely not a problem for common setups, but i don't want to rule out hangprinters support)
+// A word about the coding: The VP will be per axis and the return code will be an signed 16 bit value in 0.01 mm resolution, telling us
+// the relative travel amount t he user wants to do. So eg. if the display sends us VP=2100 with value 100, the user wants us to move X by +1 mm.
+constexpr uint16_t VP_MOVE_X = 0x2100;
+constexpr uint16_t VP_MOVE_Y = 0x2102;
+constexpr uint16_t VP_MOVE_Z = 0x2104;
+constexpr uint16_t VP_MOVE_E0 = 0x2110;
+constexpr uint16_t VP_MOVE_E1 = 0x2112;
+//constexpr uint16_t VP_MOVE_E2 = 0x2114;
+//constexpr uint16_t VP_MOVE_E3 = 0x2116;
+//constexpr uint16_t VP_MOVE_E4 = 0x2118;
+//constexpr uint16_t VP_MOVE_E5 = 0x211A;
+constexpr uint16_t VP_HOME_ALL = 0x2120;
+constexpr uint16_t VP_MOTOR_LOCK_UNLOK = 0x2130;
+
+// Power loss recovery
+constexpr uint16_t VP_POWER_LOSS_RECOVERY = 0x2180;
+
+// Fan Control Buttons , switch between "off" and "on"
+constexpr uint16_t VP_FAN0_CONTROL = 0x2200;
+constexpr uint16_t VP_FAN1_CONTROL = 0x2202;
+//constexpr uint16_t VP_FAN2_CONTROL = 0x2204;
+//constexpr uint16_t VP_FAN3_CONTROL = 0x2206;
+
+// Heater Control Buttons , triged between "cool down" and "heat PLA" state
+constexpr uint16_t VP_E0_CONTROL = 0x2210;
+constexpr uint16_t VP_E1_CONTROL = 0x2212;
+//constexpr uint16_t VP_E2_CONTROL = 0x2214;
+//constexpr uint16_t VP_E3_CONTROL = 0x2216;
+//constexpr uint16_t VP_E4_CONTROL = 0x2218;
+//constexpr uint16_t VP_E5_CONTROL = 0x221A;
+constexpr uint16_t VP_BED_CONTROL = 0x221C;
+
+// Preheat
+constexpr uint16_t VP_E0_BED_PREHEAT = 0x2220;
+constexpr uint16_t VP_E1_BED_CONTROL = 0x2222;
+//constexpr uint16_t VP_E2_BED_CONTROL = 0x2224;
+//constexpr uint16_t VP_E3_BED_CONTROL = 0x2226;
+//constexpr uint16_t VP_E4_BED_CONTROL = 0x2228;
+//constexpr uint16_t VP_E5_BED_CONTROL = 0x222A;
+
+// Filament load and unload
+constexpr uint16_t VP_E0_FILAMENT_LOAD_UNLOAD = 0x2300;
+constexpr uint16_t VP_E1_FILAMENT_LOAD_UNLOAD = 0x2302;
+
+// Settings store , reset
+constexpr uint16_t VP_SETTINGS = 0x2400;
+
+// PID autotune
+constexpr uint16_t VP_PID_AUTOTUNE_E0 = 0x2410;
+//constexpr uint16_t VP_PID_AUTOTUNE_E1 = 0x2412;
+//constexpr uint16_t VP_PID_AUTOTUNE_E2 = 0x2414;
+//constexpr uint16_t VP_PID_AUTOTUNE_E3 = 0x2416;
+//constexpr uint16_t VP_PID_AUTOTUNE_E4 = 0x2418;
+//constexpr uint16_t VP_PID_AUTOTUNE_E5 = 0x241A;
+constexpr uint16_t VP_PID_AUTOTUNE_BED = 0x2420;
+
+// Firmware version on the boot screen.
+constexpr uint16_t VP_MARLIN_VERSION = 0x3000;
+constexpr uint8_t VP_MARLIN_VERSION_LEN = 16; // there is more space on the display, if needed.
+
+// Place for status messages.
+constexpr uint16_t VP_M117 = 0x3020;
+constexpr uint8_t VP_M117_LEN = 0x20;
+
+// Temperatures.
+constexpr uint16_t VP_T_E0_Is = 0x3060; // 4 Byte Integer
+constexpr uint16_t VP_T_E0_Set = 0x3062; // 2 Byte Integer
+constexpr uint16_t VP_T_E1_Is = 0x3064; // 4 Byte Integer
+
+// reserved to support up to 6 Extruders:
+//constexpr uint16_t VP_T_E1_Set = 0x3066; // 2 Byte Integer
+//constexpr uint16_t VP_T_E2_Is = 0x3068; // 4 Byte Integer
+//constexpr uint16_t VP_T_E2_Set = 0x306A; // 2 Byte Integer
+//constexpr uint16_t VP_T_E3_Is = 0x306C; // 4 Byte Integer
+//constexpr uint16_t VP_T_E3_Set = 0x306E; // 2 Byte Integer
+//constexpr uint16_t VP_T_E4_Is = 0x3070; // 4 Byte Integer
+//constexpr uint16_t VP_T_E4_Set = 0x3072; // 2 Byte Integer
+//constexpr uint16_t VP_T_E4_Is = 0x3074; // 4 Byte Integer
+//constexpr uint16_t VP_T_E4_Set = 0x3076; // 2 Byte Integer
+//constexpr uint16_t VP_T_E5_Is = 0x3078; // 4 Byte Integer
+//constexpr uint16_t VP_T_E5_Set = 0x307A; // 2 Byte Integer
+
+constexpr uint16_t VP_T_Bed_Is = 0x3080; // 4 Byte Integer
+constexpr uint16_t VP_T_Bed_Set = 0x3082; // 2 Byte Integer
+
+constexpr uint16_t VP_Flowrate_E0 = 0x3090; // 2 Byte Integer
+constexpr uint16_t VP_Flowrate_E1 = 0x3092; // 2 Byte Integer
+
+// reserved for up to 6 Extruders:
+//constexpr uint16_t VP_Flowrate_E2 = 0x3094;
+//constexpr uint16_t VP_Flowrate_E3 = 0x3096;
+//constexpr uint16_t VP_Flowrate_E4 = 0x3098;
+//constexpr uint16_t VP_Flowrate_E5 = 0x309A;
+
+constexpr uint16_t VP_Fan0_Percentage = 0x3100; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_Fan1_Percentage = 0x33A2; // 2 Byte Integer (0..100)
+//constexpr uint16_t VP_Fan2_Percentage = 0x33A4; // 2 Byte Integer (0..100)
+//constexpr uint16_t VP_Fan3_Percentage = 0x33A6; // 2 Byte Integer (0..100)
+
+constexpr uint16_t VP_Feedrate_Percentage = 0x3102; // 2 Byte Integer (0..100)
+constexpr uint16_t VP_PrintProgress_Percentage = 0x3104; // 2 Byte Integer (0..100)
+
+constexpr uint16_t VP_PrintTime = 0x3106;
+constexpr uint16_t VP_PrintTime_LEN = 10;
+
+constexpr uint16_t VP_PrintAccTime = 0x3160;
+constexpr uint16_t VP_PrintAccTime_LEN = 32;
+
+constexpr uint16_t VP_PrintsTotal = 0x3180;
+constexpr uint16_t VP_PrintsTotal_LEN = 16;
+
+// Actual Position
+constexpr uint16_t VP_XPos = 0x3110; // 4 Byte Fixed point number; format xxx.yy
+constexpr uint16_t VP_YPos = 0x3112; // 4 Byte Fixed point number; format xxx.yy
+constexpr uint16_t VP_ZPos = 0x3114; // 4 Byte Fixed point number; format xxx.yy
+
+constexpr uint16_t VP_EPos = 0x3120; // 4 Byte Fixed point number; format xxx.yy
+
+// SDCard File Listing
+constexpr uint16_t VP_SD_FileName_LEN = 32; // LEN is shared for all entries.
+constexpr uint16_t DGUS_SD_FILESPERSCREEN = 5; // FIXME move that info to the display and read it from there.
+constexpr uint16_t VP_SD_FileName0 = 0x3200;
+constexpr uint16_t VP_SD_FileName1 = 0x3220;
+constexpr uint16_t VP_SD_FileName2 = 0x3240;
+constexpr uint16_t VP_SD_FileName3 = 0x3260;
+constexpr uint16_t VP_SD_FileName4 = 0x3280;
+
+constexpr uint16_t VP_SD_Print_ProbeOffsetZ = 0x32A0; //
+constexpr uint16_t VP_SD_Print_Filename = 0x32C0; //
+
+// Fan status
+constexpr uint16_t VP_FAN0_STATUS = 0x3300;
+constexpr uint16_t VP_FAN1_STATUS = 0x3302;
+//constexpr uint16_t VP_FAN2_STATUS = 0x3304;
+//constexpr uint16_t VP_FAN3_STATUS = 0x3306;
+
+// Heater status
+constexpr uint16_t VP_E0_STATUS = 0x3310;
+//constexpr uint16_t VP_E1_STATUS = 0x3312;
+//constexpr uint16_t VP_E2_STATUS = 0x3314;
+//constexpr uint16_t VP_E3_STATUS = 0x3316;
+//constexpr uint16_t VP_E4_STATUS = 0x3318;
+//constexpr uint16_t VP_E5_STATUS = 0x331A;
+constexpr uint16_t VP_BED_STATUS = 0x331C;
+
+constexpr uint16_t VP_MOVE_OPTION = 0x3400;
+
+// Step per mm
+constexpr uint16_t VP_X_STEP_PER_MM = 0x3600; // at the moment , 2 byte unsigned int , 0~1638.4
+//constexpr uint16_t VP_X2_STEP_PER_MM = 0x3602;
+constexpr uint16_t VP_Y_STEP_PER_MM = 0x3604;
+//constexpr uint16_t VP_Y2_STEP_PER_MM = 0x3606;
+constexpr uint16_t VP_Z_STEP_PER_MM = 0x3608;
+//constexpr uint16_t VP_Z2_STEP_PER_MM = 0x360A;
+constexpr uint16_t VP_E0_STEP_PER_MM = 0x3610;
+//constexpr uint16_t VP_E1_STEP_PER_MM = 0x3612;
+//constexpr uint16_t VP_E2_STEP_PER_MM = 0x3614;
+//constexpr uint16_t VP_E3_STEP_PER_MM = 0x3616;
+//constexpr uint16_t VP_E4_STEP_PER_MM = 0x3618;
+//constexpr uint16_t VP_E5_STEP_PER_MM = 0x361A;
+
+// PIDs
+constexpr uint16_t VP_E0_PID_P = 0x3700; // at the moment , 2 byte unsigned int , 0~1638.4
+constexpr uint16_t VP_E0_PID_I = 0x3702;
+constexpr uint16_t VP_E0_PID_D = 0x3704;
+constexpr uint16_t VP_BED_PID_P = 0x3710;
+constexpr uint16_t VP_BED_PID_I = 0x3712;
+constexpr uint16_t VP_BED_PID_D = 0x3714;
+
+// Wating screen status
+constexpr uint16_t VP_WAITING_STATUS = 0x3800;
+
+// SPs for certain variables...
+// located at 0x5000 and up
+// Not used yet!
+// This can be used e.g to make controls / data display invisible
+constexpr uint16_t SP_T_E0_Is = 0x5000;
+constexpr uint16_t SP_T_E0_Set = 0x5010;
+constexpr uint16_t SP_T_E1_Is = 0x5020;
+constexpr uint16_t SP_T_Bed_Is = 0x5030;
+constexpr uint16_t SP_T_Bed_Set = 0x5040;
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp
new file mode 100644
index 0000000..a64c237
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp
@@ -0,0 +1,553 @@
+/*********************
+ * flash_storage.cpp *
+ *********************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../compat.h"
+
+#if ENABLED(TOUCH_UI_FTDI_EVE)
+
+#include "../ftdi_eve_lib/ftdi_eve_lib.h"
+
+#include "media_file_reader.h"
+#include "flash_storage.h"
+
+// The following must be changed whenever the layout of the flash
+// data is changed in a manner that would render the data invalid.
+
+constexpr uint32_t flash_eeprom_version = 1;
+
+/* SPI Flash Memory Map:
+ *
+ * The following offsets and sizes are specified in 4k erase units:
+ *
+ * Page Size Description
+ * 0 16 DATA STORAGE AREA
+ * 16 1 VERSIONING DATA
+ * 17 inf MEDIA STORAGE AREA
+ */
+
+#define DATA_STORAGE_SIZE_64K
+
+using namespace FTDI::SPI;
+using namespace FTDI::SPI::most_significant_byte_first;
+
+bool UIFlashStorage::is_present = false;
+
+#ifdef SPI_FLASH_SS
+/************************** SPI Flash Chip Interface **************************/
+
+ void SPIFlash::wait_while_busy() {
+ uint8_t status;
+ safe_delay(1);
+ do {
+ spi_flash_select();
+ spi_write_8(READ_STATUS_1);
+ status = spi_read_8();
+ spi_flash_deselect();
+ safe_delay(1);
+ } while (status & 1);
+ }
+
+ void SPIFlash::erase_sector_4k(uint32_t addr) {
+ spi_flash_select();
+ spi_write_8(WRITE_ENABLE);
+ spi_flash_deselect();
+
+ spi_flash_select();
+ spi_write_8(ERASE_4K);
+ spi_write_24(addr);
+ spi_flash_deselect();
+
+ wait_while_busy();
+ }
+
+ void SPIFlash::erase_sector_64k(uint32_t addr) {
+ spi_flash_select();
+ spi_write_8(WRITE_ENABLE);
+ spi_flash_deselect();
+
+ spi_flash_select();
+ spi_write_8(ERASE_64K);
+ spi_write_24(addr);
+ spi_flash_deselect();
+
+ wait_while_busy();
+ }
+
+ void SPIFlash::spi_write_begin(uint32_t addr) {
+ spi_flash_select();
+ spi_write_8(WRITE_ENABLE);
+ spi_flash_deselect();
+
+ spi_flash_select();
+ spi_write_8(PAGE_PROGRAM);
+ spi_write_24(addr);
+ }
+
+ void SPIFlash::spi_write_end() {
+ spi_flash_deselect();
+ wait_while_busy();
+ }
+
+ void SPIFlash::spi_read_begin(uint32_t addr) {
+ spi_flash_select();
+ spi_write_8(READ_DATA);
+ spi_write_24(addr);
+ }
+
+ void SPIFlash::spi_read_end() {
+ spi_flash_deselect();
+ }
+
+ void SPIFlash::erase_chip() {
+ spi_flash_select();
+ spi_write_8(WRITE_ENABLE);
+ spi_flash_deselect();
+
+ spi_flash_select();
+ spi_write_8(ERASE_CHIP);
+ spi_flash_deselect();
+ wait_while_busy();
+ }
+
+ void SPIFlash::read_jedec_id(uint8_t &manufacturer_id, uint8_t &device_type, uint8_t &capacity) {
+ spi_flash_select();
+ spi_write_8(READ_JEDEC_ID);
+ manufacturer_id = spi_recv();
+ device_type = spi_recv();
+ capacity = spi_recv();
+ spi_flash_deselect ();
+ }
+
+ /* This function writes "size" bytes from "data" starting at addr, while properly
+ * taking into account the special case of writing across a 256 byte page boundary.
+ * Returns the addr directly after the write.
+ */
+ uint32_t SPIFlash::write(uint32_t addr, const void *_data, size_t size) {
+ const uint8_t *data = (const uint8_t*) _data;
+ while (size) {
+ const uint32_t page_start = addr & 0xFFFF00ul;
+ const uint32_t page_end = page_start + 256;
+ const uint32_t write_size = min(page_end - addr, size);
+ spi_write_begin(addr);
+ spi_write_bulk(data, write_size);
+ spi_write_end();
+ addr += write_size;
+ size -= write_size;
+ data += write_size;
+ }
+ return addr;
+ }
+
+ uint32_t SPIFlash::read(uint32_t addr, void *data, size_t size) {
+ spi_read_begin(addr);
+ spi_read_bulk(data, size);
+ spi_read_end();
+ return addr + size;
+ }
+
+ /********************************** UTILITY ROUTINES *********************************/
+
+ bool UIFlashStorage::check_known_device() {
+ uint8_t manufacturer_id, device_type, capacity;
+ read_jedec_id(manufacturer_id, device_type, capacity);
+
+ const bool is_known =
+ ((manufacturer_id == 0xEF) && (device_type == 0x40) && (capacity == 0x15)) || // unknown
+ ((manufacturer_id == 0x01) && (device_type == 0x40) && (capacity == 0x15)) || // Cypress S25FL116K
+ ((manufacturer_id == 0xEF) && (device_type == 0x14) && (capacity == 0x15)) || // Winbond W25Q16JV
+ ((manufacturer_id == 0x1F) && (device_type == 0x86) && (capacity == 0x01)) ; // Adesto AT255F161
+
+ if (!is_known) {
+ SERIAL_ECHO_MSG("Unable to locate supported SPI Flash Memory.");
+ SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(" Manufacturer ID, got: ", manufacturer_id);
+ SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(" Device Type , got: ", device_type);
+ SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(" Capacity , got: ", capacity);
+ }
+
+ return is_known;
+ }
+
+ void UIFlashStorage::initialize() {
+ for (uint8_t i = 0; i < 10; i++) {
+ if (check_known_device()) {
+ is_present = true;
+ break;
+ }
+ safe_delay(1000);
+ }
+ }
+
+ /**************************** DATA STORAGE AREA (first 4K or 64k) ********************/
+
+ #ifdef DATA_STORAGE_SIZE_64K
+ constexpr uint32_t data_storage_area_size = 64 * 1024; // Large erase unit
+ #else
+ constexpr uint32_t data_storage_area_size = 4 * 1024; // Small erase unit
+ #endif
+
+ /* In order to provide some degree of wear leveling, each data write to the
+ * SPI Flash chip is appended to data that was already written before, until
+ * the data storage area is completely filled. New data is written preceeded
+ * with a 32-bit delimiter 'LULZ', so that we can distinguish written and
+ * unwritten data:
+ *
+ * 'LULZ' <--- 1st record delimiter
+ *
+ *
+ *
+ * 'LULZ' <--- 2nd record delimiter
+ *
+ *
+ *
+ * ...
+ * 'LULZ' <--- Last record delimiter
+ *
+ *
+ *
+ * 0xFF <--- Start of free space
+ * 0xFF
+ * ...
+ *
+ * This function walks down the data storage area, verifying that the
+ * delimiters are either 'LULZ' or 0xFFFFFFFF. In the case that an invalid
+ * delimiter is found, this function returns -1, indicating that the Flash
+ * data is invalid (this will happen if the block_size changed with respect
+ * to earlier firmware). Otherwise, it returns the offset of the last
+ * valid delimiter 'LULZ', indicating the most recently written data.
+ */
+ int32_t UIFlashStorage::get_config_read_offset(uint32_t block_size) {
+ uint16_t stride = 4 + block_size;
+ int32_t read_offset = -1;
+
+ for (uint32_t offset = 0; offset < (data_storage_area_size - stride); offset += stride) {
+ uint32_t delim;
+ spi_read_begin(offset);
+ spi_read_bulk (&delim, sizeof(delim));
+ spi_read_end();
+ switch (delim) {
+ case 0xFFFFFFFFul: return read_offset;
+ case delimiter: read_offset = offset; break;
+ default:
+ SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("Invalid delimiter in Flash: ", delim);
+ return -1;
+ }
+ }
+ SERIAL_ECHO_MSG("No LULZ delimiter found.");
+ return -1;
+ }
+
+ /* This function returns the offset at which new data should be
+ * appended, or -1 if the Flash needs to be erased */
+ int32_t UIFlashStorage::get_config_write_offset(uint32_t block_size) {
+ int32_t read_offset = get_config_read_offset(block_size);
+ if (read_offset == -1) return -1; // The SPI flash is invalid
+
+ int32_t write_offset = read_offset + 4 + block_size;
+ if ((write_offset + 4 + block_size) > data_storage_area_size) {
+ SERIAL_ECHO_MSG("Not enough free space in Flash.");
+ return -1; // Not enough free space
+ }
+ return write_offset;
+ }
+
+ bool UIFlashStorage::verify_config_data(const void *data, size_t size) {
+ if (!is_present) return false;
+
+ int32_t read_addr = get_config_read_offset(size);
+ if (read_addr == -1) return false;
+
+ uint32_t delim;
+ spi_read_begin(read_addr);
+ spi_read_bulk (&delim, sizeof(delim));
+ bool ok = spi_verify_bulk(data,size);
+ spi_read_end();
+ return ok && delim == delimiter;
+ }
+
+ bool UIFlashStorage::read_config_data(void *data, size_t size) {
+ if (!is_present) return false;
+
+ int32_t read_addr = get_config_read_offset(size);
+ if (read_addr == -1) return false;
+
+ uint32_t delim;
+ spi_read_begin(read_addr);
+ spi_read_bulk (&delim, sizeof(delim));
+ spi_read_bulk (data, size);
+ spi_read_end();
+ return delim == delimiter;
+ }
+
+ void UIFlashStorage::write_config_data(const void *data, size_t size) {
+ if (!is_present) {
+ SERIAL_ECHO_MSG("SPI Flash chip not present. Not saving UI settings.");
+ return;
+ }
+
+ // Since Flash storage has a limited number of write cycles,
+ // make sure that the data is different before rewriting.
+
+ if (verify_config_data(data, size)) {
+ SERIAL_ECHO_MSG("UI settings already written, skipping write.");
+ return;
+ }
+
+ int16_t write_addr = get_config_write_offset(size);
+ if (write_addr == -1) {
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPGM("Erasing UI settings from SPI Flash... ");
+ #ifdef DATA_STORAGE_SIZE_64K
+ erase_sector_64k(0);
+ #else
+ erase_sector_4k(0);
+ #endif
+ write_addr = 0;
+ SERIAL_ECHOLNPGM("DONE");
+ }
+
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR("Writing UI settings to SPI Flash (offset ", write_addr);
+ SERIAL_ECHOPGM(")...");
+
+ const uint32_t delim = delimiter;
+ write_addr = write(write_addr, &delim, sizeof(delim));
+ write_addr = write(write_addr, data, size);
+
+ SERIAL_ECHOLNPGM("DONE");
+ }
+
+ /************************** VERSIONING INFO AREA ************************/
+
+ /* The version info area follows the data storage area. If the version
+ * is incorrect, the data on the chip is invalid and format_flash should
+ * be called.
+ */
+
+ typedef struct {
+ uint32_t magic;
+ uint32_t version;
+ } flash_version_info;
+
+ constexpr uint32_t version_info_addr = data_storage_area_size;
+ constexpr uint32_t version_info_size = 4 * 1024; // Small erase unit
+
+ bool UIFlashStorage::is_valid() {
+ flash_version_info info;
+
+ spi_read_begin(version_info_addr);
+ spi_read_bulk (&info, sizeof(flash_version_info));
+ spi_read_end();
+
+ return info.magic == delimiter && info.version == flash_eeprom_version;
+ }
+
+ void UIFlashStorage::write_version_info() {
+ flash_version_info info;
+
+ info.magic = delimiter;
+ info.version = flash_eeprom_version;
+
+ spi_write_begin(version_info_addr);
+ spi_write_bulk(&info, sizeof(flash_version_info));
+ spi_write_end();
+ }
+
+ /**************************** MEDIA STORAGE AREA *****************************/
+
+ /* The media storage area follows the versioning info area. It consists
+ * of a file index followed by the data for one or more media files.
+ *
+ * The file index consists of an array of 32-bit file sizes. If a file
+ * is not present, the file's size will be set to 0xFFFFFFFF
+ */
+
+ constexpr uint32_t media_storage_addr = version_info_addr + version_info_size;
+ constexpr uint8_t media_storage_slots = 4;
+
+ void UIFlashStorage::format_flash() {
+ SERIAL_ECHO_START(); SERIAL_ECHOPGM("Erasing SPI Flash...");
+ SPIFlash::erase_chip();
+ SERIAL_ECHOLNPGM("DONE");
+
+ write_version_info();
+ }
+
+ uint32_t UIFlashStorage::get_media_file_start(uint8_t slot) {
+ uint32_t addr = media_storage_addr + sizeof(uint32_t) * media_storage_slots;
+ spi_read_begin(media_storage_addr);
+ for (uint8_t i = 0; i < slot; i++)
+ addr += spi_read_32();
+ spi_read_end();
+ return addr;
+ }
+
+ void UIFlashStorage::set_media_file_size(uint8_t slot, uint32_t size) {
+ spi_write_begin(media_storage_addr + sizeof(uint32_t) * slot);
+ spi_write_32(size);
+ spi_write_end();
+ }
+
+ uint32_t UIFlashStorage::get_media_file_size(uint8_t slot) {
+ spi_read_begin(media_storage_addr + sizeof(uint32_t) * slot);
+ uint32_t size = spi_read_32();
+ spi_read_end();
+ return size;
+ }
+
+ /* Writes a media file from the SD card/USB flash drive into a slot on the SPI Flash. Media
+ * files must be written sequentially following by a chip erase and it is not possible to
+ * overwrite files. */
+ UIFlashStorage::error_t UIFlashStorage::write_media_file(progmem_str filename, uint8_t slot) {
+ #if ENABLED(SDSUPPORT)
+ uint32_t addr;
+ uint8_t buff[write_page_size];
+
+ strcpy_P( (char*) buff, (const char*) filename);
+
+ MediaFileReader reader;
+ if (!reader.open((char*) buff)) {
+ SERIAL_ECHO_MSG("Unable to find media file");
+ return FILE_NOT_FOUND;
+ }
+
+ if (get_media_file_size(slot) != 0xFFFFFFFFUL) {
+ SERIAL_ECHO_MSG("Media file already exists");
+ return WOULD_OVERWRITE;
+ }
+
+ SERIAL_ECHO_START(); SERIAL_ECHOPGM("Writing SPI Flash...");
+
+ set_media_file_size(slot, reader.size());
+ addr = get_media_file_start(slot);
+
+ // Write out the file itself
+ for (;;) {
+ const int16_t nBytes = reader.read(buff, write_page_size);
+ if (nBytes == -1) {
+ SERIAL_ECHOLNPGM("Failed to read from file");
+ return READ_ERROR;
+ }
+
+ addr = write(addr, buff, nBytes);
+ if (nBytes != write_page_size) break;
+
+ TERN_(EXTENSIBLE_UI, ExtUI::yield());
+ }
+
+ SERIAL_ECHOLNPGM("DONE");
+
+ SERIAL_ECHO_START(); SERIAL_ECHOPGM("Verifying SPI Flash...");
+
+ bool verifyOk = true;
+
+ // Verify the file index
+
+ if (get_media_file_start(slot+1) != (get_media_file_start(slot) + reader.size())) {
+ SERIAL_ECHOLNPGM("File index verification failed. ");
+ verifyOk = false;
+ }
+
+ // Verify the file itself
+ addr = get_media_file_start(slot);
+ reader.rewind();
+
+ while (verifyOk) {
+ const int16_t nBytes = reader.read(buff, write_page_size);
+ if (nBytes == -1) {
+ SERIAL_ECHOPGM("Failed to read from file");
+ verifyOk = false;
+ break;
+ }
+
+ spi_read_begin(addr);
+ if (!spi_verify_bulk(buff, nBytes)) {
+ verifyOk = false;
+ spi_read_end();
+ break;
+ }
+ spi_read_end();
+
+ addr += nBytes;
+ if (nBytes != write_page_size) break;
+ TERN_(EXTENSIBLE_UI, ExtUI::yield());
+ };
+
+ if (verifyOk) {
+ SERIAL_ECHOLNPGM("DONE");
+ return SUCCESS;
+ }
+ else {
+ SERIAL_ECHOLNPGM("FAIL");
+ return VERIFY_ERROR;
+ }
+ #else
+ return VERIFY_ERROR;
+ #endif // SDSUPPORT
+ }
+
+ bool UIFlashStorage::BootMediaReader::isAvailable(uint32_t slot) {
+ if (!is_present) return false;
+
+ bytes_remaining = get_media_file_size(slot);
+ if (bytes_remaining != 0xFFFFFFFFUL) {
+ SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR("Boot media file size:", bytes_remaining);
+ addr = get_media_file_start(slot);
+ return true;
+ }
+ return false;
+ }
+
+ int16_t UIFlashStorage::BootMediaReader::read(void *data, const size_t size) {
+ if (bytes_remaining == 0xFFFFFFFFUL) return -1;
+
+ if (size > bytes_remaining)
+ return read(data, bytes_remaining);
+
+ if (size > 0) {
+ spi_read_begin(addr);
+ spi_read_bulk(data, size);
+ spi_read_end();
+ addr += size;
+ bytes_remaining -= size;
+ }
+
+ return size;
+ }
+
+ int16_t UIFlashStorage::BootMediaReader::read(void *obj, void *data, const size_t size) {
+ return reinterpret_cast(obj)->read(data, size);
+ }
+
+#else
+ void UIFlashStorage::initialize() {}
+ bool UIFlashStorage::is_valid() {return true;}
+ void UIFlashStorage::write_config_data(const void *, size_t) {}
+ bool UIFlashStorage::verify_config_data(const void *, size_t) {return false;}
+ bool UIFlashStorage::read_config_data(void *, size_t ) {return false;}
+ UIFlashStorage::error_t UIFlashStorage::write_media_file(progmem_str, uint8_t) {return FILE_NOT_FOUND;}
+ void UIFlashStorage::format_flash() {}
+
+ bool UIFlashStorage::BootMediaReader::isAvailable(uint32_t) {return false;}
+ int16_t UIFlashStorage::BootMediaReader::read(void *, const size_t) {return -1;}
+ int16_t UIFlashStorage::BootMediaReader::read(void *, void *, const size_t) {return -1;}
+#endif // SPI_FLASH_SS
+#endif // TOUCH_UI_FTDI_EVE
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.h
new file mode 100644
index 0000000..eef8cf8
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/flash_storage.h
@@ -0,0 +1,106 @@
+/*******************
+ * flash_storage.h *
+ *******************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+class SPIFlash {
+ public:
+ static constexpr uint32_t erase_unit_size = 4 * 1024; // Minimum erase unit
+ static constexpr uint32_t write_page_size = 256; // Minimum page write unit
+
+ enum {
+ READ_STATUS_1 = 0x05,
+ READ_STATUS_2 = 0x35,
+ READ_STATUS_3 = 0x33,
+ WRITE_ENABLE = 0x06,
+ WRITE_DISABLE = 0x04,
+ READ_ID = 0x90,
+ READ_JEDEC_ID = 0x9F,
+ READ_DATA = 0x03,
+ PAGE_PROGRAM = 0x02,
+ ERASE_4K = 0x20,
+ ERASE_64K = 0xD8,
+ ERASE_CHIP = 0xC7
+ };
+
+ static void wait_while_busy();
+ static void erase_sector_4k(uint32_t addr);
+ static void erase_sector_64k(uint32_t addr);
+ static void erase_chip ();
+
+ static void read_jedec_id(uint8_t &manufacturer_id, uint8_t &device_type, uint8_t &capacity);
+
+ static void spi_read_begin(uint32_t addr);
+ static void spi_read_end();
+
+ static void spi_write_begin(uint32_t addr);
+ static void spi_write_end();
+
+ static uint32_t write(uint32_t addr, const void *data, size_t size);
+ static uint32_t read(uint32_t addr, void *data, size_t size);
+};
+
+class UIFlashStorage : private SPIFlash {
+ private:
+
+ static bool is_present;
+ static int32_t get_config_read_offset(uint32_t block_size);
+ static int32_t get_config_write_offset(uint32_t block_size);
+
+ static uint32_t get_media_file_start(uint8_t slot);
+ static void set_media_file_size(uint8_t slot, uint32_t size);
+ static uint32_t get_media_file_size(uint8_t slot);
+
+ static constexpr uint32_t delimiter = 0x4D524C4E; // 'MRLN'
+ public:
+ enum error_t {
+ SUCCESS,
+ FILE_NOT_FOUND,
+ READ_ERROR,
+ VERIFY_ERROR,
+ WOULD_OVERWRITE
+ };
+
+ static void initialize ();
+ static void format_flash ();
+ static bool check_known_device();
+
+ static bool is_valid ();
+ static void write_version_info();
+
+ static void write_config_data (const void *data, size_t size);
+ static bool verify_config_data (const void *data, size_t size);
+ static bool read_config_data (void *data, size_t size);
+ static error_t write_media_file (progmem_str filename, uint8_t slot = 0);
+
+ class BootMediaReader;
+};
+
+class UIFlashStorage::BootMediaReader {
+ private:
+ uint32_t addr;
+ uint32_t bytes_remaining;
+
+ public:
+ bool isAvailable(uint32_t slot = 0);
+ int16_t read(void *buffer, size_t const size);
+
+ static int16_t read(void *obj, void *buffer, const size_t size);
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.cpp
new file mode 100644
index 0000000..9868492
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.cpp
@@ -0,0 +1,63 @@
+/************************
+ * media_filereader.cpp *
+ ************************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../compat.h"
+
+#if ENABLED(TOUCH_UI_FTDI_EVE)
+ #include "media_file_reader.h"
+
+ #if ENABLED(SDSUPPORT)
+ bool MediaFileReader::open(const char* filename) {
+ card.init(SD_SPI_SPEED, SDSS);
+ volume.init(&card);
+ root.openRoot(&volume);
+ return file.open(&root, filename, O_READ);
+ }
+
+ int16_t MediaFileReader::read(void *buff, size_t bytes) {
+ return file.read(buff, bytes);
+ }
+
+ void MediaFileReader::close() {
+ file.close();
+ }
+
+ uint32_t MediaFileReader::size() {
+ return file.fileSize();
+ }
+
+ void MediaFileReader::rewind() {
+ file.rewind();
+ }
+
+ int16_t MediaFileReader::read(void *obj, void *buff, size_t bytes) {
+ return reinterpret_cast(obj)->read(buff, bytes);
+ }
+ #else
+ bool MediaFileReader::open(const char*) {return -1;}
+ int16_t MediaFileReader::read(void *, size_t) {return 0;}
+ void MediaFileReader::close() {}
+ uint32_t MediaFileReader::size() {return 0;}
+ void MediaFileReader::rewind() {}
+ int16_t MediaFileReader::read(void *, void *, size_t) {return 0;}
+ #endif
+#endif // TOUCH_UI_FTDI_EVE
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.h
new file mode 100644
index 0000000..be393a9
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/archim2-flash/media_file_reader.h
@@ -0,0 +1,48 @@
+/**********************
+ * media_filereader.h *
+ **********************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#include "../../../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(SDSUPPORT)
+ #include "../../../../../sd/SdFile.h"
+ #include "../../../../../sd/cardreader.h"
+#endif
+
+class MediaFileReader {
+ private:
+ #if ENABLED(SDSUPPORT)
+ Sd2Card card;
+ SdVolume volume;
+ SdFile root, file;
+ #endif
+
+ public:
+ bool open(const char* filename);
+ int16_t read(void *buff, size_t bytes);
+ uint32_t size();
+ void rewind();
+ void close();
+
+ static int16_t read(void *obj, void *buff, size_t bytes);
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h
new file mode 100644
index 0000000..c01d45e
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/compat.h
@@ -0,0 +1,53 @@
+/************
+ * compat.h *
+ ************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * This following provides compatibility whether compiling
+ * as a part of Marlin or outside it
+ */
+
+#ifdef __has_include
+ #if __has_include("../../ui_api.h")
+ #include "../../ui_api.h"
+ #endif
+#else
+ #include "../../ui_api.h"
+#endif
+
+#ifdef __MARLIN_FIRMWARE__
+ // __MARLIN_FIRMWARE__ exists when compiled within Marlin.
+ #include "pin_mappings.h"
+ #undef max
+ #define max(a,b) ((a)>(b)?(a):(b))
+ #undef min
+ #define min(a,b) ((a)<(b)?(a):(b))
+#else
+ namespace UI {
+ static inline uint32_t safe_millis() { return millis(); }
+ static inline void yield() {}
+ };
+#endif
+
+class __FlashStringHelper;
+typedef const __FlashStringHelper *progmem_str;
+extern const char G28_STR[];
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/config.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/config.h
new file mode 100644
index 0000000..76b2315
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/config.h
@@ -0,0 +1,26 @@
+/************
+ * config.h *
+ ************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#include "compat.h"
+
+// Configure this display with options in Configuration_adv.h
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/LICENSE.txt b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/LICENSE.txt
new file mode 100644
index 0000000..e600086
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/LICENSE.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/README.md b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/README.md
new file mode 100644
index 0000000..6ba985d
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/README.md
@@ -0,0 +1,28 @@
+FTDI EVE Library
+----------------
+
+The FTDI EVE Library is a fully open-source library and UI framework for the FTDI
+FT800 and FT810 graphics processor.
+
+Although the library has been developed within Lulzbot for providing a user interface
+for Marlin, the library has been written so that it can be used in any Arduino sketch.
+
+The library is split into two parts. The "basic" API provides a shallow interface to
+the underlying FTDI hardware and command FIFO and provides low-level access to the
+hardware as closely as possible to the API described in the FTDI Programmer's Guide.
+
+The "extended" API builds on top of the "basic" API to provide a GUI framework for
+handling common challenges in building a usable GUI. The GUI framework provides the
+following features:
+
+- Macros for a resolution-independent placement of widgets based on a grid.
+- Class-based UI screens, with press and unpress touch events, as well as touch repeat.
+- Event loop with button debouncing and button push visual and auditory feedback.
+- Easy screen-to-screen navigation including a navigation stack for going backwards.
+- Visual feedback for disabled vs enabled buttons, and custom button styles.
+- A sound player class for playing individual notes or complete sound sequences.
+- Display list caching, for storing static background elements of a screen in RAM_G.
+
+See the "examples" folder for Arduino sketches. Modify the "src/config.h" file in
+each to suit your particular setup. The "sample_configs" contain sample configuration
+files for running the sketches on our 3D printer boards.
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/boards.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/boards.h
new file mode 100644
index 0000000..6bb9208
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/boards.h
@@ -0,0 +1,184 @@
+/************
+ * boards.h *
+ ************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#define HAS_RESOLUTION (defined(TOUCH_UI_320x240) || defined(TOUCH_UI_480x272) || defined(TOUCH_UI_800x480))
+
+#define IS_FT800 \
+ constexpr uint16_t ftdi_chip = 800; \
+ using namespace FTDI_FT800; \
+ namespace DL { \
+ using namespace FTDI_FT800_DL; \
+ } \
+ typedef ft800_memory_map ftdi_memory_map; \
+ typedef ft800_registers ftdi_registers;
+
+#define IS_FT810 \
+ constexpr uint16_t ftdi_chip = 810; \
+ using namespace FTDI_FT810; \
+ namespace DL { \
+ using namespace FTDI_FT800_DL; \
+ using namespace FTDI_FT810_DL; \
+ } \
+ typedef ft810_memory_map ftdi_memory_map; \
+ typedef ft810_registers ftdi_registers;
+
+#ifdef LCD_FTDI_VM800B35A
+ #if !HAS_RESOLUTION
+ #define TOUCH_UI_320x240
+ #endif
+ #ifndef FTDI_API_LEVEL
+ #define FTDI_API_LEVEL 800
+ #endif
+ namespace FTDI {
+ IS_FT800
+ constexpr bool Use_Crystal = true; // 0 = use internal oscillator, 1 = module has a crystal populated
+ constexpr bool GPIO_0_Audio_Enable = false; /* 1 = does use GPIO00 for amplifier control, 0 = not in use for Audio */
+ constexpr bool GPIO_1_Audio_Shutdown = true; /* 1 = does use GPIO01 for amplifier control, 0 = not in use for Audio */
+ constexpr uint8_t Swizzle = 2;
+ constexpr uint8_t CSpread = 1;
+
+ constexpr uint16_t touch_threshold = 1200; /* touch-sensitivity */
+ }
+
+/**
+ * Settings for the Haoyu Electronics, 4.3" Graphical LCD Touchscreen, 480x272, SPI, FT800 (FT800CB-HY43B)
+ * and 5" Graphical LCD Touchscreen, 480x272, SPI, FT800 (FT800CB-HY50B)
+ * http://www.hotmcu.com/43-graphical-lcd-touchscreen-480x272-spi-ft800-p-111.html?cPath=6_16
+ * http://www.hotmcu.com/5-graphical-lcd-touchscreen-480x272-spi-ft800-p-124.html?cPath=6_16
+ * Datasheet:
+ * https://www.hantronix.com/files/data/1278363262430-3.pdf
+ * https://www.haoyuelectronics.com/Attachment/HY43-LCD/LCD%20DataSheet.pdf
+ * https://www.haoyuelectronics.com/Attachment/HY5-LCD-HD/KD50G21-40NT-A1.pdf
+ */
+#elif defined(LCD_HAOYU_FT800CB)
+ #if !HAS_RESOLUTION
+ #define TOUCH_UI_480x272
+ #endif
+ #ifndef FTDI_API_LEVEL
+ #define FTDI_API_LEVEL 800
+ #endif
+ namespace FTDI {
+ IS_FT800
+ constexpr bool Use_Crystal = true; // 0 = use internal oscillator, 1 = module has a crystal populated
+ constexpr bool GPIO_0_Audio_Enable = false;
+ constexpr bool GPIO_1_Audio_Shutdown = false;
+ constexpr uint8_t Swizzle = 0;
+ constexpr uint8_t CSpread = 1;
+ constexpr uint16_t touch_threshold = 2000; /* touch-sensitivity */
+ }
+
+/**
+ * Settings for the Haoyu Electronics, 5" Graphical LCD Touchscreen, 800x480, SPI, FT810
+ * http://www.hotmcu.com/5-graphical-lcd-touchscreen-800x480-spi-ft810-p-286.html
+ * Datasheet:
+ * https://www.haoyuelectronics.com/Attachment/HY5-LCD-HD/KD50G21-40NT-A1.pdf
+ */
+#elif defined(LCD_HAOYU_FT810CB)
+ #if !HAS_RESOLUTION
+ #define TOUCH_UI_800x480
+ #endif
+ #ifndef FTDI_API_LEVEL
+ #define FTDI_API_LEVEL 810
+ #endif
+ namespace FTDI {
+ IS_FT810
+ constexpr bool Use_Crystal = true; // 0 = use internal oscillator, 1 = module has a crystal populated
+ constexpr bool GPIO_0_Audio_Enable = false;
+ constexpr bool GPIO_1_Audio_Shutdown = false;
+ constexpr uint8_t Swizzle = 0;
+ constexpr uint8_t CSpread = 1;
+ constexpr uint16_t touch_threshold = 2000; /* touch-sensitivity */
+ }
+
+/**
+ * Settings for the 4D Systems, 4.3" Embedded SPI Display 480x272, SPI, FT800 (4DLCD-FT843)
+ * https://4dsystems.com.au/4dlcd-ft843
+ * Datasheet:
+ * https://4dsystems.com.au/mwdownloads/download/link/id/52/
+ */
+#elif defined(LCD_4DSYSTEMS_4DLCD_FT843)
+ #if !HAS_RESOLUTION
+ #define TOUCH_UI_480x272
+ #endif
+ #ifndef FTDI_API_LEVEL
+ #define FTDI_API_LEVEL 800
+ #endif
+ namespace FTDI {
+ IS_FT800
+ constexpr bool Use_Crystal = true; // 0 = use internal oscillator, 1 = module has a crystal populated
+ constexpr bool GPIO_0_Audio_Enable = false;
+ constexpr bool GPIO_1_Audio_Shutdown = true;
+ constexpr uint8_t Swizzle = 0;
+ constexpr uint8_t CSpread = 1;
+ constexpr uint16_t touch_threshold = 1200; /* touch-sensitivity */
+ }
+
+/**
+ * Settings for the Aleph Objects Color LCD User Interface
+ * Datasheet https://www.hantronix.com/files/data/s1501799605s500-gh7.pdf
+ */
+#elif defined(LCD_ALEPHOBJECTS_CLCD_UI)
+ #if !HAS_RESOLUTION
+ #define TOUCH_UI_800x480
+ #endif
+ #ifndef FTDI_API_LEVEL
+ #define FTDI_API_LEVEL 810
+ #endif
+ namespace FTDI {
+ IS_FT810
+ constexpr bool Use_Crystal = false; // 0 = use internal oscillator, 1 = module has a crystal populated
+ constexpr bool GPIO_0_Audio_Enable = true; // The AO CLCD uses GPIO0 to enable audio
+ constexpr bool GPIO_1_Audio_Shutdown = false;
+ constexpr uint8_t Swizzle = 0;
+ constexpr uint8_t CSpread = 0;
+ constexpr uint16_t touch_threshold = 2000; /* touch-sensitivity */
+ }
+
+/**
+ * FYSETC Color LCD
+ * https://www.aliexpress.com/item/4000627651757.html
+ * Product information:
+ * https://github.com/FYSETC/TFT81050
+ */
+#elif defined(LCD_FYSETC_TFT81050)
+ #if !HAS_RESOLUTION
+ #define TOUCH_UI_800x480
+ #endif
+ #ifndef FTDI_API_LEVEL
+ #define FTDI_API_LEVEL 810
+ #endif
+ namespace FTDI {
+ IS_FT810
+ constexpr bool Use_Crystal = false; // 0 = use internal oscillator, 1 = module has a crystal populated
+ constexpr bool GPIO_0_Audio_Enable = true; // The AO CLCD uses GPIO0 to enable audio
+ constexpr bool GPIO_1_Audio_Shutdown = false;
+ constexpr uint8_t Swizzle = 0;
+ constexpr uint8_t CSpread = 0;
+ constexpr uint16_t touch_threshold = 2000; /* touch-sensitivity */
+ }
+#else
+
+ #error "Unknown or no TOUCH_UI_FTDI_EVE board specified. To add a new board, modify this file."
+
+#endif
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.cpp
new file mode 100644
index 0000000..1db1175
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.cpp
@@ -0,0 +1,1194 @@
+/****************
+ * commands.cpp *
+ ****************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_basic.h"
+
+#ifdef FTDI_BASIC
+
+#define MULTIPLE_OF_4(val) ((((val)+3)>>2)<<2)
+
+using namespace FTDI;
+using namespace FTDI::SPI;
+
+void CLCD::enable() {
+ mem_write_8(REG::PCLK, Pclk);
+}
+
+void CLCD::disable() {
+ mem_write_8(REG::PCLK, 0x00);
+}
+
+void CLCD::set_brightness(uint8_t brightness) {
+ mem_write_8(REG::PWM_DUTY, min(128,brightness));
+}
+
+uint8_t CLCD::get_brightness() {
+ return mem_read_8(REG::PWM_DUTY);
+}
+
+void CLCD::turn_on_backlight() {
+ mem_write_8(REG::PWM_DUTY, 128);
+}
+
+void CLCD::FontMetrics::load(const uint8_t font) {
+ static_assert(sizeof(FontMetrics) == 148, "Sizeof font metrics is incorrect");
+ uint32_t rom_fontroot = mem_read_32(MAP::ROM_FONT_ADDR);
+ mem_read_bulk(rom_fontroot + 148 * (font - 16), (uint8_t*) this, 148);
+}
+
+uint16_t CLCD::FontMetrics::get_text_width(const char *str, size_t n) const {
+ uint16_t width = 0;
+ const uint8_t *p = (const uint8_t *) str;
+ for (;;) {
+ const uint8_t val = *p++; n--;
+ if (!val || n == 0) break;
+ width += val < 128 ? char_widths[val] : 0;
+ }
+ return width;
+}
+
+uint16_t CLCD::FontMetrics::get_text_width(progmem_str str, size_t n) const {
+ uint16_t width = 0;
+ const uint8_t *p = (const uint8_t *) str;
+ for (;;) {
+ const uint8_t val = pgm_read_byte(p++); n--;
+ if (!val || n == 0) break;
+ width += val < 128 ? char_widths[val] : 0;
+ }
+ return width;
+}
+
+/************************** HOST COMMAND FUNCTION *********************************/
+
+void CLCD::host_cmd(unsigned char host_command, unsigned char byte2) { // Sends 24-Bit Host Command to LCD
+ if (host_command != FTDI::ACTIVE) {
+ host_command |= 0x40;
+ }
+ spi_ftdi_select();
+ spi_send(host_command);
+ spi_send(byte2);
+ spi_send(0x00);
+ spi_ftdi_deselect();
+}
+
+/************************** MEMORY READ FUNCTIONS *********************************/
+
+void CLCD::spi_read_addr(uint32_t reg_address) {
+ spi_send((reg_address >> 16) & 0x3F); // Address [21:16]
+ spi_send((reg_address >> 8 ) & 0xFF); // Address [15:8]
+ spi_send((reg_address >> 0) & 0xFF); // Address [7:0]
+ spi_send(0x00); // Dummy Byte
+}
+
+// Write 4-Byte Address, Read Multiple Bytes
+void CLCD::mem_read_bulk(uint32_t reg_address, uint8_t *data, uint16_t len) {
+ spi_ftdi_select();
+ spi_read_addr(reg_address);
+ spi_read_bulk (data, len);
+ spi_ftdi_deselect();
+}
+
+// Write 4-Byte Address, Read 1-Byte Data
+uint8_t CLCD::mem_read_8(uint32_t reg_address) {
+ spi_ftdi_select();
+ spi_read_addr(reg_address);
+ uint8_t r_data = spi_read_8();
+ spi_ftdi_deselect();
+ return r_data;
+}
+
+// Write 4-Byte Address, Read 2-Bytes Data
+uint16_t CLCD::mem_read_16(uint32_t reg_address) {
+ using namespace SPI::least_significant_byte_first;
+ spi_ftdi_select();
+ spi_read_addr(reg_address);
+ uint16_t r_data = spi_read_16();
+ spi_ftdi_deselect();
+ return r_data;
+}
+
+// Write 4-Byte Address, Read 4-Bytes Data
+uint32_t CLCD::mem_read_32(uint32_t reg_address) {
+ using namespace SPI::least_significant_byte_first;
+ spi_ftdi_select();
+ spi_read_addr(reg_address);
+ uint32_t r_data = spi_read_32();
+ spi_ftdi_deselect();
+ return r_data;
+}
+
+/************************** MEMORY WRITE FUNCTIONS *********************************/
+
+// Generic operations for transforming a byte, for use with _mem_write_bulk:
+static inline uint8_t reverse_byte(uint8_t a) {
+ return ((a & 0x1) << 7) | ((a & 0x2) << 5) |
+ ((a & 0x4) << 3) | ((a & 0x8) << 1) |
+ ((a & 0x10) >> 1) | ((a & 0x20) >> 3) |
+ ((a & 0x40) >> 5) | ((a & 0x80) >> 7);
+}
+static inline uint8_t xbm_write(const uint8_t *p) {return reverse_byte(pgm_read_byte(p));}
+
+void CLCD::spi_write_addr(uint32_t reg_address) {
+ spi_send((reg_address >> 16) | 0x80); // Address [21:16]
+ spi_send((reg_address >> 8 ) & 0xFF); // Address [15:8]
+ spi_send((reg_address >> 0) & 0xFF); // Address [7:0]
+}
+
+// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from RAM
+void CLCD::mem_write_bulk(uint32_t reg_address, const void *data, uint16_t len, uint8_t padding) {
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_bulk(data, len, padding);
+ spi_ftdi_deselect();
+}
+
+// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM
+void CLCD::mem_write_bulk(uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding) {
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_bulk(str, len, padding);
+ spi_ftdi_deselect();
+}
+
+ // Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM
+void CLCD::mem_write_pgm(uint32_t reg_address, const void *data, uint16_t len, uint8_t padding) {
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_bulk(data, len, padding);
+ spi_ftdi_deselect();
+}
+
+// Write 3-Byte Address, Multiple Bytes, plus padding bytes, from PROGMEM, reversing bytes (suitable for loading XBM images)
+void CLCD::mem_write_xbm(uint32_t reg_address, progmem_str data, uint16_t len, uint8_t padding) {
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_bulk(data, len, padding);
+ spi_ftdi_deselect();
+}
+
+// Write 3-Byte Address, Write 1-Byte Data
+void CLCD::mem_write_8(uint32_t reg_address, uint8_t data) {
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_8(data);
+ spi_ftdi_deselect();
+}
+
+// Write 3-Byte Address, Write 2-Bytes Data
+void CLCD::mem_write_16(uint32_t reg_address, uint16_t data) {
+ using namespace SPI::least_significant_byte_first;
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_16(data);
+ spi_ftdi_deselect();
+}
+
+// Write 3-Byte Address, Write 4-Bytes Data
+void CLCD::mem_write_32(uint32_t reg_address, uint32_t data) {
+ using namespace SPI::least_significant_byte_first;
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ spi_write_32(data);
+ spi_ftdi_deselect();
+}
+
+// Fill area of len size with repeated data bytes
+void CLCD::mem_write_fill(uint32_t reg_address, uint8_t data, uint16_t len) {
+ spi_ftdi_select();
+ spi_write_addr(reg_address);
+ while (len--) spi_write_8(data);
+ spi_ftdi_deselect();
+}
+
+/******************* FT800/810 Co-processor Commands *********************************/
+
+#if FTDI_API_LEVEL == 800
+uint32_t CLCD::CommandFifo::command_write_ptr = 0xFFFFFFFFul;
+#endif
+
+void CLCD::CommandFifo::cmd(uint32_t cmd32) {
+ write((void*)&cmd32, sizeof(uint32_t));
+}
+
+void CLCD::CommandFifo::cmd(void* data, uint16_t len) {
+ write(data, len);
+}
+
+void CLCD::CommandFifo::bgcolor(uint32_t rgb) {
+ cmd(CMD_BGCOLOR);
+ cmd(rgb);
+}
+
+void CLCD::CommandFifo::fgcolor(uint32_t rgb) {
+ cmd(CMD_FGCOLOR);
+ cmd(rgb);
+}
+
+void CLCD::CommandFifo::gradcolor(uint32_t rgb) {
+ cmd(CMD_GRADCOLOR);
+ cmd(rgb);
+}
+
+// This sends the a text command to the command preprocessor, must be followed by str()
+void CLCD::CommandFifo::button(int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t option) {
+ struct {
+ int32_t type = CMD_BUTTON;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ int16_t h;
+ int16_t font;
+ uint16_t option;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.font = font;
+ cmd_data.option = option;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+// This sends the a text command to the command preprocessor, must be followed by str()
+void CLCD::CommandFifo::text(int16_t x, int16_t y, int16_t font, uint16_t options) {
+ struct {
+ int32_t type = CMD_TEXT;
+ int16_t x;
+ int16_t y;
+ int16_t font;
+ uint16_t options;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.font = font;
+ cmd_data.options = options;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+// This sends the a toggle command to the command preprocessor, must be followed by str()
+void CLCD::CommandFifo::toggle(int16_t x, int16_t y, int16_t w, int16_t font, uint16_t options, bool state) {
+ struct {
+ int32_t type = CMD_TOGGLE;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ int16_t font;
+ uint16_t options;
+ uint16_t state;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.font = font;
+ cmd_data.options = options;
+ cmd_data.state = state ? 65535 : 0;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+// This sends the a keys command to the command preprocessor, must be followed by str()
+void CLCD::CommandFifo::keys(int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t options) {
+ struct {
+ int32_t type = CMD_KEYS;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ int16_t h;
+ int16_t font;
+ uint16_t options;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.font = font;
+ cmd_data.options = options;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::clock(int16_t x, int16_t y, int16_t r, uint16_t options, int16_t h, int16_t m, int16_t s, int16_t ms)
+{
+ struct {
+ int32_t type = CMD_CLOCK;
+ int16_t x;
+ int16_t y;
+ int16_t r;
+ uint16_t options;
+ int16_t h;
+ int16_t m;
+ int16_t s;
+ int16_t ms;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.r = r;
+ cmd_data.options = options;
+ cmd_data.h = h;
+ cmd_data.m = m;
+ cmd_data.s = s;
+ cmd_data.ms = ms;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::gauge(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range)
+{
+ struct {
+ int32_t type = CMD_GAUGE;
+ int16_t x;
+ int16_t y;
+ int16_t r;
+ uint16_t options;
+ uint16_t major;
+ uint16_t minor;
+ uint16_t val;
+ uint16_t range;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.r = r;
+ cmd_data.options = options;
+ cmd_data.major = major;
+ cmd_data.minor = minor;
+ cmd_data.val = val;
+ cmd_data.range = range;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::dial(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t val)
+{
+ struct {
+ int32_t type = CMD_DIAL;
+ int16_t x;
+ int16_t y;
+ int16_t r;
+ uint16_t options;
+ uint16_t val;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.r = r;
+ cmd_data.options = options;
+ cmd_data.val = val;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::scrollbar(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t size, uint16_t range) {
+ struct {
+ int32_t type = CMD_SCROLLBAR;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ uint16_t h;
+ uint16_t options;
+ uint16_t val;
+ uint16_t size;
+ uint16_t range;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.options = options;
+ cmd_data.val = val;
+ cmd_data.size = size;
+ cmd_data.range = range;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::progress(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range) {
+ struct {
+ int32_t type = CMD_PROGRESS;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ int16_t h;
+ uint16_t options;
+ uint16_t val;
+ uint16_t range;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.options = options;
+ cmd_data.val = val;
+ cmd_data.range = range;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::slider(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range) {
+ struct {
+ int32_t type = CMD_SLIDER;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ int16_t h;
+ uint16_t options;
+ uint16_t val;
+ uint16_t range;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.options = options;
+ cmd_data.val = val;
+ cmd_data.range = range;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1) {
+ struct {
+ int32_t type = CMD_GRADIENT;
+ int16_t x0;
+ int16_t y0;
+ uint32_t rgb0;
+ int16_t x1;
+ int16_t y1;
+ uint32_t rgb1;
+ } cmd_data;
+
+ cmd_data.x0 = x0;
+ cmd_data.y0 = y0;
+ cmd_data.rgb0 = rgb0;
+ cmd_data.x1 = x1;
+ cmd_data.y1 = y1;
+ cmd_data.rgb1 = rgb1;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::number(int16_t x, int16_t y, int16_t font, uint16_t options, int32_t n) {
+ struct {
+ int32_t type = CMD_NUMBER;
+ int16_t x;
+ int16_t y;
+ int16_t font;
+ uint16_t options;
+ int16_t n;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.font = font;
+ cmd_data.options = options;
+ cmd_data.n = n;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::memzero(uint32_t ptr, uint32_t size) {
+ struct {
+ uint32_t type = CMD_MEMZERO;
+ uint32_t ptr;
+ uint32_t size;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.size = size;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::memset(uint32_t ptr, uint32_t val, uint32_t size) {
+ struct {
+ uint32_t type = CMD_MEMSET;
+ uint32_t ptr;
+ uint32_t val;
+ uint32_t size;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.val = val;
+ cmd_data.size = size;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::memcpy(uint32_t dst, uint32_t src, uint32_t size) {
+ struct {
+ uint32_t type = CMD_MEMCPY;
+ uint32_t dst;
+ uint32_t src;
+ uint32_t size;
+ } cmd_data;
+
+ cmd_data.dst = dst;
+ cmd_data.src = src;
+ cmd_data.size = size;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::memcrc(uint32_t ptr, uint32_t num, uint32_t result) {
+ struct {
+ uint32_t type = CMD_MEMCRC;
+ uint32_t ptr;
+ uint32_t num;
+ uint32_t result;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.num = num;
+ cmd_data.result = result;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::memwrite(uint32_t ptr, uint32_t value) {
+ struct {
+ uint32_t type = CMD_MEMWRITE;
+ uint32_t ptr;
+ uint32_t num;
+ uint32_t value;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.num = 4;
+ cmd_data.value = value;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::append(uint32_t ptr, uint32_t size) {
+ struct {
+ uint32_t type = CMD_APPEND;
+ uint32_t ptr;
+ uint32_t size;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.size = size;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::inflate(uint32_t ptr) {
+ struct {
+ uint32_t type = CMD_INFLATE;
+ uint32_t ptr;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::getptr(uint32_t result) {
+ struct {
+ uint32_t type = CMD_GETPTR;
+ uint32_t result;
+ } cmd_data;
+
+ cmd_data.result = result;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::track(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t tag) {
+ struct {
+ uint32_t type = CMD_TRACK;
+ int16_t x;
+ int16_t y;
+ int16_t w;
+ int16_t h;
+ int16_t tag;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.tag = tag;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::sketch(int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format) {
+ struct {
+ uint32_t type = CMD_SKETCH;
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ uint32_t ptr;
+ uint16_t format;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.ptr = ptr;
+ cmd_data.format = format;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::snapshot(uint32_t ptr) {
+ struct {
+ uint32_t type = CMD_SNAPSHOT;
+ uint32_t ptr;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::spinner(int16_t x, int16_t y, uint16_t style, uint16_t scale) {
+ struct {
+ uint32_t type = CMD_SPINNER;
+ uint16_t x;
+ uint16_t y;
+ uint16_t style;
+ uint16_t scale;
+ } cmd_data;
+
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.style = style;
+ cmd_data.scale = scale;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::loadimage(uint32_t ptr, uint32_t options) {
+ struct {
+ uint32_t type = CMD_LOADIMAGE;
+ uint32_t ptr;
+ uint32_t options;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.options = options;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::getprops(uint32_t ptr, uint32_t width, uint32_t height) {
+ struct {
+ uint32_t type = CMD_GETPROPS;
+ uint32_t ptr;
+ uint32_t width;
+ uint32_t height;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.width = width;
+ cmd_data.height = height;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::scale(int32_t sx, int32_t sy) {
+ struct {
+ uint32_t type = CMD_SCALE;
+ int32_t sx;
+ int32_t sy;
+ } cmd_data;
+
+ cmd_data.sx = sx;
+ cmd_data.sy = sy;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::rotate(int32_t a) {
+ struct {
+ uint32_t type = CMD_ROTATE;
+ int32_t a;
+ } cmd_data;
+
+ cmd_data.a = a;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+void CLCD::CommandFifo::translate(int32_t tx, int32_t ty) {
+ struct {
+ uint32_t type = CMD_TRANSLATE;
+ int32_t tx;
+ int32_t ty;
+ } cmd_data;
+
+ cmd_data.tx = tx;
+ cmd_data.ty = ty;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::setbase(uint8_t base) {
+ struct {
+ int32_t type = CMD_SETBASE;
+ uint32_t base;
+ } cmd_data;
+
+ cmd_data.base = base;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::setbitmap(uint32_t addr, uint16_t fmt, uint16_t w, uint16_t h) {
+ struct {
+ uint32_t type = CMD_SETBITMAP;
+ uint32_t addr;
+ uint16_t fmt;
+ uint16_t w;
+ uint16_t h;
+ uint16_t dummy;
+ } cmd_data;
+
+ cmd_data.addr = addr;
+ cmd_data.fmt = fmt;
+ cmd_data.w = w;
+ cmd_data.h = h;
+ cmd_data.dummy = 0;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::snapshot2(uint32_t format, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h) {
+ struct {
+ uint32_t type = CMD_SNAPSHOT2;
+ uint32_t format;
+ uint32_t ptr;
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ } cmd_data;
+
+ cmd_data.format = format;
+ cmd_data.ptr = ptr;
+ cmd_data.x = x;
+ cmd_data.y = y;
+ cmd_data.w = w;
+ cmd_data.h = h;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::mediafifo(uint32_t ptr, uint32_t size) {
+ struct {
+ uint32_t type = CMD_MEDIAFIFO;
+ uint32_t ptr;
+ uint32_t size;
+ } cmd_data;
+
+ cmd_data.ptr = ptr;
+ cmd_data.size = size;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::videostart() {
+ cmd( CMD_VIDEOSTART );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::videoframe(uint32_t dst, uint32_t ptr) {
+ struct {
+ uint32_t type = CMD_VIDEOFRAME;
+ uint32_t dst;
+ uint32_t ptr;
+ } cmd_data;
+
+ cmd_data.dst = dst;
+ cmd_data.ptr = ptr;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::playvideo(uint32_t options) {
+ struct {
+ uint32_t type = CMD_PLAYVIDEO;
+ uint32_t options;
+ } cmd_data;
+
+ cmd_data.options = options;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::setrotate(uint8_t rotation) {
+ struct {
+ uint32_t type = CMD_SETROTATE;
+ uint32_t rotation;
+ } cmd_data;
+
+ cmd_data.rotation = rotation;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+#if FTDI_API_LEVEL >= 810
+void CLCD::CommandFifo::romfont(uint8_t font, uint8_t romslot) {
+ struct {
+ uint32_t type = CMD_ROMFONT;
+ uint32_t font;
+ uint32_t romslot;
+ } cmd_data;
+
+ cmd_data.font = font;
+ cmd_data.romslot = romslot;
+
+ cmd( &cmd_data, sizeof(cmd_data) );
+}
+#endif
+
+/**************************** FT800/810 Co-Processor Command FIFO ****************************/
+
+bool CLCD::CommandFifo::is_processing() {
+ return (mem_read_32(REG::CMD_READ) & 0x0FFF) != (mem_read_32(REG::CMD_WRITE) & 0x0FFF);
+}
+
+bool CLCD::CommandFifo::has_fault() {
+ uint16_t Cmd_Read_Reg = mem_read_32(REG::CMD_READ) & 0x0FFF;
+ return Cmd_Read_Reg == 0x0FFF;
+}
+
+#if FTDI_API_LEVEL == 800
+void CLCD::CommandFifo::start() {
+ if (command_write_ptr == 0xFFFFFFFFul) {
+ command_write_ptr = mem_read_32(REG::CMD_WRITE) & 0x0FFF;
+ }
+}
+
+void CLCD::CommandFifo::execute() {
+ if (command_write_ptr != 0xFFFFFFFFul) {
+ mem_write_32(REG::CMD_WRITE, command_write_ptr);
+ }
+}
+
+void CLCD::CommandFifo::reset() {
+ safe_delay(100);
+ mem_write_32(REG::CPURESET, 0x00000001);
+ mem_write_32(REG::CMD_WRITE, 0x00000000);
+ mem_write_32(REG::CMD_READ, 0x00000000);
+ mem_write_32(REG::CPURESET, 0x00000000);
+ safe_delay(300);
+ command_write_ptr = 0xFFFFFFFFul;
+};
+
+template bool CLCD::CommandFifo::_write_unaligned(T data, uint16_t len) {
+ const char *ptr = (const char*)data;
+ uint32_t bytes_tail, bytes_head;
+ uint32_t command_read_ptr;
+
+ #if ENABLED(TOUCH_UI_DEBUG)
+ if (command_write_ptr == 0xFFFFFFFFul)
+ SERIAL_ECHO_MSG("Attempt to write to FIFO before CommandFifo::Cmd_Start().");
+ #endif
+
+ /* Wait until there is enough space in the circular buffer for the transfer */
+ do {
+ command_read_ptr = mem_read_32(REG::CMD_READ) & 0x0FFF;
+ if (command_read_ptr <= command_write_ptr) {
+ bytes_tail = 4096U - command_write_ptr;
+ bytes_head = command_read_ptr;
+ }
+ else {
+ bytes_tail = command_read_ptr - command_write_ptr;
+ bytes_head = 0;
+ }
+ // Check for faults which can lock up the command processor
+ if (has_fault()) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHOLNPGM("Fault waiting for space in the command processor");
+ #endif
+ return false;
+ }
+ } while ((bytes_tail + bytes_head) < len);
+
+ /* Write as many bytes as possible following REG::CMD_WRITE */
+ uint16_t bytes_to_write = min(len, bytes_tail);
+ mem_write_bulk (MAP::RAM_CMD + command_write_ptr, T(ptr), bytes_to_write);
+ command_write_ptr += bytes_to_write;
+ ptr += bytes_to_write;
+ len -= bytes_to_write;
+
+ if (len > 0) {
+ /* Write remaining bytes at start of circular buffer */
+ mem_write_bulk (MAP::RAM_CMD, T(ptr), len);
+ command_write_ptr = len;
+ }
+
+ if (command_write_ptr == 4096U) {
+ command_write_ptr = 0;
+ }
+ return true;
+}
+
+// Writes len bytes into the FIFO, if len is not
+// divisible by four, zero bytes will be written
+// to align to the boundary.
+
+template bool CLCD::CommandFifo::write(T data, uint16_t len) {
+ const uint8_t padding = MULTIPLE_OF_4(len) - len;
+
+ uint8_t pad_bytes[] = {0, 0, 0, 0};
+ return _write_unaligned(data, len) &&
+ _write_unaligned(pad_bytes, padding);
+}
+#else
+void CLCD::CommandFifo::start() {
+}
+
+void CLCD::CommandFifo::execute() {
+}
+
+void CLCD::CommandFifo::reset() {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHOLNPGM("Resetting command processor");
+ #endif
+ safe_delay(100);
+ mem_write_32(REG::CPURESET, 0x00000001);
+ mem_write_32(REG::CMD_WRITE, 0x00000000);
+ mem_write_32(REG::CMD_READ, 0x00000000);
+ mem_write_32(REG::CPURESET, 0x00000000);
+ safe_delay(300);
+};
+
+// Writes len bytes into the FIFO, if len is not
+// divisible by four, zero bytes will be written
+// to align to the boundary.
+
+template bool CLCD::CommandFifo::write(T data, uint16_t len) {
+ const uint8_t padding = MULTIPLE_OF_4(len) - len;
+
+ if (has_fault()) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHOLNPGM("Faulted... ignoring write.");
+ #endif
+ return false;
+ }
+ // The FT810 provides a special register that can be used
+ // for writing data without us having to do our own FIFO
+ // management.
+ uint16_t Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
+ if (Command_Space < (len + padding)) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR("Waiting for ", len + padding);
+ SERIAL_ECHOLNPAIR(" bytes in command queue, now free: ", Command_Space);
+ #endif
+ do {
+ Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
+ if (has_fault()) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHOLNPGM("... fault");
+ #endif
+ return false;
+ }
+ } while (Command_Space < len + padding);
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHOLNPGM("... done");
+ #endif
+ }
+ mem_write_bulk(REG::CMDB_WRITE, data, len, padding);
+ return true;
+}
+#endif
+
+template bool CLCD::CommandFifo::write(const void*, uint16_t);
+template bool CLCD::CommandFifo::write(progmem_str, uint16_t);
+
+// CO_PROCESSOR COMMANDS
+
+void CLCD::CommandFifo::str(const char * data) {
+ write(data, strlen(data)+1);
+}
+
+void CLCD::CommandFifo::str(progmem_str data) {
+ write(data, strlen_P((const char*)data)+1);
+}
+
+/******************* LCD INITIALIZATION ************************/
+
+void CLCD::init() {
+ spi_init(); // Set Up I/O Lines for SPI and FT800/810 Control
+ ftdi_reset(); // Power down/up the FT8xx with the apropriate delays
+
+ host_cmd(Use_Crystal ? CLKEXT : CLKINT, 0);
+ host_cmd(FTDI::ACTIVE, 0); // Activate the System Clock
+
+ delay(40); // FTDI/BRT recommendation: no SPI traffic during startup. EVE needs at the very least 45ms to start, so leave her alone for a little while.
+
+ /* read the device-id until it returns 0x7C or times out, should take less than 150ms */
+ uint8_t counter;
+ for (counter = 0; counter < 250; counter++) {
+ uint8_t device_id = mem_read_8(REG::ID); // Read Device ID, Should Be 0x7C;
+ if (device_id == 0x7C) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_MSG("FTDI chip initialized ");
+ #endif
+ break;
+ }
+ else
+ delay(1);
+
+ if (counter == 249) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR("Timeout waiting for device ID, should be 124, got ", device_id);
+ #endif
+ }
+ }
+
+ /* make sure that all units are in working conditions, usually the touch-controller needs a little more time */
+ for (counter = 0; counter < 100; counter++) {
+ uint8_t reset_status = mem_read_8(REG::CPURESET) & 0x03;
+ if (reset_status == 0x00) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_MSG("FTDI chip all units running ");
+ #endif
+ break;
+ }
+ else
+ delay(1);
+
+ if (ENABLED(TOUCH_UI_DEBUG) && counter == 99) {
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR("Timeout waiting for reset status. Should be 0x00, got ", reset_status);
+ }
+ }
+
+ mem_write_8(REG::PWM_DUTY, 0); // turn off Backlight, Frequency already is set to 250Hz default
+
+ /* Configure the FT8xx Registers */
+ mem_write_16(REG::HCYCLE, FTDI::Hcycle);
+ mem_write_16(REG::HOFFSET, FTDI::Hoffset);
+ mem_write_16(REG::HSYNC0, FTDI::Hsync0);
+ mem_write_16(REG::HSYNC1, FTDI::Hsync1);
+ mem_write_16(REG::VCYCLE, FTDI::Vcycle);
+ mem_write_16(REG::VOFFSET, FTDI::Voffset);
+ mem_write_16(REG::VSYNC0, FTDI::Vsync0);
+ mem_write_16(REG::VSYNC1, FTDI::Vsync1);
+ mem_write_16(REG::HSIZE, FTDI::Hsize);
+ mem_write_16(REG::VSIZE, FTDI::Vsize);
+ mem_write_8(REG::SWIZZLE, FTDI::Swizzle);
+ mem_write_8(REG::PCLK_POL, FTDI::Pclkpol);
+ mem_write_8(REG::CSPREAD, FTDI::CSpread);
+
+ /* write a basic display-list to get things started */
+ mem_write_32(MAP::RAM_DL, DL::CLEAR_COLOR_RGB);
+ mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */
+ mem_write_32(MAP::RAM_DL + 8, DL::DL_DISPLAY); /* end of display list */
+
+ mem_write_8(REG::DLSWAP, 0x02); // activate display list, Bad Magic Cookie 2 = switch to new list after current frame is scanned out
+
+ //mem_write_8(REG::TOUCH_MODE, 0x03); // Configure the Touch Screen, Bad Magic Cookie, 3 = CONTINUOUS = Reset Default
+ //mem_write_8(REG::TOUCH_ADC_MODE, 0x01); // Bad Magic Cookie, 1 = single touch = Reset Default
+ //mem_write_8(REG::TOUCH_OVERSAMPLE, 0x0F); // Reset Default = 7 - why 15?
+ mem_write_16(REG::TOUCH_RZTHRESH, touch_threshold); /* setup touch sensitivity */
+ mem_write_8(REG::VOL_SOUND, 0x00); // Turn Synthesizer Volume Off
+
+ /* turn on the display by setting DISP high */
+ /* turn on the Audio Amplifier by setting GPIO_1 high for the select few modules supporting this */
+ /* no need to use GPIOX here since DISP/GPIO_0 and GPIO_1 are on REG::GPIO for FT81x as well */
+ if (GPIO_1_Audio_Shutdown) {
+ mem_write_8(REG::GPIO_DIR, GPIO_DISP | GPIO_GP1);
+ mem_write_8(REG::GPIO, GPIO_DISP | GPIO_GP1);
+ } else if (GPIO_0_Audio_Enable) {
+ mem_write_8(REG::GPIO_DIR, GPIO_DISP | GPIO_GP0);
+ mem_write_8(REG::GPIO, GPIO_DISP | GPIO_GP0);
+ }
+ else {
+ mem_write_8(REG::GPIO, GPIO_DISP); /* REG::GPIO_DIR is set to output for GPIO_DISP by default */
+ }
+
+ mem_write_8(REG::PCLK, Pclk); // Turns on Clock by setting PCLK Register to the value necessary for the module
+
+ mem_write_16(REG::PWM_HZ, 0x00FA);
+
+ // Turning off dithering seems to help prevent horizontal line artifacts on certain colors
+ mem_write_8(REG::DITHER, 0);
+
+ default_touch_transform();
+ default_display_orientation();
+}
+
+void CLCD::default_touch_transform() {
+ // Set Initial Values for Touch Transform Registers
+ mem_write_32(REG::ROTATE, 0);
+ mem_write_32(REG::TOUCH_TRANSFORM_A, FTDI::default_transform_a);
+ mem_write_32(REG::TOUCH_TRANSFORM_B, FTDI::default_transform_b);
+ mem_write_32(REG::TOUCH_TRANSFORM_C, FTDI::default_transform_c);
+ mem_write_32(REG::TOUCH_TRANSFORM_D, FTDI::default_transform_d);
+ mem_write_32(REG::TOUCH_TRANSFORM_E, FTDI::default_transform_e);
+ mem_write_32(REG::TOUCH_TRANSFORM_F, FTDI::default_transform_f);
+}
+
+void CLCD::default_display_orientation() {
+ #if FTDI_API_LEVEL >= 810
+ // Set the initial display orientation. On the FT810, we use the command
+ // processor to do this since it will also update the transform matrices.
+ CommandFifo cmd;
+ cmd.setrotate(
+ ENABLED(TOUCH_UI_MIRRORED) * 4
+ + ENABLED(TOUCH_UI_PORTRAIT) * 2
+ + ENABLED(TOUCH_UI_INVERTED) * 1
+ );
+ cmd.execute();
+ #elif ANY(TOUCH_UI_PORTRAIT, TOUCH_UI_MIRRORED)
+ #error "PORTRAIT or MIRRORED orientation not supported on the FT800."
+ #elif ENABLED(TOUCH_UI_INVERTED)
+ mem_write_32(REG::ROTATE, 1);
+ #endif
+}
+
+#endif // FTDI_BASIC
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.h
new file mode 100644
index 0000000..376beae
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.h
@@ -0,0 +1,262 @@
+/****************
+ * commands.cpp *
+ ****************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+ /****************************************************************************
+ * FUNCTION MAP *
+ * *
+ * SPI and FT800/810 Commands *
+ * *
+ * CLCD::spi_select() Set CS line to 0 *
+ * CLCD::spi_deselect() Set CS Line to 1 *
+ * CLCD::reset() Toggle FT800/810 Power Down Line 50 ms *
+ * CLCD::spi_init() Configure I/O Lines for SPI *
+ * CLCD::spi_transfer() Send/Receive 1 SPI Byte *
+ * CLCD::init() Set FT800/810 Registers *
+ * CLCD::enable() Turn On FT800/810 PCLK *
+ * CLCD::disable() Turn Off FT8880/810 PCLK *
+ * CLCD::set_backlight() Set LCD Backlight Level *
+ * *
+ * MEMORY READ FUNCTIONS *
+ * *
+ * CLCD::mem_read_addr() Send 32-Bit Address *
+ * CLCD::mem_read_8() Read 1 Byte *
+ * CLCD::mem_read_16() Read 2 Bytes *
+ * CLCD::mem_read_32() Read 4 Bytes *
+ * *
+ * MEMORY WRITE FUNCTIONS *
+ * *
+ * CLCD::mem_write_addr() Send 24-Bit Address *
+ * CLCD::mem_write_8() Write 1 Byte *
+ * CLCD::mem_write_16() Write 2 Bytes *
+ * CLCD::mem_write_32() Write 4 Bytes *
+ * *
+ * HOST COMMAND FUNCTION *
+ * *
+ * CLCD::host_cmd() Send 24-Bit Host Command *
+ * *
+ * COMMAND BUFFER FUNCTIONS *
+ * *
+ * CLCD::cmd() Send 32-Bit Value(4 Bytes)CMD Buffer *
+ * CLCD::cmd() Send Data Structure with 32-Bit Cmd *
+ * CLCD::str() Send Text String in 32-Bit Multiples *
+
+ * *
+ * FT800/810 GRAPHIC COMMANDS *
+ * *
+ * class CLCD:CommandFifo {} Class to control Cmd FIFO *
+
+ * CommandFifo::start() Wait for CP finish - Set FIFO Ptr *
+ * CommandFifo::execute() Set REG_CMD_WRITE and start CP *
+ * CommandFifo::reset() Set Cmd Buffer Pointers to 0 *
+ *
+ * CommandFifo::fgcolor Set Graphic Item Foreground Color *
+ * CommandFifo::bgcolor Set Graphic Item Background Color *
+ * CommandFifo::begin() Begin Drawing a Primative *
+ * CommandFifo::mem_copy() Copy a Block of Memory *
+ * CommandFifo::append() Append Commands to Current DL *
+ * CommandFifo::gradient_color() Set 3D Button Highlight Color *
+ * CommandFifo::button() Draw Button with Bulk Write *
+ * CommandFifo::text() Draw Text with Bulk Write *
+ *****************************************************************************/
+
+ /**************************************************
+ * RAM_G Graphics RAM Allocation *
+ * *
+ * Address Use *
+ * *
+ * 8000 Extruder Bitmap *
+ * 8100 Bed Heat Bitmap *
+ * 8200 Fan Bitmap *
+ * 8300 Thumb Drive Symbol Bitmap *
+ * 35000 Static DL Space (FT800) *
+ * F5000 Static DL Space (FT810) *
+ **************************************************/
+
+#pragma once
+
+typedef const __FlashStringHelper *progmem_str;
+
+class UIStorage;
+
+class CLCD {
+ friend class UIStorage;
+
+ public:
+ typedef FTDI::ftdi_registers REG;
+ typedef FTDI::ftdi_memory_map MAP;
+
+ static void spi_write_addr (uint32_t reg_address);
+ static void spi_read_addr (uint32_t reg_address);
+
+ static uint8_t mem_read_8 (uint32_t reg_address);
+ static uint16_t mem_read_16 (uint32_t reg_address);
+ static uint32_t mem_read_32 (uint32_t reg_address);
+ static void mem_read_bulk (uint32_t reg_address, uint8_t *data, uint16_t len);
+
+ static void mem_write_8 (uint32_t reg_address, uint8_t w_data);
+ static void mem_write_16 (uint32_t reg_address, uint16_t w_data);
+ static void mem_write_32 (uint32_t reg_address, uint32_t w_data);
+ static void mem_write_fill (uint32_t reg_address, uint8_t w_data, uint16_t len);
+ static void mem_write_bulk (uint32_t reg_address, const void *data, uint16_t len, uint8_t padding = 0);
+ static void mem_write_pgm (uint32_t reg_address, const void *data, uint16_t len, uint8_t padding = 0);
+ static void mem_write_bulk (uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding = 0);
+ static void mem_write_xbm (uint32_t reg_address, progmem_str str, uint16_t len, uint8_t padding = 0);
+
+ public:
+ class CommandFifo;
+ class FontMetrics;
+
+ static void init();
+ static void default_touch_transform();
+ static void default_display_orientation();
+ static void turn_on_backlight();
+ static void enable();
+ static void disable();
+ static void set_brightness (uint8_t brightness);
+ static uint8_t get_brightness();
+ static void host_cmd (unsigned char host_command, unsigned char byte2);
+ static uint32_t dl_size() {return CLCD::mem_read_32(REG::CMD_DL) & 0x1FFF;}
+
+ static void get_font_metrics (uint8_t font, struct FontMetrics &fm);
+ static uint16_t get_text_width(const uint8_t font, const char *str);
+ static uint16_t get_text_width_P(const uint8_t font, const char *str);
+
+ static uint8_t get_tag () {return mem_read_8(REG::TOUCH_TAG);}
+ static bool is_touching () {return (mem_read_32(REG::TOUCH_DIRECT_XY) & 0x80000000) == 0;}
+
+ static uint8_t get_tracker (uint16_t &value) {
+ uint32_t tracker = mem_read_32(REG::TRACKER);
+ value = tracker >> 16;
+ return tracker & 0xFF;
+ }
+};
+
+/*************************** FT800/810 Font Metrics ****************************/
+
+class CLCD::FontMetrics {
+ public:
+ uint8_t char_widths[128];
+ uint32_t format;
+ uint32_t stride;
+ uint32_t width;
+ uint32_t height;
+ uint32_t ptr;
+
+ FontMetrics() {}
+ FontMetrics(uint8_t font) {load(font);}
+
+ void load(uint8_t font);
+
+ // Returns width of string, up to a maximum of n characters.
+ uint16_t get_text_width(const char *str, size_t n = SIZE_MAX) const;
+ uint16_t get_text_width(progmem_str str, size_t n = SIZE_MAX) const;
+};
+
+/******************* FT800/810 Graphic Commands *********************************/
+
+class CLCD::CommandFifo {
+ protected:
+ #if FTDI_API_LEVEL >= 810
+ uint32_t getRegCmdBSpace();
+ #else
+ static uint32_t command_write_ptr;
+ template bool _write_unaligned(T data, uint16_t len);
+ #endif
+ void start();
+
+ public:
+ template bool write(T data, uint16_t len);
+
+ public:
+ CommandFifo() {start();}
+
+ static void reset();
+ static bool is_processing();
+ static bool has_fault();
+
+ void execute();
+
+ void cmd(uint32_t cmd32);
+ void cmd(void* data, uint16_t len);
+
+ void dlstart() {cmd(FTDI::CMD_DLSTART);}
+ void swap() {cmd(FTDI::CMD_SWAP);}
+ void coldstart() {cmd(FTDI::CMD_COLDSTART);}
+ void screensaver() {cmd(FTDI::CMD_SCREENSAVER);}
+ void stop() {cmd(FTDI::CMD_STOP);}
+ void loadidentity() {cmd(FTDI::CMD_LOADIDENTITY);}
+ void setmatrix() {cmd(FTDI::CMD_SETMATRIX);}
+
+ void fgcolor (uint32_t rgb);
+ void bgcolor (uint32_t rgb);
+ void gradcolor (uint32_t rgb);
+
+ void track (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t tag);
+ void clock (int16_t x, int16_t y, int16_t r, uint16_t options, int16_t h, int16_t m, int16_t s, int16_t ms);
+ void gauge (int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range);
+ void dial (int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t val);
+ void slider (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range);
+ void progress (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range);
+ void scrollbar (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t size, uint16_t range);
+ void number (int16_t x, int16_t y, int16_t font, uint16_t options, int32_t n);
+ void spinner (int16_t x, int16_t y, uint16_t style, uint16_t scale);
+ void sketch (int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format);
+ void gradient (int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1);
+ void snapshot (uint32_t ptr);
+ void loadimage (uint32_t ptr, uint32_t options);
+ void getprops (uint32_t ptr, uint32_t width, uint32_t height);
+
+ void scale (int32_t sx, int32_t sy);
+ void rotate (int32_t a);
+ void translate (int32_t tx, int32_t ty);
+
+ #if FTDI_API_LEVEL >= 810
+ void setbase (uint8_t base);
+ void setrotate (uint8_t rotation);
+ void setbitmap (uint32_t ptr, uint16_t fmt, uint16_t w, uint16_t h);
+ void snapshot2 (uint32_t fmt, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h);
+ void mediafifo (uint32_t ptr, uint32_t size);
+ void playvideo (uint32_t options);
+ void videostart();
+ void videoframe(uint32_t dst, uint32_t ptr);
+ void romfont (uint8_t font, uint8_t romslot);
+ #endif
+
+ // All the following must be followed by str()
+ void text (int16_t x, int16_t y, int16_t font, uint16_t options);
+ void button (int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t option);
+ void toggle (int16_t x, int16_t y, int16_t w, int16_t font, uint16_t options, bool state);
+ void keys (int16_t x, int16_t y, int16_t w, int16_t h, int16_t font, uint16_t options);
+
+ // Sends the string portion of text, button, toggle and keys.
+ void str (const char * data);
+ void str (progmem_str data);
+
+ void memzero (uint32_t ptr, uint32_t size);
+ void memset (uint32_t ptr, uint32_t value, uint32_t size);
+ void memcpy (uint32_t dst, uint32_t src, uint32_t size);
+ void memcrc (uint32_t ptr, uint32_t num, uint32_t result);
+ void memwrite (uint32_t ptr, uint32_t value);
+ void inflate (uint32_t ptr);
+ void getptr (uint32_t result);
+ void append (uint32_t ptr, uint32_t size);
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/constants.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/constants.h
new file mode 100644
index 0000000..507e251
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/constants.h
@@ -0,0 +1,414 @@
+/***************
+ * constants.h *
+ ***************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+/****************************************************************************
+ * This header defines constants and commands for the FTDI FT810 LCD Driver *
+ * chip. *
+ ****************************************************************************/
+
+#pragma once
+
+// OPTIONS
+
+namespace FTDI {
+ constexpr uint16_t OPT_3D = 0x0000;
+ constexpr uint16_t OPT_RGB565 = 0x0000;
+ constexpr uint16_t OPT_MONO = 0x0001;
+ constexpr uint16_t OPT_NODL = 0x0002;
+ constexpr uint16_t OPT_FLAT = 0x0100;
+ constexpr uint16_t OPT_SIGNED = 0x0100;
+ constexpr uint16_t OPT_CENTERX = 0x0200;
+ constexpr uint16_t OPT_CENTERY = 0x0400;
+ constexpr uint16_t OPT_CENTER = (OPT_CENTERX | OPT_CENTERY);
+ constexpr uint16_t OPT_RIGHTX = 0x0800;
+ constexpr uint16_t OPT_NOBACK = 0x1000;
+ constexpr uint16_t OPT_NOTICKS = 0x2000;
+ constexpr uint16_t OPT_NOHM = 0x4000;
+ constexpr uint16_t OPT_NOPOINTER = 0x4000;
+ constexpr uint16_t OPT_NOSECS = 0x8000;
+ constexpr uint16_t OPT_NOHANDS = (OPT_NOPOINTER | OPT_NOSECS);
+}
+
+namespace FTDI_FT810 {
+ constexpr uint16_t OPT_NOTEAR = 0x0004;
+ constexpr uint16_t OPT_FULLSCREEN = 0x0008;
+ constexpr uint16_t OPT_MEDIAFIFO = 0x0010;
+ constexpr uint16_t OPT_SOUND = 0x0020;
+}
+
+// GPIO Bits
+
+namespace FTDI {
+ constexpr uint8_t GPIO_GP0 = 1 << 0;
+ constexpr uint8_t GPIO_GP1 = 1 << 1;
+ constexpr uint8_t GPIO_DISP = 1 << 7;
+}
+
+namespace FTDI_FT810 {
+ constexpr uint16_t GPIOX_GP0 = 1 << 0;
+ constexpr uint16_t GPIOX_GP1 = 1 << 1;
+ constexpr uint16_t GPIOX_DISP = 1 << 15;
+}
+
+// HOST COMMANDS
+
+namespace FTDI {
+ constexpr uint8_t ACTIVE = 0x00;
+ constexpr uint8_t STANDBY = 0x41;
+ constexpr uint8_t SLEEP = 0x42;
+ constexpr uint8_t PWRDOWN = 0x50;
+ constexpr uint8_t CLKEXT = 0x44;
+ constexpr uint8_t CLKINT = 0x48;
+ constexpr uint8_t CORESET = 0x68;
+}
+
+namespace FTDI_FT800 {
+ constexpr uint8_t CLK48M = 0x62;
+ constexpr uint8_t CLK36M = 0x61;
+}
+
+namespace FTDI_FT810 {
+ constexpr uint8_t CLKSEL = 0x61;
+}
+
+// DISPLAY LIST COMMANDS
+
+namespace FTDI {
+ constexpr uint8_t ARGB1555 = 0;
+ constexpr uint8_t L1 = 1;
+ constexpr uint8_t L4 = 2;
+ constexpr uint8_t L8 = 3;
+ constexpr uint8_t RGB332 = 4;
+ constexpr uint8_t ARGB2 = 5;
+ constexpr uint8_t ARGB4 = 6;
+ constexpr uint8_t RGB565 = 7;
+ constexpr uint8_t PALETTED = 8;
+ constexpr uint8_t TEXT8X8 = 9;
+ constexpr uint8_t TEXTVGA = 10;
+ constexpr uint8_t BARGRAPH = 11;
+
+ constexpr uint8_t ALPHA_FUNC_NEVER = 0;
+ constexpr uint8_t ALPHA_FUNC_LESS = 1;
+ constexpr uint8_t ALPHA_FUNC_LEQUAL = 2;
+ constexpr uint8_t ALPHA_FUNC_GREATER = 3;
+ constexpr uint8_t ALPHA_FUNC_GEQUAL = 4;
+ constexpr uint8_t ALPHA_FUNC_EQUAL = 5;
+ constexpr uint8_t ALPHA_FUNC_NOTEQUAL = 6;
+ constexpr uint8_t ALPHA_FUNC_ALWAYS = 7;
+
+ constexpr uint8_t NEAREST = 0;
+ constexpr uint8_t BILINEAR = 1;
+ constexpr uint8_t BORDER = 0;
+ constexpr uint8_t REPEAT = 1;
+
+ constexpr uint8_t BLEND_FUNC_ZERO = 0;
+ constexpr uint8_t BLEND_FUNC_ONE = 1;
+ constexpr uint8_t BLEND_FUNC_SRC_ALPHA = 2;
+ constexpr uint8_t BLEND_FUNC_DST_ALPHA = 3;
+ constexpr uint8_t BLEND_FUNC_ONE_MINUS_SRC_ALPHA = 4;
+ constexpr uint8_t BLEND_FUNC_ONE_MINUS_DST_ALPHA = 5;
+
+ constexpr uint32_t COLOR_MASK_RED = 8;
+ constexpr uint32_t COLOR_MASK_GRN = 4;
+ constexpr uint32_t COLOR_MASK_BLU = 2;
+ constexpr uint32_t COLOR_MASK_ALPHA = 1;
+
+ constexpr uint8_t STENCIL_FUNC_NEVER = 0;
+ constexpr uint8_t STENCIL_FUNC_LESS = 1;
+ constexpr uint8_t STENCIL_FUNC_LEQUAL = 2;
+ constexpr uint8_t STENCIL_FUNC_GREATER = 3;
+ constexpr uint8_t STENCIL_FUNC_GEQUAL = 4;
+ constexpr uint8_t STENCIL_FUNC_EQUAL = 5;
+ constexpr uint8_t STENCIL_FUNC_NOTEQUAL = 6;
+ constexpr uint8_t STENCIL_FUNC_ALWAYS = 7;
+
+ constexpr uint8_t STENCIL_OP_ZERO = 0;
+ constexpr uint8_t STENCIL_OP_KEEP = 1;
+ constexpr uint8_t STENCIL_OP_REPLACE = 2;
+ constexpr uint8_t STENCIL_OP_INCR = 3;
+ constexpr uint8_t STENCIL_OP_DECR = 4;
+ constexpr uint8_t STENCIL_OP_INVERT = 5;
+
+ typedef enum : uint32_t {
+ BITMAPS = 1,
+ POINTS = 2,
+ LINES = 3,
+ LINE_STRIP = 4,
+ EDGE_STRIP_R = 5,
+ EDGE_STRIP_L = 6,
+ EDGE_STRIP_A = 7,
+ EDGE_STRIP_B = 8,
+ RECTS = 9
+ } begin_t;
+}
+
+namespace FTDI_FT800_DL {
+ constexpr uint32_t ALPHA_FUNC = 0x09000000;
+ constexpr uint32_t BEGIN = 0x1F000000;
+ constexpr uint32_t BITMAP_HANDLE = 0x05000000;
+ constexpr uint32_t BITMAP_LAYOUT = 0x07000000;
+ constexpr uint32_t BITMAP_SIZE = 0x08000000;
+ constexpr uint32_t BITMAP_SOURCE = 0x01000000;
+ constexpr uint32_t BITMAP_TRANSFORM_A = 0x15000000;
+ constexpr uint32_t BITMAP_TRANSFORM_B = 0x16000000;
+ constexpr uint32_t BITMAP_TRANSFORM_C = 0x17000000;
+ constexpr uint32_t BITMAP_TRANSFORM_D = 0x18000000;
+ constexpr uint32_t BITMAP_TRANSFORM_E = 0x19000000;
+ constexpr uint32_t BITMAP_TRANSFORM_F = 0x1A000000;
+ constexpr uint32_t BLEND_FUNC = 0x0B000000;
+ constexpr uint32_t CALL = 0x1D000000;
+ constexpr uint32_t CELL = 0x06000000;
+ constexpr uint32_t CLEAR = 0x26000000;
+ constexpr uint32_t CLEAR_COLOR_BUFFER = 0x00000004;
+ constexpr uint32_t CLEAR_STENCIL_BUFFER = 0x00000002;
+ constexpr uint32_t CLEAR_TAG_BUFFER = 0x00000001;
+ constexpr uint32_t CLEAR_COLOR_A = 0x0F000000;
+ constexpr uint32_t CLEAR_COLOR_RGB = 0x02000000;
+ constexpr uint32_t CLEAR_STENCIL = 0x11000000;
+ constexpr uint32_t CLEAR_TAG = 0x12000000;
+ constexpr uint32_t COLOR_A = 0x10000000;
+ constexpr uint32_t COLOR_MASK = 0x20000000;
+ constexpr uint32_t COLOR_RGB = 0x04000000;
+ constexpr uint32_t DL_DISPLAY = 0x00000000;
+ constexpr uint32_t END = 0x21000000;
+ constexpr uint32_t JUMP = 0x1E000000;
+ constexpr uint32_t LINE_WIDTH = 0x0E000000;
+ constexpr uint32_t MACRO = 0x25000000;
+ constexpr uint32_t POINT_SIZE = 0x0D000000;
+ constexpr uint32_t RESTORE_CONTEXT = 0x23000000;
+ constexpr uint32_t RETURN = 0x24000000;
+ constexpr uint32_t SAVE_CONTEXT = 0x22000000;
+ constexpr uint32_t SCISSOR_SIZE = 0x1C000000;
+ constexpr uint32_t SCISSOR_XY = 0x1B000000;
+ constexpr uint32_t STENCIL_FUNC = 0x0A000000;
+ constexpr uint32_t STENCIL_MASK = 0x13000000;
+ constexpr uint32_t STENCIL_OP = 0x0C000000;
+ constexpr uint32_t TAG = 0x03000000;
+ constexpr uint32_t TAG_MASK = 0x14000000;
+ constexpr uint32_t VERTEX2F = 0x40000000;
+ constexpr uint32_t VERTEX2II = 0x80000000;
+}
+
+namespace FTDI_FT810_DL {
+ constexpr uint32_t NOP = 0x25000000;
+ constexpr uint32_t BITMAP_LAYOUT_H = 0x28000000;
+ constexpr uint32_t BITMAP_SIZE_H = 0x29000000;
+ constexpr uint32_t VERTEX_FORMAT = 0x27000000;
+ constexpr uint32_t VERTEX_TRANSLATE_X = 0x2B000000;
+ constexpr uint32_t VERTEX_TRANSLATE_Y = 0x2C000000;
+}
+
+// CO-PROCESSOR ENGINE COMMANDS
+namespace FTDI {
+ constexpr uint32_t CMD_DLSTART = 0xFFFFFF00;
+ constexpr uint32_t CMD_SWAP = 0xFFFFFF01;
+ constexpr uint32_t CMD_COLDSTART = 0xFFFFFF32;
+ constexpr uint32_t CMD_INTERRUPT = 0xFFFFFF02;
+ constexpr uint32_t CMD_APPEND = 0xFFFFFF1E;
+ constexpr uint32_t CMD_REGREAD = 0xFFFFFF19;
+ constexpr uint32_t CMD_MEMWRITE = 0xFFFFFF1A;
+ constexpr uint32_t CMD_INFLATE = 0xFFFFFF22;
+ constexpr uint32_t CMD_LOADIMAGE = 0xFFFFFF24;
+ constexpr uint32_t CMD_MEMCRC = 0xFFFFFF18;
+ constexpr uint32_t CMD_MEMZERO = 0xFFFFFF1C;
+ constexpr uint32_t CMD_MEMSET = 0xFFFFFF1B;
+ constexpr uint32_t CMD_MEMCPY = 0xFFFFFF1D;
+ constexpr uint32_t CMD_BUTTON = 0xFFFFFF0D;
+ constexpr uint32_t CMD_CLOCK = 0xFFFFFF14;
+ constexpr uint32_t CMD_FGCOLOR = 0xFFFFFF0A;
+ constexpr uint32_t CMD_BGCOLOR = 0xFFFFFF09;
+ constexpr uint32_t CMD_GRADCOLOR = 0xFFFFFF34;
+ constexpr uint32_t CMD_GAUGE = 0xFFFFFF13;
+ constexpr uint32_t CMD_GRADIENT = 0xFFFFFF0B;
+ constexpr uint32_t CMD_KEYS = 0xFFFFFF0E;
+ constexpr uint32_t CMD_PROGRESS = 0xFFFFFF0F;
+ constexpr uint32_t CMD_SCROLLBAR = 0xFFFFFF11;
+ constexpr uint32_t CMD_SLIDER = 0xFFFFFF10;
+ constexpr uint32_t CMD_DIAL = 0xFFFFFF2D;
+ constexpr uint32_t CMD_TOGGLE = 0xFFFFFF12;
+ constexpr uint32_t CMD_TEXT = 0xFFFFFF0C;
+ constexpr uint32_t CMD_NUMBER = 0xFFFFFF2E;
+ constexpr uint32_t CMD_LOADIDENTITY = 0xFFFFFF26;
+ constexpr uint32_t CMD_SETMATRIX = 0xFFFFFF2A;
+ constexpr uint32_t CMD_GETMATRIX = 0xFFFFFF33;
+ constexpr uint32_t CMD_GETPTR = 0xFFFFFF23;
+ constexpr uint32_t CMD_GETPROPS = 0xFFFFFF25;
+ constexpr uint32_t CMD_SCALE = 0xFFFFFF28;
+ constexpr uint32_t CMD_ROTATE = 0xFFFFFF29;
+ constexpr uint32_t CMD_TRANSLATE = 0xFFFFFF27;
+ constexpr uint32_t CMD_CALIBRATE = 0xFFFFFF15;
+ constexpr uint32_t CMD_SPINNER = 0xFFFFFF16;
+ constexpr uint32_t CMD_SCREENSAVER = 0xFFFFFF2F;
+ constexpr uint32_t CMD_SKETCH = 0xFFFFFF30;
+ constexpr uint32_t CMD_STOP = 0xFFFFFF17;
+ constexpr uint32_t CMD_SETFONT = 0xFFFFFF2B;
+ constexpr uint32_t CMD_TRACK = 0xFFFFFF2C;
+ constexpr uint32_t CMD_SNAPSHOT = 0xFFFFFF1F;
+ constexpr uint32_t CMD_LOGO = 0xFFFFFF31;
+}
+
+namespace FTDI_FT810 {
+ constexpr uint32_t CMD_SETROTATE = 0xFFFFFF36;
+ constexpr uint32_t CMD_SNAPSHOT2 = 0xFFFFFF37;
+ constexpr uint32_t CMD_SETBASE = 0xFFFFFF38;
+ constexpr uint32_t CMD_MEDIAFIFO = 0xFFFFFF39;
+ constexpr uint32_t CMD_PLAYVIDEO = 0xFFFFFF3A;
+ constexpr uint32_t CMD_SETFONT2 = 0xFFFFFF3B;
+ constexpr uint32_t CMD_SETSCRATCH = 0xFFFFFF3C;
+ constexpr uint32_t CMD_ROMFONT = 0xFFFFFF3F;
+ constexpr uint32_t CMD_VIDEOSTART = 0xFFFFFF40;
+ constexpr uint32_t CMD_VIDEOFRAME = 0xFFFFFF41;
+ constexpr uint32_t CMD_SETBITMAP = 0xFFFFFF43;
+}
+
+namespace FTDI {
+ enum effect_t : unsigned char {
+ SILENCE = 0x00,
+ SQUARE_WAVE = 0x01,
+ SINE_WAVE = 0x02,
+ SAWTOOTH_WAVE = 0x03,
+ TRIANGLE_WAVE = 0x04,
+ BEEPING = 0x05,
+ ALARM = 0x06,
+ WARBLE = 0x07,
+ CAROUSEL = 0x08,
+ SHORT_PIPS_1 = 0x10,
+ SHORT_PIPS_2 = 0x11,
+ SHORT_PIPS_3 = 0x12,
+ SHORT_PIPS_4 = 0x13,
+ SHORT_PIPS_5 = 0x14,
+ SHORT_PIPS_6 = 0x15,
+ SHORT_PIPS_7 = 0x16,
+ SHORT_PIPS_8 = 0x17,
+ SHORT_PIPS_9 = 0x18,
+ SHORT_PIPS_10 = 0x19,
+ SHORT_PIPS_11 = 0x1A,
+ SHORT_PIPS_12 = 0x1B,
+ SHORT_PIPS_13 = 0x1C,
+ SHORT_PIPS_14 = 0x1D,
+ SHORT_PIPS_15 = 0x1E,
+ SHORT_PIPS_16 = 0x1F,
+ DTMF_POUND = 0x23,
+ DTMF_STAR = 0x2C,
+ DTMF_0 = 0x30,
+ DTMF_1 = 0x31,
+ DTMF_2 = 0x32,
+ DTMF_3 = 0x33,
+ DTMF_4 = 0x34,
+ DTMF_5 = 0x35,
+ DTMF_6 = 0x36,
+ DTMF_7 = 0x37,
+ DTMF_8 = 0x38,
+ DTMF_9 = 0x39,
+ HARP = 0x40,
+ XYLOPHONE = 0x41,
+ TUBA = 0x42,
+ GLOCKENSPIEL = 0x43,
+ ORGAN = 0x44,
+ TRUMPET = 0x45,
+ PIANO = 0x46,
+ CHIMES = 0x47,
+ MUSIC_BOX = 0x48,
+ BELL = 0x49,
+ CLICK = 0x50,
+ SWITCH = 0x51,
+ COWBELL = 0x52,
+ NOTCH = 0x53,
+ HIHAT = 0x54,
+ KICKDRUM = 0x55,
+ POP = 0x56,
+ CLACK = 0x57,
+ CHACK = 0x58,
+ MUTE = 0x60,
+ UNMUTE = 0x61
+ };
+
+ enum note_t : unsigned char {
+ END_SONG = 0xFF,
+ REST = 0x00,
+
+ NOTE_C1 = 0x18, // 24
+ NOTE_C1S = 0x19,
+ NOTE_D1 = 0x1A,
+ NOTE_D1S = 0x1B,
+ NOTE_E1 = 0x1C,
+ NOTE_F1 = 0x1D,
+ NOTE_F1S = 0x1E,
+ NOTE_G1 = 0x1F,
+ NOTE_G1S = 0x20,
+ NOTE_A1 = 0x21,
+ NOTE_A1S = 0x22,
+ NOTE_B1 = 0x23,
+
+ NOTE_C2 = 0x24, //36
+ NOTE_C2S = 0x25,
+ NOTE_D2 = 0x26,
+ NOTE_D2S = 0x27,
+ NOTE_E2 = 0x28,
+ NOTE_F2 = 0x29,
+ NOTE_F2S = 0x2A,
+ NOTE_G2 = 0x2B,
+ NOTE_G2S = 0x2C,
+ NOTE_A2 = 0x2D,
+ NOTE_A2S = 0x2E,
+ NOTE_B2 = 0x2F,
+
+ NOTE_C3 = 0x30,
+ NOTE_C3S = 0x31,
+ NOTE_D3 = 0x32,
+ NOTE_D3S = 0x33,
+ NOTE_E3 = 0x34,
+ NOTE_F3 = 0x35,
+ NOTE_F3S = 0x36,
+ NOTE_G3 = 0x37,
+ NOTE_G3S = 0x38,
+ NOTE_A3 = 0x39,
+ NOTE_A3S = 0x3A,
+ NOTE_B3 = 0x3B,
+
+ NOTE_C4 = 0x3C,
+ NOTE_C4S = 0x3D,
+ NOTE_D4 = 0x3E,
+ NOTE_D4S = 0x3F,
+ NOTE_E4 = 0x40,
+ NOTE_F4 = 0x41,
+ NOTE_F4S = 0x42,
+ NOTE_G4 = 0x43,
+ NOTE_G4S = 0x44,
+ NOTE_A4 = 0x45,
+ NOTE_A4S = 0x46,
+ NOTE_B4 = 0x47,
+
+ NOTE_C5 = 0x48,
+ NOTE_C5S = 0x49,
+ NOTE_D5 = 0x4A,
+ NOTE_D5S = 0x4B,
+ NOTE_E5 = 0x4C,
+ NOTE_F5 = 0x4D,
+ NOTE_F5S = 0x4E,
+ NOTE_G5 = 0x4F,
+ NOTE_G5S = 0x50,
+ NOTE_A5 = 0x51,
+ NOTE_A5S = 0x52,
+ NOTE_B5 = 0x53,
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/display_list.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/display_list.h
new file mode 100644
index 0000000..99a9e0e
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/display_list.h
@@ -0,0 +1,118 @@
+/******************
+ * display_list.h *
+ *****************/
+
+/**********************************************************************************
+ * Adapted from: *
+ * https://github.com/RudolphRiedel/FT800-FT813 *
+ * By Rudolph Riedel *
+ * *
+ * MIT License *
+ * *
+ * Copyright (c) 2017 *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy *
+ * of this software and associated documentation files (the "Software"), to deal *
+ * in the Software without restriction, including without limitation the rights *
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included in all *
+ * copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
+ * SOFTWARE. *
+ * *
+ **********************************************************************************/
+
+#pragma once
+
+namespace FTDI {
+ /* FT8xx graphics engine specific macros useful for static display list generation */
+ inline uint32_t ALPHA_FUNC(uint8_t func, uint8_t ref) {return DL::ALPHA_FUNC|((func&7UL)<<8)|(ref&255UL);}
+ inline uint32_t BEGIN(begin_t prim) {return DL::BEGIN|(prim&15UL);}
+
+ inline uint32_t BITMAP_SOURCE(uint32_t ram_g_addr) {return DL::BITMAP_SOURCE|(ram_g_addr);}
+ inline uint32_t BITMAP_HANDLE(uint8_t handle) {return DL::BITMAP_HANDLE|(handle&31UL);}
+ inline uint32_t BITMAP_LAYOUT(uint8_t format, uint16_t linestride, uint16_t height)
+ {return DL::BITMAP_LAYOUT|((format&31UL)<<19)|((linestride&1023UL)<<9)|(height&511UL);}
+
+ inline uint32_t BITMAP_SIZE(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height)
+ {return DL::BITMAP_SIZE|((filter&1UL)<<20)|((wrapx&1UL)<<19)|((wrapy&1UL)<<18)|((width&511UL)<<9)|(height&511UL);}
+ #if FTDI_API_LEVEL >= 810
+ inline uint32_t BITMAP_LAYOUT_H(uint8_t linestride, uint8_t height)
+ {return DL::BITMAP_LAYOUT_H|((linestride&3UL)<<2)|(height&3UL);}
+ inline uint32_t BITMAP_SIZE_H(uint8_t width, uint8_t height)
+ {return DL::BITMAP_SIZE_H|((width&3UL)<<2)|(height&3UL);}
+ #endif
+ inline uint32_t BITMAP_TRANSFORM_A(uint16_t a) {return DL::BITMAP_TRANSFORM_A|(a&131071UL);}
+ inline uint32_t BITMAP_TRANSFORM_B(uint16_t b) {return DL::BITMAP_TRANSFORM_B|(b&131071UL);}
+ inline uint32_t BITMAP_TRANSFORM_C(uint32_t c) {return DL::BITMAP_TRANSFORM_C|(c&16777215UL);}
+ inline uint32_t BITMAP_TRANSFORM_D(uint16_t d) {return DL::BITMAP_TRANSFORM_D|(d&131071UL);}
+ inline uint32_t BITMAP_TRANSFORM_E(uint16_t e) {return DL::BITMAP_TRANSFORM_E|(e&131071UL);}
+ inline uint32_t BITMAP_TRANSFORM_F(uint32_t f) {return DL::BITMAP_TRANSFORM_F|(f&16777215UL);}
+ inline uint32_t BLEND_FUNC(uint8_t src,uint8_t dst) {return DL::BLEND_FUNC|((src&7UL)<<3)|(dst&7UL);}
+ inline uint32_t CALL(uint16_t dest) {return DL::CALL|(dest&65535UL);}
+ inline uint32_t CELL(uint8_t cell) {return DL::CELL|(cell&127UL);}
+ inline uint32_t CLEAR(bool c,bool s,bool t) {return DL::CLEAR|((c?1UL:0UL)<<2)|((s?1UL:0UL)<<1)|(t?1UL:0UL);}
+ inline uint32_t CLEAR_COLOR_A(uint8_t alpha) {return DL::CLEAR_COLOR_A|(alpha&255UL);}
+ inline uint32_t CLEAR_COLOR_RGB(uint8_t red, uint8_t green, uint8_t blue)
+ {return DL::CLEAR_COLOR_RGB|((red&255UL)<<16)|((green&255UL)<<8)|(blue&255UL);}
+ inline uint32_t CLEAR_COLOR_RGB(uint32_t rgb) {return DL::CLEAR_COLOR_RGB|rgb;}
+ inline uint32_t CLEAR_STENCIL(uint8_t s) {return DL::CLEAR_STENCIL|(s&255UL);}
+ inline uint32_t CLEAR_TAG(uint8_t s) {return DL::CLEAR_TAG|(s&255UL);}
+ inline uint32_t COLOR_A(uint8_t alpha) {return DL::COLOR_A|(alpha&255UL);}
+ inline uint32_t COLOR_MASK(bool r, bool g, bool b, bool a) {return DL::COLOR_MASK|((r?1UL:0UL)<<3)|((g?1UL:0UL)<<2)|((b?1UL:0UL)<<1)|(a?1UL:0UL);}
+ inline uint32_t COLOR_RGB(uint8_t red,uint8_t green,uint8_t blue)
+ {return DL::COLOR_RGB|((red&255UL)<<16)|((green&255UL)<<8)|(blue&255UL);}
+ inline uint32_t COLOR_RGB(uint32_t rgb) {return DL::COLOR_RGB|rgb;}
+ /* inline uint32_t DISPLAY() {return (0UL<<24)) */
+ inline uint32_t END() {return DL::END;}
+ inline uint32_t JUMP(uint16_t dest) {return DL::JUMP|(dest&65535UL);}
+ inline uint32_t LINE_WIDTH(uint16_t width) {return DL::LINE_WIDTH|(width&4095UL);}
+ inline uint32_t MACRO(uint8_t m) {return DL::MACRO|(m&1UL);}
+ inline uint32_t POINT_SIZE(uint16_t size) {return DL::POINT_SIZE|(size&8191UL);}
+ inline uint32_t RESTORE_CONTEXT() {return DL::RESTORE_CONTEXT;}
+ inline uint32_t RETURN () {return DL::RETURN;}
+ inline uint32_t SAVE_CONTEXT() {return DL::SAVE_CONTEXT;}
+ inline uint32_t SCISSOR_XY(uint16_t x,uint16_t y) {
+ return DL::SCISSOR_XY |
+ (FTDI::ftdi_chip >= 810
+ ? ((x&2047UL)<<11)|(y&2047UL)
+ : ((x& 511UL)<<10)|(y&511UL));
+ }
+ inline uint32_t SCISSOR_SIZE(uint16_t w,uint16_t h) {
+ return DL::SCISSOR_SIZE |
+ (FTDI::ftdi_chip >= 810
+ ? ((w&4095UL)<<12)|(h&4095UL)
+ : ((w&1023UL)<<10)|(h&1023UL));
+ }
+ inline uint32_t SCISSOR_XY() {return DL::SCISSOR_XY;}
+ inline uint32_t SCISSOR_SIZE() {
+ return DL::SCISSOR_SIZE |
+ (FTDI::ftdi_chip >= 810
+ ? (2048UL<<12)|(2048UL)
+ : ( 512UL<<10)|( 512UL));
+ }
+ inline uint32_t STENCIL_FUNC(uint16_t func, uint8_t ref, uint8_t mask)
+ {return DL::STENCIL_FUNC|((func&7UL)<<16)|((ref&255UL)<<8)|(mask&255UL);}
+ inline uint32_t STENCIL_MASK(uint8_t mask) {return DL::STENCIL_MASK|(mask&255UL);}
+ inline uint32_t STENCIL_OP(uint8_t sfail, uint8_t spass) {return DL::STENCIL_OP|(((sfail)&7UL)<<3)|(spass&7UL);}
+ inline uint32_t TAG(uint8_t s) {return DL::TAG|(s&255UL);}
+ inline uint32_t TAG_MASK(bool mask) {return DL::TAG_MASK|(mask?1:0);}
+ inline uint32_t VERTEX2F(uint16_t x, uint16_t y) {return DL::VERTEX2F|((x&32767UL)<<15)|(y&32767UL);}
+ inline uint32_t VERTEX2II(uint16_t x,uint16_t y, uint8_t handle = 0, uint8_t cell = 0)
+ {return DL::VERTEX2II|((x&511UL)<<21)|((y&511UL)<<12)|((handle&31UL)<<7)|(cell&127UL);}
+
+ #if FTDI_API_LEVEL >= 810
+ inline uint32_t VERTEX_FORMAT(uint8_t frac) {return DL::VERTEX_FORMAT|(frac&7UL);}
+ inline uint32_t VERTEX_TRANSLATE_X(int32_t x) {return DL::VERTEX_TRANSLATE_X|(x&131071UL);}
+ inline uint32_t VERTEX_TRANSLATE_Y(int32_t y) {return DL::VERTEX_TRANSLATE_Y|(y&131071UL);}
+ #endif
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/ftdi_basic.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/ftdi_basic.h
new file mode 100644
index 0000000..47cd698
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/ftdi_basic.h
@@ -0,0 +1,40 @@
+/****************
+ * ftdi_basic.h *
+ ****************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2019 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#include "../compat.h"
+
+#ifndef __MARLIN_FIRMWARE__
+ #define FTDI_BASIC
+#endif
+
+#ifdef FTDI_BASIC
+ #include "registers_ft800.h"
+ #include "registers_ft810.h"
+ #include "constants.h"
+ #include "boards.h"
+ #include "commands.h"
+ #include "spi.h"
+ #include "display_list.h"
+ #include "resolutions.h"
+#endif
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft800.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft800.h
new file mode 100644
index 0000000..2605370
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft800.h
@@ -0,0 +1,150 @@
+/*********************
+ * registers_ft800.h *
+ *********************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+/****************************************************************************
+ * This header defines registers for the FTDI FT800 LCD Driver chip. *
+ ****************************************************************************/
+
+/*******************************************************************************
+ * FT810 *
+ * *
+ * START END ADDR SIZE NAME DESCRIPTION *
+ * *
+ * 0x000000 0x03FFFF 256 kB RAM_G Main Graphics RAM *
+ * *
+ * 0x0C0000 0x0C0003 4 B ROM_CHIPID [0:1] 0x800 Chip Id *
+ * [1:2] 0x0100 Vers ID *
+ * *
+ * 0x0BB23C 0x0FFFFB 275 kB ROM_FONT Font table and bitmap *
+ * *
+ * 0x0FFFFC 0x0FFFFF 4 B ROM_FONT_ADDR Font table pointer address *
+ * *
+ * 0x100000 0x101FFF 8 kB RAM_DL Display List RAM *
+ * *
+ * 0x102000 0x1023FF 1 kB RAM_PAL Palette RAM *
+ * *
+ * 0x102400 0x10257F 380 B * Registers *
+ * *
+ * 0x108000 0x108FFF 4 kB RAM_CMD Command Buffer *
+ * *
+ *******************************************************************************/
+
+#pragma once
+
+namespace FTDI {
+ struct ft800_memory_map {
+
+ // MEMORY LOCATIONS FT800
+ static constexpr uint32_t RAM_G = 0x000000; // Main Graphics RAM
+ static constexpr uint32_t ROM_CHIPID = 0x0C0000; // Chip ID/Version ID
+ static constexpr uint32_t ROM_FONT = 0x0BB23C; // Font ROM
+ static constexpr uint32_t ROM_FONT_ADDR = 0x0FFFFC; // Font Table Pointer
+ static constexpr uint32_t RAM_DL = 0x100000; // Display List RAM
+ static constexpr uint32_t RAM_PAL = 0x102000; // Palette RAM
+ static constexpr uint32_t RAM_REG = 0x102400; // Registers
+ static constexpr uint32_t RAM_CMD = 0x108000; // Command Buffer
+
+ static constexpr uint32_t RAM_G_SIZE = 256*1024L; // 256k
+ };
+
+ struct ft800_registers {
+ // REGISTERS AND ADDRESSES FT800
+
+ // REGISTER ADDRESS SIZE RESET VALUE TYPE DESCRIPTION
+
+ static constexpr uint32_t ID = 0x102400; // 8 0x7C r Identification Register, Always 0x7C
+ static constexpr uint32_t FRAMES = 0x102404; // 32 0x00000000 r Frame Counter, Since Reset
+ static constexpr uint32_t CLOCK = 0x102408; // 32 0x00000000 r Clock cycles, Since Reset
+ static constexpr uint32_t FREQUENCY = 0x10240C; // 28 0x03938700 r/w Main Clock Frequency
+ static constexpr uint32_t RENDERMODE = 0x102410; // 1 0x00 r/w Rendering Mode: 0 = normal, 1 = single-line
+ static constexpr uint32_t SNAPY = 0x102414; // 11 0x0000 r/w Scan Line Select for RENDERMODE 1
+ static constexpr uint32_t SNAPSHOT = 0x102418; // 1 - r Trigger for RENDERMODE 1
+ static constexpr uint32_t CPURESET = 0x10241C; // 3 0x02 r/w RESET Bit2 Audio - Bit1 Touch - Bit0 Graphics
+ static constexpr uint32_t TAP_CRC = 0x102420; // 32 - r Live Video Tap
+ static constexpr uint32_t TAP_MASK = 0x102424; // 32 0xFFFFFFFF r/w Live Video Tap Mask
+ static constexpr uint32_t HCYCLE = 0x102428; // 12 0x224 r/w Horizontal Total Cycle Count
+ static constexpr uint32_t HOFFSET = 0x10242C; // 12 0x02B r/w Horizontal Display Start Offset
+ static constexpr uint32_t HSIZE = 0x102430; // 12 0x1E0 r/w Horizontal Display Pixel Count
+ static constexpr uint32_t HSYNC0 = 0x102434; // 12 0x000 r/w Horizontal Sync Fall Offset
+ static constexpr uint32_t HSYNC1 = 0x102438; // 12 0x029 r/w Horizontal Sync Rise Offset
+ static constexpr uint32_t VCYCLE = 0x10243C; // 12 0x124 r/w Vertical Total Cycle Count
+ static constexpr uint32_t VOFFSET = 0x102440; // 12 0x00C r/w Vertical Display Start Offset
+ static constexpr uint32_t VSIZE = 0x102444; // 12 0x110 r/w Vertical Display Line Count
+ static constexpr uint32_t VSYNC0 = 0x102448; // 10 0x000 r/w Vertical Sync Fall Offset
+ static constexpr uint32_t VSYNC1 = 0x10244C; // 10 0x00A r/w Vertical Sync Rise Offset
+ static constexpr uint32_t DLSWAP = 0x102450; // 2 0x00 r/w Display List Swap Control
+ static constexpr uint32_t ROTATE = 0x102454; // 3 0x00 r/w Screen 90,180, 270 degree rotate
+ static constexpr uint32_t OUTBITS = 0x102458; // 9 0x1B6 r/w Output Resolution, 3x3x3 Bits
+ static constexpr uint32_t DITHER = 0x10245C; // 1 0x01 r/w Output Dither Enable
+ static constexpr uint32_t SWIZZLE = 0x102460; // 4 0x00 r/w Output RGB Swizzle, Pin Change for PCB Routing
+ static constexpr uint32_t CSPREAD = 0x102464; // 1 0x01 r/w Output Clock Spreading Enable
+ static constexpr uint32_t PCLK_POL = 0x102468; // 1 0x00 r/w PCLK Polarity: 0 = Rising Edge, 1 = Falling Edge
+ static constexpr uint32_t PCLK = 0x10246C; // 8 0x00 r/w PCLK Frequency Divider, 0 = Disable Clock
+ static constexpr uint32_t TAG_X = 0x102470; // 11 0x000 r/w Tag Query X Coordinate
+ static constexpr uint32_t TAG_Y = 0x102474; // 11 0x000 r/w Tag Query Y Coordinate
+ static constexpr uint32_t TAG = 0x102478; // 8 0x00 r Tag Query Result
+ static constexpr uint32_t VOL_PB = 0x10247C; // 8 0xFF r/w Audio Playback Volume
+ static constexpr uint32_t VOL_SOUND = 0x102480; // 8 0xFF r/w Audio Synthesizer Volume
+ static constexpr uint32_t SOUND = 0x102484; // 16 0x0000 r/w Audio Sound Effect Select
+ static constexpr uint32_t PLAY = 0x102488; // 1 0x00 r/w Audio Start Effect Playback
+ static constexpr uint32_t GPIO_DIR = 0x10248C; // 8 0x80 r/w GPIO Pin Direction: 0 = Input , 1 = Output
+ static constexpr uint32_t GPIO = 0x102490; // 8 0x00 r/w GPIO Pin Values for 0, 1, 7 Drive Strength 2, 3, 4, 5, 6
+ static constexpr uint32_t INT_FLAGS = 0x102498; // 8 0x00 r Interrupt Flags, Clear by Reading
+ static constexpr uint32_t INT_EN = 0x10249C; // 1 0x00 r/w Global Interrupt Enable
+ static constexpr uint32_t INT_MASK = 0x1024A0; // 8 0xFF r/w Interrupt Enable Mask
+ static constexpr uint32_t PLAYBACK_START = 0x1024A4; // 20 0x00000 r/w Audio Playback RAM Start Address
+ static constexpr uint32_t PLAYBACK_LENGTH = 0x1024A8; // 20 0x00000 r/w Audio Playback Sample Length (Bytes)
+ static constexpr uint32_t PLAYBACK_READPTR = 0x1024AC; // 20 - r Audio Playback Read Pointer
+ static constexpr uint32_t PLAYBACK_FREQ = 0x1024B0; // 16 0x1F40 r/w Audio Playback Frequency (Hz)
+ static constexpr uint32_t PLAYBACK_FORMAT = 0x1024B4; // 2 0x00 r/w Audio Playback Format
+ static constexpr uint32_t PLAYBACK_LOOP = 0x1024B8; // 1 0x00 r/w Audio Playback Loop Enable
+ static constexpr uint32_t PLAYBACK_PLAY = 0x1024BC; // 1 0x00 r Audio Start Playback
+ static constexpr uint32_t PWM_HZ = 0x1024C0; // 14 0x00FA r/w Backlight PWM Frequency (Hz)
+ static constexpr uint32_t PWM_DUTY = 0x1024C4; // 8 0x80 r/w Backlight PWM Duty Cycle: 0 = 0%, 128 = 100%
+ static constexpr uint32_t MACRO_0 = 0x1024C8; // 32 0x00000000 r/w Display List Macro Command 0
+ static constexpr uint32_t MACRO_1 = 0x1024CC; // 32 0x00000000 r/w Display List Macro Command 1
+ static constexpr uint32_t CMD_READ = 0x1024E4; // 12 0x000 r/w Command Buffer Read Pointer
+ static constexpr uint32_t CMD_WRITE = 0x1024E8; // 12 0x000 r/w Command Buffer Write Pointer
+ static constexpr uint32_t CMD_DL = 0x1024EC; // 13 0x0000 r/w Command Display List Offset
+ static constexpr uint32_t TOUCH_MODE = 0x1024F0; // 2 0x03 r/w Touch-Screen Sampling Mode
+ static constexpr uint32_t TOUCH_ADC_MODE = 0x1024F4; // 1 0x01 r/w Select Single Ended or Differential Sampling
+ static constexpr uint32_t TOUCH_CHARGE = 0x1024F8; // 16 0x1770 r/w Touch Screen Charge Time, n x 6 Clocks
+ static constexpr uint32_t TOUCH_SETTLE = 0x1024FC; // 4 0x03 r/w Touch-Screen Settle Time, n x 6 Clocks
+ static constexpr uint32_t TOUCH_OVERSAMPLE = 0x102500; // 4 0x07 r/w Touch-Screen Oversample Factor
+ static constexpr uint32_t TOUCH_RZTHRESH = 0x102504; // 16 0xFFFF r/w Touch-Screen Resistance Threshold
+ static constexpr uint32_t TOUCH_RAW_XY = 0x102508; // 32 - r Touch-Screen Raw (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_RZ = 0x10250C; // 16 - r Touch-Screen Resistance
+ static constexpr uint32_t TOUCH_SCREEN_XY = 0x102510; // 32 - r Touch-Screen Screen (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_TAG_XY = 0x102514; // 32 - r Touch-Screen Tag 0 Lookup (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_TAG = 0x102518; // 8 - r Touch-Screen Tag 0 Result
+ static constexpr uint32_t TOUCH_TRANSFORM_A = 0x10251C; // 32 0x00010000 r/w Touch-Screen Transform Coefficient A (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_B = 0x102520; // 32 0x00000000 r/w Touch-Screen Transform Coefficient B (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_C = 0x102524; // 32 0x00000000 r/w Touch-Screen Transform Coefficient C (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_D = 0x102528; // 32 0x00000000 r/w Touch-Screen Transform Coefficient D (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_E = 0x10252C; // 32 0x00010000 r/w Touch-Screen Transform Coefficient E (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_F = 0x102530; // 32 0x00000000 r/w Touch-Screen Transform Coefficient F (s15.16)
+ // Reserved Addresses 0x102434 - 0x102470
+ static constexpr uint32_t TOUCH_DIRECT_XY = 0x102574; // 32 - r Touch-Screen Direct Conversions XY (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_DIRECT_Z1Z2 = 0x102578; // 32 - r Touch-Screen Direct Conversions Z (z1-MSB16; z2-LSB16)
+ static constexpr uint32_t TRACKER = 0x109000; // 32 0x00000000 r/w Track Register (Track Value MSB16; Tag Value - LSB8)
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft810.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft810.h
new file mode 100644
index 0000000..e57d11c
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/registers_ft810.h
@@ -0,0 +1,187 @@
+/*********************
+ * registers_ft810.h *
+ *********************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+/****************************************************************************
+ * This header defines registers for the FTDI FT810 LCD Driver chip. *
+ ****************************************************************************/
+
+/*******************************************************************************
+ * FT810 *
+ * *
+ * START END ADDR SIZE NAME DESCRIPTION *
+ * *
+ * 0x000000 0x0FFFFF 1024 kB RAM_G Main Graphics RAM (0 to 1048572) *
+ * *
+ * 0x0C0000 0x0C0003 4 B ROM_CHIPID [0:1] 0x800 Chip Id *
+ * [1:2] 0x0100 Vers ID *
+ * *
+ * 0x1E0000 0x2FFFFB 1152 kB ROM_FONT Font table and bitmap *
+ * *
+ * 0x201EE0 0x2029DC 2812 B ROM_FONT_ROOT ROM font table *
+ * *
+ * 0x2FFFFC 0x2FFFFF 4 B ROM_FONT_ADDR Font table pointer address *
+ * *
+ * 0x300000 0x301FFF 8 kB RAM_DL Display List RAM *
+ * *
+ * 0x302000 0x302FFF 4 kB * Registers *
+ * *
+ * 0x308000 0x308FFF 4 kB RAM_CMD Command Buffer *
+ * *
+ *******************************************************************************/
+
+#pragma once
+
+namespace FTDI {
+ struct ft810_memory_map {
+ // MEMORY LOCATIONS FT810
+ static constexpr uint32_t RAM_G = 0x000000; // Main Graphics RAM
+ static constexpr uint32_t ROM_CHIPID = 0x0C0000; // Chip ID/Version ID
+ static constexpr uint32_t ROM_FONT = 0x1E0000; // Font ROM
+ static constexpr uint32_t ROM_FONT_ADDR = 0x2FFFFC; // Font Table Pointer
+ static constexpr uint32_t RAM_DL = 0x300000; // Display List RAM
+ static constexpr uint32_t RAM_REG = 0x302000; // Registers
+ static constexpr uint32_t RAM_CMD = 0x308000; // Command Buffer
+
+ static constexpr uint32_t RAM_G_SIZE = 1024*1024L; // 1024k
+ };
+
+ struct ft810_registers {
+ // REGISTERS AND ADDRESSES FT810
+
+ // REGISTER ADDRESS SIZE RESET VALUE TYPE DESCRIPTION
+
+ static constexpr uint32_t ID = 0x302000; // 8 0x7C r Identification Register, Always 0x7C
+ static constexpr uint32_t FRAMES = 0x302004; // 32 0x00000000 r Frame Counter, Since Reset
+ static constexpr uint32_t CLOCK = 0x302008; // 32 0x00000000 r Clock cycles, Since Reset
+ static constexpr uint32_t FREQUENCY = 0x30200C; // 28 0x03938700 r/w Main Clock Frequency
+ static constexpr uint32_t RENDERMODE = 0x302010; // 1 0x00 r/w Rendering Mode: 0 = normal, 1 = single-line
+ static constexpr uint32_t SNAPY = 0x302014; // 11 0x0000 r/w Scan Line Select for RENDERMODE 1
+ static constexpr uint32_t SNAPSHOT = 0x302018; // 1 - r Trigger for RENDERMODE 1
+ static constexpr uint32_t SNAPFORMAT = 0x30201C; // 6 0x20 r/w Pixel Format for Scanline Readout
+ static constexpr uint32_t CPURESET = 0x302020; // 3 0x02 r/w RESET Bit2 Audio - Bit1 Touch - Bit0 Graphics
+ static constexpr uint32_t TAP_CRC = 0x302024; // 32 - r Live Video Tap
+ static constexpr uint32_t TAP_MASK = 0x302028; // 32 0xFFFFFFFF r/w Live Video Tap Mask
+ static constexpr uint32_t HCYCLE = 0x30202C; // 12 0x224 r/w Horizontal Total Cycle Count
+ static constexpr uint32_t HOFFSET = 0x302030; // 12 0x02B r/w Horizontal Display Start Offset
+ static constexpr uint32_t HSIZE = 0x302034; // 12 0x1E0 r/w Horizontal Display Pixel Count
+ static constexpr uint32_t HSYNC0 = 0x302038; // 12 0x000 r/w Horizontal Sync Fall Offset
+ static constexpr uint32_t HSYNC1 = 0x30203C; // 12 0x029 r/w Horizontal Sync Rise Offset
+ static constexpr uint32_t VCYCLE = 0x302040; // 12 0x124 r/w Vertical Total Cycle Count
+ static constexpr uint32_t VOFFSET = 0x302044; // 12 0x00C r/w Vertical Display Start Offset
+ static constexpr uint32_t VSIZE = 0x302048; // 12 0x110 r/w Vertical Display Line Count
+ static constexpr uint32_t VSYNC0 = 0x30204C; // 10 0x000 r/w Vertical Sync Fall Offset
+ static constexpr uint32_t VSYNC1 = 0x302050; // 10 0x00A r/w Vertical Sync Rise Offset
+ static constexpr uint32_t DLSWAP = 0x302054; // 2 0x00 r/w Display List Swap Control
+ static constexpr uint32_t ROTATE = 0x302058; // 3 0x00 r/w Screen 90,180, 270 degree rotate
+ static constexpr uint32_t OUTBITS = 0x30205C; // 9 0x1B6 r/w Output Resolution, 3x3x3 Bits
+ static constexpr uint32_t DITHER = 0x302060; // 1 0x01 r/w Output Dither Enable
+ static constexpr uint32_t SWIZZLE = 0x302064; // 4 0x00 r/w Output RGB Swizzle, Pin Change for PCB Routing
+ static constexpr uint32_t CSPREAD = 0x302068; // 1 0x01 r/w Output Clock Spreading Enable
+ static constexpr uint32_t PCLK_POL = 0x30206C; // 1 0x00 r/w PCLK Polarity: 0 = Rising Edge, 1 = Falling Edge
+ static constexpr uint32_t PCLK = 0x302070; // 8 0x00 r/w PCLK Frequency Divider, 0 = Disable Clock
+ static constexpr uint32_t TAG_X = 0x302074; // 11 0x000 r/w Tag Query X Coordinate
+ static constexpr uint32_t TAG_Y = 0x302078; // 11 0x000 r/w Tag Query Y Coordinate
+ static constexpr uint32_t TAG = 0x30207C; // 8 0x00 r Tag Query Result
+ static constexpr uint32_t VOL_PB = 0x302080; // 8 0xFF r/w Audio Playback Volume
+ static constexpr uint32_t VOL_SOUND = 0x302084; // 8 0xFF r/w Audio Synthesizer Volume
+ static constexpr uint32_t SOUND = 0x302088; // 16 0x0000 r/w Audio Sound Effect Select
+ static constexpr uint32_t PLAY = 0x30208C; // 1 0x00 r/w Audio Start Effect Playback
+ static constexpr uint32_t GPIO_DIR = 0x302090; // 8 0x80 r/w GPIO Pin Direction: 0 = Input , 1 = Output
+ static constexpr uint32_t GPIO = 0x302094; // 8 0x00 r/w GPIO Pin Values for 0, 1, 7 Drive Strength 2, 3, 4, 5, 6
+ static constexpr uint32_t GPIOX_DIR = 0x302098; // 16 0x8000 r/w Extended GPIO Pin Direction
+ static constexpr uint32_t GPIOX = 0x30209C; // 16 0x0080 r/w Extended GPIO Pin Values
+ // Reserved Addr 0x3020A0
+ // Reserved Addr 0x3020A4
+ static constexpr uint32_t INT_FLAGS = 0x3020A8; // 8 0x00 r Interrupt Flags, Clear by Reading
+ static constexpr uint32_t INT_EN = 0x3020AC; // 1 0x00 r/w Global Interrupt Enable
+ static constexpr uint32_t INT_MASK = 0x3020B0; // 8 0xFF r/w Interrupt Enable Mask
+ static constexpr uint32_t PLAYBACK_START = 0x3020B4; // 20 0x00000 r/w Audio Playback RAM Start Address
+ static constexpr uint32_t PLAYBACK_LENGTH = 0x3020B8; // 20 0x00000 r/w Audio Playback Sample Length (Bytes)
+ static constexpr uint32_t PLAYBACK_READPTR = 0x3020BC; // 20 - r Audio Playback Read Pointer
+ static constexpr uint32_t PLAYBACK_FREQ = 0x3020C0; // 16 0x1F40 r/w Audio Playback Frequency (Hz)
+ static constexpr uint32_t PLAYBACK_FORMAT = 0x3020C4; // 2 0x00 r/w Audio Playback Format
+ static constexpr uint32_t PLAYBACK_LOOP = 0x3020C8; // 1 0x00 r/w Audio Playback Loop Enable
+ static constexpr uint32_t PLAYBACK_PLAY = 0x3020CC; // 1 0x00 r Audio Start Playback
+ static constexpr uint32_t PWM_HZ = 0x3020D0; // 14 0x00FA r/w Backlight PWM Frequency (Hz)
+ static constexpr uint32_t PWM_DUTY = 0x3020D4; // 8 0x80 r/w Backlight PWM Duty Cycle: 0 = 0%, 128 = 100%
+ static constexpr uint32_t MACRO_0 = 0x3020D8; // 32 0x00000000 r/w Display List Macro Command 0
+ static constexpr uint32_t MACRO_1 = 0x3020DC; // 32 0x00000000 r/w Display List Macro Command 1
+ // Reserved Addr 0x3020E0
+ // Reserved Addr 0x3020E4
+ // Reserved Addr 0x3020E8
+ // Reserved Addr 0x3020EC
+ // Reserved Addr 0x3020F0
+ // Reserved Addr 0x3020F4
+ static constexpr uint32_t CMD_READ = 0x3020F8; // 12 0x000 r/w Command Buffer Read Pointer
+ static constexpr uint32_t CMD_WRITE = 0x3020FC; // 12 0x000 r/w Command Buffer Write Pointer
+ static constexpr uint32_t CMD_DL = 0x302100; // 13 0x0000 r/w Command Display List Offset
+ static constexpr uint32_t TOUCH_MODE = 0x302104; // 2 0x03 r/w Touch-Screen Sampling Mode
+ static constexpr uint32_t TOUCH_ADC_MODE = 0x302108; // 1 0x01 r/w Select Single Ended or Differential Sampling
+ static constexpr uint32_t TOUCH_CHARGE = 0x30210C; // 16 0x1770 r/w Touch Screen Charge Time, n x 6 Clocks
+ static constexpr uint32_t TOUCH_SETTLE = 0x302110; // 4 0x03 r/w Touch-Screen Settle Time, n x 6 Clocks
+ static constexpr uint32_t TOUCH_OVERSAMPLE = 0x302114; // 4 0x07 r/w Touch-Screen Oversample Factor
+ static constexpr uint32_t TOUCH_RZTHRESH = 0x302118; // 16 0xFFFF r/w Touch-Screen Resistance Threshold
+ static constexpr uint32_t TOUCH_RAW_XY = 0x30211C; // 32 - r Touch-Screen Raw (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_RZ = 0x302120; // 16 - r Touch-Screen Resistance
+ static constexpr uint32_t TOUCH_SCREEN_XY = 0x302124; // 32 - r Touch-Screen Screen (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_TAG_XY = 0x302128; // 32 - r Touch-Screen Tag 0 Lookup (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_TAG = 0x30212C; // 8 - r Touch-Screen Tag 0 Result
+ static constexpr uint32_t TOUCH_TAG1_XY = 0x302130; // 32 - r Touch-Screen Tag 1 Lookup
+ static constexpr uint32_t TOUCH_TAG1 = 0x302134; // 8 - r Touch-Screen Tag 1 Result
+ static constexpr uint32_t TOUCH_TAG2_XY = 0x302138; // 32 - r Touch-Screen Tag 2 Lookup
+ static constexpr uint32_t TOUCH_TAG2 = 0x30213C; // 8 - r Touch-Screen Tag 2 Result
+ static constexpr uint32_t TOUCH_TAG3_XY = 0x302140; // 32 - r Touch-Screen Tag 3 Lookup
+ static constexpr uint32_t TOUCH_TAG3 = 0x302144; // 8 - r Touch-Screen Tag 3 Result
+ static constexpr uint32_t TOUCH_TAG4_XY = 0x302148; // 32 - r Touch-Screen Tag 4 Lookup
+ static constexpr uint32_t TOUCH_TAG4 = 0x30214C; // 8 - r Touch-Screen Tag 4 Result
+ static constexpr uint32_t TOUCH_TRANSFORM_A = 0x302150; // 32 0x00010000 r/w Touch-Screen Transform Coefficient A (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_B = 0x302154; // 32 0x00000000 r/w Touch-Screen Transform Coefficient B (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_C = 0x302158; // 32 0x00000000 r/w Touch-Screen Transform Coefficient C (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_D = 0x30215C; // 32 0x00000000 r/w Touch-Screen Transform Coefficient D (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_E = 0x302160; // 32 0x00010000 r/w Touch-Screen Transform Coefficient E (s15.16)
+ static constexpr uint32_t TOUCH_TRANSFORM_F = 0x302164; // 32 0x00000000 r/w Touch-Screen Transform Coefficient F (s15.16)
+ static constexpr uint32_t TOUCH_CONFIG = 0x302168; // 16 0x8381 r/w Touch Configuration
+ static constexpr uint32_t CTOUCH_TOUCH4_X = 0x30216C; // 16 - r Extended Mode Touch Screen
+ // Reserved Addresses 0x302170
+ static constexpr uint32_t BIST_EN = 0x302174; // 1 0 r/w BIST Memory Mapping Enable
+ // Reserved Addr 0x302178
+ // Reserved Addr 0x30217C
+ static constexpr uint32_t TRIM = 0x302180; // 8 0 r/w Internal Clock Trimming
+ static constexpr uint32_t ANA_COMP = 0x302184; // 8 0 r/w Analog Control Register
+ static constexpr uint32_t SPI_WIDTH = 0x302188; // 3 0 r/w QSPI Bus Width Setting
+ static constexpr uint32_t TOUCH_DIRECT_XY = 0x30218C; // 32 - r Touch-Screen Direct Conversions XY (x-MSB16; y-LSB16)
+ static constexpr uint32_t TOUCH_DIRECT_Z1Z2 = 0x302190; // 32 - r Touch-Screen Direct Conversions Z (z1-MSB16; z2-LSB16)
+ // Reserved Addresses 0x302194 - 0x302560
+ static constexpr uint32_t DATESTAMP = 0x320564; // 128 - r Stamp Date Code
+ static constexpr uint32_t CMDB_SPACE = 0x302574; // 12 0xFFC r/w Command DL Space Available
+ static constexpr uint32_t CMDB_WRITE = 0x302578; // 32 0 w Command DL Write
+
+ static constexpr uint32_t TRACKER = 0x309000; // 32 0x00000000 r/w Track Register (Track Value MSB16; Tag Value - LSB8)
+ static constexpr uint32_t TRACKER_1 = 0x309004; // 32 0x00000000 r/w Track Register (Track Value MSB16; Tag Value - LSB8)
+ static constexpr uint32_t TRACKER_2 = 0x309008; // 32 0x00000000 r/w Track Register (Track Value MSB16; Tag Value - LSB8)
+ static constexpr uint32_t TRACKER_3 = 0x30900C; // 32 0x00000000 r/w Track Register (Track Value MSB16; Tag Value - LSB8)
+ static constexpr uint32_t TRACKER_4 = 0x309010; // 32 0x00000000 r/w Track Register (Track Value MSB16; Tag Value - LSB8)
+
+ static constexpr uint32_t MEDIAFIFO_READ = 0x309014; // 32 0x00000000 r/w Media FIFO read pointer
+ static constexpr uint32_t MEDIAFIFO_WRITE = 0x309018; // 32 0x00000000 r/w Media FIFO write pointer
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/resolutions.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/resolutions.h
new file mode 100644
index 0000000..5b29816
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/resolutions.h
@@ -0,0 +1,127 @@
+/*****************
+ * resolutions.h *
+ *****************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2019 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/***
+ * The FT8xx has odd registers that don't correspond to timing values in
+ * display datasheets. This macro computes the register values using the
+ * formulas given in the document:
+ *
+ * Bridgetek Application Note
+ * AN_336 FT8xx
+ * Selecting an LCD Display
+ * Version 2.1
+ * Issue Date: 2017-11-14
+ */
+#define COMPUTE_REGS_FROM_DATASHEET \
+ constexpr uint16_t Hoffset = thfp + thb - 1; \
+ constexpr uint16_t Hcycle = th; \
+ constexpr uint16_t Hsync0 = thfp - 1 ; \
+ constexpr uint16_t Hsync1 = thfp + thpw - 1; \
+ constexpr uint16_t Voffset = tvfp + tvb - 1; \
+ constexpr uint16_t Vcycle = tv; \
+ constexpr uint16_t Vsync0 = tvfp - 1; \
+ constexpr uint16_t Vsync1 = tvfp + tvpw - 1; \
+ static_assert(thfp + thb + Hsize == th, "Mismatch in display th"); \
+ static_assert(tvfp + tvb + Vsize == tv, "Mismatch in display tv");
+
+#if ENABLED(TOUCH_UI_320x240)
+ namespace FTDI {
+ constexpr uint8_t Pclk = 8;
+ constexpr uint8_t Pclkpol = 0;
+ constexpr uint16_t Hsize = 320;
+ constexpr uint16_t Vsize = 240;
+ constexpr uint16_t Vsync0 = 0;
+ constexpr uint16_t Vsync1 = 2;
+ constexpr uint16_t Voffset = 13;
+ constexpr uint16_t Vcycle = 263;
+ constexpr uint16_t Hsync0 = 0;
+ constexpr uint16_t Hsync1 = 10;
+ constexpr uint16_t Hoffset = 70;
+ constexpr uint16_t Hcycle = 408;
+
+ constexpr uint32_t default_transform_a = 0x000054AD;
+ constexpr uint32_t default_transform_b = 0xFFFFFF52;
+ constexpr uint32_t default_transform_c = 0xFFF7F6E4;
+ constexpr uint32_t default_transform_d = 0x00000065;
+ constexpr uint32_t default_transform_e = 0xFFFFBE3B;
+ constexpr uint32_t default_transform_f = 0x00F68E75;
+ }
+
+#elif defined(TOUCH_UI_480x272)
+ namespace FTDI {
+ constexpr uint8_t Pclk = 7;
+ constexpr uint8_t Pclkpol = 1;
+ constexpr uint16_t Hsize = 480;
+ constexpr uint16_t Vsize = 272;
+
+ constexpr uint16_t th = 525; // One horizontal line
+ constexpr uint16_t thfp = 43; // HS Front porch
+ constexpr uint16_t thb = 2; // HS Back porch (blanking)
+ constexpr uint16_t thpw = 41; // HS pulse width
+
+ constexpr uint16_t tv = 286; // Vertical period time
+ constexpr uint16_t tvfp = 12; // VS Front porch
+ constexpr uint16_t tvb = 2; // VS Back porch (blanking)
+ constexpr uint16_t tvpw = 10; // VS pulse width
+
+ COMPUTE_REGS_FROM_DATASHEET
+
+ constexpr uint32_t default_transform_a = 0x00008100;
+ constexpr uint32_t default_transform_b = 0x00000000;
+ constexpr uint32_t default_transform_c = 0xFFF18000;
+ constexpr uint32_t default_transform_d = 0x00000000;
+ constexpr uint32_t default_transform_e = 0xFFFFB100;
+ constexpr uint32_t default_transform_f = 0x0120D000;
+ }
+
+#elif defined(TOUCH_UI_800x480)
+ namespace FTDI {
+ constexpr uint8_t Pclk = 3;
+ constexpr uint8_t Pclkpol = 1;
+ constexpr uint16_t Hsize = 800;
+ constexpr uint16_t Vsize = 480;
+
+ constexpr uint16_t th = 1056; // One horizontal line
+ constexpr uint16_t thfp = 210; // HS Front porch
+ constexpr uint16_t thb = 46; // HS Back porch (blanking)
+ constexpr uint16_t thpw = 23; // HS pulse width
+
+ constexpr uint16_t tv = 525; // Vertical period time
+ constexpr uint16_t tvfp = 22; // VS Front porch
+ constexpr uint16_t tvb = 23; // VS Back porch (blanking)
+ constexpr uint16_t tvpw = 10; // VS pulse width
+
+ COMPUTE_REGS_FROM_DATASHEET
+
+ constexpr uint32_t default_transform_a = 0x0000D8B9;
+ constexpr uint32_t default_transform_b = 0x00000124;
+ constexpr uint32_t default_transform_c = 0xFFE23926;
+ constexpr uint32_t default_transform_d = 0xFFFFFF51;
+ constexpr uint32_t default_transform_e = 0xFFFF7E4F;
+ constexpr uint32_t default_transform_f = 0x01F0AF70;
+ }
+
+#else
+ #error "Unknown or no TOUCH_UI_FTDI_EVE display resolution specified. To add a display resolution, modify 'ftdi_eve_resolutions.h'."
+#endif
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.cpp
new file mode 100644
index 0000000..006cbe8
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.cpp
@@ -0,0 +1,175 @@
+/***********
+ * spi.cpp *
+ ***********/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_basic.h"
+
+#ifdef FTDI_BASIC
+
+/********************************* SPI Functions *********************************/
+
+namespace FTDI {
+
+ #ifndef CLCD_USE_SOFT_SPI
+ #ifdef CLCD_SPI_BUS
+ SPIClass EVE_SPI(CLCD_SPI_BUS);
+ #endif
+ #ifndef CLCD_HW_SPI_SPEED
+ #define CLCD_HW_SPI_SPEED 8000000 >> SD_SPI_SPEED
+ #endif
+ SPISettings SPI::spi_settings(CLCD_HW_SPI_SPEED, MSBFIRST, SPI_MODE0);
+ #endif
+
+ void SPI::spi_init() {
+ SET_OUTPUT(CLCD_MOD_RESET); // Module Reset (a.k.a. PD, not SPI)
+ WRITE(CLCD_MOD_RESET, 0); // start with module in power-down
+
+ SET_OUTPUT(CLCD_SPI_CS);
+ WRITE(CLCD_SPI_CS, 1);
+
+ #ifdef CLCD_SPI_EXTRA_CS
+ SET_OUTPUT(CLCD_SPI_EXTRA_CS);
+ WRITE(CLCD_SPI_EXTRA_CS, 1);
+ #endif
+
+ #ifdef SPI_FLASH_SS
+ SET_OUTPUT(SPI_FLASH_SS);
+ WRITE(SPI_FLASH_SS, 1);
+ #endif
+
+ #ifdef CLCD_USE_SOFT_SPI
+ SET_OUTPUT(CLCD_SOFT_SPI_MOSI);
+ WRITE(CLCD_SOFT_SPI_MOSI, 1);
+
+ SET_OUTPUT(CLCD_SOFT_SPI_SCLK);
+ WRITE(CLCD_SOFT_SPI_SCLK, 0);
+
+ SET_INPUT_PULLUP(CLCD_SOFT_SPI_MISO);
+ #else
+ SPI_OBJ.begin();
+ #endif
+ }
+
+ #ifdef CLCD_USE_SOFT_SPI
+ uint8_t SPI::_soft_spi_xfer(uint8_t spiOutByte) {
+ uint8_t spiIndex = 0x80;
+ uint8_t spiInByte = 0;
+ uint8_t k;
+
+ noInterrupts();
+ for (k = 0; k < 8; k++) { // Output and Read each bit of spiOutByte and spiInByte
+ WRITE(CLCD_SOFT_SPI_MOSI, (spiOutByte & spiIndex) ? 1 : 0); // Output MOSI Bit
+ WRITE(CLCD_SOFT_SPI_SCLK, 1); // Pulse Clock
+ if (READ(CLCD_SOFT_SPI_MISO)) spiInByte |= spiIndex; // MISO changes on the falling edge of clock, so sample it before
+ WRITE(CLCD_SOFT_SPI_SCLK, 0);
+ spiIndex >>= 1;
+ }
+ interrupts();
+ return spiInByte;
+ }
+ #endif
+
+ #ifdef CLCD_USE_SOFT_SPI
+ void SPI::_soft_spi_send(uint8_t spiOutByte) {
+ uint8_t k, spiIndex = 0x80;
+
+ noInterrupts();
+ for (k = 0; k < 8; k++) { // Output each bit of spiOutByte
+ WRITE(CLCD_SOFT_SPI_MOSI, (spiOutByte & spiIndex) ? 1 : 0); // Output MOSI Bit
+ WRITE(CLCD_SOFT_SPI_SCLK, 1); // Pulse Clock
+ WRITE(CLCD_SOFT_SPI_SCLK, 0);
+ spiIndex >>= 1;
+ }
+ interrupts();
+ }
+ #endif
+
+ void SPI::spi_read_bulk(void *data, uint16_t len) {
+ uint8_t* p = (uint8_t *)data;
+ while (len--) *p++ = spi_recv();
+ }
+
+ bool SPI::spi_verify_bulk(const void *data, uint16_t len) {
+ const uint8_t* p = (const uint8_t *)data;
+ while (len--) if (*p++ != spi_recv()) return false;
+ return true;
+ }
+
+ // CLCD SPI - Chip Select
+ void SPI::spi_ftdi_select() {
+ #ifndef CLCD_USE_SOFT_SPI
+ SPI_OBJ.beginTransaction(spi_settings);
+ #endif
+ WRITE(CLCD_SPI_CS, 0);
+ #ifdef CLCD_SPI_EXTRA_CS
+ WRITE(CLCD_SPI_EXTRA_CS, 0);
+ #endif
+ delayMicroseconds(1);
+ }
+
+ // CLCD SPI - Chip Deselect
+ void SPI::spi_ftdi_deselect() {
+ WRITE(CLCD_SPI_CS, 1);
+ #ifdef CLCD_SPI_EXTRA_CS
+ WRITE(CLCD_SPI_EXTRA_CS, 1);
+ #endif
+ #ifndef CLCD_USE_SOFT_SPI
+ SPI_OBJ.endTransaction();
+ #endif
+ }
+
+ #ifdef SPI_FLASH_SS
+ // Serial SPI Flash SPI - Chip Select
+ void SPI::spi_flash_select() {
+ #ifndef CLCD_USE_SOFT_SPI
+ SPI_OBJ.beginTransaction(spi_settings);
+ #endif
+ WRITE(SPI_FLASH_SS, 0);
+ delayMicroseconds(1);
+ }
+
+ // Serial SPI Flash SPI - Chip Deselect
+ void SPI::spi_flash_deselect() {
+ WRITE(SPI_FLASH_SS, 1);
+ #ifndef CLCD_USE_SOFT_SPI
+ SPI_OBJ.endTransaction();
+ #endif
+ }
+ #endif
+
+ // Not really a SPI signal...
+ void SPI::ftdi_reset() {
+ WRITE(CLCD_MOD_RESET, 0);
+ delay(6); /* minimum time for power-down is 5ms */
+ WRITE(CLCD_MOD_RESET, 1);
+ delay(21); /* minimum time to allow from rising PD_N to first access is 20ms */
+ }
+
+ // Not really a SPI signal...
+ void SPI::test_pulse() {
+ #ifdef CLCD_AUX_0
+ WRITE(CLCD_AUX_0, 1);
+ delayMicroseconds(10);
+ WRITE(CLCD_AUX_0, 0);
+ #endif
+ }
+}
+#endif // FTDI_BASIC
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.h
new file mode 100644
index 0000000..e3a23d7
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/spi.h
@@ -0,0 +1,136 @@
+/*********
+ * spi.h *
+ *********/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#ifndef CLCD_USE_SOFT_SPI
+ #include
+#endif
+
+namespace FTDI {
+
+ #if !defined(CLCD_SPI_BUS) || defined(CLCD_USE_SOFT_SPI)
+ #define SPI_OBJ ::SPI
+ #else
+ extern SPIClass EVE_SPI;
+ #define SPI_OBJ EVE_SPI
+ #endif
+
+ namespace SPI {
+ #ifndef CLCD_USE_SOFT_SPI
+ extern SPISettings spi_settings;
+ #endif
+
+ uint8_t _soft_spi_xfer (uint8_t val);
+ void _soft_spi_send (uint8_t val);
+
+ void spi_init ();
+
+ void spi_ftdi_select ();
+ void spi_ftdi_deselect ();
+
+ void spi_flash_select ();
+ void spi_flash_deselect ();
+
+ inline uint8_t spi_recv() {
+ #ifdef CLCD_USE_SOFT_SPI
+ return _soft_spi_xfer(0x00);
+ #else
+ return SPI_OBJ.transfer(0x00);
+ #endif
+ };
+
+ inline void spi_send (uint8_t val) {
+ #ifdef CLCD_USE_SOFT_SPI
+ _soft_spi_send(val);
+ #else
+ SPI_OBJ.transfer(val);
+ #endif
+ };
+
+ inline void spi_write_8 (uint8_t val) {spi_send(val);};
+ inline uint8_t spi_read_8 () {return spi_recv();};
+
+ namespace least_significant_byte_first {
+ inline void spi_write_16 (uint16_t val) {spi_send(val >> 0);
+ spi_send(val >> 8);};
+ inline void spi_write_32 (uint32_t val) {spi_send(val >> 0);
+ spi_send(val >> 8);
+ spi_send(val >> 16);
+ spi_send(val >> 24);};
+
+ inline uint8_t spi_read_8 () {return spi_recv();};
+ inline uint16_t spi_read_16 () {return (((uint16_t) spi_recv()) << 0) |
+ (((uint16_t) spi_recv()) << 8);};
+ inline uint32_t spi_read_32 () {return (((uint32_t) spi_recv()) << 0) |
+ (((uint32_t) spi_recv()) << 8) |
+ (((uint32_t) spi_recv()) << 16) |
+ (((uint32_t) spi_recv()) << 24);};
+ }
+
+ namespace most_significant_byte_first {
+ inline void spi_write_16 (uint16_t val) {spi_send(val >> 8);
+ spi_send(val >> 0);};
+ inline void spi_write_24 (uint32_t val) {spi_send(val >> 16);
+ spi_send(val >> 8);
+ spi_send(val >> 0);};
+ inline void spi_write_32 (uint32_t val) {spi_send(val >> 24);
+ spi_send(val >> 16);
+ spi_send(val >> 8);
+ spi_send(val >> 0);};
+
+ inline uint16_t spi_read_16 () {return (((uint16_t) spi_recv()) << 8) |
+ (((uint16_t) spi_recv()) << 0);};
+ inline uint32_t spi_read_32 () {return (((uint32_t) spi_recv()) << 24) |
+ (((uint32_t) spi_recv()) << 16) |
+ (((uint32_t) spi_recv()) << 8) |
+ (((uint32_t) spi_recv()) << 0);};
+ }
+
+ inline uint8_t ram_write(const uint8_t *p) {return *p;}
+ inline uint8_t pgm_write(const uint8_t *p) {return pgm_read_byte(p);}
+
+ typedef uint8_t (*bulk_write_op)(const uint8_t*);
+
+ // Generic template for function for writing multiple bytes, plus padding bytes.
+ // The template parameter op is an inlineable function which is applied to each byte.
+
+ template
+ void spi_write_bulk(const void *data, uint16_t len, uint8_t padding) {
+ const uint8_t* p = (const uint8_t *)data;
+ while (len--) spi_send(byte_op(p++));
+ while (padding--) spi_send(0);
+ }
+
+ template
+ void spi_write_bulk(const void *data, uint16_t len) {
+ const uint8_t* p = (const uint8_t *)data;
+ while (len--) spi_send(byte_op(p++));
+ }
+
+ void spi_read_bulk( void *data, uint16_t len);
+ bool spi_verify_bulk(const void *data, uint16_t len);
+
+ void ftdi_reset();
+ void test_pulse();
+ }
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/compat.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/compat.h
new file mode 100644
index 0000000..9be7882
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/compat.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#include "../config.h"
+
+#ifdef __MARLIN_FIRMWARE__
+
+ // Marlin will define the I/O functions for us
+ #if ENABLED(TOUCH_UI_FTDI_EVE)
+ #define FTDI_BASIC
+ #define FTDI_EXTENDED
+ #endif
+
+#else // !__MARLIN_FIRMWARE__
+
+ #include
+
+ #ifndef CLCD_USE_SOFT_SPI
+ #include
+ #endif
+
+ namespace fast_io {
+
+ template
+ struct port_pin {
+ typedef port_t port;
+ static inline void set_high() {port::port() = (port::port() | bits);}
+ static inline void set_low() {port::port() = (port::port() & (~bits));}
+ static inline void set_input() {port::ddr() = (port::ddr() & (~bits));}
+ static inline void set_input_pullup() {set_input(); set_high();}
+ static inline void set_output() {port::ddr() = (port::ddr() | bits);}
+ static inline uint8_t read() {return port::pin() & bits;}
+ static inline void write(bool v) {if (v) set_high(); else set_low();}
+ };
+
+ #define MAKE_AVR_PORT_PINS(ID) \
+ struct port_##ID { \
+ static volatile uint8_t &pin() {return PIN##ID;}; \
+ static volatile uint8_t &port() {return PORT##ID;}; \
+ static volatile uint8_t &ddr() {return DDR##ID;}; \
+ }; \
+ typedef port_pin AVR_##ID##0; \
+ typedef port_pin AVR_##ID##1; \
+ typedef port_pin AVR_##ID##2; \
+ typedef port_pin AVR_##ID##3; \
+ typedef port_pin AVR_##ID##4; \
+ typedef port_pin AVR_##ID##5; \
+ typedef port_pin AVR_##ID##6; \
+ typedef port_pin AVR_##ID##7;
+
+ #ifdef PORTA
+ MAKE_AVR_PORT_PINS(A);
+ #endif
+ #ifdef PORTB
+ MAKE_AVR_PORT_PINS(B);
+ #endif
+ #ifdef PORTC
+ MAKE_AVR_PORT_PINS(C);
+ #endif
+ #ifdef PORTD
+ MAKE_AVR_PORT_PINS(D);
+ #endif
+ #ifdef PORTE
+ MAKE_AVR_PORT_PINS(E);
+ #endif
+ #ifdef PORTF
+ MAKE_AVR_PORT_PINS(F);
+ #endif
+ #ifdef PORTG
+ MAKE_AVR_PORT_PINS(G);
+ #endif
+ #ifdef PORTH
+ MAKE_AVR_PORT_PINS(H);
+ #endif
+ #ifdef PORTJ
+ MAKE_AVR_PORT_PINS(J);
+ #endif
+ #ifdef PORTK
+ MAKE_AVR_PORT_PINS(K);
+ #endif
+ #ifdef PORTL
+ MAKE_AVR_PORT_PINS(L);
+ #endif
+ #ifdef PORTQ
+ MAKE_AVR_PORT_PINS(Q);
+ #endif
+ #ifdef PORTR
+ MAKE_AVR_PORT_PINS(R);
+ #endif
+
+ #undef MAKE_AVR_PORT_PINS
+
+ template
+ struct arduino_digital_pin {
+ static constexpr uint8_t pin = p;
+ static inline void set_high() {digitalWrite(p, HIGH);}
+ static inline void set_low() {digitalWrite(p, LOW);}
+ static inline void set_input() {pinMode(p, INPUT);}
+ static inline void set_input_pullup() {pinMode(p, INPUT_PULLUP);}
+ static inline void set_output() {pinMode(p, OUTPUT);}
+ static inline uint8_t read() {return digitalRead(p);}
+ static inline void write(bool v) {digitalWrite(p, v ? HIGH : LOW);}
+ };
+
+ #define MAKE_ARDUINO_PINS(ID) typedef arduino_digital_pin ARDUINO_DIGITAL_##ID;
+ MAKE_ARDUINO_PINS( 0);
+ MAKE_ARDUINO_PINS( 1);
+ MAKE_ARDUINO_PINS( 2);
+ MAKE_ARDUINO_PINS( 3);
+ MAKE_ARDUINO_PINS( 4);
+ MAKE_ARDUINO_PINS( 5);
+ MAKE_ARDUINO_PINS( 6);
+ MAKE_ARDUINO_PINS( 7);
+ MAKE_ARDUINO_PINS( 8);
+ MAKE_ARDUINO_PINS( 9);
+ MAKE_ARDUINO_PINS(10);
+ MAKE_ARDUINO_PINS(11);
+ MAKE_ARDUINO_PINS(12);
+ MAKE_ARDUINO_PINS(13);
+ MAKE_ARDUINO_PINS(14);
+ MAKE_ARDUINO_PINS(15);
+ MAKE_ARDUINO_PINS(16);
+ MAKE_ARDUINO_PINS(17);
+ MAKE_ARDUINO_PINS(18);
+ MAKE_ARDUINO_PINS(19);
+ MAKE_ARDUINO_PINS(10);
+ MAKE_ARDUINO_PINS(21);
+ MAKE_ARDUINO_PINS(22);
+ MAKE_ARDUINO_PINS(23);
+ MAKE_ARDUINO_PINS(24);
+ MAKE_ARDUINO_PINS(25);
+ MAKE_ARDUINO_PINS(26);
+ MAKE_ARDUINO_PINS(27);
+ MAKE_ARDUINO_PINS(28);
+ MAKE_ARDUINO_PINS(29);
+ MAKE_ARDUINO_PINS(30);
+ MAKE_ARDUINO_PINS(31);
+ MAKE_ARDUINO_PINS(32);
+ MAKE_ARDUINO_PINS(33);
+ MAKE_ARDUINO_PINS(34);
+ MAKE_ARDUINO_PINS(35);
+ MAKE_ARDUINO_PINS(36);
+ MAKE_ARDUINO_PINS(37);
+ MAKE_ARDUINO_PINS(38);
+ MAKE_ARDUINO_PINS(39);
+ MAKE_ARDUINO_PINS(40);
+ MAKE_ARDUINO_PINS(41);
+ MAKE_ARDUINO_PINS(42);
+ MAKE_ARDUINO_PINS(43);
+ MAKE_ARDUINO_PINS(44);
+ MAKE_ARDUINO_PINS(45);
+ MAKE_ARDUINO_PINS(46);
+ MAKE_ARDUINO_PINS(47);
+ MAKE_ARDUINO_PINS(48);
+ MAKE_ARDUINO_PINS(49);
+ MAKE_ARDUINO_PINS(50);
+ MAKE_ARDUINO_PINS(51);
+ MAKE_ARDUINO_PINS(52);
+ MAKE_ARDUINO_PINS(53);
+ #undef MAKE_ARDUINO_PINS
+ } // namespace fast_io
+
+ #define SET_INPUT(pin) fast_io::pin::set_input()
+ #define SET_INPUT_PULLUP(pin) do{ fast_io::pin::set_input(); fast_io::pin::set_high(); }while(0)
+ #define SET_INPUT_PULLDOWN SET_INPUT
+ #define SET_OUTPUT(pin) fast_io::pin::set_output()
+ #define READ(pin) fast_io::pin::read()
+ #define WRITE(pin, value) fast_io::pin::write(value)
+
+ #ifndef pgm_read_word_far
+ #define pgm_read_word_far pgm_read_word
+ #endif
+
+ #ifndef pgm_read_dword_far
+ #define pgm_read_dword_far pgm_read_dword
+ #endif
+
+ #ifndef pgm_read_ptr_far
+ #define pgm_read_ptr_far pgm_read_ptr
+ #endif
+
+ #define SERIAL_ECHO_START()
+ #define SERIAL_ECHOLNPGM(str) Serial.println(F(str))
+ #define SERIAL_ECHOPGM(str) Serial.print(F(str))
+ #define SERIAL_ECHO_MSG(str) Serial.println(str)
+ #define SERIAL_ECHOLNPAIR(str, val) do{ Serial.print(F(str)); Serial.println(val); }while(0)
+ #define SERIAL_ECHOPAIR(str, val) do{ Serial.print(F(str)); Serial.print(val); }while(0)
+
+ #define safe_delay delay
+
+ // Define macros for compatibility
+
+ // Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments
+ #define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
+ #define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+
+ #define _CAT(a,V...) a##V
+ #define CAT(a,V...) _CAT(a,V)
+
+ #define FIRST(a,...) a
+ #define SECOND(a,b,...) b
+ #define THIRD(a,b,c,...) c
+
+ #define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0
+ #define PROBE() ~, 1 // Second item will be 1 if this is passed
+ #define _NOT_0 PROBE()
+ #define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
+ #define _BOOL(x) NOT(NOT(x)) // NOT('0') gets '0'. Anything else gets '1'.
+
+ #define _DO_1(W,C,A) (_##W##_1(A))
+ #define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B))
+ #define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V))
+ #define _DO_4(W,C,A,V...) (_##W##_1(A) C _DO_3(W,C,V))
+ #define _DO_5(W,C,A,V...) (_##W##_1(A) C _DO_4(W,C,V))
+ #define _DO_6(W,C,A,V...) (_##W##_1(A) C _DO_5(W,C,V))
+ #define _DO_7(W,C,A,V...) (_##W##_1(A) C _DO_6(W,C,V))
+ #define _DO_8(W,C,A,V...) (_##W##_1(A) C _DO_7(W,C,V))
+ #define _DO_9(W,C,A,V...) (_##W##_1(A) C _DO_8(W,C,V))
+ #define _DO_10(W,C,A,V...) (_##W##_1(A) C _DO_9(W,C,V))
+ #define _DO_11(W,C,A,V...) (_##W##_1(A) C _DO_10(W,C,V))
+ #define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V))
+ #define __DO_N(W,C,N,V...) _DO_##N(W,C,V)
+ #define _DO_N(W,C,N,V...) __DO_N(W,C,N,V)
+ #define DO(W,C,V...) _DO_N(W,C,NUM_ARGS(V),V)
+
+ #define _ISENA_ ~,1
+ #define _ISENA_1 ~,1
+ #define _ISENA_0x1 ~,1
+ #define _ISENA_true ~,1
+ #define _ISENA(V...) IS_PROBE(V)
+ #define _ENA_1(O) _ISENA(CAT(_IS,CAT(ENA_, O)))
+ #define _DIS_1(O) NOT(_ENA_1(O))
+ #define ENABLED(V...) DO(ENA,&&,V)
+ #define DISABLED(V...) DO(DIS,&&,V)
+
+ #define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION converted to '0' or '1'
+ #define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION converted to A or '0'
+ #define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION converted to A or '1'
+ #define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION converted to A or ''
+ #define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1'
+ #define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
+ #define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
+
+ #define IF_ENABLED TERN_
+ #define IF_DISABLED(O,A) _TERN(_ENA_1(O),,A)
+
+ #define ANY(V...) !DISABLED(V)
+ #define NONE(V...) DISABLED(V)
+ #define ALL(V...) ENABLED(V)
+ #define BOTH(V1,V2) ALL(V1,V2)
+ #define EITHER(V1,V2) ANY(V1,V2)
+
+ // Remove compiler warning on an unused variable
+ #ifndef UNUSED
+ #if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
+ #define UNUSED(X) (void)X
+ #else
+ #define UNUSED(x) ((void)(x))
+ #endif
+ #endif
+
+#endif // !__MARLIN_FIRMWARE__
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/bitmap_info.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/bitmap_info.h
new file mode 100644
index 0000000..7326070
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/bitmap_info.h
@@ -0,0 +1,49 @@
+/*****************
+ * bitmap_info.h *
+ *****************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#ifndef FORCEDINLINE
+ #define FORCEDINLINE __attribute__((always_inline)) inline
+#endif
+
+namespace FTDI {
+ // The following functions *must* be inlined since we are relying on the compiler to do
+ // substitution of the constants from the data structure rather than actually storing
+ // it in PROGMEM (which would fail, since we are not using pgm_read to read them).
+ // Plus, by inlining, all the equations are evaluated at compile-time as everything
+ // should be a constant.
+
+ typedef struct {
+ const uint8_t format;
+ const uint16_t linestride;
+ const uint8_t filter;
+ const uint8_t wrapx;
+ const uint8_t wrapy;
+ const uint32_t RAMG_offset;
+ const uint16_t width;
+ const uint16_t height;
+ } bitmap_info_t;
+
+ FORCEDINLINE uint32_t BITMAP_SOURCE (const bitmap_info_t& info) {return BITMAP_SOURCE (ftdi_memory_map::RAM_G + info.RAMG_offset);};
+ FORCEDINLINE uint32_t BITMAP_LAYOUT (const bitmap_info_t& info) {return BITMAP_LAYOUT (info.format, info.linestride, info.height);};
+ FORCEDINLINE uint32_t BITMAP_SIZE (const bitmap_info_t& info) {return BITMAP_SIZE (info.filter, info.wrapx, info.wrapy, info.width, info.height);}
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.cpp
new file mode 100644
index 0000000..e324cb9
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.cpp
@@ -0,0 +1,29 @@
+/*************************
+ * command_processor.cpp *
+ *************************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+CommandProcessor::btn_style_func_t *CommandProcessor::_btn_style_callback = CommandProcessor::default_button_style_func;
+bool CommandProcessor::is_tracking = false;
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h
new file mode 100644
index 0000000..da51ee6
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h
@@ -0,0 +1,437 @@
+/***********************
+ * command_processor.h *
+ ***********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+typedef struct {
+ uint32_t bg;
+ uint32_t grad;
+ uint32_t fg;
+ uint32_t rgb;
+} btn_colors;
+
+// Disable TOUCH_UI_FIT_TEXT on a case-by-case basis
+namespace FTDI {
+ constexpr uint16_t OPT_NOFIT = OPT_NOTICKS;
+}
+
+/**************************** Enhanced Command Processor **************************/
+
+/* The CommandProcessor class wraps the CommandFifo with several features to make
+ * defining user interfaces much easier.
+ *
+ * - Implements chaining on all methods
+ * - Automatically adds text to button, toggle, text and keys.
+ * - Constrains all widgets to fit inside a box for ease of layout.
+ * - Font size is specified using a chained modifier.
+ * - Option argument is given the default OPT_3D value.
+ */
+
+class CommandProcessor : public CLCD::CommandFifo {
+ public:
+ static constexpr uint8_t STYLE_DISABLED = 0x80;
+
+ private:
+ static bool default_button_style_func(CommandProcessor &, uint8_t tag, uint8_t & /*style*/, uint16_t &options, bool) {
+ if (tag != 0 && FTDI::EventLoop::get_pressed_tag() == tag) {
+ options = FTDI::OPT_FLAT;
+ }
+ return false;
+ }
+
+ typedef bool btn_style_func_t(CommandProcessor &cmd, uint8_t tag, uint8_t &style, uint16_t &options, bool post);
+
+ static btn_style_func_t *_btn_style_callback;
+ static bool is_tracking;
+ int8_t _font = 26, _tag = 0;
+ uint8_t _style = 0;
+
+ protected:
+ // Returns the cannonical thickness of a widget (i.e. the height of a toggle element)
+ uint16_t widget_thickness() {
+ CLCD::FontMetrics fm(_font);
+ return fm.height * 20.0/16;
+ }
+
+ FORCEDINLINE void linear_widget_box(int16_t &x, int16_t &y, int16_t &w, int16_t &h, bool tracker = false) {
+ const uint16_t th = widget_thickness() / 2;
+ if (w > h) {
+ x += tracker ? th * 2.5 : th;
+ y += (h - th) / 2;
+ w -= tracker ? th * 5.0 : th * 2;
+ h = th;
+ }
+ else {
+ x += (w - th) / 2;
+ y += tracker ? th * 2.5 : th;
+ w = th;
+ h -= tracker ? th * 5.0 : th * 2;
+ }
+ }
+
+ FORCEDINLINE uint16_t circular_widget_box(int16_t &x, int16_t &y, int16_t &w, int16_t &h) {
+ const uint16_t r = min(w,h) / 2;
+ x += w / 2;
+ y += h / 2;
+ w = 1;
+ h = 1;
+ return r;
+ }
+
+ public:
+ // Helper method for setting all colors at once
+ inline CommandProcessor& colors(const btn_colors &colors) {
+ cmd(FTDI::COLOR_RGB(colors.rgb))
+ .gradcolor(colors.grad)
+ .fgcolor(colors.fg)
+ .bgcolor(colors.bg);
+ return *this;
+ }
+
+ inline CommandProcessor& bitmap_size(uint8_t filter, uint8_t wrapx, uint8_t wrapy, uint16_t width, uint16_t height) {
+ cmd(FTDI::BITMAP_SIZE(filter, wrapx, wrapy, width, height));
+ #if FTDI_API_LEVEL >= 810
+ if (FTDI::ftdi_chip >= 810)
+ cmd(FTDI::BITMAP_SIZE_H(width >> 9, height >> 9));
+ #endif
+ return *this;
+ }
+
+ inline CommandProcessor& bitmap_layout(uint8_t format, uint16_t linestride, uint16_t height) {
+ cmd(FTDI::BITMAP_LAYOUT(format, linestride, height));
+ #if FTDI_API_LEVEL >= 810
+ if (FTDI::ftdi_chip >= 810)
+ cmd(FTDI::BITMAP_LAYOUT_H(linestride >> 10, height >> 9));
+ #endif
+ return *this;
+ }
+
+ inline CommandProcessor& set_button_style_callback(const btn_style_func_t *func) {
+ _btn_style_callback = func ? func : default_button_style_func;
+ return *this;
+ }
+
+ inline CommandProcessor& tag (uint8_t tag) {_tag = tag; cmd(FTDI::TAG(tag)); return *this;}
+
+ inline CommandProcessor& font (int16_t font) {_font = font; return *this;}
+
+ inline CommandProcessor& enabled (bool enabled=false) {
+ if (enabled)
+ _style &= ~STYLE_DISABLED;
+ else
+ _style |= STYLE_DISABLED;
+ return *this;
+ }
+
+ inline CommandProcessor& style (uint8_t style) {
+ _style = (_style & STYLE_DISABLED) | style;
+ return *this;
+ }
+
+ // Wrap all the CommandFifo routines to allow method chaining
+
+ inline CommandProcessor& cmd (uint32_t cmd32) {CLCD::CommandFifo::cmd(cmd32); return *this;}
+ inline CommandProcessor& cmd (void* data, uint16_t len) {CLCD::CommandFifo::cmd(data, len); return *this;}
+ inline CommandProcessor& execute() {CLCD::CommandFifo::execute(); return *this;}
+
+ inline CommandProcessor& fgcolor (uint32_t rgb) {CLCD::CommandFifo::fgcolor(rgb); return *this;}
+ inline CommandProcessor& bgcolor (uint32_t rgb) {CLCD::CommandFifo::bgcolor(rgb); return *this;}
+ inline CommandProcessor& gradcolor(uint32_t rgb) {CLCD::CommandFifo::gradcolor(rgb); return *this;}
+
+ inline CommandProcessor& snapshot (uint32_t ptr) {CLCD::CommandFifo::snapshot(ptr); return *this;}
+
+ inline CommandProcessor& loadimage(uint32_t ptr, uint32_t options)
+ {CLCD::CommandFifo::loadimage(ptr, options); return *this;}
+ inline CommandProcessor& sketch (int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format)
+ {CLCD::CommandFifo::sketch(x, y, w, h, ptr, format); return *this;}
+ inline CommandProcessor& screensaver () {CLCD::CommandFifo::screensaver(); return *this;}
+ #if FTDI_API_LEVEL >= 810
+ inline CommandProcessor& setbase (uint8_t base) {CLCD::CommandFifo::setbase(base); return *this;}
+ #endif
+ inline CommandProcessor& loadidentity () {CLCD::CommandFifo::loadidentity(); return *this;}
+ inline CommandProcessor& scale (int32_t sx, int32_t sy) {CLCD::CommandFifo::scale(sx,sy); return *this;}
+ inline CommandProcessor& rotate (int32_t a) {CLCD::CommandFifo::rotate(a); return *this;}
+ inline CommandProcessor& translate(int32_t tx, int32_t ty) {CLCD::CommandFifo::translate(tx,ty); return *this;}
+ inline CommandProcessor& setmatrix () {CLCD::CommandFifo::setmatrix(); return *this;}
+ inline CommandProcessor& stop () {CLCD::CommandFifo::stop(); return *this;}
+
+ inline CommandProcessor& memzero (uint32_t ptr, uint32_t size)
+ {CLCD::CommandFifo::memzero(ptr, size); return *this;}
+ inline CommandProcessor& memset (uint32_t ptr, uint32_t val, uint32_t size)
+ {CLCD::CommandFifo::memset(ptr, val, size); return *this;}
+ inline CommandProcessor& memcpy (uint32_t src, uint32_t dst, uint32_t size)
+ {CLCD::CommandFifo::memcpy(src, dst, size); return *this;}
+ inline CommandProcessor& memcrc (uint32_t ptr, uint32_t num, uint32_t result)
+ {CLCD::CommandFifo::memcrc(ptr, num, result); return *this;}
+ inline CommandProcessor& memwrite (uint32_t ptr, uint32_t value)
+ {CLCD::CommandFifo::memwrite(ptr, value); return *this;}
+ inline CommandProcessor& inflate (uint32_t ptr)
+ {CLCD::CommandFifo::inflate(ptr); return *this;}
+ inline CommandProcessor& getptr (uint32_t result)
+ {CLCD::CommandFifo::getptr(result); return *this;}
+ inline CommandProcessor& getprops (uint32_t ptr, uint32_t width, uint32_t height)
+ {CLCD::CommandFifo::getprops(ptr, width, height); return *this;}
+
+ #if FTDI_API_LEVEL >= 810
+ inline CommandProcessor& setbitmap (uint32_t ptr, uint16_t fmt, uint16_t w, uint16_t h)
+ {CLCD::CommandFifo::setbitmap(ptr,fmt,w,h); return *this;}
+ inline CommandProcessor& snapshot2 (uint32_t fmt, uint32_t ptr, int16_t x, int16_t y, uint16_t w, uint16_t h)
+ {CLCD::CommandFifo::snapshot2(fmt,ptr,x,y,w,h); return *this;}
+ inline CommandProcessor& mediafifo (uint32_t p, uint32_t s) {CLCD::CommandFifo::mediafifo(p, s); return *this;}
+ inline CommandProcessor& playvideo(uint32_t options) {CLCD::CommandFifo::playvideo(options); return *this;}
+ inline CommandProcessor& romfont(uint8_t font, uint8_t slot) {CLCD::CommandFifo::romfont(font, slot); return *this;}
+ #endif
+
+ inline CommandProcessor& gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1)
+ {CLCD::CommandFifo::gradient(x0,y0,rgb0,x1,y1,rgb1); return *this;}
+
+ inline CommandProcessor& rectangle(int16_t x, int16_t y, int16_t w, int16_t h) {
+ using namespace FTDI;
+ CLCD::CommandFifo::cmd(BEGIN(RECTS));
+ CLCD::CommandFifo::cmd(VERTEX2F(x * 16, y * 16));
+ CLCD::CommandFifo::cmd(VERTEX2F((x + w) * 16, (y + h) * 16));
+ return *this;
+ }
+
+ template
+ FORCEDINLINE CommandProcessor& toggle(int16_t x, int16_t y, int16_t w, int16_t h, T text, bool state, uint16_t options = FTDI::OPT_3D) {
+ CLCD::FontMetrics fm(_font);
+ const int16_t widget_h = fm.height * 20.0 / 16;
+ //const int16_t outer_bar_r = widget_h / 2;
+ //const int16_t knob_r = outer_bar_r - 1.5;
+ // The y coordinate of the toggle is the baseline of the text,
+ // so we must introduce a fudge factor based on the line height to
+ // actually center the control.
+ const int16_t fudge_y = fm.height * 5 / 16;
+ CLCD::CommandFifo::toggle(x + h / 2, y + (h - widget_h) / 2 + fudge_y, w - h, _font, options, state);
+ CLCD::CommandFifo::str(text);
+ return *this;
+ }
+
+ CommandProcessor& toggle2(int16_t x, int16_t y, int16_t w, int16_t h, progmem_str no, progmem_str yes, bool state, uint16_t options = FTDI::OPT_3D) {
+ char text[strlen_P((const char *)no) + strlen_P((const char *)yes) + 2];
+ strcpy_P(text, (const char *)no);
+ strcat(text, "\xFF");
+ strcat_P(text, (const char *)yes);
+ return toggle(x, y, w, h, text, state, options);
+ }
+
+ // Contrained drawing routines. These constrain the widget inside a box for easier layout.
+ // The FORCEDINLINE ensures that the code is inlined so that all the math is done at compile time.
+
+ FORCEDINLINE CommandProcessor& track_linear(int16_t x, int16_t y, int16_t w, int16_t h, int16_t tag) {
+ linear_widget_box(x, y, w, h, true);
+ CLCD::CommandFifo::track(x, y, w, h, tag);
+ is_tracking = true;
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& track_circular(int16_t x, int16_t y, int16_t w, int16_t h, int16_t tag) {
+ circular_widget_box(x,y, w, h);
+ CLCD::CommandFifo::track(x, y, w, h, tag);
+ is_tracking = true;
+ return *this;
+ }
+
+ uint8_t track_tag (uint16_t &value) {
+ if (is_tracking) {
+ if (FTDI::EventLoop::is_touch_held()) {
+ return CLCD::get_tracker(value);
+ }
+ else {
+ CLCD::CommandFifo::track(0, 0, 0, 0, 0);
+ CLCD::CommandFifo::execute();
+ is_tracking = false;
+ }
+ }
+ return 0;
+ }
+
+ FORCEDINLINE CommandProcessor& clock(int16_t x, int16_t y, int16_t w, int16_t h, int16_t hr, int16_t m, int16_t s, int16_t ms, uint16_t options = FTDI::OPT_3D) {
+ const uint16_t r = circular_widget_box(x, y, w, h);
+ CLCD::CommandFifo::clock(x, y, r, options, hr, m, s, ms);
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& gauge(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t major, uint16_t minor, uint16_t val, uint16_t range, uint16_t options = FTDI::OPT_3D) {
+ const uint16_t r = circular_widget_box(x, y, w, h);
+ CLCD::CommandFifo::gauge(x, y, r, options, major, minor, val, range);
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& dial(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t options = FTDI::OPT_3D) {
+ const uint16_t r = circular_widget_box(x, y, w, h);
+ CLCD::CommandFifo::dial(x, y, r, options, val);
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& slider(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t range, uint16_t options = FTDI::OPT_3D) {
+ linear_widget_box(x, y, w, h);
+ CLCD::CommandFifo::slider(x, y, w, h, options, val, range);
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& progress(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t range, uint16_t options = FTDI::OPT_3D) {
+ linear_widget_box(x, y, w, h);
+ CLCD::CommandFifo::progress(x, y, w, h, options, val, range);
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& scrollbar(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t val, uint16_t size, uint16_t range, uint16_t options = 0) {
+ linear_widget_box(x, y, w, h);
+ CLCD::CommandFifo::scrollbar(x, y, w, h, options, val, size, range);
+ return *this;
+ }
+
+ void apply_text_alignment(int16_t &x, int16_t &y, int16_t w, int16_t h, uint16_t options) {
+ using namespace FTDI;
+ x += ((options & OPT_CENTERX) ? w/2 : ((options & OPT_RIGHTX) ? w : 0));
+ y += ((options & OPT_CENTERY) ? h/2 : h);
+ }
+
+ // Reduce font size until text fits the enclosing box.
+ template
+ int8_t apply_fit_text(int16_t w, int16_t h, T text) {
+ using namespace FTDI;
+ int8_t font = _font;
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ const bool is_utf8 = has_utf8_chars(text);
+ #endif
+ for (;font > 26;) {
+ int16_t width, height;
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ if (is_utf8) {
+ width = get_utf8_text_width(text, font_size_t::from_romfont(font));
+ height = font_size_t::from_romfont(font).get_height();
+ }
+ else
+ #endif
+ {
+ CLCD::FontMetrics fm(font);
+ width = fm.get_text_width(text);
+ height = fm.height;
+ }
+ if (width < w && height < h) break;
+ font--;
+ }
+ return font;
+ }
+
+ CommandProcessor& number(int16_t x, int16_t y, int16_t w, int16_t h, int32_t n, uint16_t options = FTDI::OPT_CENTER) {
+ using namespace FTDI;
+ apply_text_alignment(x, y, w, h, options);
+ CLCD::CommandFifo::number(x, y, _font, options, n);
+ return *this;
+ }
+
+ template
+ uint16_t text_width(T text) {
+ using namespace FTDI;
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ if (has_utf8_chars(text))
+ return get_utf8_text_width(text, font_size_t::from_romfont(_font));
+ #endif
+ CLCD::FontMetrics fm(_font);
+ return fm.get_text_width(text);
+ }
+
+ template
+ CommandProcessor& text(int16_t x, int16_t y, int16_t w, int16_t h, T text, uint16_t options = FTDI::OPT_CENTER) {
+ using namespace FTDI;
+ apply_text_alignment(x, y, w, h, options);
+ #ifdef TOUCH_UI_FIT_TEXT
+ const int8_t font = (options & OPT_NOFIT) ? _font : apply_fit_text(w, h, text);
+ #else
+ const int8_t font = _font;
+ #endif
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ if (has_utf8_chars(text))
+ draw_utf8_text(*this, x, y, text, font_size_t::from_romfont(font), options);
+ else
+ #endif
+ {
+ CLCD::CommandFifo::text(x, y, font, options);
+ CLCD::CommandFifo::str(text);
+ }
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& icon(int16_t x, int16_t y, int16_t w, int16_t h, const FTDI::bitmap_info_t& info, const float scale = 1) {
+ using namespace FTDI;
+ cmd(BEGIN(BITMAPS));
+ if (scale != 1) {
+ cmd(BITMAP_TRANSFORM_A(uint32_t(float(256)/scale)));
+ cmd(BITMAP_TRANSFORM_E(uint32_t(float(256)/scale)));
+ }
+ cmd(BITMAP_SIZE(info.filter, info.wrapx, info.wrapy, info.width*scale, info.height*scale));
+ cmd(VERTEX2F((x + w/2 - info.width*scale/2)*16, (y + h/2 - info.height*scale/2)*16));
+ if (scale != 1) {
+ cmd(BITMAP_TRANSFORM_A(256));
+ cmd(BITMAP_TRANSFORM_E(256));
+ }
+ return *this;
+ }
+
+ template
+ CommandProcessor& button(int16_t x, int16_t y, int16_t w, int16_t h, T text, uint16_t options = FTDI::OPT_3D) {
+ using namespace FTDI;
+ bool styleModified = false;
+ if (_btn_style_callback) styleModified = _btn_style_callback(*this, _tag, _style, options, false);
+ #ifdef TOUCH_UI_FIT_TEXT
+ const int8_t font = (options & OPT_NOFIT) ? _font : apply_fit_text(w, h, text);
+ #else
+ const int8_t font = _font;
+ #endif
+ CLCD::CommandFifo::button(x, y, w, h, font, options);
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ if (has_utf8_chars(text)) {
+ CLCD::CommandFifo::str(F(""));
+ apply_text_alignment(x, y, w, h, OPT_CENTER);
+ if (!(options & FTDI::OPT_FLAT)) {
+ // Reproduce the black "shadow" the FTDI adds to the button label
+ CLCD::CommandFifo::cmd(SAVE_CONTEXT());
+ CLCD::CommandFifo::cmd(COLOR_RGB(0x00000));
+ draw_utf8_text(*this, x-1, y-1, text, font_size_t::from_romfont(font), OPT_CENTER);
+ CLCD::CommandFifo::cmd(RESTORE_CONTEXT());
+ }
+ // Draw the button label
+ draw_utf8_text(*this, x, y, text, font_size_t::from_romfont(font), OPT_CENTER);
+ }
+ else
+ #endif
+ CLCD::CommandFifo::str(text);
+ if (_btn_style_callback && styleModified) _btn_style_callback(*this, _tag, _style, options, true);
+ return *this;
+ }
+
+ template
+ CommandProcessor& keys(int16_t x, int16_t y, int16_t w, int16_t h, T keys, uint16_t options = FTDI::OPT_3D) {
+ CLCD::CommandFifo::keys(x, y, w, h, _font, options);
+ CLCD::CommandFifo::str(keys);
+ return *this;
+ }
+
+ FORCEDINLINE CommandProcessor& spinner(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t style = 0, uint16_t scale = 0) {
+ circular_widget_box(x, y, w, h);
+ CLCD::CommandFifo::spinner(x, y, style, scale);
+ return *this;
+ }
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.cpp
new file mode 100644
index 0000000..a13c362
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.cpp
@@ -0,0 +1,180 @@
+/****************
+ * dl_cache.cpp *
+ ****************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+/* The Display List Cache mechanism stores the display list corresponding
+ * to a menu into RAM_G so that on subsequent calls drawing the menu does
+ * not require as much SPI traffic.
+ *
+ * Layout of Cache memory:
+ *
+ * The cache memory begins with a table at
+ * DL_CACHE_START: each table entry contains
+ * an address, size and used bytes for a cached
+ * DL slot.
+ *
+ * Immediately following the table is the
+ * DL_FREE_ADDR, which points to free cache
+ * space; following this is occupied DL space,
+ * and after that free space that is yet to
+ * be used.
+ *
+ * location data sizeof
+ *
+ * DL_CACHE_START slot0_addr 4
+ * slot0_size 4
+ * slot0_used 4
+ * slot1_addr 4
+ * slot1_size 4
+ * slot1_used 4
+ * ...
+ * slotN_addr 4
+ * slotN_size 4
+ * slotN_used 4
+ * DL_FREE_ADDR dl_free_ptr 4
+ * cached data
+ * ...
+ * dl_free_ptr empty space
+ * ...
+ */
+
+#define DL_CACHE_START MAP::RAM_G_SIZE - 0xFFFF
+#define DL_FREE_ADDR DL_CACHE_START + DL_CACHE_SLOTS * 12
+
+using namespace FTDI;
+
+// The init function ensures all cache locations are marked as empty
+
+void DLCache::init() {
+ CLCD::mem_write_32(DL_FREE_ADDR, DL_FREE_ADDR + 4);
+ for (uint8_t slot = 0; slot < DL_CACHE_SLOTS; slot++)
+ save_slot(slot, 0, 0, 0);
+}
+
+bool DLCache::has_data() {
+ return dl_slot_size != 0;
+}
+
+bool DLCache::wait_until_idle() {
+ const unsigned long startTime = millis();
+ do {
+ if ((millis() - startTime) > 250) {
+ SERIAL_ECHO_MSG("Timeout on DL_Cache::Wait_Until_Idle()");
+ CLCD::CommandFifo::reset();
+ return false;
+ }
+ #ifdef __MARLIN_FIRMWARE__
+ ExtUI::yield();
+ #endif
+ } while (CLCD::CommandFifo::is_processing());
+ return true;
+}
+
+/* This caches the current display list in RAMG so
+ * that it can be appended later. The memory is
+ * dynamically allocated following DL_FREE_ADDR.
+ *
+ * If min_bytes is provided, then that many bytes
+ * will be reserved so that the cache may be re-written
+ * later with potentially a bigger DL.
+ */
+
+bool DLCache::store(uint32_t min_bytes /* = 0*/) {
+ CLCD::CommandFifo cmd;
+
+ // Execute any commands already in the FIFO
+ cmd.execute();
+ if (!wait_until_idle())
+ return false;
+
+ // Figure out how long the display list is
+ const uint32_t dl_size = CLCD::dl_size();
+
+ if (dl_slot_addr == 0) {
+ // If we are allocating new space...
+ dl_slot_addr = CLCD::mem_read_32(DL_FREE_ADDR);
+ dl_slot_size = max(dl_size, min_bytes);
+
+ const uint32_t free_space = MAP::RAM_G_SIZE - dl_slot_addr;
+ if (dl_slot_size <= free_space) {
+ CLCD::mem_write_32(DL_FREE_ADDR, dl_slot_addr + dl_slot_size);
+ }
+ else {
+ dl_slot_addr = 0;
+ dl_slot_size = 0;
+ dl_slot_used = 0;
+ }
+ }
+
+ if (dl_size > dl_slot_size) {
+ // Not enough memory to cache the display list.
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR ("Not enough space in GRAM to cache display list, free space: ", dl_slot_size);
+ SERIAL_ECHOLNPAIR(" Required: ", dl_size);
+ #endif
+ dl_slot_used = 0;
+ save_slot();
+ return false;
+ }
+ else {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR ("Saving DL to RAMG cache, bytes: ", dl_slot_used);
+ SERIAL_ECHOLNPAIR(" Free space: ", dl_slot_size);
+ #endif
+ dl_slot_used = dl_size;
+ save_slot();
+ cmd.memcpy(dl_slot_addr, MAP::RAM_DL, dl_slot_used);
+ cmd.execute();
+ return true;
+ }
+}
+
+void DLCache::save_slot(uint8_t indx, uint32_t addr, uint16_t size, uint16_t used) {
+ CLCD::mem_write_32(DL_CACHE_START + indx * 12 + 0, addr);
+ CLCD::mem_write_32(DL_CACHE_START + indx * 12 + 4, size);
+ CLCD::mem_write_32(DL_CACHE_START + indx * 12 + 8, used);
+}
+
+void DLCache::load_slot(uint8_t indx, uint32_t &addr, uint16_t &size, uint16_t &used) {
+ addr = CLCD::mem_read_32(DL_CACHE_START + indx * 12 + 0);
+ size = CLCD::mem_read_32(DL_CACHE_START + indx * 12 + 4);
+ used = CLCD::mem_read_32(DL_CACHE_START + indx * 12 + 8);
+}
+
+void DLCache::append() {
+ CLCD::CommandFifo cmd;
+ cmd.append(dl_slot_addr, dl_slot_used);
+ #if ENABLED(TOUCH_UI_DEBUG)
+ cmd.execute();
+ wait_until_idle();
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR ("Appending to DL from RAMG cache, bytes: ", dl_slot_used);
+ SERIAL_ECHOLNPAIR(" REG_CMD_DL: ", CLCD::mem_read_32(REG::CMD_DL));
+ #endif
+}
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.h
new file mode 100644
index 0000000..73b4b0b
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.h
@@ -0,0 +1,70 @@
+/**************
+ * dl_cache.h *
+ **************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/******************* DISPLAY LIST CACHE MANAGEMENT ************************/
+/* The Display List Cache mechanism stores the display list corresponding
+ * to a menu into RAM_G so that on subsequent calls drawing the menu does
+ * not require as much SPI traffic. Dynamic content, such as indicators,
+ * should not be cached.
+ *
+ * The DLCache can be used like so:
+ *
+ * DLCache dlcache(UNIQUE_ID);
+ *
+ * if (dlcache.hasData())
+ * dlcache.append();
+ * else
+ * dlcache.store(); // Add stuff to the DL
+ */
+class DLCache {
+ private:
+ typedef FTDI::ftdi_registers REG;
+ typedef FTDI::ftdi_memory_map MAP;
+
+ uint8_t dl_slot_indx;
+ uint32_t dl_slot_addr;
+ uint16_t dl_slot_size;
+ uint16_t dl_slot_used;
+
+ void load_slot() {load_slot(dl_slot_indx, dl_slot_addr, dl_slot_size, dl_slot_used);}
+ void save_slot() {save_slot(dl_slot_indx, dl_slot_addr, dl_slot_size, dl_slot_used);}
+
+ static void load_slot(uint8_t indx, uint32_t &addr, uint16_t &size, uint16_t &used);
+ static void save_slot(uint8_t indx, uint32_t addr, uint16_t size, uint16_t used);
+
+ bool wait_until_idle();
+
+ public:
+ static void init();
+
+ DLCache(uint8_t slot) {
+ dl_slot_indx = slot;
+ load_slot();
+ }
+
+ bool has_data();
+ bool store(uint32_t min_bytes = 0);
+ void append();
+};
+
+#define DL_CACHE_SLOTS 250
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.cpp
new file mode 100644
index 0000000..6c0392c
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.cpp
@@ -0,0 +1,228 @@
+/******************
+ * event_loop.cpp *
+ ******************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+using namespace FTDI;
+
+enum {
+ UNPRESSED = 0x00
+};
+
+tiny_timer_t touch_timer;
+UIData::flags_t UIData::flags;
+uint8_t pressed_tag = UNPRESSED;
+
+uint8_t UIData::get_persistent_data_mask() {
+ // A bit mask for flags that should be stored to the EEPROM.
+ // Others are considered temporarily values that need not be
+ // saved.
+ constexpr flags_t persistent_flags = {
+ bits: {
+ touch_start_sound: true,
+ touch_end_sound: true,
+ touch_repeat_sound: true,
+ show_animations: true
+ }
+ };
+ return persistent_flags.value;
+}
+
+void UIData::reset_persistent_data() {
+ // Default values for persistent data
+ constexpr flags_t default_flags = {
+ bits: {
+ touch_start_sound: true,
+ touch_end_sound: true,
+ touch_repeat_sound: true,
+ show_animations: true,
+ touch_debouncing: false,
+ ignore_unpress: false
+ }
+ };
+ flags.value = default_flags.value;
+}
+
+uint8_t UIData::get_persistent_data() {
+ return flags.value & get_persistent_data_mask();
+}
+
+void UIData::set_persistent_data(uint8_t value) {
+ flags.value = value & get_persistent_data_mask();
+}
+
+
+void UIData::enable_touch_sounds(bool enabled) {
+ UIData::flags.bits.touch_start_sound = enabled;
+ UIData::flags.bits.touch_end_sound = enabled;
+ UIData::flags.bits.touch_repeat_sound = enabled;
+}
+
+bool UIData::touch_sounds_enabled() {
+ return UIData::flags.bits.touch_start_sound || UIData::flags.bits.touch_end_sound || UIData::flags.bits.touch_repeat_sound;
+}
+
+void UIData::enable_animations(bool enabled) {
+ UIData::flags.bits.show_animations = enabled;
+}
+
+bool UIData::animations_enabled() {
+ return UIData::flags.bits.show_animations;
+}
+
+namespace FTDI {
+ uint8_t EventLoop::get_pressed_tag() {
+ return pressed_tag;
+ }
+
+ bool EventLoop::is_touch_held() {
+ return pressed_tag != 0;
+ }
+
+ /**
+ * process_events(): Process events from the touch panel.
+ *
+ * This function consists of a state machine that accomplishes the following:
+ *
+ * - Reads the tag register from the touch panel
+ * - Dispatches onTouchStart and onTouchEnd events to the active screen.
+ * - Handles auto-repetition by sending onTouchHeld to the active screen periodically.
+ * - Plays touch feedback "click" sounds when appropriate.
+ * - Performs debouncing to supress spurious touch events.
+ */
+ void EventLoop::process_events() {
+ // If the LCD is processing commands, don't check
+ // for tags since they may be changing and could
+ // cause spurious events.
+ if (!touch_timer.elapsed(TOUCH_UPDATE_INTERVAL) || CLCD::CommandFifo::is_processing()) {
+ return;
+ }
+
+ const uint8_t tag = CLCD::get_tag();
+
+ switch (pressed_tag) {
+ case UNPRESSED:
+ if (tag != 0) {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR("Touch start: ", tag);
+ #endif
+
+ pressed_tag = tag;
+ current_screen.onRefresh();
+
+ // When the user taps on a button, activate the onTouchStart handler
+ const uint8_t lastScreen = current_screen.getScreen();
+
+ if (current_screen.onTouchStart(tag)) {
+ touch_timer.start();
+ if (UIData::flags.bits.touch_start_sound) sound.play(press_sound);
+ }
+
+ // In the case in which a touch event triggered a new screen to be
+ // drawn, we don't issue a touchEnd since it would be sent to the
+ // wrong screen.
+ UIData::flags.bits.ignore_unpress = (lastScreen != current_screen.getScreen());
+ }
+ else {
+ touch_timer.start();
+ }
+ break;
+ default: // PRESSED
+ if (!UIData::flags.bits.touch_debouncing) {
+ if (tag == pressed_tag) {
+ // The user is holding down a button.
+ if (touch_timer.elapsed(1000 / TOUCH_REPEATS_PER_SECOND)) {
+ if (current_screen.onTouchHeld(tag)) {
+ current_screen.onRefresh();
+ if (UIData::flags.bits.touch_repeat_sound) sound.play(repeat_sound);
+ }
+ touch_timer.start();
+ }
+ }
+ else if (tag == 0) {
+ touch_timer.start();
+ UIData::flags.bits.touch_debouncing = true;
+ }
+ }
+
+ else {
+ // Debouncing...
+
+ if (tag == pressed_tag) {
+ // If while debouncing, we detect a press, then cancel debouncing.
+ UIData::flags.bits.touch_debouncing = false;
+ }
+
+ else if (touch_timer.elapsed(DEBOUNCE_PERIOD)) {
+ UIData::flags.bits.touch_debouncing = false;
+
+ if (UIData::flags.bits.ignore_unpress) {
+ UIData::flags.bits.ignore_unpress = false;
+ pressed_tag = UNPRESSED;
+ break;
+ }
+
+ if (UIData::flags.bits.touch_end_sound) sound.play(unpress_sound);
+
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR("Touch end: ", pressed_tag);
+ #endif
+
+ const uint8_t saved_pressed_tag = pressed_tag;
+ pressed_tag = UNPRESSED;
+ current_screen.onTouchEnd(saved_pressed_tag);
+ current_screen.onRefresh();
+ }
+ }
+ break;
+ } // switch (pressed_tag)
+
+ } // processEvents()
+
+ void EventLoop::setup() {
+ CLCD::init();
+ DLCache::init();
+ UIData::reset_persistent_data();
+ current_screen.start();
+ }
+
+ void EventLoop::loop() {
+ sound.onIdle();
+
+ /**
+ * Guard against re-entry of UI methods, which can
+ * crash. Re-entry can happen because some functions
+ * (e.g. planner.synchronize) call idle().
+ */
+ if (!UIData::flags.bits.prevent_reentry) {
+ UIData::flags.bits.prevent_reentry = true;
+ current_screen.onIdle();
+ process_events();
+ UIData::flags.bits.prevent_reentry = false;
+ }
+ }
+} // namespace FTDI
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.h
new file mode 100644
index 0000000..c5f0829
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/event_loop.h
@@ -0,0 +1,74 @@
+/****************
+ * event_loop.h *
+ ****************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#define STATUS_UPDATE_INTERVAL 1000
+#define TOUCH_UPDATE_INTERVAL 50
+#define TOUCH_REPEATS_PER_SECOND 4
+#define DEBOUNCE_PERIOD 150
+
+class UIData {
+ private:
+ typedef union {
+ struct {
+ uint8_t touch_start_sound : 1;
+ uint8_t touch_end_sound : 1;
+ uint8_t touch_repeat_sound : 1;
+ uint8_t show_animations : 1;
+ uint8_t touch_debouncing : 1;
+ uint8_t ignore_unpress : 1;
+ uint8_t prevent_reentry : 1;
+ } bits;
+ uint8_t value;
+ } flags_t;
+
+ public:
+ static flags_t flags;
+
+ static uint8_t get_persistent_data_mask();
+ static uint8_t get_persistent_data();
+ static void set_persistent_data(uint8_t value);
+ static void reset_persistent_data();
+
+ static void enable_touch_sounds(bool enabled);
+ static bool touch_sounds_enabled();
+ static void enable_animations(bool enabled);
+ static bool animations_enabled();
+};
+
+namespace FTDI {
+ class EventLoop {
+ private:
+ static constexpr FTDI::effect_t press_sound = FTDI::CHACK;
+ static constexpr FTDI::effect_t repeat_sound = FTDI::CHACK;
+ static constexpr FTDI::effect_t unpress_sound = FTDI::POP;
+ static void process_events();
+
+ public:
+ static void setup();
+ static void loop();
+
+ static uint8_t get_pressed_tag();
+ static bool is_touch_held();
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/ftdi_extended.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/ftdi_extended.h
new file mode 100644
index 0000000..fd84c79
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/ftdi_extended.h
@@ -0,0 +1,52 @@
+/*******************
+ * ftdi_extended.h *
+ *******************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2019 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 201( - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+#include "../compat.h"
+#include "../basic/ftdi_basic.h"
+
+#ifndef __MARLIN_FIRMWARE__
+ #define FTDI_EXTENDED
+#endif
+
+#if ENABLED(FTDI_EXTENDED)
+ #include "unicode/font_size_t.h"
+ #include "unicode/unicode.h"
+ #include "unicode/standard_char_set.h"
+ #include "unicode/western_char_set.h"
+ #include "unicode/cyrillic_char_set.h"
+ #include "unicode/font_bitmaps.h"
+ #include "rgb_t.h"
+ #include "bitmap_info.h"
+ #include "tiny_timer.h"
+ #include "grid_layout.h"
+ #include "dl_cache.h"
+ #include "event_loop.h"
+ #include "command_processor.h"
+ #include "screen_types.h"
+ #include "sound_player.h"
+ #include "sound_list.h"
+ #include "polygon.h"
+ #include "text_box.h"
+ #include "text_ellipsis.h"
+#endif
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/grid_layout.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/grid_layout.h
new file mode 100644
index 0000000..82bb8ab
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/grid_layout.h
@@ -0,0 +1,98 @@
+/*****************
+ * grid_layout.h *
+ *****************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/* The grid layout macros allow buttons to be arranged on a grid so
+ * that their locations become independent of the display size. The
+ * layout model is similar to that of HTML TABLEs.
+ *
+ * These macros are meant to be evaluated into constants at compile
+ * time, so resolution independence can be as efficient as using
+ * hard-coded coordinates.
+ */
+
+// Margin defines the margin (in pixels) on each side of a button in
+// the layout
+
+#ifdef TOUCH_UI_800x480
+ #define MARGIN_L 5
+ #define MARGIN_R 5
+ #define MARGIN_T 5
+ #define MARGIN_B 5
+ #define MARGIN_DEFAULT 5
+#else
+ #define MARGIN_L 3
+ #define MARGIN_R 3
+ #define MARGIN_T 3
+ #define MARGIN_B 3
+ #define MARGIN_DEFAULT 3
+#endif
+
+// EDGE_R adds some black space on the right edge of the display
+// This shifts some of the screens left to visually center them.
+
+#define EDGE_R 0
+
+// GRID_X and GRID_Y computes the positions of the divisions on
+// the layout grid.
+#define GRID_X(x) ((x)*(FTDI::display_width-EDGE_R)/GRID_COLS)
+#define GRID_Y(y) ((y)*FTDI::display_height/GRID_ROWS)
+
+// BTN_X, BTN_Y, BTN_W and BTN_X returns the top-left and width
+// and height of a button, taking into account the button margins.
+
+#define BTN_X(x) (GRID_X((x)-1) + MARGIN_L)
+#define BTN_Y(y) (GRID_Y((y)-1) + MARGIN_T)
+#define BTN_W(w) (GRID_X(w) - MARGIN_L - MARGIN_R)
+#define BTN_H(h) (GRID_Y(h) - MARGIN_T - MARGIN_B)
+
+// Abbreviations for common phrases, to allow a button to be
+// defined in one line of source.
+#define BTN_POS(x,y) BTN_X(x), BTN_Y(y)
+#define BTN_SIZE(w,h) BTN_W(w), BTN_H(h)
+
+// Draw a reference grid for ease of spacing out widgets.
+#define DRAW_LAYOUT_GRID \
+ { \
+ cmd.cmd(LINE_WIDTH(4)); \
+ for (int i = 1; i <= GRID_COLS; i++) { \
+ cmd.cmd(BEGIN(LINES)); \
+ cmd.cmd(VERTEX2F(GRID_X(i) *16, 0 *16)); \
+ cmd.cmd(VERTEX2F(GRID_X(i) *16, FTDI::display_height *16)); \
+ } \
+ for (int i = 1; i < GRID_ROWS; i++) { \
+ cmd.cmd(BEGIN(LINES)); \
+ cmd.cmd(VERTEX2F(0 *16, GRID_Y(i) *16)); \
+ cmd.cmd(VERTEX2F(FTDI::display_width *16, GRID_Y(i) *16)); \
+ } \
+ cmd.cmd(LINE_WIDTH(16)); \
+ }
+
+namespace FTDI {
+ #if ENABLED(TOUCH_UI_PORTRAIT)
+ constexpr uint16_t display_width = Vsize;
+ constexpr uint16_t display_height = Hsize;
+ #else
+ constexpr uint16_t display_width = Hsize;
+ constexpr uint16_t display_height = Vsize;
+ #endif
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/polygon.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/polygon.h
new file mode 100644
index 0000000..6aa52f0
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/polygon.h
@@ -0,0 +1,96 @@
+/*************
+ * polygon.h *
+ *************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * The Polygon class helps drawing filled or stroked polygons on the FTDI EVE:
+ *
+ * CommandProcessor cmd;
+ * cmd.cmd(COLOR_RGB(0x00FF00));
+ *
+ * Polygon p(cmd);
+ * p.begin_fill();
+ * p.begin_loop();
+ * p(10,10);
+ * p(20,10);
+ * p(20,20);
+ * p(10,20);
+ * p.end_loop();
+ * p.begin_loop();
+ * ... // Additional closed paths
+ * p.end_loop();
+ * ...
+ * p.end_fill();
+ *
+ * Based on the example from "Applicaton Note AN_334, FT801 Polygon Application":
+ *
+ * https://brtchip.com/wp-content/uploads/Support/Documentation/Application_Notes/ICs/EVE/AN_334-FT801_Polygon_Application.pdf
+ */
+
+namespace FTDI {
+ class Polygon {
+ private:
+ FTDI::begin_t path_initiator = FTDI::LINE_STRIP;
+
+ public:
+ CommandProcessor &cmd;
+
+ Polygon(CommandProcessor &c) : cmd(c) {}
+
+ void begin_fill() {
+ using namespace FTDI;
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(TAG_MASK(0));
+ cmd.cmd(CLEAR(0,1,0));
+ cmd.cmd(COLOR_MASK(0,0,0,0));
+ cmd.cmd(STENCIL_OP(STENCIL_OP_KEEP, STENCIL_OP_INVERT));
+ cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_ALWAYS, 255, 255));
+ // Drawing the edge strip along scan lines
+ // seems to yield the best performance
+ #if ENABLED(TOUCH_UI_PORTRAIT)
+ path_initiator = EDGE_STRIP_B;
+ #else
+ path_initiator = EDGE_STRIP_R;
+ #endif
+ }
+
+ // Specify a clipping rectangle to paint fewer pixels and reduce rendering time, otherwise all pixels will be painted.
+ void end_fill(const int16_t x1 = 0, const int16_t y1 = 0, const int16_t x2 = display_width * 16, const int16_t y2 = display_height * 16) {
+ using namespace FTDI;
+ cmd.cmd(RESTORE_CONTEXT());
+
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_NOTEQUAL, 0, 255));
+ cmd.cmd(BEGIN(RECTS));
+ cmd.cmd(VERTEX2F(x1, y1));
+ cmd.cmd(VERTEX2F(x2, y2));
+ cmd.cmd(RESTORE_CONTEXT());
+ }
+
+ void begin_stroke() {path_initiator = FTDI::LINE_STRIP;}
+ void begin_loop() {cmd.cmd(FTDI::BEGIN(path_initiator));}
+ void end_stroke() {}
+ void end_loop() {}
+
+ void operator()(const uint16_t x, const uint16_t y) {cmd.cmd(FTDI::VERTEX2F(x, y));}
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/rgb_t.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/rgb_t.h
new file mode 100644
index 0000000..62762ee
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/rgb_t.h
@@ -0,0 +1,84 @@
+/***********
+ * rgb_t.h *
+ ***********/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * Implementation of hsl_to_rgb as constexpr functions based on:
+ *
+ * https://www.rapidtables.com/convert/color/hsl-to-rgb.html
+ */
+
+constexpr float _hsl_fmod(float x, float y) {
+ return x - int(x/y)*y;
+}
+
+constexpr float _hsl_c(float, float S, float L) {
+ return (1.0f - fabs(2*L-1.0f)) * S;
+}
+
+constexpr float _hsl_x(float H, float S, float L) {
+ return _hsl_c(H,S,L) * (1.0f - fabs(_hsl_fmod(H/60, 2) - 1));
+}
+
+constexpr float _hsl_m(float H, float S, float L) {
+ return L - _hsl_c(H,S,L)/2;
+}
+
+constexpr float _hsl_rgb(float H, float S, float L, float r, float g, float b) {
+ return ((uint32_t((r + _hsl_m(H,S,L))*255+0.5) << 16) |
+ (uint32_t((g + _hsl_m(H,S,L))*255+0.5) << 8) |
+ (uint32_t((b + _hsl_m(H,S,L))*255+0.5) << 0));
+}
+
+constexpr uint32_t hsl_to_rgb(float H, float S, float L) {
+ return (H < 60) ? _hsl_rgb(H,S,L,_hsl_c(H,S,L), _hsl_x(H,S,L), 0) :
+ (H < 120) ? _hsl_rgb(H,S,L,_hsl_x(H,S,L), _hsl_c(H,S,L), 0) :
+ (H < 180) ? _hsl_rgb(H,S,L, 0, _hsl_c(H,S,L), _hsl_x(H,S,L)) :
+ (H < 240) ? _hsl_rgb(H,S,L, 0, _hsl_x(H,S,L), _hsl_c(H,S,L)) :
+ (H < 300) ? _hsl_rgb(H,S,L,_hsl_x(H,S,L), 0, _hsl_c(H,S,L)) :
+ _hsl_rgb(H,S,L,_hsl_c(H,S,L), 0, _hsl_x(H,S,L));
+}
+
+/**
+ * Structure for RGB colors
+ */
+struct rgb_t {
+ union {
+ struct {
+ uint8_t b,g,r,a;
+ };
+ uint32_t packed;
+ };
+
+ rgb_t() : packed(0) {}
+ rgb_t(uint32_t rgb) : packed(rgb) {}
+ rgb_t(uint8_t r, uint8_t g, uint8_t b) : b(b), g(g), r(r), a(0) {}
+ operator uint32_t() const {return packed;};
+
+ static void lerp(float t, const rgb_t a, const rgb_t b, rgb_t &c) {
+ c.r = a.r + t * (b.r - a.r);
+ c.g = a.g + t * (b.g - a.g);
+ c.b = a.b + t * (b.b - a.b);
+ }
+
+ uint8_t luminance() const {return 0.299*r + 0.587*g + 0.114*b;}
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.cpp
new file mode 100644
index 0000000..944237b
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.cpp
@@ -0,0 +1,105 @@
+/******************
+ * screen_types.h *
+ ******************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+/********************** VIRTUAL DISPATCH DATA TYPE ******************************/
+
+uint8_t ScreenRef::lookupScreen(onRedraw_func_t onRedraw_ptr) {
+ for (uint8_t type = 0; type < functionTableSize; type++) {
+ if (GET_METHOD(type, onRedraw) == onRedraw_ptr) {
+ return type;
+ }
+ }
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR("Screen not found: ", (uintptr_t) onRedraw_ptr);
+ #endif
+ return 0xFF;
+}
+
+void ScreenRef::setScreen(onRedraw_func_t onRedraw_ptr) {
+ uint8_t type = lookupScreen(onRedraw_ptr);
+ if (type != 0xFF) {
+ setType(type);
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR("New screen: ", type);
+ #endif
+ }
+}
+
+void ScreenRef::initializeAll() {
+ for (uint8_t type = 0; type < functionTableSize; type++)
+ GET_METHOD(type, onStartup)();
+}
+
+/********************** SCREEN STACK ******************************/
+
+void ScreenStack::start() {
+ initializeAll();
+ onEntry();
+}
+
+void ScreenStack::push(onRedraw_func_t onRedraw_ptr) {
+ stack[3] = stack[2];
+ stack[2] = stack[1];
+ stack[1] = stack[0];
+ stack[0] = lookupScreen(onRedraw_ptr);
+}
+
+void ScreenStack::push() {
+ stack[3] = stack[2];
+ stack[2] = stack[1];
+ stack[1] = stack[0];
+ stack[0] = getType();
+}
+
+void ScreenStack::pop() {
+ setType(stack[0]);
+ forget();
+}
+
+void ScreenStack::forget() {
+ stack[0] = stack[1];
+ stack[1] = stack[2];
+ stack[2] = stack[3];
+ stack[3] = 0;
+}
+
+void ScreenStack::goTo(onRedraw_func_t s) {
+ push();
+ onExit();
+ setScreen(s);
+ onEntry();
+}
+
+void ScreenStack::goBack() {
+ onExit();
+ pop();
+ onEntry();
+}
+
+ScreenStack current_screen;
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.h
new file mode 100644
index 0000000..1581cbb
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.h
@@ -0,0 +1,241 @@
+/********************
+ * screen_types.cpp *
+ ********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+typedef enum {
+ BACKGROUND = 1,
+ FOREGROUND = 2,
+ BOTH = 3
+} draw_mode_t;
+
+ /********************** VIRTUAL DISPATCH DATA TYPE ******************************/
+
+// True virtual classes are extremely expensive on the Arduino
+// as the compiler stores the virtual function tables in RAM.
+// We invent a data type called ScreenRef that gives us
+// polymorphism by mapping an ID to virtual methods on various
+// classes. This works by keeping a table in PROGMEM of pointers
+// to static methods.
+
+#define DECL_SCREEN(className) { \
+ className::onStartup, \
+ className::onEntry, \
+ className::onExit, \
+ className::onIdle, \
+ className::onRefresh, \
+ className::onRedraw, \
+ className::onTouchStart, \
+ className::onTouchHeld, \
+ className::onTouchEnd \
+}
+
+#define GET_METHOD(type, method) reinterpret_cast(pgm_read_ptr_far(&functionTable[type].method##_ptr))
+#define SCREEN_TABLE PROGMEM const ScreenRef::table_t ScreenRef::functionTable[] =
+#define SCREEN_TABLE_POST const uint8_t ScreenRef::functionTableSize = sizeof(ScreenRef::functionTable)/sizeof(ScreenRef::functionTable[0]);
+
+class ScreenRef {
+ protected:
+ typedef void onStartup_func_t();
+ typedef void onEntry_func_t();
+ typedef void onExit_func_t();
+ typedef void onIdle_func_t();
+ typedef void onRefresh_func_t();
+ typedef void onRedraw_func_t(draw_mode_t);
+ typedef bool onTouchStart_func_t(uint8_t);
+ typedef bool onTouchHeld_func_t(uint8_t);
+ typedef bool onTouchEnd_func_t(uint8_t);
+
+ private:
+ typedef struct {
+ onStartup_func_t *onStartup_ptr;
+ onEntry_func_t *onEntry_ptr;
+ onExit_func_t *onExit_ptr;
+ onIdle_func_t *onIdle_ptr;
+ onRefresh_func_t *onRefresh_ptr;
+ onRedraw_func_t *onRedraw_ptr;
+ onTouchStart_func_t *onTouchStart_ptr;
+ onTouchHeld_func_t *onTouchHeld_ptr;
+ onTouchEnd_func_t *onTouchEnd_ptr;
+ } table_t;
+
+ uint8_t type = 0;
+ static PROGMEM const table_t functionTable[];
+ static const uint8_t functionTableSize;
+
+ public:
+ uint8_t getType() {return type;}
+
+ void setType(uint8_t t) {
+ type = t;
+ }
+
+ uint8_t lookupScreen(onRedraw_func_t onRedraw_ptr);
+
+ void setScreen(onRedraw_func_t onRedraw_ptr);
+
+ void onStartup() {GET_METHOD(type, onStartup)();}
+ void onEntry() {GET_METHOD(type, onEntry)();}
+ void onExit() {GET_METHOD(type, onExit)();}
+ void onIdle() {GET_METHOD(type, onIdle)();}
+ void onRefresh() {GET_METHOD(type, onRefresh)();}
+ void onRedraw(draw_mode_t dm) {GET_METHOD(type, onRedraw)(dm);}
+ bool onTouchStart(uint8_t tag) {return GET_METHOD(type, onTouchStart)(tag);}
+ bool onTouchHeld(uint8_t tag) {return GET_METHOD(type, onTouchHeld)(tag);}
+ bool onTouchEnd(uint8_t tag) {return GET_METHOD(type, onTouchEnd)(tag);}
+
+ void initializeAll();
+};
+
+/********************** SCREEN STACK ******************************/
+
+// To conserve dynamic memory, the screen stack is hard-coded to
+// have four values, allowing a menu of up to four levels.
+
+class ScreenStack : public ScreenRef {
+ private:
+ uint8_t stack[4];
+
+ public:
+ void start();
+ void push(onRedraw_func_t);
+ void push();
+ void pop();
+ void forget();
+ void goTo(onRedraw_func_t);
+ void goBack();
+
+ uint8_t peek() {return stack[0];}
+ uint8_t getScreen() {return getType();}
+};
+
+extern ScreenStack current_screen;
+
+/********************** BASE SCREEN CLASS ******************************/
+
+/* UIScreen is the base class for all user interface screens.
+ */
+class UIScreen {
+ public:
+ static void onStartup() {}
+ static void onEntry() {current_screen.onRefresh();}
+ static void onExit() {}
+ static void onIdle() {}
+ static bool onTouchStart(uint8_t) {return true;}
+ static bool onTouchHeld(uint8_t) {return false;}
+ static bool onTouchEnd(uint8_t) {return true;}
+};
+
+#define PUSH_SCREEN(screen) current_screen.push(screen::onRedraw)
+#define GOTO_SCREEN(screen) current_screen.goTo(screen::onRedraw)
+#define GOTO_PREVIOUS() current_screen.goBack();
+#define AT_SCREEN(screen) (current_screen.getType() == current_screen.lookupScreen(screen::onRedraw))
+#define IS_PARENT_SCREEN(screen) (current_screen.peek() == current_screen.lookupScreen(screen::onRedraw))
+
+/************************** CACHED VS UNCHACHED SCREENS ***************************/
+
+class UncachedScreen {
+ public:
+ static void onRefresh() {
+ using namespace FTDI;
+ CommandProcessor cmd;
+ cmd.cmd(CMD_DLSTART);
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ load_utf8_bitmaps(cmd);
+ #endif
+
+ current_screen.onRedraw(BOTH);
+
+ cmd.cmd(DL::DL_DISPLAY);
+ cmd.cmd(CMD_SWAP);
+ cmd.execute();
+ }
+};
+
+template
+class CachedScreen {
+ protected:
+ static void gfxError() {
+ using namespace FTDI;
+ CommandProcessor cmd;
+ cmd.cmd(CMD_DLSTART)
+ .cmd(CLEAR(true,true,true))
+ .font(30)
+ .text(0, 0, display_width, display_height, F("GFX MEM FULL"));
+ }
+
+ static bool storeBackground() {
+ DLCache dlcache(DL_SLOT);
+ if (!dlcache.store(DL_SIZE)) {
+ SERIAL_ECHO_MSG("CachedScreen::storeBackground() failed: not enough DL cache space");
+ gfxError(); // Try to cache a shorter error message instead.
+ dlcache.store(DL_SIZE);
+ return false;
+ }
+ return true;
+ }
+
+ static void repaintBackground() {
+ using namespace FTDI;
+ DLCache dlcache(DL_SLOT);
+ CommandProcessor cmd;
+
+ cmd.cmd(CMD_DLSTART);
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ load_utf8_bitmaps(cmd);
+ #endif
+ current_screen.onRedraw(BACKGROUND);
+
+ dlcache.store(DL_SIZE);
+ }
+
+ public:
+ static void onRefresh() {
+ #if ENABLED(TOUCH_UI_DEBUG)
+ const uint32_t start_time = millis();
+ #endif
+ using namespace FTDI;
+ DLCache dlcache(DL_SLOT);
+ CommandProcessor cmd;
+
+ cmd.cmd(CMD_DLSTART);
+
+ if (dlcache.has_data()) {
+ dlcache.append();
+ }
+ else {
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ load_utf8_bitmaps(cmd);
+ #endif
+ current_screen.onRedraw(BACKGROUND);
+ dlcache.store(DL_SIZE);
+ }
+
+ current_screen.onRedraw(FOREGROUND);
+
+ cmd.cmd(DL::DL_DISPLAY);
+ cmd.cmd(CMD_SWAP);
+ cmd.execute();
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHOLNPAIR("Time to draw screen (ms): ", millis() - start_time);
+ #endif
+ }
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_list.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_list.h
new file mode 100644
index 0000000..20df15a
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_list.h
@@ -0,0 +1,38 @@
+/****************
+ * sound_list.h *
+ ****************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+class SoundList {
+ private:
+ static PROGMEM const struct list_t {
+ const char *const PROGMEM name;
+ const FTDI::SoundPlayer::sound_t* data;
+ } list[];
+ public:
+ static const uint8_t n;
+ static inline const char* name(uint8_t val) {
+ return (const char* ) pgm_read_ptr_far(&list[val].name);
+ }
+ static inline FTDI::SoundPlayer::sound_t* data(uint8_t val) {
+ return (FTDI::SoundPlayer::sound_t*) pgm_read_ptr_far(&list[val].data);
+ }
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.cpp
new file mode 100644
index 0000000..07d1ff5
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.cpp
@@ -0,0 +1,110 @@
+/********************
+ * sound_player.cpp *
+ ********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+namespace FTDI {
+ SoundPlayer sound; // Global sound player object
+
+ void SoundPlayer::set_volume(uint8_t vol) {
+ CLCD::mem_write_8(REG::VOL_SOUND, vol);
+ }
+
+ uint8_t SoundPlayer::get_volume() {
+ return CLCD::mem_read_8(REG::VOL_SOUND);
+ }
+
+ void SoundPlayer::play(effect_t effect, note_t note) {
+
+ #if ENABLED(TOUCH_UI_DEBUG)
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR ("Playing note ", int(note));
+ SERIAL_ECHOLNPAIR(", instrument ", int(effect));
+ #endif
+
+ // Play the note
+ CLCD::mem_write_16(REG::SOUND, (note == REST) ? 0 : (((note ? note : NOTE_C4) << 8) | effect));
+ CLCD::mem_write_8(REG::PLAY, 1);
+ }
+
+ note_t SoundPlayer::frequency_to_midi_note(const uint16_t frequency_hz) {
+ const float f0 = 440;
+ return note_t(NOTE_A4 + (log(frequency_hz)-log(f0))*12/log(2) + 0.5);
+ }
+
+ // Plays a tone of a given frequency and duration. Since the FTDI FT810 only
+ // supports MIDI notes, we round down to the nearest note.
+
+ void SoundPlayer::play_tone(const uint16_t frequency_hz, const uint16_t duration_ms) {
+ play(ORGAN, frequency_to_midi_note(frequency_hz));
+
+ // Schedule silence to squelch the note after the duration expires.
+ sequence = silence;
+ wait = duration_ms;
+ timer.start();
+ }
+
+ void SoundPlayer::play(const sound_t* seq, play_mode_t mode) {
+ sequence = seq;
+ wait = 250; // Adding this delay causes the note to not be clipped, not sure why.
+ timer.start();
+
+ if (mode == PLAY_ASYNCHRONOUS) return;
+
+ // If playing synchronously, then play all the notes here
+
+ while (has_more_notes()) {
+ onIdle();
+ TERN_(TOUCH_UI_FTDI_EVE, ExtUI::yield());
+ }
+ }
+
+ bool SoundPlayer::is_sound_playing() {
+ return CLCD::mem_read_8( REG::PLAY ) & 0x1;
+ }
+
+ void SoundPlayer::onIdle() {
+ if (!sequence) return;
+
+ const bool ready_for_next_note = (wait == 0) ? !is_sound_playing() : timer.elapsed(wait);
+
+ if (ready_for_next_note) {
+ const effect_t fx = effect_t(pgm_read_byte(&sequence->effect));
+ const note_t nt = note_t(pgm_read_byte(&sequence->note));
+ const uint32_t ms = uint32_t(pgm_read_byte(&sequence->sixteenths)) * 1000 / 16;
+
+ if (ms == 0 && fx == SILENCE && nt == END_SONG) {
+ sequence = 0;
+ play(SILENCE, REST);
+ }
+ else {
+ wait = ms;
+ timer.start();
+ play(fx, nt);
+ sequence++;
+ }
+ }
+ }
+} // namespace FTDI
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.h
new file mode 100644
index 0000000..fcfe70b
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/sound_player.h
@@ -0,0 +1,70 @@
+/******************
+ * sound_player.h *
+ ******************/
+
+/****************************************************************************
+ * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+namespace FTDI {
+ typedef enum {
+ PLAY_ASYNCHRONOUS,
+ PLAY_SYNCHRONOUS
+ } play_mode_t;
+
+ class SoundPlayer {
+ typedef FTDI::ftdi_registers REG;
+ typedef FTDI::ftdi_memory_map MAP;
+
+ public:
+ struct sound_t {
+ effect_t effect; // The sound effect number
+ note_t note; // The MIDI note value
+ uint16_t sixteenths; // Duration of note, in sixteeths of a second, or zero to play to completion
+ };
+
+ const uint8_t WAIT = 0;
+
+ private:
+ const sound_t *sequence;
+ tiny_timer_t timer;
+ tiny_time_t wait;
+
+ note_t frequency_to_midi_note(const uint16_t frequency);
+
+ public:
+ static void set_volume(uint8_t volume);
+ static uint8_t get_volume();
+
+ static void play(effect_t effect, note_t note = NOTE_C4);
+ static bool is_sound_playing();
+
+ void play(const sound_t* seq, play_mode_t mode = PLAY_SYNCHRONOUS);
+ void play_tone(const uint16_t frequency_hz, const uint16_t duration_ms);
+ bool has_more_notes() {return sequence != 0;};
+
+ void onIdle();
+ };
+
+ extern SoundPlayer sound;
+
+ const PROGMEM SoundPlayer::sound_t silence[] = {
+ {SILENCE, END_SONG, 0}
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp
new file mode 100644
index 0000000..b7422a0
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp
@@ -0,0 +1,129 @@
+/****************
+ * text_box.cpp *
+ ****************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+namespace FTDI {
+ /**
+ * Given a str, end will be set to the position at which a line needs to
+ * be broken so that the display width is less than w. The line will also
+ * be broken after a '\n'. Returns the display width of the line.
+ */
+ static uint16_t find_line_break(const FontMetrics &fm, uint16_t w, const char *str, const char *&end) {
+ w -= fm.get_char_width(' ');
+ const char *p = str;
+ end = str;
+ uint16_t lw = 0, result = 0;
+ for (;;) {
+ utf8_char_t c = get_utf8_char_and_inc(p);
+ if (c == ' ' || c == '\n' || c == '\0') {
+ if (lw < w || end == str) {
+ end = (c == '\0') ? p-1 : p;
+ result = lw;
+ }
+ if (c == '\0' || c == '\n') break;
+ }
+ lw += fm.get_char_width(c);
+ }
+ if (end == str) {
+ end = p-1;
+ result = lw;
+ }
+ return result;
+ }
+
+ /**
+ * This function returns a measurements of the word-wrapped text box.
+ */
+ static void measure_text_box(const FontMetrics &fm, const char *str, uint16_t &width, uint16_t &height) {
+ const char *line_start = (const char*)str;
+ const char *line_end;
+ const uint16_t wrap_width = width;
+ width = height = 0;
+ for (;;) {
+ uint16_t line_width = find_line_break(fm, wrap_width, line_start, line_end);
+ if (line_end == line_start) break;
+ width = max(width, line_width);
+ height += fm.get_height();
+ line_start = line_end;
+ }
+ }
+
+ /**
+ * This function draws text inside a bounding box, doing word wrapping and using the largest font that will fit.
+ */
+ void draw_text_box(CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options, uint8_t font) {
+ uint16_t box_width, box_height;
+
+ FontMetrics fm(font);
+
+ // Shrink the font until we find a font that fits
+ for (;;) {
+ box_width = w;
+ measure_text_box(fm, str, box_width, box_height);
+ if (box_width <= (uint16_t)w && box_height <= (uint16_t)h) break;
+ fm.load(--font);
+ if (font == 26) break;
+ }
+
+ const uint16_t dx = (options & OPT_RIGHTX) ? w : (options & OPT_CENTERX) ? w/2 : 0;
+ const uint16_t dy = (options & OPT_CENTERY) ? (h - box_height)/2 : 0;
+
+ const char *line_start = str;
+ const char *line_end;
+ for (;;) {
+ find_line_break(fm, w, line_start, line_end);
+ if (line_end == line_start) break;
+
+ const size_t line_len = line_end - line_start;
+ if (line_len) {
+ char line[line_len + 1];
+ strncpy(line, line_start, line_len);
+ line[line_len] = 0;
+ if (line[line_len - 1] == '\n' || line[line_len - 1] == ' ')
+ line[line_len - 1] = 0;
+
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ if (has_utf8_chars(line)) {
+ draw_utf8_text(cmd, x + dx, y + dy, line, fm.fs, options & ~OPT_CENTERY);
+ } else
+ #endif
+ {
+ cmd.CLCD::CommandFifo::text(x + dx, y + dy, font, options & ~OPT_CENTERY);
+ cmd.CLCD::CommandFifo::str(line);
+ }
+ }
+ y += fm.get_height();
+
+ line_start = line_end;
+ }
+ }
+
+ void draw_text_box(CommandProcessor& cmd, int x, int y, int w, int h, progmem_str pstr, uint16_t options, uint8_t font) {
+ char str[strlen_P((const char*)pstr) + 1];
+ strcpy_P(str, (const char*)pstr);
+ draw_text_box(cmd, x, y, w, h, (const char*) str, options, font);
+ }
+} // namespace FTDI
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.h
new file mode 100644
index 0000000..9d8cd44
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.h
@@ -0,0 +1,30 @@
+/**************
+ * text_box.h *
+ **************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * This function draws text inside a bounding box, doing word wrapping and using the largest font that will fit.
+ */
+namespace FTDI {
+ void draw_text_box(class CommandProcessor& cmd, int x, int y, int w, int h, progmem_str str, uint16_t options = 0, uint8_t font = 31);
+ void draw_text_box(class CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options = 0, uint8_t font = 31);
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp
new file mode 100644
index 0000000..5fc89f1
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp
@@ -0,0 +1,91 @@
+/*********************
+ * text_ellipsis.cpp *
+ *********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+namespace FTDI {
+
+ /**
+ * Helper function for drawing text with ellipses. The str buffer may be modified and should have space for up to two extra characters.
+ */
+ static void _draw_text_with_ellipsis(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, char *str, uint16_t options, uint8_t font) {
+ FontMetrics fm(font);
+ const int16_t ellipsisWidth = fm.get_char_width('.') * 3;
+
+ // Compute the total line length, as well as
+ // the location in the string where it can
+ // split and still allow the ellipsis to fit.
+ int16_t lineWidth = 0;
+ char *breakPoint = str;
+ #ifdef TOUCH_UI_USE_UTF8
+ char *tstr = str;
+ while (*tstr) {
+ breakPoint = tstr;
+ const utf8_char_t c = get_utf8_char_and_inc(tstr);
+ lineWidth += fm.get_char_width(c);
+ if (lineWidth + ellipsisWidth < w)
+ break;
+ }
+ #else
+ for (char* c = str; *c; c++) {
+ lineWidth += fm.get_char_width(*c);
+ if (lineWidth + ellipsisWidth < w)
+ breakPoint = c;
+ }
+ #endif
+
+ if (lineWidth > w) {
+ *breakPoint = '\0';
+ strcpy_P(breakPoint,PSTR("..."));
+ }
+
+ cmd.apply_text_alignment(x, y, w, h, options);
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ if (has_utf8_chars(str)) {
+ draw_utf8_text(cmd, x, y, str, font_size_t::from_romfont(font), options);
+ } else
+ #endif
+ {
+ cmd.CLCD::CommandFifo::text(x, y, font, options);
+ cmd.CLCD::CommandFifo::str(str);
+ }
+ }
+
+ /**
+ * These functions draws text inside a bounding box, truncating the text and
+ * adding ellipsis if the text does not fit.
+ */
+ void draw_text_with_ellipsis(CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options, uint8_t font) {
+ char tmp[strlen(str) + 3];
+ strcpy(tmp, str);
+ _draw_text_with_ellipsis(cmd, x, y, w, h, tmp, options, font);
+ }
+
+ void draw_text_with_ellipsis(CommandProcessor& cmd, int x, int y, int w, int h, progmem_str pstr, uint16_t options, uint8_t font) {
+ char tmp[strlen_P((const char*)pstr) + 3];
+ strcpy_P(tmp, (const char*)pstr);
+ _draw_text_with_ellipsis(cmd, x, y, w, h, tmp, options, font);
+ }
+} // namespace FTDI
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.h
new file mode 100644
index 0000000..a2d8aa9
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.h
@@ -0,0 +1,31 @@
+/*******************
+ * text_ellipsis.h *
+ *******************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2020 - SynDaver Labs, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * This function draws text inside a bounding box, truncating the text and
+ * showing ellipsis if it does not fit.
+ */
+namespace FTDI {
+ void draw_text_with_ellipsis(class CommandProcessor& cmd, int x, int y, int w, int h, progmem_str str, uint16_t options = 0, uint8_t font = 31);
+ void draw_text_with_ellipsis(class CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options = 0, uint8_t font = 31);
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.cpp
new file mode 100644
index 0000000..5219c0d
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.cpp
@@ -0,0 +1,39 @@
+/******************
+ * tiny_timer.cpp *
+ ******************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+bool tiny_timer_t::elapsed(tiny_time_t duration) {
+ uint8_t now = tiny_time_t::tiny_time(
+ TERN(__MARLIN_FIRMWARE__, ExtUI::safe_millis(), millis())
+ );
+ uint8_t elapsed = now - _start;
+ return elapsed >= duration._duration;
+}
+
+void tiny_timer_t::start() {
+ _start = tiny_time_t::tiny_time(
+ TERN(__MARLIN_FIRMWARE__, ExtUI::safe_millis(), millis())
+ );
+}
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.h
new file mode 100644
index 0000000..f64d033
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/tiny_timer.h
@@ -0,0 +1,56 @@
+/****************
+ * tiny_timer.h *
+ ****************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/* Helpful Reference:
+ *
+ * https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover
+ */
+
+/* tiny_interval_t downsamples a 32-bit millis() value
+ into a 8-bit value which can record periods of
+ a few seconds with a rougly 1/16th of second
+ resolution. This allows us to measure small
+ intervals without needing to use four-byte counters.
+ */
+class tiny_time_t {
+ private:
+ friend class tiny_timer_t;
+ uint8_t _duration;
+
+ static uint8_t tiny_time(uint32_t ms) {return ceil(float(ms) / 64);};
+
+ public:
+ tiny_time_t() : _duration(0) {}
+ tiny_time_t(uint32_t ms) : _duration(tiny_time(ms)) {}
+ tiny_time_t & operator= (uint32_t ms) {_duration = tiny_time(ms); return *this;}
+ bool operator == (uint32_t ms) {return _duration == tiny_time(ms);}
+};
+
+class tiny_timer_t {
+ private:
+ uint8_t _start;
+
+ public:
+ void start();
+ bool elapsed(tiny_time_t interval);
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/README.txt b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/README.txt
new file mode 100644
index 0000000..818bf08
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/README.txt
@@ -0,0 +1,40 @@
+
+FTDI EVE Unicode Rendering
+--------------------------
+
+The FTDI EVE chips have several fonts in ROM, but these fonts only contain a
+subset of ASCII characters. Notably, this excludes diacritics and accents
+used in most Western languages.
+
+While the FTDI EVE has the capability for user-defined fonts, such fonts only
+support 127 character positions, making them as limiting as the built-in fonts.
+
+As a further complication, high resolution TFT displays require high resolution
+fonts. It is not feasible to put a complete international font into the limited
+flash memory of most microprocessors.
+
+To work around these limitations, this library uses a custom font renderer with
+the following characteristics:
+
+ 1) Rather than providing bitmaps for different font sizes, it uses a single
+ bitmap for the largest font size (romfont 31) and emulates other sizes by
+ scaling the bitmaps using BITMAP_TRANSFORM.
+
+ 2) Rather than loading an entire font, it combines symbols from romfont 31
+ with a limited number of symbols from a custom font. For accented letters,
+ the rendering code combine basic letter shapes from romfont 31 with
+ bitmaps containing only the accent themselves.
+
+ 3) The custom bitmap is RLE compressed into PROGMEM. For accents, which have
+ a fairly small number of non-white pixels, the savings are significant.
+
+These characteristics enable an alphabet for Western languages to be
+synthesized from only a few dozen custom symbols and modest PROGMEM use (~10k)
+
+The text layout is done by the code in "unicode.cpp" with the help of one of
+more character renderers (e.g. "western_char_set.cpp"). Each character render
+is responsible for loading the necessary bitmap data into RAMG and drawing
+characters as requested.
+
+To add symbols for other languages, it will only be necessary to make a bitmap
+and implement a corresponding character renderer.
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.cpp
new file mode 100644
index 0000000..1c193ad
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.cpp
@@ -0,0 +1,139 @@
+/************************
+ * cyrillic_char_set.cpp *
+ ************************/
+
+/****************************************************************************
+ * Written By Kirill Shashlov 2020 *
+ * Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../ftdi_extended.h"
+
+#if ALL(FTDI_EXTENDED, TOUCH_UI_USE_UTF8, TOUCH_UI_UTF8_CYRILLIC_CHARSET)
+
+ #include "cyrillic_char_set_bitmap_31.h"
+
+ #define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
+
+ #define UTF8(A) uint16_t(utf8(U##A))
+
+ using namespace FTDI;
+
+ constexpr static uint8_t cyrillic_font_handle = 6;
+
+ uint32_t FTDI::CyrillicCharSet::bitmap_addr;
+
+ /**
+ * Load bitmap data into RAMG. This function is called once at the start
+ * of the program.
+ *
+ * Parameters:
+ *
+ * addr - Address in RAMG where the font data is written
+ *
+ * Returns: Last wrote address
+ */
+
+ uint32_t FTDI::CyrillicCharSet::load_data(uint32_t addr) {
+ if (addr % 4 != 0)
+ addr += 4 - (addr % 4);
+
+ // Load the alternative font metrics
+ CLCD::FontMetrics cyrillic_fm;
+ cyrillic_fm.ptr = addr + 148;
+ cyrillic_fm.format = L4;
+ cyrillic_fm.stride = 20;
+ cyrillic_fm.width = 40;
+ cyrillic_fm.height = 49;
+ LOOP_L_N(i, 127)
+ cyrillic_fm.char_widths[i] = 0;
+
+ // For cyrillic characters, copy the character widths from the widths tables
+ LOOP_L_N(i, NUM_ELEMENTS(cyrillic_font_widths)) {
+ cyrillic_fm.char_widths[i] = cyrillic_font_widths[i];
+ }
+ CLCD::mem_write_bulk(addr, &cyrillic_fm, 148);
+
+ // Decode the RLE data and load it into RAMG as a bitmap
+ uint32_t lastaddr = write_rle_data(addr + 148, cyrillic_font, sizeof(cyrillic_font));
+
+ bitmap_addr = addr;
+
+ return lastaddr;
+ }
+
+ /**
+ * Populates the bitmap handles for the custom into the display list.
+ * This function is called once at the start of each display list.
+ *
+ * Parameters:
+ *
+ * cmd - Object used for writing to the FTDI chip command queue.
+ */
+
+ void FTDI::CyrillicCharSet::load_bitmaps(CommandProcessor& cmd) {
+ CLCD::FontMetrics cyrillic_fm;
+ cyrillic_fm.ptr = bitmap_addr + 148;
+ cyrillic_fm.format = L4;
+ cyrillic_fm.stride = 20;
+ cyrillic_fm.width = 40;
+ cyrillic_fm.height = 49;
+ set_font_bitmap(cmd, cyrillic_fm, cyrillic_font_handle);
+ }
+
+ /**
+ * Renders a character at location x and y. The x position is incremented
+ * by the width of the character.
+ *
+ * Parameters:
+ *
+ * cmd - If non-NULL the symbol is drawn to the screen.
+ * If NULL, only increment position for text measurement.
+ *
+ * x, y - The location at which to draw the character. On output,
+ * incremented to the location of the next character.
+ *
+ * fs - A scaling object used to scale the font. The display will
+ * already be configured to scale bitmaps, but positions
+ * must be scaled using fs.scale()
+ *
+ * c - The unicode code point to draw. If the renderer does not
+ * support the character, it should return false.
+ *
+ * Returns: Whether the character was supported.
+ */
+
+ bool FTDI::CyrillicCharSet::render_glyph(CommandProcessor* cmd, int &x, int &y, font_size_t fs, utf8_char_t c) {
+ // A supported character?
+ if ((c < UTF8('А') || c > UTF8('я')) && (c != UTF8('Ё')) && (c != UTF8('ё'))) return false;
+
+ uint8_t idx = (c == UTF8('Ё')) ? 64 :
+ (c == UTF8('ё')) ? 65 :
+ (c < UTF8('р')) ? c - UTF8('А') :
+ c - UTF8('р') + 48
+ ;
+
+ uint8_t width = cyrillic_font_widths[idx];
+
+ // Draw the character
+ if (cmd) ext_vertex2ii(*cmd, x, y, cyrillic_font_handle, idx);
+
+ // Increment X to the next character position
+ x += fs.scale(width);
+ return true;
+ }
+
+#endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8 && TOUCH_UI_UTF8_WESTERN_CHARSET
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.h
new file mode 100644
index 0000000..63493b8
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set.h
@@ -0,0 +1,32 @@
+/**********************
+ * cyrillic_char_set.h *
+ **********************/
+
+/****************************************************************************
+ * Written By Kirill Shashlov 2020 *
+ * Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+namespace FTDI {
+ class CyrillicCharSet {
+ private:
+ static uint32_t bitmap_addr;
+ public:
+ static uint32_t load_data(uint32_t addr);
+ static void load_bitmaps(CommandProcessor&);
+ static bool render_glyph(CommandProcessor*, int &x, int &y, font_size_t, utf8_char_t);
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set_bitmap_31.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set_bitmap_31.h
new file mode 100644
index 0000000..00bfe37
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/cyrillic_char_set_bitmap_31.h
@@ -0,0 +1,2529 @@
+/********************************
+ * cyrillic_char_set_bitmap_31.h *
+ ********************************/
+
+/****************************************************************************
+ * Written By Kirill Shashlov 2020 *
+ * Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * Used GNU FreeFont FreeSans font (licensed under the GPL) *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+const uint8_t cyrillic_font_widths[] PROGMEM = {
+ 27, // А (0)
+ 26, // Б
+ 26, // В
+ 24, // Г
+ 33, // Д
+ 25, // Е
+ 37, // Ж
+ 26, // З
+
+ 28, // И (8)
+ 28, // Й
+ 26, // К
+ 25, // Л
+ 33, // М
+ 27, // Н
+ 31, // О
+ 27, // П
+
+ 26, // Р (16)
+ 29, // С
+ 28, // Т
+ 26, // У
+ 34, // Ф
+ 27, // Х
+ 30, // Ц
+ 23, // Ч
+
+ 32, // Ш (24)
+ 34, // Щ
+ 26, // Ь
+ 34, // Ы
+ 34, // Ъ
+ 28, // Э
+ 40, // Ю
+ 26, // Я
+
+ 22, // а (32)
+ 21, // б
+ 20, // в
+ 16, // г
+ 24, // д
+ 21, // е
+ 31, // ж
+ 19, // з
+
+ 21, // и (40)
+ 21, // й
+ 20, // к
+ 19, // л
+ 23, // м
+ 21, // н
+ 21, // о
+ 21, // п
+
+ 22, // р (48)
+ 20, // с
+ 17, // т
+ 19, // у
+ 34, // ф
+ 19, // х
+ 23, // ц
+ 19, // ч
+ 26, // ш
+ 28, // щ
+ 20, // ь
+ 26, // ы
+ 26, // ъ
+ 20, // э
+ 30, // ю
+ 20, // я
+
+ 26, // Ё
+ 21, // ё
+};
+
+
+/* This is a dump of "font_bitmaps/cyrillic_char_set_bitmap_31.png"
+ * using the tool "bitmap2cpp.py". The tool converts the image into
+ * 16-level grayscale and packs two pixels per byte. The resulting
+ * bytes are then RLE compressed to yield (count, byte) pairs.
+ */
+
+const unsigned char cyrillic_font[] PROGMEM = {
+ /* 0 */
+ 0xb9, 0x00, 0x01, 0x2f, 0x02, 0xff, 0x01, 0x30, 0x10, 0x00, 0x01, 0x7f,
+ 0x02, 0xff, 0x01, 0x90, 0x10, 0x00, 0x01, 0xdf, 0x02, 0xff, 0x01, 0xe0,
+ 0x0f, 0x00, 0x01, 0x03, 0x03, 0xff, 0x01, 0xf4, 0x0f, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xfb, 0x01, 0xff, 0x01, 0xfa, 0x0f, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf1, 0x02, 0xff, 0x0f, 0x00, 0x01, 0x5f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x50, 0x0e, 0x00, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0x40, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xb0, 0x0d, 0x00,
+ 0x01, 0x01, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xf1, 0x0d, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf8, 0x01, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf7, 0x0d, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x01, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xfc, 0x0d, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0x20, 0x0c, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x60, 0x02, 0x00,
+ 0x01, 0x9f, 0x01, 0xff, 0x01, 0x80, 0x0c, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0x10, 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xd0, 0x0b, 0x00,
+ 0x01, 0x03, 0x01, 0xff, 0x01, 0xfa, 0x03, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x01, 0xf3, 0x0b, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf5, 0x03, 0x00,
+ 0x01, 0x09, 0x01, 0xff, 0x01, 0xf9, 0x0b, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x01, 0xe0, 0x03, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0x4f, 0x01, 0xff, 0x01, 0xb4, 0x04, 0x44, 0x02, 0xff, 0x01, 0x40,
+ 0x0a, 0x00, 0x01, 0xaf, 0x08, 0xff, 0x01, 0xa0, 0x0a, 0x00, 0x09, 0xff,
+ 0x01, 0xf0, 0x09, 0x00, 0x01, 0x06, 0x02, 0xff, 0x05, 0xee, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xf5, 0x09, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf5,
+ 0x05, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfb, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xf0, 0x05, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x10,
+ 0x08, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x90, 0x06, 0x00, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0x70, 0x08, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x40,
+ 0x06, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xfe, 0x07, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xf2,
+ 0x07, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf8, 0x07, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf8, 0x07, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf2,
+ 0x07, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xfd, 0x07, 0x00, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0x30,
+ 0x06, 0x00, 0x01, 0x8d, 0x01, 0xdd, 0x01, 0x60, 0x08, 0x00, 0x01, 0xad,
+ 0x01, 0xdd, 0x01, 0x70, 0xce, 0x00,
+
+ /* 1 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf4, 0x09, 0x00, 0x01, 0x1f,
+ 0x09, 0xff, 0x01, 0xf4, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf4,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd5, 0x07, 0x55, 0x01, 0x51,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xfe,
+ 0x04, 0xee, 0x01, 0xdb, 0x01, 0x84, 0x0b, 0x00, 0x01, 0x1f, 0x08, 0xff,
+ 0x01, 0xe7, 0x0a, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xd2, 0x09, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd6, 0x04, 0x66, 0x01, 0x68, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0xfd, 0x01, 0x10, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x05, 0x00, 0x01, 0x04, 0x01, 0xef, 0x01, 0xff, 0x01, 0x90,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf5, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf7,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf9, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf7,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf4, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xe0, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x05, 0x02, 0xff, 0x01, 0x80,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe7, 0x04, 0x77, 0x01, 0x89,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0xfe, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff,
+ 0x01, 0xe2, 0x09, 0x00, 0x01, 0x1f, 0x08, 0xff, 0x01, 0xfb, 0x01, 0x10,
+ 0x09, 0x00, 0x01, 0x1d, 0x06, 0xdd, 0x01, 0xdc, 0x01, 0xb7, 0x01, 0x20,
+ 0xd1, 0x00,
+
+ /* 2 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x06, 0xff, 0x01, 0xec, 0x01, 0x94, 0x0b, 0x00,
+ 0x01, 0x1f, 0x08, 0xff, 0x01, 0xc3, 0x0a, 0x00, 0x01, 0x1f, 0x09, 0xff,
+ 0x01, 0x40, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd6, 0x03, 0x66,
+ 0x01, 0x67, 0x01, 0x9d, 0x02, 0xff, 0x01, 0xe1, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x4e, 0x01, 0xff, 0x01, 0xf9,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x04,
+ 0x02, 0xff, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0x20, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x06, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x30, 0x08, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0xaf, 0x01, 0xff,
+ 0x01, 0x20, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00,
+ 0x01, 0xcf, 0x01, 0xff, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfa, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x1d, 0x01, 0xff, 0x01, 0xf2,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd2, 0x03, 0x22, 0x01, 0x23,
+ 0x01, 0x59, 0x02, 0xff, 0x01, 0x50, 0x09, 0x00, 0x01, 0x1f, 0x08, 0xff,
+ 0x01, 0xd3, 0x0a, 0x00, 0x01, 0x1f, 0x08, 0xff, 0x01, 0xb3, 0x0a, 0x00,
+ 0x01, 0x1f, 0x09, 0xff, 0x01, 0xa0, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xd4, 0x04, 0x44, 0x01, 0x45, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xfd,
+ 0x01, 0x10, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00,
+ 0x01, 0x01, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xa0, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf6, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf9,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xf7, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf5, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x05,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x90, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xe7, 0x04, 0x77, 0x01, 0x79, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x10, 0x08, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xe3, 0x09, 0x00,
+ 0x01, 0x1f, 0x08, 0xff, 0x01, 0xfa, 0x01, 0x10, 0x09, 0x00, 0x01, 0x1d,
+ 0x07, 0xdd, 0x01, 0xb7, 0x01, 0x20, 0xd1, 0x00,
+
+ /* 3 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf4, 0x09, 0x00, 0x01, 0x1f,
+ 0x09, 0xff, 0x01, 0xf4, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf4,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd5, 0x07, 0x55, 0x01, 0x51,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1e,
+ 0x01, 0xee, 0x01, 0xb0, 0xd8, 0x00,
+
+ /* 4 */
+ 0xb8, 0x00, 0x01, 0x08, 0x09, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08,
+ 0x09, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08, 0x09, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfa, 0x05, 0x66, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf5, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf5,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xf4, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf3, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf2,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xf0, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xf0, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0xa0, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x70, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0x30,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x08, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xfe, 0x06, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x08, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf1,
+ 0x06, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x05, 0x00, 0x01, 0x02,
+ 0x01, 0x22, 0x01, 0x28, 0x02, 0xff, 0x01, 0xc7, 0x06, 0x77, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0x52, 0x01, 0x22, 0x04, 0x00, 0x01, 0x0f, 0x0f, 0xff,
+ 0x04, 0x00, 0x01, 0x0f, 0x0f, 0xff, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xed, 0x0b, 0xdd, 0x01, 0xef, 0x01, 0xff, 0x04, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x04, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x5f, 0x01, 0xff,
+ 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x5f,
+ 0x01, 0xff, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00,
+ 0x01, 0x5f, 0x01, 0xff, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x50,
+ 0x0b, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x04, 0x00, 0x01, 0x06, 0x01, 0x66,
+ 0x01, 0x20, 0x0b, 0x00, 0x01, 0x26, 0x01, 0x66, 0x54, 0x00,
+
+ /* 5 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x0a, 0xff, 0x09, 0x00, 0x01, 0x1f, 0x0a, 0xff,
+ 0x09, 0x00, 0x01, 0x1f, 0x0a, 0xff, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xd6, 0x07, 0x66, 0x01, 0x65, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc1, 0x07, 0x11, 0x01, 0x10, 0x09, 0x00,
+ 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf5, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff,
+ 0x01, 0xf5, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf5, 0x09, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd4, 0x07, 0x44, 0x01, 0x41, 0x09, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe7, 0x08, 0x77, 0x01, 0x50, 0x08, 0x00,
+ 0x01, 0x1f, 0x0a, 0xff, 0x01, 0xb0, 0x08, 0x00, 0x01, 0x1f, 0x0a, 0xff,
+ 0x01, 0xb0, 0x08, 0x00, 0x01, 0x1e, 0x0a, 0xee, 0x01, 0xa0, 0xcf, 0x00,
+
+ /* 6 */
+ 0xb5, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xf3, 0x04, 0x00, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xe1,
+ 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00,
+ 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x0a, 0x02, 0xff,
+ 0x01, 0x30, 0x03, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff, 0x01, 0xb0,
+ 0x03, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0xf5, 0x05, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf8,
+ 0x03, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x03,
+ 0x02, 0xff, 0x01, 0x80, 0x05, 0x00, 0x01, 0x05, 0x02, 0xff, 0x01, 0x50,
+ 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x1e,
+ 0x01, 0xff, 0x01, 0xfb, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xf2,
+ 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfd,
+ 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x07, 0x00, 0x01, 0x01, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0xb0, 0x01, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xf4, 0x09, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xf7, 0x01, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x02, 0x02, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x05, 0x02, 0xff,
+ 0x01, 0x40, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x1d, 0x01, 0xff,
+ 0x01, 0xfa, 0x0b, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xe2, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x90, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xc0, 0x0b, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfc, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x98,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10, 0x0c, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xf3, 0x0d, 0x00,
+ 0x01, 0x2e, 0x05, 0xff, 0x01, 0x60, 0x0d, 0x00, 0x01, 0x07, 0x04, 0xff,
+ 0x01, 0xfc, 0x0e, 0x00, 0x01, 0x2e, 0x05, 0xff, 0x01, 0x60, 0x0c, 0x00,
+ 0x01, 0x01, 0x01, 0xef, 0x01, 0xff, 0x01, 0xef, 0x01, 0xff, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xf4, 0x0c, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfd,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0x9a, 0x02, 0xff, 0x01, 0x30, 0x0b, 0x00,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0xe2, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0xe2, 0x0a, 0x00, 0x01, 0x09, 0x02, 0xff,
+ 0x01, 0x30, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x0d, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0x10, 0x09, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf4,
+ 0x01, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x01, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xc0, 0x08, 0x00, 0x01, 0x06, 0x02, 0xff, 0x01, 0x50,
+ 0x01, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xfb, 0x08, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xf7,
+ 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x04,
+ 0x02, 0xff, 0x01, 0x90, 0x06, 0x00, 0x01, 0x03, 0x02, 0xff, 0x01, 0x80,
+ 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0xf7, 0x06, 0x00, 0x01, 0x2e, 0x01, 0xff, 0x01, 0xfa,
+ 0x03, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x08,
+ 0x02, 0xff, 0x01, 0x50, 0x04, 0x00, 0x01, 0x01, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xb0, 0x03, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00,
+ 0x01, 0xaf, 0x01, 0xff, 0x01, 0xf4, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xfc, 0x04, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00,
+ 0x01, 0x0b, 0x02, 0xff, 0x01, 0x20, 0x03, 0x00, 0x01, 0xaf, 0x01, 0xff,
+ 0x01, 0xd1, 0x04, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90, 0x04, 0x00,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0xe1, 0x02, 0x00, 0x01, 0x08, 0x01, 0xff,
+ 0x01, 0xfe, 0x01, 0x20, 0x04, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x90,
+ 0x04, 0x00, 0x01, 0x2e, 0x01, 0xff, 0x01, 0xfd, 0x01, 0x10, 0x01, 0x00,
+ 0x01, 0x5d, 0x01, 0xdd, 0x01, 0xd3, 0x05, 0x00, 0x01, 0x3d, 0x01, 0xdd,
+ 0x01, 0x80, 0x04, 0x00, 0x01, 0x03, 0x02, 0xdd, 0x01, 0x90, 0xc9, 0x00,
+
+ /* 7 */
+ 0xa5, 0x00, 0x01, 0x45, 0x01, 0x67, 0x01, 0x65, 0x01, 0x20, 0x0e, 0x00,
+ 0x01, 0x06, 0x01, 0xcf, 0x03, 0xff, 0x01, 0xfe, 0x01, 0x92, 0x0c, 0x00,
+ 0x01, 0x04, 0x01, 0xef, 0x06, 0xff, 0x01, 0x90, 0x0b, 0x00, 0x01, 0x6f,
+ 0x02, 0xff, 0x01, 0xfd, 0x01, 0xcb, 0x01, 0xcf, 0x02, 0xff, 0x01, 0xfc,
+ 0x0a, 0x00, 0x01, 0x04, 0x02, 0xff, 0x01, 0xd6, 0x01, 0x10, 0x02, 0x00,
+ 0x01, 0x39, 0x02, 0xff, 0x01, 0xa0, 0x09, 0x00, 0x01, 0x0d, 0x01, 0xff,
+ 0x01, 0xf9, 0x05, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xf3, 0x09, 0x00,
+ 0x01, 0x4f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf9, 0x09, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xfe, 0x09, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x07, 0x00,
+ 0x01, 0xdf, 0x01, 0xff, 0x09, 0x00, 0x01, 0xac, 0x01, 0xcb, 0x07, 0x00,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x10, 0x10, 0x00, 0x01, 0x04, 0x02, 0xff,
+ 0x11, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xfc, 0x10, 0x00, 0x01, 0x01,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0xf5, 0x10, 0x00, 0x01, 0x5d, 0x02, 0xff,
+ 0x01, 0xa0, 0x0d, 0x00, 0x02, 0x99, 0x01, 0xbe, 0x02, 0xff, 0x01, 0xf8,
+ 0x0e, 0x00, 0x05, 0xff, 0x01, 0x40, 0x0e, 0x00, 0x05, 0xff, 0x01, 0xf9,
+ 0x0e, 0x00, 0x02, 0xbb, 0x01, 0xcd, 0x03, 0xff, 0x01, 0xd1, 0x10, 0x00,
+ 0x01, 0x16, 0x01, 0xef, 0x01, 0xff, 0x01, 0xfc, 0x11, 0x00, 0x01, 0x0a,
+ 0x02, 0xff, 0x01, 0x60, 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x07, 0x01, 0x99, 0x01, 0x80, 0x07, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xf0, 0x07, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf0,
+ 0x07, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf1, 0x07, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xf2, 0x07, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf1,
+ 0x07, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x07, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xe0, 0x07, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0x20,
+ 0x06, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xa0, 0x08, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0xd2, 0x05, 0x00, 0x01, 0x03, 0x02, 0xff, 0x01, 0x30,
+ 0x08, 0x00, 0x01, 0x1e, 0x02, 0xff, 0x01, 0x81, 0x03, 0x00, 0x01, 0x01,
+ 0x01, 0x8f, 0x01, 0xff, 0x01, 0xfa, 0x09, 0x00, 0x01, 0x03, 0x01, 0xef,
+ 0x02, 0xff, 0x01, 0xda, 0x01, 0x98, 0x01, 0x9a, 0x01, 0xdf, 0x02, 0xff,
+ 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x2d, 0x07, 0xff, 0x01, 0xfa, 0x0c, 0x00,
+ 0x01, 0x6d, 0x05, 0xff, 0x01, 0xfb, 0x01, 0x30, 0x0d, 0x00, 0x01, 0x27,
+ 0x01, 0x9b, 0x01, 0xcd, 0x01, 0xba, 0x01, 0x95, 0x01, 0x10, 0xbe, 0x00,
+
+ /* 8 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x07, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x06, 0x00, 0x01, 0x07, 0x02, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x06, 0x00, 0x01, 0x2f, 0x02, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x06, 0x00, 0x01, 0xcf,
+ 0x02, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x05, 0x00, 0x01, 0x06, 0x03, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x05, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xfa, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0x1e, 0x01, 0xff,
+ 0x01, 0xe1, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x60,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x03, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xfb, 0x01, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x03, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf2, 0x01, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x03, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x70, 0x01, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x02, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xfd, 0x02, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x02, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf3, 0x02, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x02, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x80, 0x02, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfd, 0x03, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x01, 0x01, 0xef, 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf5, 0x04, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0xb0, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x10, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x99, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x03, 0xff, 0x01, 0x20,
+ 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f,
+ 0x02, 0xff, 0x01, 0xf7, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x01, 0xd0, 0x06, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x01, 0x30,
+ 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1e,
+ 0x01, 0xee, 0x01, 0xe8, 0x07, 0x00, 0x01, 0x0e, 0x01, 0xee, 0x01, 0xa0,
+ 0xce, 0x00,
+
+ /* 9 */
+ 0x2c, 0x00, 0x01, 0x7f, 0x01, 0xf1, 0x03, 0x00, 0x01, 0x9f, 0x01, 0xe0,
+ 0x0d, 0x00, 0x01, 0x5f, 0x01, 0xf8, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xb0, 0x0d, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xb6, 0x01, 0x45,
+ 0x01, 0x9f, 0x01, 0xff, 0x01, 0x50, 0x0d, 0x00, 0x01, 0x05, 0x04, 0xff,
+ 0x01, 0xfb, 0x0f, 0x00, 0x01, 0x5e, 0x03, 0xff, 0x01, 0x90, 0x10, 0x00,
+ 0x01, 0x46, 0x01, 0x87, 0x01, 0x51, 0x20, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x07, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x06, 0x00, 0x01, 0x07, 0x02, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x06, 0x00,
+ 0x01, 0x2f, 0x02, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x06, 0x00, 0x01, 0xbf, 0x02, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0x06, 0x03, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x05, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xef, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0xaf, 0x01, 0xff,
+ 0x01, 0x4f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x04, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xfa, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x04, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xe1, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x04, 0x00,
+ 0x01, 0x9f, 0x01, 0xff, 0x01, 0x60, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x04,
+ 0x01, 0xff, 0x01, 0xfb, 0x01, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x0d,
+ 0x01, 0xff, 0x01, 0xf2, 0x01, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x70, 0x01, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xfd, 0x02, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf3, 0x02, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0x80, 0x02, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xfd, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x01, 0x01, 0xef,
+ 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x0a, 0x01, 0xff,
+ 0x01, 0xf5, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xb0,
+ 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x01, 0xef, 0x01, 0xff, 0x01, 0x10, 0x04, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x99, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xc0, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x03, 0xff, 0x01, 0x20, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x01, 0xf7, 0x06, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x02, 0xff,
+ 0x01, 0xd0, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x1f, 0x02, 0xff, 0x01, 0x30, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xe8, 0x07, 0x00,
+ 0x01, 0x0e, 0x01, 0xee, 0x01, 0xa0, 0xce, 0x00,
+
+ /* 10 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x1d,
+ 0x01, 0xff, 0x01, 0xfa, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x04, 0x00, 0x01, 0x01, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xa0, 0x09, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x04, 0x00, 0x01, 0x1d, 0x01, 0xff,
+ 0x01, 0xf9, 0x0a, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x03, 0x00,
+ 0x01, 0x01, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x90, 0x0a, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x2d, 0x01, 0xff, 0x01, 0xf9,
+ 0x0b, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x90, 0x0b, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x02, 0x00, 0x01, 0x2e, 0x01, 0xff, 0x01, 0xf8, 0x0c, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x01, 0x00, 0x01, 0x02, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x01, 0x00, 0x01, 0x2e, 0x01, 0xff, 0x01, 0xf8, 0x0d, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x01, 0x02, 0x01, 0xef, 0x01, 0xff, 0x01, 0x80,
+ 0x0d, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x01, 0x2e, 0x01, 0xff,
+ 0x01, 0xf7, 0x0e, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc3, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x70, 0x0e, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xee,
+ 0x01, 0xff, 0x01, 0xf7, 0x0f, 0x00, 0x01, 0x1f, 0x03, 0xff, 0x01, 0x70,
+ 0x0f, 0x00, 0x01, 0x1f, 0x03, 0xff, 0x01, 0x20, 0x0f, 0x00, 0x01, 0x1f,
+ 0x03, 0xff, 0x01, 0xe2, 0x0f, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xdd,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x0e, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc1, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xe2, 0x0e, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x01, 0x1d, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20,
+ 0x0d, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x01, 0x01, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0xe2, 0x0d, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x01, 0x00, 0x01, 0x1d, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x0c, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x01, 0x00, 0x01, 0x01, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0xe2, 0x0c, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x02, 0x00, 0x01, 0x1d, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x0b, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x01, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0xe2, 0x0b, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x03, 0x00, 0x01, 0x1d, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x30, 0x0a, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x02, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xe3, 0x0a, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x04, 0x00, 0x01, 0x2e, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x30, 0x09, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x04, 0x00, 0x01, 0x02, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xe3, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0x2e, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x30, 0x08, 0x00,
+ 0x01, 0x1e, 0x01, 0xee, 0x01, 0xb0, 0x05, 0x00, 0x01, 0x02, 0x01, 0xde,
+ 0x01, 0xee, 0x01, 0xd2, 0xcf, 0x00,
+
+ /* 11 */
+ 0xb6, 0x00, 0x01, 0x08, 0x09, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08,
+ 0x09, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08, 0x09, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfa, 0x05, 0x66, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf5, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf4,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xf4, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf3, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf1,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf0, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xe0, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x60, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x20,
+ 0x05, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x08, 0x00, 0x01, 0x01,
+ 0x01, 0xff, 0x01, 0xfe, 0x06, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x08, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf9, 0x06, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x30, 0x08, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf2,
+ 0x06, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x07, 0x00, 0x01, 0x1a,
+ 0x02, 0xff, 0x01, 0xa0, 0x06, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30,
+ 0x07, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10, 0x06, 0x00,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x07, 0x00, 0x01, 0x2f, 0x01, 0xff,
+ 0x01, 0xf4, 0x07, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x07, 0x00,
+ 0x01, 0x2f, 0x01, 0xfb, 0x01, 0x20, 0x07, 0x00, 0x01, 0xae, 0x01, 0xee,
+ 0x01, 0x30, 0x07, 0x00, 0x01, 0x03, 0x01, 0x10, 0xc6, 0x00,
+
+ /* 12 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x02, 0xee, 0x01, 0x70, 0x08, 0x00, 0x02, 0xee,
+ 0x01, 0xe7, 0x05, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x01, 0xc0, 0x07, 0x00,
+ 0x01, 0x05, 0x02, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x02, 0xff,
+ 0x01, 0xf2, 0x07, 0x00, 0x01, 0x0b, 0x02, 0xff, 0x01, 0xf8, 0x05, 0x00,
+ 0x01, 0x1f, 0x02, 0xff, 0x01, 0xf7, 0x07, 0x00, 0x01, 0x1f, 0x02, 0xff,
+ 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x01, 0xfd, 0x07, 0x00,
+ 0x01, 0x6f, 0x02, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xcf, 0x01, 0xff, 0x01, 0x30, 0x06, 0x00, 0x01, 0xbf, 0x01, 0xfc,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x9d,
+ 0x01, 0xff, 0x01, 0x80, 0x05, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xf7,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x98,
+ 0x01, 0xff, 0x01, 0xe0, 0x05, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xe2,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x92,
+ 0x01, 0xff, 0x01, 0xf3, 0x05, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0x92,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0xdf, 0x01, 0xf9, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x42,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x7f, 0x01, 0xfe, 0x05, 0x00, 0x01, 0x6f, 0x01, 0xfe, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x2f, 0x01, 0xff, 0x01, 0x40, 0x04, 0x00, 0x01, 0xcf, 0x01, 0xf9,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x0c, 0x01, 0xff, 0x01, 0x90, 0x03, 0x00, 0x01, 0x01,
+ 0x01, 0xff, 0x01, 0xf3, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x07, 0x01, 0xff, 0x01, 0xe0,
+ 0x03, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xe0, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x01,
+ 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0x80,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x01, 0x00, 0x01, 0xcf, 0x01, 0xfa, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x30, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x6f, 0x01, 0xff,
+ 0x03, 0x00, 0x01, 0x7f, 0x01, 0xfd, 0x01, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0x50, 0x02, 0x00, 0x01, 0xcf, 0x01, 0xf8,
+ 0x01, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xa0,
+ 0x01, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf3, 0x01, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x01, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xd0, 0x01, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0xff,
+ 0x01, 0xf6, 0x01, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0x80, 0x01, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0x90, 0x02, 0x00, 0x01, 0xaf, 0x01, 0xfb, 0x01, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x20, 0x01, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x5f,
+ 0x01, 0xff, 0x01, 0x10, 0x01, 0x7f, 0x01, 0xfd, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x02, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x60, 0x01, 0xdf, 0x01, 0xf7,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xc2,
+ 0x01, 0xff, 0x01, 0xf2, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00, 0x01, 0x04,
+ 0x01, 0xff, 0x01, 0xfa, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x03, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0x70, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x03, 0x00, 0x01, 0x9f, 0x02, 0xff, 0x01, 0x20, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x03, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xfc, 0x03, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x05, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0x80,
+ 0x03, 0x00, 0x01, 0x0d, 0x01, 0xee, 0x01, 0xe6, 0x03, 0x00, 0x01, 0x02,
+ 0x01, 0xee, 0x01, 0xe7, 0xcc, 0x00,
+
+ /* 13 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x0b, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x0b, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x0b, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd4,
+ 0x07, 0x44, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1e,
+ 0x01, 0xee, 0x01, 0xb0, 0x07, 0x00, 0x01, 0x8e, 0x01, 0xee, 0x01, 0x40,
+ 0xce, 0x00,
+
+ /* 14 */
+ 0xa6, 0x00, 0x01, 0x13, 0x01, 0x56, 0x01, 0x64, 0x01, 0x31, 0x0e, 0x00,
+ 0x01, 0x02, 0x01, 0x8d, 0x04, 0xff, 0x01, 0xc7, 0x01, 0x10, 0x0b, 0x00,
+ 0x01, 0x01, 0x01, 0x9f, 0x06, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x3e,
+ 0x08, 0xff, 0x01, 0xd2, 0x09, 0x00, 0x01, 0x04, 0x02, 0xff, 0x01, 0xfc,
+ 0x01, 0x72, 0x01, 0x00, 0x01, 0x01, 0x01, 0x38, 0x01, 0xdf, 0x02, 0xff,
+ 0x01, 0x30, 0x08, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x50,
+ 0x04, 0x00, 0x01, 0x07, 0x02, 0xff, 0x01, 0xe2, 0x07, 0x00, 0x01, 0x01,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0xd1, 0x06, 0x00, 0x01, 0x2e, 0x01, 0xff,
+ 0x01, 0xfd, 0x07, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10,
+ 0x06, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x60, 0x06, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xf4, 0x08, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xe0,
+ 0x06, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xa0, 0x08, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf5, 0x06, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x30,
+ 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xfb, 0x05, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xfd, 0x0a, 0x00, 0x02, 0xff, 0x05, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf9, 0x0a, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x30,
+ 0x04, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf5, 0x0a, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x04, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf4,
+ 0x0a, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x70, 0x04, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xf2, 0x0a, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x80,
+ 0x04, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf2, 0x0a, 0x00, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf3,
+ 0x0a, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x80, 0x04, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf4, 0x0a, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x60,
+ 0x04, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf7, 0x0a, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x50, 0x04, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xfb,
+ 0x0a, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x10, 0x05, 0x00, 0x02, 0xff,
+ 0x01, 0x10, 0x08, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfd, 0x06, 0x00,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0x70, 0x08, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf8, 0x06, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xe1, 0x08, 0x00,
+ 0x01, 0x2f, 0x01, 0xff, 0x01, 0xf1, 0x06, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xfa, 0x08, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xa0, 0x06, 0x00,
+ 0x01, 0x04, 0x02, 0xff, 0x01, 0x80, 0x06, 0x00, 0x01, 0x0a, 0x01, 0xff,
+ 0x01, 0xfe, 0x01, 0x10, 0x07, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0x01, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xf5, 0x08, 0x00,
+ 0x01, 0x0b, 0x02, 0xff, 0x01, 0xe6, 0x01, 0x10, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0x8f, 0x02, 0xff, 0x01, 0x80, 0x09, 0x00, 0x01, 0xaf, 0x02, 0xff,
+ 0x01, 0xfc, 0x01, 0xa8, 0x01, 0x8a, 0x01, 0xdf, 0x02, 0xff, 0x01, 0xf6,
+ 0x0a, 0x00, 0x01, 0x06, 0x01, 0xef, 0x06, 0xff, 0x01, 0xfd, 0x01, 0x40,
+ 0x0b, 0x00, 0x01, 0x18, 0x01, 0xef, 0x04, 0xff, 0x01, 0xfd, 0x01, 0x60,
+ 0x0d, 0x00, 0x01, 0x03, 0x01, 0x7a, 0x01, 0xcd, 0x01, 0xdc, 0x01, 0xa7,
+ 0x01, 0x30, 0xbd, 0x00,
+
+ /* 15 */
+ 0xb5, 0x00, 0x01, 0x1f, 0x0b, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x0b, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x0b, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe6, 0x07, 0x66, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1e,
+ 0x01, 0xee, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9e, 0x01, 0xee, 0x01, 0x40,
+ 0xce, 0x00,
+
+ /* 16 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x06, 0xee, 0x01, 0xec, 0x01, 0x95, 0x0b, 0x00,
+ 0x01, 0x1f, 0x08, 0xff, 0x01, 0xe5, 0x0a, 0x00, 0x01, 0x1f, 0x09, 0xff,
+ 0x01, 0x80, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd6, 0x03, 0x66,
+ 0x01, 0x67, 0x01, 0x9d, 0x02, 0xff, 0x01, 0xf5, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x4e, 0x01, 0xff, 0x01, 0xfe,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x03,
+ 0x02, 0xff, 0x01, 0x50, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x90, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xb0,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xc0, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xa0,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x70, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0x1b, 0x02, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc1, 0x03, 0x11, 0x01, 0x12, 0x01, 0x48, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xf9, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xc0,
+ 0x09, 0x00, 0x01, 0x1f, 0x08, 0xff, 0x01, 0xfb, 0x01, 0x10, 0x09, 0x00,
+ 0x01, 0x1f, 0x07, 0xff, 0x01, 0xfb, 0x01, 0x40, 0x0a, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd4, 0x04, 0x44, 0x01, 0x32, 0x0c, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xb0, 0xd8, 0x00,
+
+ /* 17 */
+ 0xa6, 0x00, 0x01, 0x35, 0x01, 0x66, 0x01, 0x54, 0x01, 0x10, 0x0e, 0x00,
+ 0x01, 0x06, 0x01, 0xcf, 0x03, 0xff, 0x01, 0xfd, 0x01, 0x71, 0x0c, 0x00,
+ 0x01, 0x05, 0x01, 0xef, 0x06, 0xff, 0x01, 0x60, 0x0b, 0x00, 0x01, 0xaf,
+ 0x07, 0xff, 0x01, 0xf8, 0x0a, 0x00, 0x01, 0x0a, 0x02, 0xff, 0x01, 0xd7,
+ 0x01, 0x20, 0x01, 0x00, 0x01, 0x03, 0x01, 0x9f, 0x02, 0xff, 0x01, 0x70,
+ 0x09, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x01,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0xf2, 0x08, 0x00, 0x01, 0x02, 0x02, 0xff,
+ 0x01, 0x60, 0x05, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfa, 0x08, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0x02, 0x02, 0xff,
+ 0x01, 0x10, 0x07, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00,
+ 0x01, 0xaf, 0x01, 0xff, 0x01, 0x60, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff,
+ 0x01, 0x60, 0x07, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x10, 0x07, 0x00, 0x01, 0x05, 0x01, 0x55,
+ 0x01, 0x40, 0x06, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xfb, 0x11, 0x00,
+ 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x11, 0x00, 0x01, 0x08, 0x01, 0xff,
+ 0x01, 0xf5, 0x11, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf3, 0x11, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf2, 0x11, 0x00, 0x01, 0x0b, 0x01, 0xff,
+ 0x01, 0xf2, 0x11, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf3, 0x11, 0x00,
+ 0x01, 0x09, 0x01, 0xff, 0x01, 0xf4, 0x11, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf6, 0x11, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xfa, 0x08, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x01, 0x01, 0xff,
+ 0x01, 0xfe, 0x08, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf3, 0x07, 0x00,
+ 0x01, 0xcf, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xf0, 0x07, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xb0, 0x07, 0x00,
+ 0x01, 0x7f, 0x01, 0xff, 0x01, 0xb0, 0x07, 0x00, 0x01, 0x1e, 0x01, 0xff,
+ 0x01, 0xf5, 0x07, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0x60, 0x07, 0x00,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x05, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10, 0x08, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xe3, 0x05, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xf7, 0x09, 0x00,
+ 0x01, 0x3f, 0x02, 0xff, 0x01, 0x92, 0x03, 0x00, 0x01, 0x29, 0x02, 0xff,
+ 0x01, 0xc0, 0x09, 0x00, 0x01, 0x04, 0x03, 0xff, 0x01, 0xda, 0x01, 0x88,
+ 0x01, 0x9c, 0x02, 0xff, 0x01, 0xfe, 0x01, 0x10, 0x0a, 0x00, 0x01, 0x3d,
+ 0x07, 0xff, 0x01, 0xc1, 0x0c, 0x00, 0x01, 0x7e, 0x05, 0xff, 0x01, 0xd6,
+ 0x0e, 0x00, 0x01, 0x37, 0x01, 0xac, 0x01, 0xdd, 0x01, 0xca, 0x01, 0x73,
+ 0xbe, 0x00,
+
+ /* 18 */
+ 0xb4, 0x00, 0x01, 0x2f, 0x0b, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x2f,
+ 0x0b, 0xff, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x2f, 0x0b, 0xff, 0x01, 0xa0,
+ 0x07, 0x00, 0x01, 0x16, 0x04, 0x66, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xd6,
+ 0x04, 0x66, 0x01, 0x40, 0x0c, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x2e, 0x01, 0xee, 0x01, 0xa0, 0xd4, 0x00,
+
+ /* 19 */
+ 0xb4, 0x00, 0x01, 0x8e, 0x01, 0xee, 0x01, 0xe2, 0x07, 0x00, 0x01, 0xde,
+ 0x01, 0xee, 0x01, 0xa0, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xfa,
+ 0x06, 0x00, 0x01, 0x06, 0x02, 0xff, 0x01, 0x30, 0x07, 0x00, 0x01, 0x08,
+ 0x02, 0xff, 0x01, 0x20, 0x05, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xfa,
+ 0x08, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0xf2, 0x09, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf2,
+ 0x05, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xa0, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x06, 0x02, 0xff, 0x01, 0x20,
+ 0x09, 0x00, 0x01, 0x08, 0x02, 0xff, 0x01, 0x20, 0x03, 0x00, 0x01, 0x0d,
+ 0x01, 0xff, 0x01, 0xfa, 0x0a, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0x90, 0x03, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00,
+ 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf2, 0x03, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0x90, 0x0b, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x05, 0x02, 0xff, 0x01, 0x20, 0x0b, 0x00, 0x01, 0x07, 0x02, 0xff,
+ 0x01, 0x20, 0x01, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf9, 0x0d, 0x00,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x90, 0x01, 0x00, 0x01, 0x5f, 0x01, 0xff,
+ 0x01, 0xf1, 0x0d, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xf2, 0x01, 0x00,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0x80, 0x0d, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x01, 0xf9, 0x01, 0x05, 0x02, 0xff, 0x01, 0x10, 0x0d, 0x00, 0x01, 0x07,
+ 0x02, 0xff, 0x01, 0x2d, 0x01, 0xff, 0x01, 0xf8, 0x0f, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xf1, 0x0f, 0x00, 0x01, 0x7f,
+ 0x03, 0xff, 0x01, 0x80, 0x0f, 0x00, 0x01, 0x0e, 0x02, 0xff, 0x01, 0xfe,
+ 0x01, 0x10, 0x0f, 0x00, 0x01, 0x06, 0x02, 0xff, 0x01, 0xf7, 0x11, 0x00,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0xe0, 0x10, 0x00, 0x01, 0x01, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x70, 0x10, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfe,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xf6, 0x11, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0xe0, 0x10, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x60,
+ 0x10, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfe, 0x11, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xf6, 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xd0,
+ 0x10, 0x00, 0x01, 0x05, 0x02, 0xff, 0x01, 0x50, 0x10, 0x00, 0x01, 0x0c,
+ 0x01, 0xee, 0x01, 0xec, 0xd7, 0x00,
+
+ /* 20 */
+ 0xbb, 0x00, 0x01, 0x0b, 0x01, 0xee, 0x01, 0xe2, 0x11, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf2, 0x11, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf2,
+ 0x10, 0x00, 0x01, 0x01, 0x01, 0x2d, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x10,
+ 0x0d, 0x00, 0x01, 0x48, 0x01, 0xce, 0x05, 0xff, 0x01, 0xfd, 0x01, 0x96,
+ 0x01, 0x10, 0x09, 0x00, 0x01, 0x7d, 0x09, 0xff, 0x01, 0xfa, 0x01, 0x20,
+ 0x07, 0x00, 0x01, 0x2d, 0x0b, 0xff, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x03,
+ 0x01, 0xef, 0x02, 0xff, 0x01, 0xfb, 0x01, 0x75, 0x01, 0x4d, 0x01, 0xff,
+ 0x01, 0xf6, 0x01, 0x56, 0x01, 0x9d, 0x03, 0xff, 0x01, 0x80, 0x05, 0x00,
+ 0x01, 0x1e, 0x02, 0xff, 0x01, 0xe6, 0x02, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x02, 0x00, 0x01, 0x3b, 0x02, 0xff, 0x01, 0xf5, 0x05, 0x00,
+ 0x01, 0x8f, 0x01, 0xff, 0x01, 0xfb, 0x01, 0x10, 0x02, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf2, 0x03, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xfe,
+ 0x05, 0x00, 0x02, 0xff, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x03, 0x00, 0x01, 0x07, 0x02, 0xff, 0x01, 0x50, 0x03, 0x00,
+ 0x01, 0x05, 0x02, 0xff, 0x01, 0x20, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xb0, 0x03, 0x00,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xfc, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xe0, 0x03, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xf0, 0x03, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xf1, 0x03, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xf1, 0x03, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xf0, 0x03, 0x00,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xfc, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xe0, 0x03, 0x00,
+ 0x01, 0x05, 0x02, 0xff, 0x01, 0x30, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xb0, 0x04, 0x00,
+ 0x02, 0xff, 0x01, 0xd1, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf2,
+ 0x03, 0x00, 0x01, 0x08, 0x02, 0xff, 0x01, 0x60, 0x04, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0xfc, 0x01, 0x10, 0x02, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf2, 0x03, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xfe, 0x05, 0x00,
+ 0x01, 0x1e, 0x02, 0xff, 0x01, 0xf7, 0x01, 0x10, 0x01, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf2, 0x02, 0x00, 0x01, 0x4c, 0x02, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0x04, 0x03, 0xff, 0x01, 0xfb, 0x01, 0x86, 0x01, 0x5d,
+ 0x01, 0xff, 0x01, 0xf6, 0x01, 0x67, 0x01, 0xae, 0x03, 0xff, 0x01, 0xa0,
+ 0x06, 0x00, 0x01, 0x4e, 0x0b, 0xff, 0x01, 0xf8, 0x07, 0x00, 0x01, 0x01,
+ 0x01, 0x8e, 0x09, 0xff, 0x01, 0xfb, 0x01, 0x30, 0x09, 0x00, 0x01, 0x48,
+ 0x01, 0xbe, 0x05, 0xff, 0x01, 0xed, 0x01, 0xa6, 0x01, 0x10, 0x0d, 0x00,
+ 0x01, 0x1c, 0x01, 0xff, 0x01, 0xf3, 0x01, 0x10, 0x10, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf2, 0x11, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf2,
+ 0x11, 0x00, 0x01, 0x0b, 0x01, 0xee, 0x01, 0xe2, 0xd2, 0x00,
+
+ /* 21 */
+ 0xb4, 0x00, 0x01, 0x0b, 0x01, 0xee, 0x01, 0xec, 0x07, 0x00, 0x01, 0x2e,
+ 0x01, 0xee, 0x01, 0xe7, 0x07, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x80,
+ 0x06, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xc0, 0x08, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0xf3, 0x05, 0x00, 0x01, 0x06, 0x02, 0xff, 0x01, 0x20,
+ 0x08, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfd, 0x05, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xf6, 0x09, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0x80, 0x04, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xb0, 0x0a, 0x00,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0xf3, 0x03, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xfe, 0x01, 0x10, 0x0a, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xfd,
+ 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xf5, 0x0b, 0x00, 0x01, 0x01,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x80, 0x02, 0x00, 0x01, 0xbf, 0x01, 0xff,
+ 0x01, 0x90, 0x0c, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xf3, 0x01, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xfd, 0x0d, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xf3, 0x0e, 0x00,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0x80, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x70,
+ 0x0e, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf9, 0x01, 0xff, 0x01, 0xfc,
+ 0x0f, 0x00, 0x01, 0x08, 0x03, 0xff, 0x01, 0xf2, 0x10, 0x00, 0x01, 0xcf,
+ 0x02, 0xff, 0x01, 0x50, 0x10, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xfc,
+ 0x11, 0x00, 0x01, 0xaf, 0x02, 0xff, 0x01, 0x30, 0x0f, 0x00, 0x01, 0x05,
+ 0x03, 0xff, 0x01, 0xd0, 0x0f, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xfd,
+ 0x01, 0xff, 0x01, 0xf9, 0x0f, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x91,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x50, 0x0d, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xe1, 0x0d, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf3, 0x01, 0x00, 0x01, 0x0b, 0x01, 0xff,
+ 0x01, 0xfb, 0x0d, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x80, 0x01, 0x00,
+ 0x01, 0x01, 0x02, 0xff, 0x01, 0x60, 0x0b, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xfd, 0x03, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00,
+ 0x01, 0x4f, 0x01, 0xff, 0x01, 0xf3, 0x03, 0x00, 0x01, 0x0b, 0x01, 0xff,
+ 0x01, 0xfc, 0x0a, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff, 0x01, 0x80,
+ 0x03, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0x80, 0x09, 0x00, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xfd, 0x05, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xf4,
+ 0x09, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xf3, 0x05, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10, 0x07, 0x00, 0x01, 0x02, 0x02, 0xff,
+ 0x01, 0x80, 0x05, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0xa0, 0x07, 0x00,
+ 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfd, 0x07, 0x00, 0x01, 0x6f, 0x01, 0xff,
+ 0x01, 0xf5, 0x07, 0x00, 0x01, 0x6e, 0x01, 0xee, 0x01, 0xe3, 0x07, 0x00,
+ 0x01, 0x0b, 0x01, 0xee, 0x01, 0xed, 0x01, 0x10, 0xce, 0x00,
+
+ /* 22 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xc0, 0x07, 0x00, 0x01, 0x9e,
+ 0x01, 0xee, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40,
+ 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x07, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xe6, 0x07, 0x66, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x51,
+ 0x01, 0x10, 0x06, 0x00, 0x01, 0x1f, 0x0c, 0xff, 0x01, 0xf1, 0x06, 0x00,
+ 0x01, 0x1f, 0x0c, 0xff, 0x01, 0xf1, 0x06, 0x00, 0x01, 0x1f, 0x0c, 0xff,
+ 0x01, 0xf1, 0x11, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf1, 0x11, 0x00,
+ 0x01, 0x03, 0x01, 0xff, 0x01, 0xf1, 0x11, 0x00, 0x01, 0x03, 0x01, 0xff,
+ 0x01, 0xf1, 0x11, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf1, 0x11, 0x00,
+ 0x01, 0x03, 0x01, 0xff, 0x01, 0xf1, 0x11, 0x00, 0x01, 0x01, 0x01, 0x77,
+ 0x01, 0x70, 0x55, 0x00,
+
+ /* 23 */
+ 0xb4, 0x00, 0x01, 0x04, 0x01, 0xee, 0x01, 0xe8, 0x06, 0x00, 0x01, 0xbe,
+ 0x01, 0xee, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8,
+ 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8,
+ 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8,
+ 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf8,
+ 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x08, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x08, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xfa,
+ 0x06, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x09, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x40, 0x05, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x09, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xfd, 0x01, 0xba, 0x04, 0xaa,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0x10, 0x09, 0x00, 0x01, 0x0b, 0x09, 0xff,
+ 0x01, 0x10, 0x0a, 0x00, 0x01, 0x8f, 0x08, 0xff, 0x01, 0x10, 0x0a, 0x00,
+ 0x01, 0x01, 0x01, 0x69, 0x05, 0xaa, 0x01, 0xef, 0x01, 0xff, 0x01, 0x10,
+ 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10,
+ 0x11, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x10, 0x11, 0x00, 0x01, 0xbe,
+ 0x01, 0xee, 0x01, 0x10, 0xd0, 0x00,
+
+ /* 24 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x1e,
+ 0x01, 0xee, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe6, 0x03, 0x66, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0xe6, 0x03, 0x66, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x0d, 0xff, 0x01, 0xd0, 0x05, 0x00, 0x01, 0x1f,
+ 0x0d, 0xff, 0x01, 0xd0, 0x05, 0x00, 0x01, 0x1f, 0x0d, 0xff, 0x01, 0xc0,
+ 0xcc, 0x00,
+
+ /* 25 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x1e,
+ 0x01, 0xee, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe6, 0x03, 0x66, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0xe6, 0x03, 0x66, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xd1,
+ 0x01, 0x10, 0x04, 0x00, 0x01, 0x1f, 0x0e, 0xff, 0x01, 0xfa, 0x04, 0x00,
+ 0x01, 0x1f, 0x0e, 0xff, 0x01, 0xfa, 0x04, 0x00, 0x01, 0x1f, 0x0e, 0xff,
+ 0x01, 0xfa, 0x12, 0x00, 0x01, 0xbf, 0x01, 0xfa, 0x12, 0x00, 0x01, 0xbf,
+ 0x01, 0xfa, 0x12, 0x00, 0x01, 0xbf, 0x01, 0xfa, 0x12, 0x00, 0x01, 0xbf,
+ 0x01, 0xfa, 0x12, 0x00, 0x01, 0xbf, 0x01, 0xfa, 0x12, 0x00, 0x01, 0x57,
+ 0x01, 0x74, 0x53, 0x00,
+
+ /* 26 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe8,
+ 0x03, 0x88, 0x01, 0x76, 0x01, 0x53, 0x0c, 0x00, 0x01, 0x1f, 0x07, 0xff,
+ 0x01, 0xfb, 0x01, 0x50, 0x0a, 0x00, 0x01, 0x1f, 0x08, 0xff, 0x01, 0xfd,
+ 0x01, 0x30, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xfc, 0x03, 0xcc,
+ 0x01, 0xcd, 0x01, 0xef, 0x02, 0xff, 0x01, 0xf5, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x04, 0x00, 0x01, 0x01, 0x01, 0x7e, 0x02, 0xff,
+ 0x01, 0x20, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00,
+ 0x01, 0x02, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xb0, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xf6, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf8, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xf9,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf8, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x06, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf2,
+ 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0xc0, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x05, 0x00, 0x01, 0x1a, 0x02, 0xff, 0x01, 0x40, 0x08, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd6, 0x04, 0x66, 0x01, 0x7b, 0x02, 0xff, 0x01, 0xf9,
+ 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xa0, 0x09, 0x00, 0x01, 0x1f,
+ 0x08, 0xff, 0x01, 0xe6, 0x0a, 0x00, 0x01, 0x1e, 0x06, 0xee, 0x01, 0xed,
+ 0x01, 0xa5, 0xd2, 0x00,
+
+ /* 27 */
+ 0xb5, 0x00, 0x01, 0x1e, 0x01, 0xee, 0x01, 0xb0, 0x0a, 0x00, 0x01, 0x3e,
+ 0x01, 0xee, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xe8, 0x03, 0x88, 0x01, 0x76, 0x01, 0x52, 0x05, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x07, 0xff,
+ 0x01, 0xfb, 0x01, 0x50, 0x03, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0,
+ 0x04, 0x00, 0x01, 0x1f, 0x08, 0xff, 0x01, 0xfd, 0x01, 0x30, 0x02, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xfd, 0x04, 0xdd, 0x01, 0xef, 0x02, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x04, 0x00, 0x01, 0x01, 0x01, 0x7e, 0x02, 0xff, 0x01, 0x20,
+ 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x02, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xb0, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x3f, 0x01, 0xff,
+ 0x01, 0xf1, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x0b, 0x01, 0xff,
+ 0x01, 0xf6, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf8, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x04, 0x01, 0xff,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x05, 0x01, 0xff,
+ 0x01, 0xf8, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf6, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x01, 0xf2, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x06, 0x00, 0x01, 0xaf, 0x01, 0xff,
+ 0x01, 0xc0, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x1a, 0x02, 0xff,
+ 0x01, 0x40, 0x01, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd6, 0x04, 0x66, 0x01, 0x7a, 0x02, 0xff,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00,
+ 0x01, 0x1f, 0x09, 0xff, 0x01, 0xa0, 0x02, 0x00, 0x01, 0x3f, 0x01, 0xff,
+ 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1f, 0x08, 0xff, 0x01, 0xe6, 0x03, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x1e, 0x06, 0xee,
+ 0x01, 0xed, 0x01, 0xa5, 0x04, 0x00, 0x01, 0x3e, 0x01, 0xee, 0x01, 0xa0,
+ 0xcb, 0x00,
+
+ /* 28 */
+ 0xb4, 0x00, 0x01, 0x2e, 0x06, 0xee, 0x01, 0x50, 0x0c, 0x00, 0x01, 0x2f,
+ 0x06, 0xff, 0x01, 0x50, 0x0c, 0x00, 0x01, 0x2f, 0x06, 0xff, 0x01, 0x50,
+ 0x0c, 0x00, 0x01, 0x17, 0x04, 0x77, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x50,
+ 0x11, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x11, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x11, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50,
+ 0x11, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x11, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x11, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50,
+ 0x11, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x11, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0xb8, 0x03, 0x88, 0x01, 0x76, 0x01, 0x41, 0x0c, 0x00,
+ 0x01, 0x8f, 0x07, 0xff, 0x01, 0xe8, 0x01, 0x20, 0x0a, 0x00, 0x01, 0x8f,
+ 0x08, 0xff, 0x01, 0xf9, 0x0a, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xed,
+ 0x04, 0xdd, 0x03, 0xff, 0x01, 0xc0, 0x09, 0x00, 0x01, 0x8f, 0x01, 0xff,
+ 0x01, 0x50, 0x04, 0x00, 0x01, 0x03, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xfb,
+ 0x09, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x05, 0x00, 0x01, 0x07,
+ 0x02, 0xff, 0x01, 0x40, 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50,
+ 0x06, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xa0, 0x08, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x06, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xe0,
+ 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x06, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50,
+ 0x06, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x06, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x06, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50,
+ 0x06, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xb0, 0x08, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x05, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x50,
+ 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x05, 0x00, 0x01, 0x4e,
+ 0x01, 0xff, 0x01, 0xfd, 0x09, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x96,
+ 0x04, 0x66, 0x01, 0x8d, 0x02, 0xff, 0x01, 0xf3, 0x09, 0x00, 0x01, 0x8f,
+ 0x08, 0xff, 0x01, 0xfe, 0x01, 0x40, 0x09, 0x00, 0x01, 0x8f, 0x08, 0xff,
+ 0x01, 0xb2, 0x0a, 0x00, 0x01, 0x7e, 0x06, 0xee, 0x01, 0xec, 0x01, 0x83,
+ 0xce, 0x00,
+
+ /* 29 */
+ 0xa5, 0x00, 0x01, 0x14, 0x01, 0x56, 0x01, 0x54, 0x01, 0x20, 0x0e, 0x00,
+ 0x01, 0x02, 0x01, 0x8e, 0x03, 0xff, 0x01, 0xfe, 0x01, 0xa4, 0x0d, 0x00,
+ 0x01, 0x8f, 0x06, 0xff, 0x01, 0xc2, 0x0b, 0x00, 0x01, 0x0c, 0x08, 0xff,
+ 0x01, 0x50, 0x0a, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xfd, 0x01, 0x73,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0x49, 0x02, 0xff, 0x01, 0xf6, 0x09, 0x00,
+ 0x01, 0x05, 0x02, 0xff, 0x01, 0x80, 0x04, 0x00, 0x01, 0x2c, 0x02, 0xff,
+ 0x01, 0x30, 0x08, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf8, 0x06, 0x00,
+ 0x01, 0xaf, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0x5f, 0x01, 0xff,
+ 0x01, 0xd0, 0x06, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf6, 0x08, 0x00,
+ 0x01, 0xaf, 0x01, 0xff, 0x01, 0x60, 0x06, 0x00, 0x01, 0x03, 0x01, 0xff,
+ 0x01, 0xfe, 0x08, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0x10, 0x07, 0x00,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0x40, 0x07, 0x00, 0x01, 0x55, 0x01, 0x54,
+ 0x08, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x90, 0x11, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf1,
+ 0x11, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf4, 0x0a, 0x00, 0x01, 0xbf,
+ 0x08, 0xff, 0x01, 0xf5, 0x0a, 0x00, 0x01, 0xbf, 0x08, 0xff, 0x01, 0xf6,
+ 0x0a, 0x00, 0x01, 0xbf, 0x08, 0xff, 0x01, 0xf7, 0x0a, 0x00, 0x01, 0x35,
+ 0x06, 0x55, 0x01, 0x5a, 0x01, 0xff, 0x01, 0xf6, 0x11, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xf5, 0x11, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf3,
+ 0x06, 0x00, 0x01, 0x09, 0x01, 0xee, 0x01, 0xe5, 0x08, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf0, 0x06, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf8,
+ 0x08, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xd0, 0x06, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xfd, 0x08, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x70,
+ 0x06, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0x20, 0x07, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x20, 0x07, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x90,
+ 0x06, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfb, 0x08, 0x00, 0x01, 0x5f,
+ 0x01, 0xff, 0x01, 0xf3, 0x06, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xf3,
+ 0x08, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x04, 0x00,
+ 0x01, 0x06, 0x02, 0xff, 0x01, 0xa0, 0x08, 0x00, 0x01, 0x03, 0x02, 0xff,
+ 0x01, 0xe6, 0x03, 0x00, 0x01, 0x03, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xfd,
+ 0x0a, 0x00, 0x01, 0x5f, 0x02, 0xff, 0x01, 0xfb, 0x01, 0x87, 0x01, 0x8a,
+ 0x01, 0xef, 0x02, 0xff, 0x01, 0xd1, 0x0a, 0x00, 0x01, 0x04, 0x01, 0xef,
+ 0x06, 0xff, 0x01, 0xfb, 0x01, 0x10, 0x0b, 0x00, 0x01, 0x19, 0x05, 0xff,
+ 0x01, 0xfc, 0x01, 0x50, 0x0d, 0x00, 0x01, 0x15, 0x01, 0x9b, 0x01, 0xde,
+ 0x01, 0xdc, 0x01, 0xa7, 0x01, 0x20, 0xbe, 0x00,
+
+ /* 30 */
+ 0xab, 0x00, 0x01, 0x13, 0x01, 0x56, 0x01, 0x54, 0x01, 0x20, 0x06, 0x00,
+ 0x01, 0x1e, 0x01, 0xee, 0x01, 0xb0, 0x05, 0x00, 0x01, 0x02, 0x01, 0x8d,
+ 0x03, 0xff, 0x01, 0xfe, 0x01, 0x93, 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x04, 0x00, 0x01, 0x01, 0x01, 0x9f, 0x06, 0xff, 0x01, 0xb2,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x04, 0x00, 0x01, 0x3e,
+ 0x08, 0xff, 0x01, 0x50, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0,
+ 0x03, 0x00, 0x01, 0x03, 0x02, 0xff, 0x01, 0xfc, 0x01, 0x62, 0x01, 0x00,
+ 0x01, 0x02, 0x01, 0x6b, 0x02, 0xff, 0x01, 0xf6, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x03, 0x00, 0x01, 0x1e, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x40, 0x04, 0x00, 0x01, 0x3d, 0x02, 0xff, 0x01, 0x30, 0x02, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xff,
+ 0x01, 0xd1, 0x05, 0x00, 0x01, 0x01, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xd0,
+ 0x02, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x04,
+ 0x02, 0xff, 0x01, 0x10, 0x06, 0x00, 0x01, 0x1e, 0x01, 0xff, 0x01, 0xf7,
+ 0x02, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf6, 0x07, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xfd,
+ 0x02, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xe0, 0x08, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x40,
+ 0x01, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0x80, 0x08, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x90,
+ 0x01, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x20, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x01, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x09, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf0, 0x01, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x01, 0x00, 0x01, 0x01, 0x01, 0xff,
+ 0x01, 0xfc, 0x09, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf3, 0x01, 0x00,
+ 0x01, 0x1f, 0x05, 0xff, 0x01, 0xfb, 0x09, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf4, 0x01, 0x00, 0x01, 0x1f, 0x05, 0xff, 0x01, 0xfa, 0x09, 0x00,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xf5, 0x01, 0x00, 0x01, 0x1f, 0x05, 0xff,
+ 0x01, 0xf9, 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf5, 0x01, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe5, 0x01, 0x55, 0x01, 0x57, 0x01, 0xff,
+ 0x01, 0xfa, 0x09, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x01, 0x00, 0x01, 0x01, 0x01, 0xff,
+ 0x01, 0xfb, 0x09, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf3, 0x01, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0xff, 0x01, 0xfd,
+ 0x09, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf1, 0x01, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x10,
+ 0x08, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xe0, 0x01, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x50,
+ 0x08, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xa0, 0x01, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xb0,
+ 0x08, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x50, 0x01, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf2,
+ 0x07, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xfe, 0x02, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfb,
+ 0x07, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf6, 0x02, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0x01, 0x02, 0xff, 0x01, 0x70,
+ 0x06, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xd0, 0x02, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xf7,
+ 0x05, 0x00, 0x01, 0x06, 0x02, 0xff, 0x01, 0x30, 0x02, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x09, 0x02, 0xff, 0x01, 0xc4,
+ 0x03, 0x00, 0x01, 0x03, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xf6, 0x03, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x04, 0x00, 0x01, 0x9f, 0x02, 0xff,
+ 0x01, 0xea, 0x01, 0x87, 0x01, 0x8a, 0x01, 0xef, 0x02, 0xff, 0x01, 0x50,
+ 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x04, 0x00, 0x01, 0x06,
+ 0x07, 0xff, 0x01, 0xd4, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0,
+ 0x05, 0x00, 0x01, 0x19, 0x05, 0xff, 0x01, 0xe7, 0x0e, 0x00, 0x01, 0x04,
+ 0x01, 0x9b, 0x01, 0xce, 0x01, 0xdc, 0x01, 0x95, 0xb9, 0x00,
+
+ /* 31 */
+ 0xb7, 0x00, 0x01, 0x04, 0x01, 0x9c, 0x01, 0xde, 0x06, 0xee, 0x01, 0xc0,
+ 0x09, 0x00, 0x01, 0x04, 0x01, 0xdf, 0x08, 0xff, 0x01, 0xd0, 0x09, 0x00,
+ 0x01, 0x6f, 0x09, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0x04, 0x02, 0xff,
+ 0x01, 0xfb, 0x01, 0x87, 0x04, 0x77, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xd0,
+ 0x08, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xfc, 0x01, 0x20, 0x05, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0x4f, 0x01, 0xff,
+ 0x01, 0xe1, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00,
+ 0x01, 0x9f, 0x01, 0xff, 0x01, 0x60, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xd0, 0x08, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x30, 0x06, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0xcf, 0x01, 0xff,
+ 0x01, 0x10, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00,
+ 0x01, 0xaf, 0x01, 0xff, 0x01, 0x20, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xd0, 0x08, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x50, 0x06, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xfa, 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xd0, 0x08, 0x00, 0x01, 0x02, 0x01, 0xef, 0x01, 0xff, 0x01, 0xe8,
+ 0x01, 0x54, 0x04, 0x44, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xd0, 0x09, 0x00,
+ 0x01, 0x4f, 0x09, 0xff, 0x01, 0xd0, 0x09, 0x00, 0x01, 0x03, 0x01, 0xdf,
+ 0x08, 0xff, 0x01, 0xd0, 0x0a, 0x00, 0x01, 0x05, 0x01, 0xae, 0x07, 0xff,
+ 0x01, 0xd0, 0x0c, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x32,
+ 0x01, 0x22, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xd0, 0x0c, 0x00, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0xe2, 0x02, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0,
+ 0x0b, 0x00, 0x01, 0x08, 0x02, 0xff, 0x01, 0x30, 0x02, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xd0, 0x0b, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xf5,
+ 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x0a, 0x00, 0x01, 0x04,
+ 0x02, 0xff, 0x01, 0x60, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0,
+ 0x0a, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xd0, 0x09, 0x00, 0x01, 0x02, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0x90, 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x09, 0x00,
+ 0x01, 0x1d, 0x01, 0xff, 0x01, 0xfb, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xd0, 0x09, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x08, 0x00, 0x01, 0x0b, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0x10, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0,
+ 0x08, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xe1, 0x06, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x07, 0x02, 0xff, 0x01, 0x20,
+ 0x06, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0, 0x07, 0x00, 0x01, 0x5f,
+ 0x01, 0xff, 0x01, 0xf4, 0x07, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xd0,
+ 0xcf, 0x00,
+
+ /* 32 */
+ 0xff, 0x00, 0x45, 0x00, 0x01, 0x01, 0x01, 0x11, 0x10, 0x00, 0x01, 0x02,
+ 0x01, 0x8d, 0x02, 0xff, 0x01, 0xfd, 0x01, 0x93, 0x0e, 0x00, 0x01, 0x9f,
+ 0x05, 0xff, 0x01, 0xb0, 0x0c, 0x00, 0x01, 0x0b, 0x06, 0xff, 0x01, 0xfb,
+ 0x0c, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xf8, 0x01, 0x42, 0x01, 0x12,
+ 0x01, 0x4a, 0x02, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0xcf, 0x01, 0xff,
+ 0x01, 0x30, 0x03, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x90, 0x0b, 0x00,
+ 0x01, 0xff, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xb0,
+ 0x0a, 0x00, 0x01, 0x02, 0x01, 0xdd, 0x01, 0xd5, 0x04, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xc0,
+ 0x11, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xc0, 0x0e, 0x00, 0x01, 0x02,
+ 0x01, 0x57, 0x01, 0xad, 0x02, 0xff, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x16,
+ 0x01, 0xad, 0x05, 0xff, 0x01, 0xc0, 0x0b, 0x00, 0x01, 0x09, 0x04, 0xff,
+ 0x01, 0xfe, 0x01, 0x9d, 0x01, 0xff, 0x01, 0xc0, 0x0b, 0x00, 0x01, 0xcf,
+ 0x02, 0xff, 0x01, 0xc9, 0x01, 0x64, 0x01, 0x10, 0x01, 0x0b, 0x01, 0xff,
+ 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x71,
+ 0x03, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xc0,
+ 0x0a, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x70,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xc0,
+ 0x0a, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf2, 0x03, 0x00, 0x01, 0x0a,
+ 0x02, 0xff, 0x01, 0xc0, 0x0a, 0x00, 0x01, 0x07, 0x02, 0xff, 0x01, 0x83,
+ 0x01, 0x12, 0x01, 0x48, 0x01, 0xef, 0x02, 0xff, 0x01, 0xf4, 0x0b, 0x00,
+ 0x01, 0xcf, 0x05, 0xff, 0x01, 0x76, 0x02, 0xff, 0x01, 0xf6, 0x0a, 0x00,
+ 0x01, 0x1b, 0x04, 0xff, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0xf6, 0x0b, 0x00, 0x01, 0x39, 0x01, 0xce, 0x01, 0xdc, 0x01, 0x94,
+ 0x02, 0x00, 0x01, 0x2a, 0x01, 0xde, 0x01, 0xb3, 0xbd, 0x00,
+
+ /* 33 */
+ 0x93, 0x00, 0x01, 0x03, 0x01, 0xcc, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xd0, 0x10, 0x00, 0x01, 0x26, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xa0, 0x0d, 0x00, 0x01, 0x02, 0x01, 0x69, 0x01, 0xbe, 0x03, 0xff,
+ 0x01, 0x40, 0x0c, 0x00, 0x01, 0x02, 0x01, 0xcf, 0x04, 0xff, 0x01, 0xf6,
+ 0x0d, 0x00, 0x01, 0x3f, 0x03, 0xff, 0x01, 0xfe, 0x01, 0xa6, 0x01, 0x10,
+ 0x0d, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xfc, 0x01, 0x85, 0x01, 0x10,
+ 0x0e, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6, 0x11, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x40, 0x11, 0x00, 0x01, 0x7f, 0x01, 0xf7, 0x02, 0x00,
+ 0x01, 0x10, 0x0f, 0x00, 0x01, 0xdf, 0x01, 0xe0, 0x01, 0x3a, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xfb, 0x01, 0x71, 0x0c, 0x00, 0x01, 0x01, 0x01, 0xff,
+ 0x01, 0x99, 0x04, 0xff, 0x01, 0xfe, 0x01, 0x60, 0x0b, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xdf, 0x05, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x08,
+ 0x02, 0xff, 0x01, 0xfe, 0x01, 0x72, 0x01, 0x11, 0x01, 0x5b, 0x02, 0xff,
+ 0x01, 0x50, 0x0a, 0x00, 0x01, 0x0b, 0x02, 0xff, 0x01, 0xc1, 0x03, 0x00,
+ 0x01, 0x7f, 0x01, 0xff, 0x01, 0xe1, 0x0a, 0x00, 0x01, 0x0d, 0x01, 0xff,
+ 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf7,
+ 0x0a, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xf6, 0x04, 0x00, 0x01, 0x01,
+ 0x01, 0xff, 0x01, 0xfd, 0x0a, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xf1,
+ 0x05, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x10, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x50,
+ 0x09, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x80,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80, 0x09, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x70, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80, 0x05, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x80, 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90,
+ 0x05, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x50,
+ 0x09, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf1, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x10, 0x09, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf8,
+ 0x04, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfd, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x20, 0x03, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf6,
+ 0x0b, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xe3, 0x03, 0x00, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0xd0, 0x0b, 0x00, 0x01, 0x0c, 0x02, 0xff, 0x01, 0xa6,
+ 0x01, 0x45, 0x01, 0x8e, 0x02, 0xff, 0x01, 0x30, 0x0b, 0x00, 0x01, 0x01,
+ 0x01, 0xcf, 0x05, 0xff, 0x01, 0xf5, 0x0d, 0x00, 0x01, 0x08, 0x04, 0xff,
+ 0x01, 0xfc, 0x01, 0x30, 0x0e, 0x00, 0x01, 0x16, 0x01, 0xac, 0x01, 0xed,
+ 0x01, 0xc8, 0x01, 0x30, 0xc0, 0x00,
+
+ /* 34 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x04, 0x77, 0x01, 0x63, 0x0e, 0x00,
+ 0x01, 0xef, 0x05, 0xff, 0x01, 0xd5, 0x0d, 0x00, 0x01, 0xef, 0x06, 0xff,
+ 0x01, 0x60, 0x0c, 0x00, 0x01, 0xef, 0x01, 0xfd, 0x02, 0x99, 0x01, 0xac,
+ 0x02, 0xff, 0x01, 0xf1, 0x0c, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00,
+ 0x01, 0x2d, 0x01, 0xff, 0x01, 0xf5, 0x0c, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x03, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf8, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x04, 0x00, 0x01, 0xff, 0x01, 0xf7, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x03, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x0c, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x2d, 0x01, 0xff, 0x01, 0xe0,
+ 0x0c, 0x00, 0x01, 0xef, 0x01, 0xfd, 0x02, 0x99, 0x01, 0xac, 0x02, 0xff,
+ 0x01, 0x40, 0x0c, 0x00, 0x01, 0xef, 0x05, 0xff, 0x01, 0xf3, 0x0d, 0x00,
+ 0x01, 0xef, 0x05, 0xff, 0x01, 0xfe, 0x01, 0x60, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xfc, 0x03, 0x88, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xf8, 0x0c, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x02, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0x30, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x5f,
+ 0x01, 0xff, 0x01, 0x70, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00,
+ 0x01, 0x2f, 0x01, 0xff, 0x01, 0x90, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x04, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0x90, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x04, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x70, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xfa, 0x03, 0x22, 0x01, 0x4b, 0x02, 0xff, 0x01, 0x10,
+ 0x0b, 0x00, 0x01, 0xef, 0x06, 0xff, 0x01, 0xf8, 0x0c, 0x00, 0x01, 0xef,
+ 0x06, 0xff, 0x01, 0x80, 0x0c, 0x00, 0x01, 0xef, 0x04, 0xff, 0x01, 0xfd,
+ 0x01, 0x93, 0xd4, 0x00,
+
+ /* 35 */
+ 0xff, 0x00, 0x56, 0x00, 0x06, 0x77, 0x01, 0x70, 0x0d, 0x00, 0x01, 0xef,
+ 0x05, 0xff, 0x01, 0xf0, 0x0d, 0x00, 0x01, 0xef, 0x05, 0xff, 0x01, 0xf0,
+ 0x0d, 0x00, 0x01, 0xef, 0x01, 0xfd, 0x04, 0x99, 0x01, 0x90, 0x0d, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0xd9, 0x00,
+
+ /* 36 */
+ 0xff, 0x00, 0x58, 0x00, 0x01, 0x57, 0x06, 0x77, 0x01, 0x20, 0x0c, 0x00,
+ 0x01, 0xcf, 0x06, 0xff, 0x01, 0x50, 0x0c, 0x00, 0x01, 0xdf, 0x06, 0xff,
+ 0x01, 0x50, 0x0c, 0x00, 0x01, 0xdf, 0x01, 0xfd, 0x03, 0x99, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0x50, 0x0c, 0x00, 0x01, 0xdf, 0x01, 0xfa, 0x03, 0x00,
+ 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50, 0x0c, 0x00, 0x01, 0xef, 0x01, 0xfa,
+ 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xfa, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50, 0x0c, 0x00,
+ 0x01, 0xef, 0x01, 0xfa, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50,
+ 0x0c, 0x00, 0x01, 0xff, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff,
+ 0x01, 0x50, 0x0c, 0x00, 0x01, 0xff, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xf8,
+ 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf6, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50,
+ 0x0b, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xf5, 0x03, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf3,
+ 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf0, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50,
+ 0x0b, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x90,
+ 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0x30, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x50,
+ 0x0a, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xfd, 0x04, 0x22, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x50, 0x09, 0x00, 0x01, 0x6a, 0x01, 0xae, 0x08, 0xff,
+ 0x01, 0xca, 0x01, 0xa0, 0x08, 0x00, 0x01, 0x9f, 0x0a, 0xff, 0x01, 0xf0,
+ 0x08, 0x00, 0x01, 0x9f, 0x0a, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x9f,
+ 0x01, 0xf5, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x9f,
+ 0x01, 0xf5, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x9f,
+ 0x01, 0xf5, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x9f,
+ 0x01, 0xf5, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf0, 0x08, 0x00, 0x01, 0x8e,
+ 0x01, 0xe5, 0x08, 0x00, 0x01, 0xde, 0x01, 0xe0, 0x6c, 0x00,
+
+ /* 37 */
+ 0xff, 0x00, 0x58, 0x00, 0x01, 0x28, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xfc,
+ 0x01, 0x71, 0x0e, 0x00, 0x01, 0x09, 0x05, 0xff, 0x01, 0x60, 0x0c, 0x00,
+ 0x01, 0x01, 0x01, 0xcf, 0x05, 0xff, 0x01, 0xf8, 0x0c, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x73, 0x01, 0x11, 0x01, 0x5b, 0x02, 0xff,
+ 0x01, 0x50, 0x0b, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xc1, 0x03, 0x00,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0xe0, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xfe,
+ 0x01, 0x10, 0x03, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf6, 0x0a, 0x00,
+ 0x01, 0x05, 0x01, 0xff, 0x01, 0xf5, 0x05, 0x00, 0x01, 0xdf, 0x01, 0xfc,
+ 0x0a, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xe0, 0x05, 0x00, 0x01, 0x7f,
+ 0x01, 0xff, 0x0a, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xb0, 0x05, 0x00,
+ 0x01, 0x4f, 0x01, 0xff, 0x01, 0x30, 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xc6, 0x05, 0x66, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x60, 0x09, 0x00,
+ 0x01, 0x1f, 0x09, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x2f, 0x09, 0xff,
+ 0x01, 0x80, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xb6, 0x07, 0x66,
+ 0x01, 0x30, 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x80, 0x11, 0x00,
+ 0x01, 0x0e, 0x01, 0xff, 0x01, 0xb0, 0x11, 0x00, 0x01, 0x0a, 0x01, 0xff,
+ 0x01, 0xf0, 0x05, 0x00, 0x01, 0x48, 0x01, 0x88, 0x0a, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xef, 0x01, 0xfc, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xd2, 0x03, 0x00,
+ 0x01, 0x6f, 0x01, 0xff, 0x01, 0xe1, 0x0b, 0x00, 0x01, 0x0c, 0x02, 0xff,
+ 0x01, 0xa6, 0x01, 0x45, 0x01, 0x7c, 0x02, 0xff, 0x01, 0x50, 0x0b, 0x00,
+ 0x01, 0x01, 0x01, 0xcf, 0x05, 0xff, 0x01, 0xf6, 0x0d, 0x00, 0x01, 0x08,
+ 0x04, 0xff, 0x01, 0xfd, 0x01, 0x40, 0x0e, 0x00, 0x01, 0x16, 0x01, 0xad,
+ 0x01, 0xee, 0x01, 0xc9, 0x01, 0x40, 0xc0, 0x00,
+
+ /* 38 */
+ 0xff, 0x00, 0x55, 0x00, 0x01, 0x03, 0x02, 0x77, 0x03, 0x00, 0x01, 0x01,
+ 0x01, 0x77, 0x01, 0x71, 0x03, 0x00, 0x01, 0x06, 0x01, 0x77, 0x01, 0x73,
+ 0x06, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xb0, 0x02, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xb0,
+ 0x06, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfb, 0x02, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf4, 0x02, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xfb,
+ 0x08, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xa0, 0x01, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf4, 0x02, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xc0,
+ 0x08, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfa, 0x01, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf4, 0x01, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfc,
+ 0x0a, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0xa0, 0x01, 0x03, 0x01, 0xff,
+ 0x01, 0xf4, 0x01, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xc0, 0x0a, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf9, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf4,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0xbf, 0x01, 0xff,
+ 0x01, 0x93, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xc1,
+ 0x0c, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfb, 0x01, 0xff, 0x01, 0xfb,
+ 0x01, 0xff, 0x01, 0xfc, 0x01, 0x10, 0x0d, 0x00, 0x01, 0xcf, 0x04, 0xff,
+ 0x01, 0xd1, 0x0e, 0x00, 0x01, 0x0d, 0x03, 0xff, 0x01, 0xfd, 0x01, 0x10,
+ 0x0e, 0x00, 0x01, 0x5f, 0x04, 0xff, 0x01, 0x60, 0x0d, 0x00, 0x01, 0x05,
+ 0x05, 0xff, 0x01, 0xf6, 0x0d, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xe5,
+ 0x01, 0xff, 0x01, 0xf5, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x60, 0x0b, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x23, 0x01, 0xff, 0x01, 0xf4,
+ 0x01, 0x1d, 0x01, 0xff, 0x01, 0xf7, 0x0b, 0x00, 0x01, 0x6f, 0x01, 0xff,
+ 0x01, 0xe2, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x01, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xfd,
+ 0x01, 0x20, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x00, 0x01, 0x1d,
+ 0x01, 0xff, 0x01, 0xf7, 0x09, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xd1,
+ 0x01, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x00, 0x01, 0x01,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0x70, 0x07, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0x10, 0x01, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf4,
+ 0x02, 0x00, 0x01, 0x1c, 0x01, 0xff, 0x01, 0xf8, 0x07, 0x00, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0xd1, 0x02, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf4,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x80, 0x05, 0x00,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xfd, 0x01, 0x10, 0x02, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0x1c, 0x01, 0xff, 0x01, 0xf8,
+ 0x05, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xd1, 0x03, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0x01, 0x01, 0xcf, 0x01, 0xff,
+ 0x01, 0x80, 0xcc, 0x00,
+
+ /* 39 */
+ 0xff, 0x00, 0x45, 0x00, 0x01, 0x01, 0x11, 0x00, 0x01, 0x17, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0xa5, 0x0e, 0x00, 0x01, 0x06, 0x05, 0xff,
+ 0x01, 0xd3, 0x0d, 0x00, 0x01, 0x5f, 0x06, 0xff, 0x01, 0x30, 0x0c, 0x00,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0xc5, 0x01, 0x21, 0x01, 0x26, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0xd0, 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xfb,
+ 0x03, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf5, 0x0b, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xf3, 0x03, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xf9,
+ 0x0b, 0x00, 0x01, 0x05, 0x01, 0x88, 0x01, 0x80, 0x04, 0x00, 0x01, 0xff,
+ 0x01, 0xfa, 0x11, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf9, 0x11, 0x00,
+ 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf4, 0x0e, 0x00, 0x01, 0x01, 0x01, 0x33,
+ 0x01, 0x36, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xb0, 0x0e, 0x00, 0x01, 0x09,
+ 0x03, 0xff, 0x01, 0xfa, 0x01, 0x10, 0x0e, 0x00, 0x01, 0x09, 0x03, 0xff,
+ 0x01, 0xfa, 0x01, 0x10, 0x0e, 0x00, 0x01, 0x08, 0x01, 0xee, 0x03, 0xff,
+ 0x01, 0xe3, 0x10, 0x00, 0x01, 0x01, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xfd,
+ 0x11, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x40, 0x0a, 0x00, 0x01, 0x06,
+ 0x01, 0x66, 0x01, 0x30, 0x04, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x70,
+ 0x0a, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xb0, 0x04, 0x00, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x80, 0x0a, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xf1,
+ 0x04, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x60, 0x0a, 0x00, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xfb, 0x03, 0x00, 0x01, 0x04, 0x02, 0xff, 0x01, 0x10,
+ 0x0a, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0xe8, 0x01, 0x53, 0x01, 0x46,
+ 0x01, 0xbf, 0x01, 0xff, 0x01, 0xf8, 0x0c, 0x00, 0x01, 0x7f, 0x06, 0xff,
+ 0x01, 0xb0, 0x0c, 0x00, 0x01, 0x06, 0x01, 0xef, 0x04, 0xff, 0x01, 0xf7,
+ 0x0e, 0x00, 0x01, 0x05, 0x01, 0x9c, 0x01, 0xde, 0x01, 0xdc, 0x01, 0x95,
+ 0xc1, 0x00,
+
+ /* 40 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x74, 0x04, 0x00, 0x01, 0x05,
+ 0x01, 0x77, 0x01, 0x76, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x04, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x03, 0x00, 0x01, 0x05, 0x02, 0xff, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x0e, 0x02, 0xff, 0x01, 0xfe,
+ 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x7f, 0x01, 0xff,
+ 0x01, 0xcf, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x01, 0x01, 0xff, 0x01, 0xf9, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xe1,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0x70, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0xcf, 0x01, 0xfd, 0x01, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf4, 0x01, 0x00, 0x01, 0x9f, 0x01, 0xfe,
+ 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x01, 0xb0, 0x01, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x20, 0x01, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf8, 0x02, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xe0, 0x02, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0x60, 0x02, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0xdf, 0x01, 0xfc, 0x03, 0x00, 0x01, 0x9f,
+ 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xf3, 0x03, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xa0,
+ 0x03, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x02, 0xff,
+ 0x01, 0x10, 0x03, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xff, 0x01, 0xe0, 0x04, 0x00, 0x01, 0x9f, 0x01, 0xfe,
+ 0xd2, 0x00,
+
+ /* 41 */
+ 0xca, 0x00, 0x01, 0x2a, 0x01, 0xa2, 0x03, 0x00, 0x01, 0x3a, 0x01, 0xa2,
+ 0x0d, 0x00, 0x01, 0x2f, 0x01, 0xf9, 0x03, 0x00, 0x01, 0xaf, 0x01, 0xf1,
+ 0x0d, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0x82, 0x01, 0x00, 0x01, 0x29,
+ 0x01, 0xff, 0x01, 0xc0, 0x0d, 0x00, 0x01, 0x05, 0x05, 0xff, 0x01, 0x30,
+ 0x0e, 0x00, 0x01, 0x7f, 0x03, 0xff, 0x01, 0xf6, 0x0f, 0x00, 0x01, 0x02,
+ 0x01, 0x8b, 0x01, 0xdd, 0x01, 0xb8, 0x01, 0x10, 0x21, 0x00, 0x01, 0x67,
+ 0x01, 0x74, 0x04, 0x00, 0x01, 0x05, 0x01, 0x77, 0x01, 0x76, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0xfe,
+ 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0xcf, 0x01, 0xff,
+ 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x05,
+ 0x02, 0xff, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00,
+ 0x01, 0x0e, 0x02, 0xff, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x03, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xcf, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xf9,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf1, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0x70,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0xcf, 0x01, 0xfd, 0x01, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf4,
+ 0x01, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x01, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xb0, 0x01, 0x00, 0x01, 0x9f,
+ 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x20, 0x01, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x02, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xe0, 0x02, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x60, 0x02, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0xdf,
+ 0x01, 0xfc, 0x03, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef,
+ 0x02, 0xff, 0x01, 0xf3, 0x03, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00,
+ 0x01, 0xef, 0x02, 0xff, 0x01, 0xa0, 0x03, 0x00, 0x01, 0x9f, 0x01, 0xfe,
+ 0x0b, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0x10, 0x03, 0x00, 0x01, 0x9f,
+ 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xe0,
+ 0x04, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0xd2, 0x00,
+
+ /* 42 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x74, 0x04, 0x00, 0x01, 0x67,
+ 0x01, 0x77, 0x01, 0x10, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x03, 0x00,
+ 0x01, 0x09, 0x01, 0xff, 0x01, 0xf6, 0x0c, 0x00, 0x01, 0xef, 0x01, 0xf8,
+ 0x03, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x60, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf8, 0x02, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf5, 0x0d, 0x00,
+ 0x01, 0xef, 0x01, 0xf8, 0x02, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x50,
+ 0x0d, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0x00, 0x01, 0x0a, 0x01, 0xff,
+ 0x01, 0xf5, 0x0e, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0x00, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0x50, 0x0e, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xf4, 0x0f, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x40, 0x0f, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xf4,
+ 0x10, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0x40, 0x10, 0x00, 0x01, 0xef,
+ 0x02, 0xff, 0x01, 0xa0, 0x10, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xfa,
+ 0x10, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xb0,
+ 0x0f, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xfb,
+ 0x0f, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0x00, 0x01, 0xaf, 0x01, 0xff,
+ 0x01, 0xb0, 0x0e, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x01, 0x00, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xfb, 0x0e, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x02, 0x00,
+ 0x01, 0x9f, 0x01, 0xff, 0x01, 0xc0, 0x0d, 0x00, 0x01, 0xef, 0x01, 0xf8,
+ 0x02, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfc, 0x0d, 0x00, 0x01, 0xef,
+ 0x01, 0xf8, 0x03, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xc0, 0x0c, 0x00,
+ 0x01, 0xef, 0x01, 0xf8, 0x03, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfc,
+ 0x0c, 0x00, 0x01, 0xef, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x9f, 0x01, 0xff,
+ 0x01, 0xc1, 0xd2, 0x00,
+
+ /* 43 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x02, 0x06, 0x77, 0x01, 0x75, 0x0c, 0x00,
+ 0x01, 0x05, 0x06, 0xff, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x05, 0x06, 0xff,
+ 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xfb, 0x03, 0xaa,
+ 0x01, 0xef, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x05, 0x01, 0xff,
+ 0x01, 0xf2, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf2, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00,
+ 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc,
+ 0x0c, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x03, 0x00, 0x01, 0xbf,
+ 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x03, 0x00,
+ 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0,
+ 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x08, 0x01, 0xff,
+ 0x01, 0xf0, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf0, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xd0, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc,
+ 0x0c, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xb0, 0x03, 0x00, 0x01, 0xbf,
+ 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x80, 0x03, 0x00,
+ 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x3f, 0x01, 0xff, 0x01, 0x40,
+ 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x9f, 0x01, 0xff,
+ 0x01, 0x10, 0x03, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0b, 0x00, 0x01, 0x04,
+ 0x01, 0xff, 0x01, 0xf9, 0x04, 0x00, 0x01, 0xbf, 0x01, 0xfc, 0x0b, 0x00,
+ 0x01, 0x8f, 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00, 0x01, 0xbf, 0x01, 0xfc,
+ 0x0b, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x70, 0x04, 0x00, 0x01, 0xbf,
+ 0x01, 0xfc, 0x0b, 0x00, 0x01, 0x9f, 0x01, 0xf6, 0x05, 0x00, 0x01, 0xbf,
+ 0x01, 0xfc, 0x0b, 0x00, 0x01, 0x34, 0xc7, 0x00,
+
+ /* 44 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x77, 0x01, 0x30, 0x04, 0x00,
+ 0x01, 0x03, 0x02, 0x77, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xd0,
+ 0x04, 0x00, 0x01, 0x0b, 0x02, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0xf3, 0x04, 0x00, 0x01, 0x2f, 0x02, 0xff, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0xfa, 0x04, 0x00, 0x01, 0x9f, 0x02, 0xff, 0x0a, 0x00,
+ 0x01, 0xef, 0x02, 0xff, 0x01, 0x10, 0x03, 0x00, 0x03, 0xff, 0x0a, 0x00,
+ 0x01, 0xef, 0x02, 0xff, 0x01, 0x80, 0x02, 0x00, 0x01, 0x06, 0x03, 0xff,
+ 0x0a, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xe0, 0x02, 0x00, 0x01, 0x0d,
+ 0x03, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfd, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0xdf, 0x01, 0xff, 0x0a, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0xdf, 0x01, 0xfc, 0x02, 0x00, 0x01, 0xaf,
+ 0x01, 0xfe, 0x01, 0x8f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x01, 0x7f, 0x01, 0xff, 0x01, 0x30, 0x01, 0x01, 0x01, 0xff, 0x01, 0xf8,
+ 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf2, 0x01, 0x7f,
+ 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x0a, 0x01, 0xff,
+ 0x01, 0xf1, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xb0, 0x01, 0x7f, 0x01, 0xff,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x03, 0x01, 0xff, 0x01, 0xf7,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0x40, 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0xcf, 0x01, 0xfd, 0x01, 0xcf,
+ 0x01, 0xfe, 0x01, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x6f, 0x02, 0xff, 0x01, 0xf7, 0x01, 0x00,
+ 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00,
+ 0x01, 0x0f, 0x02, 0xff, 0x01, 0xf1, 0x01, 0x00, 0x01, 0x7f, 0x01, 0xff,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0x09, 0x02, 0xff,
+ 0x01, 0xa0, 0x01, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x02, 0x02, 0xff, 0x01, 0x40, 0x01, 0x00,
+ 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0xcf, 0x01, 0xfd, 0x02, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x5f, 0x01, 0xf7, 0x02, 0x00,
+ 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0x61, 0x02, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x0a, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x06, 0x00, 0x01, 0x7f, 0x01, 0xff, 0xd1, 0x00,
+
+ /* 45 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x74, 0x05, 0x00, 0x01, 0x77,
+ 0x01, 0x73, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xfd, 0x05, 0xaa, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x07, 0xff, 0x01, 0xf8, 0x0b, 0x00,
+ 0x01, 0xef, 0x07, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xfc,
+ 0x05, 0x77, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf8, 0xd2, 0x00,
+
+ /* 46 */
+ 0xff, 0x00, 0x58, 0x00, 0x01, 0x39, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xeb,
+ 0x01, 0x60, 0x0e, 0x00, 0x01, 0x1b, 0x04, 0xff, 0x01, 0xfe, 0x01, 0x50,
+ 0x0c, 0x00, 0x01, 0x02, 0x01, 0xef, 0x05, 0xff, 0x01, 0xf8, 0x0c, 0x00,
+ 0x01, 0x0d, 0x02, 0xff, 0x01, 0x83, 0x01, 0x12, 0x01, 0x5c, 0x02, 0xff,
+ 0x01, 0x50, 0x0b, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xd1, 0x03, 0x00,
+ 0x01, 0x7f, 0x01, 0xff, 0x01, 0xe1, 0x0a, 0x00, 0x01, 0x01, 0x01, 0xff,
+ 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf7,
+ 0x0a, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00, 0x01, 0x01,
+ 0x01, 0xff, 0x01, 0xfd, 0x0a, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf1,
+ 0x05, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x10, 0x09, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x50,
+ 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90, 0x05, 0x00, 0x01, 0x3f,
+ 0x01, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80,
+ 0x05, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80, 0x09, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x70, 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90,
+ 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80, 0x05, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x80, 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90,
+ 0x05, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x50,
+ 0x09, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf1, 0x05, 0x00, 0x01, 0xaf,
+ 0x01, 0xff, 0x01, 0x10, 0x09, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf8,
+ 0x04, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xfd, 0x0b, 0x00, 0x02, 0xff,
+ 0x01, 0x20, 0x03, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf6, 0x0b, 0x00,
+ 0x01, 0x8f, 0x01, 0xff, 0x01, 0xe3, 0x03, 0x00, 0x01, 0xaf, 0x01, 0xff,
+ 0x01, 0xd0, 0x0b, 0x00, 0x01, 0x0c, 0x02, 0xff, 0x01, 0xa5, 0x01, 0x34,
+ 0x01, 0x7e, 0x02, 0xff, 0x01, 0x30, 0x0b, 0x00, 0x01, 0x01, 0x01, 0xcf,
+ 0x05, 0xff, 0x01, 0xf5, 0x0d, 0x00, 0x01, 0x19, 0x04, 0xff, 0x01, 0xfc,
+ 0x01, 0x30, 0x0e, 0x00, 0x01, 0x27, 0x01, 0xbd, 0x01, 0xee, 0x01, 0xc9,
+ 0x01, 0x40, 0xc0, 0x00,
+
+ /* 47 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x07, 0x77, 0x01, 0x73, 0x0b, 0x00,
+ 0x01, 0xef, 0x07, 0xff, 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x07, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xfd, 0x05, 0xaa, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0xd2, 0x00,
+
+ /* 48 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x72, 0x01, 0x00, 0x01, 0x29,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0xc7, 0x01, 0x10, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf4, 0x01, 0x08, 0x04, 0xff, 0x01, 0xf6, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf4, 0x01, 0xaf, 0x05, 0xff, 0x01, 0x80, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xfc, 0x01, 0xff, 0x01, 0xf9, 0x01, 0x42, 0x01, 0x37, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0xf6, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x30, 0x02, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf3, 0x04, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x70, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0x90,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x30, 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf2,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfe, 0x05, 0x00, 0x01, 0x05, 0x01, 0xff,
+ 0x01, 0xf5, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x05, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf7, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfa, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xf8, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xf9, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfa, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xf9, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x05, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfe,
+ 0x05, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf5, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x30, 0x04, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf2,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xd0, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf4,
+ 0x04, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x70, 0x0a, 0x00, 0x01, 0xef,
+ 0x02, 0xff, 0x01, 0x40, 0x02, 0x00, 0x01, 0x1b, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x10, 0x0a, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xfb, 0x01, 0x64,
+ 0x01, 0x58, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf5, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0xaf, 0x05, 0xff, 0x01, 0x70, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x08, 0x04, 0xff, 0x01, 0xe4, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x28, 0x01, 0xce, 0x01, 0xed, 0x01, 0xa5,
+ 0x0d, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xde, 0x01, 0xe8,
+ 0x25, 0x00,
+
+ /* 49 */
+ 0xff, 0x00, 0x58, 0x00, 0x01, 0x38, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xea,
+ 0x01, 0x50, 0x0e, 0x00, 0x01, 0x19, 0x04, 0xff, 0x01, 0xfd, 0x01, 0x20,
+ 0x0c, 0x00, 0x01, 0x01, 0x01, 0xcf, 0x05, 0xff, 0x01, 0xf2, 0x0c, 0x00,
+ 0x01, 0x0c, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x73, 0x01, 0x12, 0x01, 0x6d,
+ 0x01, 0xff, 0x01, 0xfd, 0x0c, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xc1,
+ 0x03, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x60, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xb0,
+ 0x0a, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf6, 0x04, 0x00, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xf0, 0x0a, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf1,
+ 0x04, 0x00, 0x01, 0x04, 0x01, 0xbb, 0x01, 0xb1, 0x0a, 0x00, 0x01, 0x0d,
+ 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90,
+ 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80, 0x11, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x70, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80,
+ 0x11, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90, 0x11, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xc0, 0x05, 0x00, 0x01, 0x55, 0x01, 0x52, 0x0a, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf1, 0x04, 0x00, 0x01, 0x04, 0x01, 0xff,
+ 0x01, 0xf4, 0x0a, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf6, 0x04, 0x00,
+ 0x01, 0x09, 0x01, 0xff, 0x01, 0xf1, 0x0b, 0x00, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x10, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xc0, 0x0b, 0x00,
+ 0x01, 0x8f, 0x01, 0xff, 0x01, 0xd2, 0x02, 0x00, 0x01, 0x01, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x60, 0x0b, 0x00, 0x01, 0x0c, 0x02, 0xff, 0x01, 0x94,
+ 0x01, 0x34, 0x01, 0x8e, 0x01, 0xff, 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x01,
+ 0x01, 0xdf, 0x05, 0xff, 0x01, 0xe1, 0x0d, 0x00, 0x01, 0x19, 0x04, 0xff,
+ 0x01, 0xfa, 0x01, 0x10, 0x0e, 0x00, 0x01, 0x27, 0x01, 0xcd, 0x01, 0xee,
+ 0x01, 0xc8, 0x01, 0x20, 0xc0, 0x00,
+
+ /* 50 */
+ 0xff, 0x00, 0x55, 0x00, 0x01, 0x47, 0x06, 0x77, 0x01, 0x76, 0x0c, 0x00,
+ 0x01, 0x9f, 0x06, 0xff, 0x01, 0xfe, 0x0c, 0x00, 0x01, 0x9f, 0x06, 0xff,
+ 0x01, 0xfe, 0x0c, 0x00, 0x01, 0x6a, 0x02, 0xaa, 0x01, 0xdf, 0x01, 0xff,
+ 0x02, 0xaa, 0x01, 0xa9, 0x0f, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00, 0x01, 0x9f, 0x01, 0xfe, 0x12, 0x00,
+ 0x01, 0x9f, 0x01, 0xfe, 0xd7, 0x00,
+
+ /* 51 */
+ 0xff, 0x00, 0x55, 0x00, 0x01, 0x67, 0x01, 0x75, 0x05, 0x00, 0x01, 0x05,
+ 0x01, 0x77, 0x01, 0x70, 0x0a, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x05, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xb0, 0x0a, 0x00, 0x01, 0x5f, 0x01, 0xff,
+ 0x01, 0x50, 0x04, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x50, 0x0a, 0x00,
+ 0x01, 0x0f, 0x01, 0xff, 0x01, 0xb0, 0x04, 0x00, 0x01, 0xbf, 0x01, 0xff,
+ 0x0b, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf0, 0x03, 0x00, 0x01, 0x01,
+ 0x01, 0xff, 0x01, 0xf9, 0x0b, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xf5,
+ 0x03, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf3, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xfb, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xd0, 0x0c, 0x00,
+ 0x01, 0x9f, 0x01, 0xff, 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x70,
+ 0x0c, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x50, 0x02, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x20, 0x0c, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xb0,
+ 0x02, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x0d, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf1, 0x01, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xf5, 0x0d, 0x00,
+ 0x01, 0x04, 0x01, 0xff, 0x01, 0xf5, 0x01, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf0, 0x0e, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x01, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0x90, 0x0e, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0x10,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0x40, 0x0e, 0x00, 0x01, 0x3f, 0x01, 0xff,
+ 0x01, 0x50, 0x01, 0xbf, 0x01, 0xfd, 0x0f, 0x00, 0x01, 0x0d, 0x01, 0xff,
+ 0x01, 0xb1, 0x01, 0xff, 0x01, 0xf8, 0x0f, 0x00, 0x01, 0x08, 0x01, 0xff,
+ 0x01, 0xf7, 0x01, 0xff, 0x01, 0xf2, 0x0f, 0x00, 0x01, 0x03, 0x03, 0xff,
+ 0x01, 0xc0, 0x10, 0x00, 0x01, 0xdf, 0x02, 0xff, 0x01, 0x60, 0x10, 0x00,
+ 0x01, 0x8f, 0x02, 0xff, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xfa,
+ 0x11, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf4, 0x11, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x80,
+ 0x11, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x20, 0x11, 0x00, 0x01, 0xef,
+ 0x01, 0xfc, 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf6, 0x0f, 0x00,
+ 0x01, 0x05, 0x01, 0x76, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xd0, 0x0f, 0x00,
+ 0x01, 0x09, 0x03, 0xff, 0x01, 0x50, 0x0f, 0x00, 0x01, 0x09, 0x02, 0xff,
+ 0x01, 0xf7, 0x10, 0x00, 0x01, 0x05, 0x01, 0xce, 0x01, 0xda, 0x01, 0x30,
+ 0x24, 0x00,
+
+ /* 52 */
+ 0xe3, 0x00, 0x01, 0x05, 0x01, 0x99, 0x01, 0x80, 0x11, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0,
+ 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0,
+ 0x0c, 0x00, 0x01, 0x01, 0x01, 0x8d, 0x01, 0xff, 0x01, 0xeb, 0x01, 0x40,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x01, 0x02, 0x01, 0x9e, 0x01, 0xff,
+ 0x01, 0xea, 0x01, 0x50, 0x07, 0x00, 0x01, 0x6f, 0x03, 0xff, 0x01, 0xfa,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x01, 0x5f, 0x03, 0xff, 0x01, 0xfc,
+ 0x01, 0x20, 0x05, 0x00, 0x01, 0x06, 0x05, 0xff, 0x01, 0x98, 0x01, 0xff,
+ 0x01, 0xe4, 0x05, 0xff, 0x01, 0xd1, 0x05, 0x00, 0x01, 0x3f, 0x01, 0xff,
+ 0x01, 0xfc, 0x01, 0x53, 0x01, 0x36, 0x01, 0xcf, 0x01, 0xfc, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0xff, 0x01, 0x83, 0x01, 0x24, 0x01, 0x9f, 0x01, 0xff,
+ 0x01, 0xfb, 0x05, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x90, 0x02, 0x00,
+ 0x01, 0x0a, 0x03, 0xff, 0x01, 0xe2, 0x02, 0x00, 0x01, 0x03, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x40, 0x03, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfc,
+ 0x04, 0x00, 0x01, 0xdf, 0x02, 0xff, 0x01, 0x40, 0x03, 0x00, 0x01, 0x5f,
+ 0x01, 0xff, 0x01, 0xb0, 0x03, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf4,
+ 0x04, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xfb, 0x04, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf1, 0x03, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xe0,
+ 0x04, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xf6, 0x04, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xb0,
+ 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf7, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0x90,
+ 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf0, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf9, 0x03, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0x80, 0x04, 0x00,
+ 0x01, 0x09, 0x01, 0xff, 0x01, 0xf0, 0x05, 0x00, 0x01, 0xff, 0x01, 0xfa,
+ 0x03, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0x70, 0x04, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xe0, 0x05, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x03, 0x00,
+ 0x01, 0x2f, 0x01, 0xff, 0x01, 0x80, 0x04, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf0, 0x05, 0x00, 0x01, 0xff, 0x01, 0xfa, 0x03, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0x90, 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf0,
+ 0x05, 0x00, 0x01, 0xff, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x0f, 0x01, 0xff,
+ 0x01, 0xb0, 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf3, 0x04, 0x00,
+ 0x01, 0x03, 0x01, 0xff, 0x01, 0xf7, 0x03, 0x00, 0x01, 0x0c, 0x01, 0xff,
+ 0x01, 0xf0, 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xf7, 0x04, 0x00,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf4, 0x03, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf5, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xfc, 0x04, 0x00,
+ 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf1, 0x03, 0x00, 0x01, 0x04, 0x01, 0xff,
+ 0x01, 0xfc, 0x04, 0x00, 0x01, 0xdf, 0x02, 0xff, 0x01, 0x40, 0x03, 0x00,
+ 0x01, 0x5f, 0x01, 0xff, 0x01, 0xb0, 0x04, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xa0, 0x02, 0x00, 0x01, 0x0b, 0x03, 0xff, 0x01, 0xe3, 0x02, 0x00,
+ 0x01, 0x04, 0x02, 0xff, 0x01, 0x40, 0x04, 0x00, 0x01, 0x5f, 0x01, 0xff,
+ 0x01, 0xfd, 0x01, 0x74, 0x01, 0x47, 0x01, 0xdf, 0x01, 0xfe, 0x03, 0xff,
+ 0x01, 0x95, 0x01, 0x45, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xfb, 0x05, 0x00,
+ 0x01, 0x08, 0x05, 0xff, 0x01, 0xb8, 0x01, 0xff, 0x01, 0xe6, 0x05, 0xff,
+ 0x01, 0xd1, 0x06, 0x00, 0x01, 0x7f, 0x03, 0xff, 0x01, 0xfa, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xe0, 0x01, 0x6f, 0x03, 0xff, 0x01, 0xfa, 0x01, 0x10,
+ 0x06, 0x00, 0x01, 0x02, 0x01, 0x8c, 0x01, 0xef, 0x01, 0xdb, 0x01, 0x50,
+ 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x01, 0x02, 0x01, 0x8d, 0x01, 0xee,
+ 0x01, 0xd9, 0x01, 0x30, 0x0c, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0,
+ 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0,
+ 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0,
+ 0x11, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xe0, 0x1e, 0x00,
+
+ /* 53 */
+ 0xff, 0x00, 0x55, 0x00, 0x01, 0x37, 0x01, 0x77, 0x01, 0x30, 0x04, 0x00,
+ 0x01, 0x17, 0x01, 0x77, 0x01, 0x40, 0x0a, 0x00, 0x01, 0x0d, 0x01, 0xff,
+ 0x01, 0xe1, 0x04, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x20, 0x0a, 0x00,
+ 0x01, 0x03, 0x01, 0xff, 0x01, 0xfb, 0x03, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf6, 0x0c, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x50, 0x02, 0x00,
+ 0x01, 0x2f, 0x01, 0xff, 0x01, 0xb0, 0x0c, 0x00, 0x01, 0x0d, 0x01, 0xff,
+ 0x01, 0xe1, 0x02, 0x00, 0x01, 0xcf, 0x01, 0xfe, 0x01, 0x10, 0x0c, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xfb, 0x01, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf5, 0x0e, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0x60, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x90, 0x0e, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf2,
+ 0x01, 0xcf, 0x01, 0xfd, 0x0f, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0xff, 0x01, 0xf3, 0x10, 0x00, 0x01, 0x6f, 0x02, 0xff, 0x01, 0x70,
+ 0x10, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xfc, 0x11, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xfd, 0x11, 0x00, 0x01, 0x4f, 0x02, 0xff, 0x01, 0x80,
+ 0x0f, 0x00, 0x01, 0x01, 0x01, 0xef, 0x02, 0xff, 0x01, 0xf3, 0x0f, 0x00,
+ 0x01, 0x0a, 0x01, 0xff, 0x01, 0xe3, 0x01, 0xef, 0x01, 0xfd, 0x0f, 0x00,
+ 0x01, 0x6f, 0x01, 0xff, 0x01, 0x50, 0x01, 0x5f, 0x01, 0xff, 0x01, 0x90,
+ 0x0d, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfb, 0x01, 0x00, 0x01, 0x0a,
+ 0x01, 0xff, 0x01, 0xf4, 0x0d, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xe1,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xfd, 0x0d, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0x50, 0x02, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x90,
+ 0x0b, 0x00, 0x01, 0x03, 0x01, 0xff, 0x01, 0xfa, 0x03, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xf4, 0x0b, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xe1,
+ 0x03, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xfe, 0x01, 0x10, 0x0a, 0x00,
+ 0x01, 0x9f, 0x01, 0xff, 0x01, 0x50, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff,
+ 0x01, 0xa0, 0x0a, 0x00, 0x02, 0x11, 0x05, 0x00, 0x01, 0x01, 0x01, 0x11,
+ 0x01, 0x10, 0xbe, 0x00,
+
+ /* 54 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x74, 0x05, 0x00, 0x01, 0x77,
+ 0x01, 0x73, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x00, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x05, 0x11, 0x01, 0xff,
+ 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xef, 0x07, 0xff, 0x01, 0xfc, 0x01, 0x99,
+ 0x0a, 0x00, 0x01, 0xef, 0x09, 0xff, 0x0a, 0x00, 0x01, 0xef, 0x09, 0xff,
+ 0x12, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x12, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x12, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x12, 0x00, 0x01, 0x0e, 0x01, 0xff,
+ 0x12, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x6d, 0x00,
+
+ /* 55 */
+ 0xff, 0x00, 0x55, 0x00, 0x01, 0x02, 0x01, 0x77, 0x01, 0x71, 0x04, 0x00,
+ 0x01, 0x77, 0x01, 0x73, 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00,
+ 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8,
+ 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x04, 0x00,
+ 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x05, 0x01, 0xff,
+ 0x01, 0xf2, 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x03,
+ 0x01, 0xff, 0x01, 0xf6, 0x04, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x0c, 0x00,
+ 0x02, 0xff, 0x01, 0x85, 0x03, 0x55, 0x01, 0xff, 0x01, 0xf8, 0x0c, 0x00,
+ 0x01, 0x6f, 0x06, 0xff, 0x01, 0xf8, 0x0c, 0x00, 0x01, 0x07, 0x06, 0xff,
+ 0x01, 0xf8, 0x0d, 0x00, 0x01, 0x17, 0x01, 0xbc, 0x03, 0xcc, 0x01, 0xff,
+ 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x12, 0x00, 0x01, 0x11, 0x01, 0x10, 0xbf, 0x00,
+
+ /* 56 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x66, 0x01, 0x64, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x66, 0x01, 0x62, 0x02, 0x00, 0x01, 0x02, 0x01, 0x66, 0x01, 0x60,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x11, 0x01, 0x13,
+ 0x01, 0xff, 0x01, 0xf6, 0x02, 0x11, 0x01, 0x17, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0xef, 0x0a, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x0a, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x0a, 0xff, 0x01, 0xf1,
+ 0xcf, 0x00,
+
+ /* 57 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x66, 0x01, 0x63, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x66, 0x01, 0x62, 0x02, 0x00, 0x01, 0x02, 0x01, 0x66, 0x01, 0x60,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff,
+ 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf5, 0x02, 0x00, 0x01, 0x06, 0x01, 0xff,
+ 0x01, 0xf1, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x11, 0x01, 0x13,
+ 0x01, 0xff, 0x01, 0xf6, 0x02, 0x11, 0x01, 0x17, 0x01, 0xff, 0x01, 0xf1,
+ 0x08, 0x00, 0x01, 0xef, 0x0a, 0xff, 0x01, 0xf9, 0x01, 0x95, 0x07, 0x00,
+ 0x01, 0xef, 0x0b, 0xff, 0x01, 0xf9, 0x07, 0x00, 0x01, 0xef, 0x0b, 0xff,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0x5f, 0x01, 0xf9, 0x12, 0x00, 0x01, 0x5f,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0x5f, 0x01, 0xf9, 0x12, 0x00, 0x01, 0x5f,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0x5f, 0x01, 0xf9, 0x6a, 0x00,
+
+ /* 58 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x56, 0x01, 0x63, 0x12, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xff, 0x02, 0xee, 0x01, 0xed,
+ 0x01, 0xc9, 0x01, 0x60, 0x0d, 0x00, 0x01, 0xef, 0x06, 0xff, 0x01, 0x70,
+ 0x0c, 0x00, 0x01, 0xef, 0x06, 0xff, 0x01, 0xfa, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xfa, 0x02, 0x33, 0x01, 0x34, 0x01, 0x6a, 0x02, 0xff, 0x01, 0x50,
+ 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff,
+ 0x01, 0xd0, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x0c,
+ 0x01, 0xff, 0x01, 0xf1, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00,
+ 0x01, 0x09, 0x01, 0xff, 0x01, 0xf3, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x04, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf4, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x2f, 0x01, 0xff, 0x01, 0xe0,
+ 0x0b, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x11, 0x01, 0x38, 0x02, 0xff,
+ 0x01, 0x70, 0x0b, 0x00, 0x01, 0xef, 0x06, 0xff, 0x01, 0xfc, 0x0c, 0x00,
+ 0x01, 0xef, 0x06, 0xff, 0x01, 0xc1, 0x0c, 0x00, 0x01, 0xef, 0x05, 0xff,
+ 0x01, 0xb5, 0x0d, 0x00, 0x05, 0x11, 0xc2, 0x00,
+
+ /* 59 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x56, 0x01, 0x63, 0x07, 0x00, 0x01, 0x02,
+ 0x01, 0x66, 0x01, 0x60, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x07, 0x00,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x07, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x07, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x07, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x07, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x07, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x07, 0x00,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xff,
+ 0x02, 0xee, 0x01, 0xed, 0x01, 0xc9, 0x01, 0x60, 0x02, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x06, 0xff, 0x01, 0x70,
+ 0x01, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef,
+ 0x06, 0xff, 0x01, 0xfa, 0x01, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xfa, 0x02, 0x33, 0x01, 0x34, 0x01, 0x6b,
+ 0x02, 0xff, 0x01, 0x50, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xd0,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf1, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf3, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf4,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf2, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x04, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xe0, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x03, 0x11, 0x01, 0x37, 0x02, 0xff, 0x01, 0x70,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x06, 0xff,
+ 0x01, 0xfc, 0x01, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00,
+ 0x01, 0xef, 0x06, 0xff, 0x01, 0xc1, 0x01, 0x00, 0x01, 0x07, 0x01, 0xff,
+ 0x01, 0xf0, 0x08, 0x00, 0x01, 0xef, 0x05, 0xff, 0x01, 0xb5, 0x02, 0x00,
+ 0x01, 0x07, 0x01, 0xff, 0x01, 0xf0, 0x08, 0x00, 0x05, 0x11, 0x05, 0x00,
+ 0x01, 0x11, 0x01, 0x10, 0xbb, 0x00,
+
+ /* 60 */
+ 0xff, 0x00, 0x55, 0x00, 0x01, 0x36, 0x04, 0x66, 0x01, 0x63, 0x0e, 0x00,
+ 0x01, 0x9f, 0x04, 0xff, 0x01, 0xf8, 0x0e, 0x00, 0x01, 0x9f, 0x04, 0xff,
+ 0x01, 0xf8, 0x0e, 0x00, 0x01, 0x6a, 0x03, 0xaa, 0x01, 0xff, 0x01, 0xf8,
+ 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8,
+ 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x12, 0x00, 0x01, 0xff, 0x01, 0xf8,
+ 0x12, 0x00, 0x02, 0xff, 0x02, 0xee, 0x01, 0xed, 0x01, 0xc9, 0x01, 0x50,
+ 0x0d, 0x00, 0x06, 0xff, 0x01, 0xfe, 0x01, 0x60, 0x0c, 0x00, 0x07, 0xff,
+ 0x01, 0xf9, 0x0c, 0x00, 0x01, 0xff, 0x01, 0xfa, 0x02, 0x33, 0x01, 0x34,
+ 0x01, 0x6b, 0x02, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0xff, 0x01, 0xf8,
+ 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0xc0, 0x0b, 0x00, 0x01, 0xff,
+ 0x01, 0xf8, 0x04, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf1, 0x0b, 0x00,
+ 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf3,
+ 0x0b, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf3, 0x0b, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00, 0x01, 0x0b,
+ 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0xff, 0x01, 0xf8, 0x04, 0x00,
+ 0x01, 0x3f, 0x01, 0xff, 0x01, 0xe0, 0x0b, 0x00, 0x01, 0xff, 0x01, 0xf9,
+ 0x03, 0x11, 0x01, 0x38, 0x02, 0xff, 0x01, 0x70, 0x0b, 0x00, 0x07, 0xff,
+ 0x01, 0xfc, 0x0c, 0x00, 0x07, 0xff, 0x01, 0xb1, 0x0c, 0x00, 0x06, 0xff,
+ 0x01, 0xb5, 0x0d, 0x00, 0x05, 0x11, 0xbf, 0x00,
+
+ /* 61 */
+ 0xff, 0x00, 0x57, 0x00, 0x01, 0x02, 0x01, 0x8c, 0x01, 0xff, 0x01, 0xfd,
+ 0x01, 0x94, 0x0f, 0x00, 0x01, 0x9f, 0x04, 0xff, 0x01, 0xb2, 0x0d, 0x00,
+ 0x01, 0x0c, 0x05, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x0c, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0xf8, 0x01, 0x42, 0x01, 0x36, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0xe1, 0x0b, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20,
+ 0x02, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfa, 0x0b, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xf5, 0x04, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x20,
+ 0x0a, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xe0, 0x04, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0x90, 0x0a, 0x00, 0x01, 0x0a, 0x01, 0xcc, 0x01, 0x80,
+ 0x04, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xe0, 0x11, 0x00, 0x01, 0x08,
+ 0x01, 0xff, 0x01, 0xf1, 0x0d, 0x00, 0x01, 0x69, 0x03, 0x99, 0x01, 0x9b,
+ 0x01, 0xff, 0x01, 0xf4, 0x0d, 0x00, 0x01, 0xaf, 0x05, 0xff, 0x01, 0xf5,
+ 0x0d, 0x00, 0x01, 0xaf, 0x05, 0xff, 0x01, 0xf6, 0x0d, 0x00, 0x01, 0x58,
+ 0x03, 0x88, 0x01, 0x8a, 0x01, 0xff, 0x01, 0xf5, 0x11, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf4, 0x0a, 0x00, 0x01, 0x05, 0x01, 0x55, 0x01, 0x10,
+ 0x04, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf2, 0x0a, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0x80, 0x04, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xe0,
+ 0x0a, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xd0, 0x04, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xa0, 0x0a, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xf5,
+ 0x04, 0x00, 0x01, 0xbf, 0x01, 0xff, 0x01, 0x40, 0x0a, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xfe, 0x01, 0x20, 0x02, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xfc, 0x0c, 0x00, 0x01, 0x9f, 0x01, 0xff, 0x01, 0xf9, 0x01, 0x42,
+ 0x01, 0x37, 0x01, 0xdf, 0x01, 0xff, 0x01, 0xf2, 0x0c, 0x00, 0x01, 0x0b,
+ 0x06, 0xff, 0x01, 0x40, 0x0d, 0x00, 0x01, 0x8f, 0x04, 0xff, 0x01, 0xc2,
+ 0x0e, 0x00, 0x01, 0x01, 0x01, 0x8c, 0x01, 0xef, 0x01, 0xed, 0x01, 0x94,
+ 0xc1, 0x00,
+
+ /* 62 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x56, 0x01, 0x63, 0x04, 0x00, 0x01, 0x05,
+ 0x01, 0xae, 0x01, 0xff, 0x01, 0xed, 0x01, 0x83, 0x09, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x03, 0x00, 0x01, 0x03, 0x01, 0xdf, 0x04, 0xff, 0x01, 0xa1,
+ 0x08, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x6f, 0x05, 0xff,
+ 0x01, 0xfe, 0x01, 0x20, 0x07, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0x04, 0x02, 0xff, 0x01, 0xd6, 0x01, 0x32, 0x01, 0x48, 0x02, 0xff,
+ 0x01, 0xe0, 0x07, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x1c, 0x01, 0xff, 0x01, 0xf9,
+ 0x07, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x7f, 0x01, 0xff,
+ 0x01, 0xb0, 0x03, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff, 0x01, 0x10,
+ 0x06, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0x20, 0x04, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x70, 0x06, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0x02, 0x01, 0xff, 0x01, 0xfb,
+ 0x05, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xb0, 0x06, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xe0, 0x06, 0x00, 0x01, 0xef, 0x01, 0xfd,
+ 0x01, 0x99, 0x01, 0x9c, 0x01, 0xff, 0x01, 0xf3, 0x05, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xf1, 0x06, 0x00, 0x01, 0xef, 0x04, 0xff, 0x01, 0xf2,
+ 0x05, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf2, 0x06, 0x00, 0x01, 0xef,
+ 0x04, 0xff, 0x01, 0xf1, 0x05, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf3,
+ 0x06, 0x00, 0x01, 0xef, 0x01, 0xfc, 0x01, 0x88, 0x01, 0x8c, 0x01, 0xff,
+ 0x01, 0xf2, 0x05, 0x00, 0x01, 0x07, 0x01, 0xff, 0x01, 0xf2, 0x06, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x01, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf3,
+ 0x05, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xf1, 0x06, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x04, 0x01, 0xff, 0x01, 0xf6, 0x05, 0x00,
+ 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf0, 0x06, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0xff, 0x01, 0xfb, 0x05, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xb0, 0x06, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00,
+ 0x01, 0xcf, 0x01, 0xff, 0x01, 0x20, 0x04, 0x00, 0x01, 0x7f, 0x01, 0xff,
+ 0x01, 0x70, 0x06, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0xb0, 0x03, 0x00, 0x01, 0x01, 0x01, 0xef, 0x01, 0xff,
+ 0x01, 0x10, 0x06, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x0e,
+ 0x01, 0xff, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x2d, 0x01, 0xff, 0x01, 0xf9,
+ 0x07, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x04, 0x02, 0xff,
+ 0x01, 0xd7, 0x01, 0x32, 0x01, 0x49, 0x02, 0xff, 0x01, 0xd0, 0x07, 0x00,
+ 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x6f, 0x05, 0xff, 0x01, 0xfd,
+ 0x01, 0x20, 0x07, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x03, 0x00, 0x01, 0x03,
+ 0x01, 0xdf, 0x04, 0xff, 0x01, 0xa1, 0x08, 0x00, 0x01, 0x11, 0x01, 0x10,
+ 0x04, 0x00, 0x01, 0x05, 0x01, 0xad, 0x01, 0xff, 0x01, 0xec, 0x01, 0x82,
+ 0xbc, 0x00,
+
+ /* 63 */
+ 0xff, 0x00, 0x58, 0x00, 0x01, 0x14, 0x05, 0x66, 0x01, 0x60, 0x0c, 0x00,
+ 0x01, 0x2b, 0x06, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0x02, 0x01, 0xef,
+ 0x06, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0x0c, 0x02, 0xff, 0x01, 0xeb,
+ 0x02, 0xaa, 0x01, 0xac, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0x4f,
+ 0x01, 0xff, 0x01, 0xf5, 0x03, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x0b, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0x70, 0x03, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0x30,
+ 0x03, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0x9f,
+ 0x01, 0xff, 0x01, 0x20, 0x03, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x0b, 0x00, 0x01, 0x6f, 0x01, 0xff, 0x01, 0x70, 0x03, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xf8,
+ 0x01, 0x20, 0x02, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00,
+ 0x01, 0x08, 0x07, 0xff, 0x01, 0xf2, 0x0c, 0x00, 0x01, 0x8f, 0x06, 0xff,
+ 0x01, 0xf2, 0x0c, 0x00, 0x01, 0x02, 0x01, 0x9d, 0x05, 0xff, 0x01, 0xf2,
+ 0x0d, 0x00, 0x01, 0x01, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x62, 0x01, 0x27,
+ 0x01, 0xff, 0x01, 0xf2, 0x0d, 0x00, 0x01, 0x0c, 0x01, 0xff, 0x01, 0xf7,
+ 0x01, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x0d, 0x00, 0x01, 0xcf,
+ 0x01, 0xff, 0x01, 0x80, 0x01, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x0c, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf9, 0x02, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf2, 0x0c, 0x00, 0x01, 0xaf, 0x01, 0xff, 0x01, 0xa0,
+ 0x02, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x0b, 0x00, 0x01, 0x09,
+ 0x01, 0xff, 0x01, 0xfa, 0x03, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x0b, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x01, 0xb0, 0x03, 0x00, 0x01, 0x05,
+ 0x01, 0xff, 0x01, 0xf2, 0x0a, 0x00, 0x01, 0x08, 0x01, 0xff, 0x01, 0xfb,
+ 0x04, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2, 0x0a, 0x00, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0xc0, 0x04, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf2,
+ 0x0a, 0x00, 0x02, 0x11, 0x06, 0x00, 0x01, 0x11, 0x01, 0x10, 0xbe, 0x00,
+
+ /* 64 */
+ 0x2c, 0x00, 0x01, 0xbd, 0x01, 0xdd, 0x01, 0x60, 0x01, 0x05, 0x01, 0xdd,
+ 0x01, 0xdc, 0x0e, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x70, 0x01, 0x06,
+ 0x01, 0xff, 0x01, 0xfe, 0x0e, 0x00, 0x01, 0xdf, 0x01, 0xff, 0x01, 0x70,
+ 0x01, 0x06, 0x01, 0xff, 0x01, 0xfe, 0x0e, 0x00, 0x01, 0xdf, 0x01, 0xff,
+ 0x01, 0x70, 0x01, 0x06, 0x01, 0xff, 0x01, 0xfe, 0x0e, 0x00, 0x01, 0x67,
+ 0x01, 0x77, 0x01, 0x30, 0x01, 0x02, 0x01, 0x77, 0x01, 0x76, 0x33, 0x00,
+ 0x01, 0x1c, 0x0a, 0xcc, 0x09, 0x00, 0x01, 0x1f, 0x0a, 0xff, 0x09, 0x00,
+ 0x01, 0x1f, 0x0a, 0xff, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xe8,
+ 0x08, 0x88, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xfe, 0x07, 0xee,
+ 0x01, 0xe4, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf5, 0x09, 0x00,
+ 0x01, 0x1f, 0x09, 0xff, 0x01, 0xf5, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xe7, 0x07, 0x77, 0x01, 0x72, 0x09, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00,
+ 0x01, 0x1f, 0x01, 0xff, 0x01, 0xc0, 0x11, 0x00, 0x01, 0x1f, 0x01, 0xff,
+ 0x01, 0xd4, 0x08, 0x44, 0x01, 0x30, 0x08, 0x00, 0x01, 0x1f, 0x0a, 0xff,
+ 0x01, 0xb0, 0x08, 0x00, 0x01, 0x1f, 0x0a, 0xff, 0x01, 0xb0, 0x08, 0x00,
+ 0x01, 0x1f, 0x0a, 0xff, 0x01, 0xb0, 0x08, 0x00, 0x01, 0x01, 0x0a, 0x11,
+ 0xbc, 0x00,
+
+ /* 65 */
+ 0xb6, 0x00, 0x01, 0x01, 0x02, 0x55, 0x01, 0x00, 0x01, 0x04, 0x01, 0x55,
+ 0x01, 0x52, 0x0d, 0x00, 0x01, 0x05, 0x02, 0xff, 0x01, 0x00, 0x01, 0x0d,
+ 0x01, 0xff, 0x01, 0xf7, 0x0d, 0x00, 0x01, 0x05, 0x02, 0xff, 0x01, 0x00,
+ 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf7, 0x0d, 0x00, 0x01, 0x05, 0x02, 0xff,
+ 0x01, 0x00, 0x01, 0x0d, 0x01, 0xff, 0x01, 0xf7, 0x0d, 0x00, 0x01, 0x04,
+ 0x02, 0xee, 0x01, 0x00, 0x01, 0x0c, 0x01, 0xee, 0x01, 0xe6, 0x4a, 0x00,
+ 0x01, 0x17, 0x01, 0xbe, 0x01, 0xff, 0x01, 0xdb, 0x01, 0x60, 0x0e, 0x00,
+ 0x01, 0x07, 0x04, 0xff, 0x01, 0xfe, 0x01, 0x50, 0x0d, 0x00, 0x01, 0xbf,
+ 0x05, 0xff, 0x01, 0xf7, 0x0c, 0x00, 0x01, 0x0a, 0x02, 0xff, 0x01, 0x94,
+ 0x01, 0x23, 0x01, 0x6c, 0x02, 0xff, 0x01, 0x50, 0x0b, 0x00, 0x01, 0x6f,
+ 0x01, 0xff, 0x01, 0xd2, 0x03, 0x00, 0x01, 0x7f, 0x01, 0xff, 0x01, 0xd0,
+ 0x0b, 0x00, 0x01, 0xef, 0x01, 0xfe, 0x01, 0x10, 0x03, 0x00, 0x01, 0x07,
+ 0x01, 0xff, 0x01, 0xf6, 0x0a, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf6,
+ 0x05, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x0a, 0x00, 0x01, 0x09, 0x01, 0xff,
+ 0x01, 0xf0, 0x05, 0x00, 0x01, 0x8f, 0x01, 0xff, 0x0a, 0x00, 0x01, 0x0d,
+ 0x01, 0xff, 0x01, 0xb0, 0x05, 0x00, 0x01, 0x4f, 0x01, 0xff, 0x01, 0x30,
+ 0x09, 0x00, 0x01, 0x0f, 0x01, 0xff, 0x01, 0xb5, 0x05, 0x55, 0x01, 0x7f,
+ 0x01, 0xff, 0x01, 0x50, 0x09, 0x00, 0x01, 0x1f, 0x09, 0xff, 0x01, 0x70,
+ 0x09, 0x00, 0x01, 0x2f, 0x09, 0xff, 0x01, 0x70, 0x09, 0x00, 0x01, 0x1f,
+ 0x01, 0xff, 0x01, 0xb7, 0x07, 0x77, 0x01, 0x40, 0x09, 0x00, 0x01, 0x0f,
+ 0x01, 0xff, 0x01, 0x80, 0x11, 0x00, 0x01, 0x0e, 0x01, 0xff, 0x01, 0xb0,
+ 0x11, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xe0, 0x05, 0x00, 0x01, 0x37,
+ 0x01, 0x77, 0x0a, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf5, 0x05, 0x00,
+ 0x01, 0xdf, 0x01, 0xfd, 0x0b, 0x00, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10,
+ 0x03, 0x00, 0x01, 0x06, 0x01, 0xff, 0x01, 0xf8, 0x0b, 0x00, 0x01, 0x8f,
+ 0x01, 0xff, 0x01, 0xc1, 0x03, 0x00, 0x01, 0x5f, 0x01, 0xff, 0x01, 0xf1,
+ 0x0b, 0x00, 0x01, 0x0c, 0x02, 0xff, 0x01, 0x94, 0x01, 0x23, 0x01, 0x6b,
+ 0x02, 0xff, 0x01, 0x60, 0x0b, 0x00, 0x01, 0x01, 0x01, 0xcf, 0x05, 0xff,
+ 0x01, 0xf8, 0x0d, 0x00, 0x01, 0x19, 0x04, 0xff, 0x01, 0xfe, 0x01, 0x50,
+ 0x0e, 0x00, 0x01, 0x27, 0x01, 0xce, 0x01, 0xff, 0x01, 0xda, 0x01, 0x50,
+ 0xc0, 0x00,
+
+ /* 48 */
+ 0xff, 0x00, 0x56, 0x00, 0x01, 0x67, 0x01, 0x72, 0x01, 0x00, 0x01, 0x29,
+ 0x01, 0xdf, 0x01, 0xff, 0x01, 0xc7, 0x01, 0x10, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf4, 0x01, 0x08, 0x04, 0xff, 0x01, 0xf6, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf4, 0x01, 0xaf, 0x05, 0xff, 0x01, 0x80, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xfc, 0x01, 0xff, 0x01, 0xf9, 0x01, 0x42, 0x01, 0x37, 0x01, 0xdf,
+ 0x01, 0xff, 0x01, 0xf6, 0x0b, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x30, 0x02, 0x00, 0x01, 0x09, 0x01, 0xff, 0x01, 0xfe, 0x01, 0x10,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf3, 0x04, 0x00, 0x01, 0xbf,
+ 0x01, 0xff, 0x01, 0x70, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0x90,
+ 0x04, 0x00, 0x01, 0x1f, 0x01, 0xff, 0x01, 0xd0, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x30, 0x04, 0x00, 0x01, 0x0a, 0x01, 0xff, 0x01, 0xf2,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfe, 0x05, 0x00, 0x01, 0x05, 0x01, 0xff,
+ 0x01, 0xf5, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x05, 0x00, 0x01, 0x02,
+ 0x01, 0xff, 0x01, 0xf7, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfa, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xf8, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xf9, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfa, 0x06, 0x00,
+ 0x01, 0xff, 0x01, 0xf9, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfb, 0x05, 0x00,
+ 0x01, 0x02, 0x01, 0xff, 0x01, 0xf8, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xfe,
+ 0x05, 0x00, 0x01, 0x05, 0x01, 0xff, 0x01, 0xf5, 0x0a, 0x00, 0x01, 0xef,
+ 0x01, 0xff, 0x01, 0x30, 0x04, 0x00, 0x01, 0x0b, 0x01, 0xff, 0x01, 0xf2,
+ 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xa0, 0x04, 0x00, 0x01, 0x2f,
+ 0x01, 0xff, 0x01, 0xd0, 0x0a, 0x00, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf4,
+ 0x04, 0x00, 0x01, 0xcf, 0x01, 0xff, 0x01, 0x70, 0x0a, 0x00, 0x01, 0xef,
+ 0x02, 0xff, 0x01, 0x40, 0x02, 0x00, 0x01, 0x1b, 0x01, 0xff, 0x01, 0xfe,
+ 0x01, 0x10, 0x0a, 0x00, 0x01, 0xef, 0x02, 0xff, 0x01, 0xfb, 0x01, 0x64,
+ 0x01, 0x58, 0x01, 0xef, 0x01, 0xff, 0x01, 0xf5, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0xaf, 0x05, 0xff, 0x01, 0x70, 0x0b, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x08, 0x04, 0xff, 0x01, 0xe4, 0x0c, 0x00, 0x01, 0xef,
+ 0x01, 0xf9, 0x01, 0x00, 0x01, 0x28, 0x01, 0xce, 0x01, 0xed, 0x01, 0xa5,
+ 0x0d, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9,
+ 0x12, 0x00, 0x01, 0xef, 0x01, 0xf9, 0x12, 0x00, 0x01, 0xde, 0x01, 0xe8,
+ 0x25, 0x00,
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.cpp
new file mode 100644
index 0000000..d9acb4f
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.cpp
@@ -0,0 +1,58 @@
+/*******************
+ * font_bitmap.cpp *
+ *******************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../ftdi_extended.h"
+
+#if ENABLED(FTDI_EXTENDED)
+
+namespace FTDI {
+
+ uint32_t write_rle_data(uint32_t addr, const uint8_t *data, size_t n) {
+ for (; n >= 2; n -= 2) {
+ uint8_t count = pgm_read_byte(data++);
+ uint8_t value = pgm_read_byte(data++);
+ CLCD::mem_write_fill(addr, value, count);
+ addr += count;
+ }
+ return addr;
+ }
+
+ void set_font_bitmap(CommandProcessor& cmd, CLCD::FontMetrics &fm, uint8_t handle) {
+ cmd.cmd(BITMAP_HANDLE(handle));
+ cmd.cmd(BITMAP_SOURCE(fm.ptr));
+ cmd.bitmap_layout(fm.format, fm.stride, fm.height);
+ cmd.bitmap_size(BILINEAR, BORDER, BORDER, fm.width, fm.height);
+ }
+
+ void ext_vertex2ii(CommandProcessor &cmd, int x, int y, uint8_t handle, uint8_t cell) {
+ if (x < 0 || y < 0 || x > 511 || y > 511) {
+ cmd.cmd(BITMAP_HANDLE(handle));
+ cmd.cmd(CELL(cell));
+ cmd.cmd(VERTEX2F(x * 16, y * 16));
+ }
+ else {
+ cmd.cmd(VERTEX2II(x, y, handle, cell));
+ }
+ }
+
+} // namespace FTDI
+
+#endif // FTDI_EXTENDED
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.h
new file mode 100644
index 0000000..2b0a533
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps.h
@@ -0,0 +1,30 @@
+/******************
+ * font_bitmaps.h *
+ ******************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+class CommandProcessor;
+
+namespace FTDI {
+ uint32_t write_rle_data(uint32_t addr, const uint8_t *data, size_t n);
+ void set_font_bitmap(CommandProcessor& cmd, CLCD::FontMetrics &fm, uint8_t handle);
+ void ext_vertex2ii(CommandProcessor &cmd, int x, int y, uint8_t handle, uint8_t cell);
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.png b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.png
new file mode 100644
index 0000000..bc46ebe
Binary files /dev/null and b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.png differ
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.svg b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.svg
new file mode 100644
index 0000000..25893f5
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/cyrillic_char_set_bitmap_31.svg
@@ -0,0 +1,535 @@
+
+
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.pbm b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.pbm
new file mode 100644
index 0000000..39cb670
Binary files /dev/null and b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.pbm differ
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.png b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.png
new file mode 100644
index 0000000..baafc82
Binary files /dev/null and b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/romfont_31.png differ
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.png b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.png
new file mode 100644
index 0000000..ef68192
Binary files /dev/null and b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.png differ
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.svg b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.svg
new file mode 100644
index 0000000..f803126
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_bitmaps/western_char_set_bitmap_31.svg
@@ -0,0 +1,443 @@
+
+
+
+
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.cpp
new file mode 100644
index 0000000..0e251f7
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.cpp
@@ -0,0 +1,46 @@
+/*******************
+ * font_size_t.cpp *
+ *******************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../ftdi_extended.h"
+
+#if BOTH(FTDI_EXTENDED, TOUCH_UI_USE_UTF8)
+
+namespace FTDI {
+ // Returns the height of a standard FTDI romfont
+ uint8_t font_size_t::get_romfont_height(uint8_t font) {
+ static const uint8_t tbl[] PROGMEM = {
+ 8, 8, 16, 16, 13, 17, 20, 22, 29, 38, 16, 20, 25, 28, 36, 49, 63, 83, 108
+ };
+ return pgm_read_byte(&tbl[font - 16]);
+ }
+
+ // Sets the scaling coefficient to match a romfont size
+ font_size_t font_size_t::from_romfont(uint8_t font) {
+ return font_size_t(uint32_t(std_height) * 256 / get_romfont_height(font));
+ }
+
+ // Returns the height of the font
+ uint8_t font_size_t::get_height() const {
+ return scale(std_height);
+ }
+}
+
+#endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.h
new file mode 100644
index 0000000..a2cb8b2
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/font_size_t.h
@@ -0,0 +1,55 @@
+/*****************
+ * font_size_t.h *
+ *****************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+class CommandProcessor;
+
+namespace FTDI {
+
+ /* The unicode rendering of different font sizes happens by scaling a
+ * large-sized font bitmap using the FTDI bitmap transformation matrix.
+ * This keeps us from having to have load bitmaps for all font sizes.
+ *
+ * The font_size_t class helps manage this scaling factor.
+ */
+ class font_size_t {
+ private:
+ // Standard height for font bitmaps
+ static constexpr uint8_t std_height = 49;
+
+ // 8.8 fixed point scaling coefficient
+ uint16_t coefficient;
+
+ font_size_t(uint16_t v) : coefficient(v) {}
+ public:
+ font_size_t() : coefficient(256) {}
+
+ static uint8_t get_romfont_height(uint8_t font);
+
+ static font_size_t from_romfont(uint8_t size);
+
+ template T scale(T val) const {return (int32_t(val) * 256 / coefficient);}
+
+ uint8_t get_height() const;
+ uint16_t get_coefficient() const {return coefficient;}
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.cpp
new file mode 100644
index 0000000..d12bf97
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.cpp
@@ -0,0 +1,107 @@
+/*************************
+ * standard_char_set.cpp *
+ *************************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../ftdi_extended.h"
+
+#if BOTH(FTDI_EXTENDED, TOUCH_UI_USE_UTF8)
+
+ constexpr static uint8_t std_font = 31;
+
+ /* Lookup table of the char widths for standard ROMFONT 31 */
+
+ uint8_t FTDI::StandardCharSet::std_char_width(char c) {
+ static const uint8_t tbl[] PROGMEM = {
+ 10, 11, 15, 26, 25, 31, 26, 10, 15, 14, 18, 24, 9, 18, 11, 17, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 10, 10, 21, 23, 22, 20, 37, 27, 27, 26,
+ 28, 23, 22, 28, 29, 12, 23, 26, 22, 35, 29, 28, 26, 29, 27, 26, 26, 28,
+ 27, 36, 27, 26, 25, 12, 18, 12, 18, 21, 13, 23, 24, 22, 24, 22, 15, 24,
+ 24, 10, 11, 22, 10, 36, 24, 24, 24, 24, 15, 22, 14, 24, 21, 32, 21, 21,
+ 22, 15, 10, 15, 29, 10
+ };
+ return pgm_read_byte(&tbl[c - ' ']);
+ }
+
+ /**
+ * Load bitmap data into RAMG. This function is called once at the start
+ * of the program.
+ *
+ * Parameters:
+ *
+ * addr - Address in RAMG where the font data is written
+ */
+
+ uint32_t FTDI::StandardCharSet::load_data(uint32_t addr) {
+ return addr;
+ }
+
+ /**
+ * Populates the bitmap handles for the custom into the display list.
+ * This function is called once at the start of each display list.
+ *
+ * Parameters:
+ *
+ * cmd - Object used for writing to the FTDI chip command queue.
+ */
+
+ void FTDI::StandardCharSet::load_bitmaps(CommandProcessor& cmd) {
+ CLCD::FontMetrics std_fm(std_font);
+ set_font_bitmap(cmd, std_fm, std_font);
+ }
+
+ /**
+ * Renders a character at location x and y. The x position is incremented
+ * by the width of the character.
+ *
+ * Parameters:
+ *
+ * cmd - If non-NULL the symbol is drawn to the screen.
+ * If NULL, only increment position for text measurement.
+ *
+ * x, y - The location at which to draw the character. On output,
+ * incremented to the location of the next character.
+ *
+ * fs - A scaling object used to scale the font. The display will
+ * already be configured to scale bitmaps, but positions
+ * must be scaled using fs.scale()
+ *
+ * c - The unicode code point to draw. If the renderer does not
+ * support the character, it should draw nothing.
+ */
+
+ bool FTDI::StandardCharSet::render_glyph(CommandProcessor* cmd, int &x, int &y, font_size_t fs, utf8_char_t c) {
+ uint8_t which = (c >= ' ' && c < 128) ? c : '?';
+ uint8_t width = std_char_width(which);
+
+ if (c == '\t') {
+ // Special handling for the tab character
+ which = ' ';
+ width = std_char_width(' ');
+ }
+
+ // Draw the character
+ if (cmd) ext_vertex2ii(*cmd, x, y, std_font, which);
+
+ // Increment X to the next character position
+ x += fs.scale(width);
+ return true;
+ }
+
+#endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.h
new file mode 100644
index 0000000..48794d4
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/standard_char_set.h
@@ -0,0 +1,30 @@
+/***********************
+ * standard_char_set.h *
+ ***********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+namespace FTDI {
+ class StandardCharSet {
+ public:
+ static uint8_t std_char_width(char);
+ static uint32_t load_data(uint32_t addr);
+ static void load_bitmaps(CommandProcessor&);
+ static bool render_glyph(CommandProcessor*, int &x, int &y, font_size_t, utf8_char_t);
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp
new file mode 100644
index 0000000..39b8759
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp
@@ -0,0 +1,238 @@
+/***************
+ * unicode.cpp *
+ ***************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../ftdi_extended.h"
+
+#if BOTH(FTDI_EXTENDED, TOUCH_UI_USE_UTF8)
+
+ using namespace FTDI;
+
+ /**
+ * Return true if a string has UTF8 characters
+ *
+ * Parameters:
+ *
+ * c - Pointer to a string.
+ *
+ * Returns: True if the strings has UTF8 characters
+ */
+
+ bool FTDI::has_utf8_chars(const char *str) {
+ for (;;) {
+ const char c = *str++;
+ if (!c) break;
+ if ((c & 0xC0) == 0x80) return true;
+ }
+ return false;
+ }
+
+ bool FTDI::has_utf8_chars(progmem_str _str) {
+ const char *str = (const char *) _str;
+ for (;;) {
+ const char c = pgm_read_byte(str++);
+ if (!c) break;
+ if ((c & 0xC0) == 0x80) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return a character in a UTF8 string and increment the
+ * pointer to the next character
+ *
+ * Parameters:
+ *
+ * c - Pointer to a UTF8 encoded string.
+ *
+ * Returns: The packed bytes of a UTF8 encoding of a single
+ * character (this is not the unicode codepoint)
+ */
+
+ utf8_char_t FTDI::get_utf8_char_and_inc(const char *&c) {
+ utf8_char_t val = *(uint8_t*)c++;
+ while ((*c & 0xC0) == 0x80)
+ val = (val << 8) | *(uint8_t*)c++;
+ return val;
+ }
+
+ utf8_char_t FTDI::get_utf8_char_and_inc(char *&c) {
+ utf8_char_t val = *(uint8_t*)c++;
+ while ((*c & 0xC0) == 0x80)
+ val = (val << 8) | *(uint8_t*)c++;
+ return val;
+ }
+
+ /**
+ * Helper function to draw and/or measure a UTF8 string
+ *
+ * Parameters:
+ *
+ * cmd - If non-NULL the symbol is drawn to the screen.
+ * If NULL, only increment position for text measurement.
+ *
+ * x, y - The location at which to draw the string.
+ *
+ * str - The UTF8 string to draw or measure.
+ *
+ * fs - A scaling object used to specify the font size.
+ */
+
+ static uint16_t render_utf8_text(CommandProcessor* cmd, int x, int y, const char *str, font_size_t fs) {
+ const int start_x = x;
+ while (*str) {
+ const utf8_char_t c = get_utf8_char_and_inc(str);
+ #ifdef TOUCH_UI_UTF8_CYRILLIC_CHARSET
+ CyrillicCharSet::render_glyph(cmd, x, y, fs, c) ||
+ #endif
+ #ifdef TOUCH_UI_UTF8_WESTERN_CHARSET
+ WesternCharSet::render_glyph(cmd, x, y, fs, c) ||
+ #endif
+ StandardCharSet::render_glyph(cmd, x, y, fs, c);
+ }
+ return x - start_x;
+ }
+
+ /**
+ * Load the font bitmap data into RAMG. Called once at program start.
+ *
+ * Parameters:
+ *
+ * addr - Address in RAMG where the font data is written
+ */
+
+ void FTDI::load_utf8_data(uint32_t addr) {
+ #ifdef TOUCH_UI_UTF8_CYRILLIC_CHARSET
+ addr = CyrillicCharSet::load_data(addr);
+ #endif
+ #ifdef TOUCH_UI_UTF8_WESTERN_CHARSET
+ addr = WesternCharSet::load_data(addr);
+ #endif
+ addr = StandardCharSet::load_data(addr);
+ }
+
+ /**
+ * Populate the bitmap handles for the custom fonts into the display list.
+ * Called once at the start of each display list.
+ *
+ * Parameters:
+ *
+ * cmd - Object used for writing to the FTDI chip command queue.
+ */
+
+ void FTDI::load_utf8_bitmaps(CommandProcessor &cmd) {
+ #ifdef TOUCH_UI_UTF8_CYRILLIC_CHARSET
+ CyrillicCharSet::load_bitmaps(cmd);
+ #endif
+ #ifdef TOUCH_UI_UTF8_WESTERN_CHARSET
+ WesternCharSet::load_bitmaps(cmd);
+ #endif
+ StandardCharSet::load_bitmaps(cmd);
+ }
+
+ /**
+ * Measure a UTF8 text character
+ *
+ * Parameters:
+ *
+ * c - The unicode code point to measure.
+ *
+ * fs - A scaling object used to specify the font size.
+ *
+ * Returns: A width in pixels
+ */
+
+ uint16_t FTDI::get_utf8_char_width(utf8_char_t c, font_size_t fs) {
+ int x = 0, y = 0;
+ #ifdef TOUCH_UI_UTF8_CYRILLIC_CHARSET
+ CyrillicCharSet::render_glyph(nullptr, x, y, fs, c) ||
+ #endif
+ #ifdef TOUCH_UI_UTF8_WESTERN_CHARSET
+ WesternCharSet::render_glyph(nullptr, x, y, fs, c) ||
+ #endif
+ StandardCharSet::render_glyph(nullptr, x, y, fs, c);
+ return x;
+ }
+
+ /**
+ * Measure a UTF8 text string
+ *
+ * Parameters:
+ *
+ * str - The UTF8 string to measure.
+ *
+ * fs - A scaling object used to specify the font size.
+ *
+ * Returns: A width in pixels
+ */
+
+ uint16_t FTDI::get_utf8_text_width(const char *str, font_size_t fs) {
+ return render_utf8_text(nullptr, 0, 0, str, fs);
+ }
+
+ uint16_t FTDI::get_utf8_text_width(progmem_str pstr, font_size_t fs) {
+ char str[strlen_P((const char*)pstr) + 1];
+ strcpy_P(str, (const char*)pstr);
+ return get_utf8_text_width(str, fs);
+ }
+
+ /**
+ * Draw a UTF8 text string
+ *
+ * Parameters:
+ *
+ * cmd - Object used for writing to the FTDI chip command queue.
+ *
+ * x, y - The location at which to draw the string.
+ *
+ * str - The UTF8 string to draw.
+ *
+ * fs - A scaling object used to specify the font size.
+ *
+ * options - Text alignment options (i.e. OPT_CENTERX, OPT_CENTERY, OPT_CENTER or OPT_RIGHTX)
+ *
+ */
+
+ void FTDI::draw_utf8_text(CommandProcessor& cmd, int x, int y, const char *str, font_size_t fs, uint16_t options) {
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(BITMAP_TRANSFORM_A(fs.get_coefficient()));
+ cmd.cmd(BITMAP_TRANSFORM_E(fs.get_coefficient()));
+ cmd.cmd(BEGIN(BITMAPS));
+
+ // Apply alignment options
+ if (options & OPT_CENTERX)
+ x -= get_utf8_text_width(str, fs) / 2;
+ else if (options & OPT_RIGHTX)
+ x -= get_utf8_text_width(str, fs);
+ if (options & OPT_CENTERY)
+ y -= fs.get_height()/2;
+
+ // Render the text
+ render_utf8_text(&cmd, x, y, str, fs);
+ cmd.cmd(RESTORE_CONTEXT());
+ }
+
+ void FTDI::draw_utf8_text(CommandProcessor& cmd, int x, int y, progmem_str pstr, font_size_t fs, uint16_t options) {
+ char str[strlen_P((const char*)pstr) + 1];
+ strcpy_P(str, (const char*)pstr);
+ draw_utf8_text(cmd, x, y, (const char*) str, fs, options);
+ }
+
+#endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.h
new file mode 100644
index 0000000..5bb87d9
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.h
@@ -0,0 +1,112 @@
+/*************
+ * unicode.h *
+ *************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+class CommandProcessor;
+
+namespace FTDI {
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ typedef uint16_t utf8_char_t;
+
+ /**
+ * Converts a 32-bit codepoint into UTF-8. This compile-time function
+ * will be useful until the u8'a' character literal becomes more common.
+ */
+ constexpr uint32_t utf8(const uint32_t c) {
+ return (c < 0x7F ) ? c :
+ (c < 0x7FF) ? (0x0000C080 | ((c & 0b011111000000) << 2) | (c & 0b111111)) :
+ (c < 0xFFFF) ? (0x00E08080 | ((c & 0b001111000000000000) << 4) | ((c & 0b111111000000) << 2) | (c & 0b111111)) :
+ (0xF0808080 | ((c & 0b000111000000000000000000) << 6) | ((c & 0b111111000000000000) << 4) | ((c & 0b111111000000) << 2) | (c & 0b111111));
+ }
+
+ /* Returns true if the string has UTF8 string characters */
+
+ bool has_utf8_chars(progmem_str str);
+ bool has_utf8_chars(const char *str);
+
+ /* Returns the next character in a UTF8 string and increments the
+ * pointer to the next character */
+
+ utf8_char_t get_utf8_char_and_inc(const char *&c);
+ utf8_char_t get_utf8_char_and_inc(char *&c);
+
+ /* Returns the next character in a UTF8 string, without incrementing */
+
+ inline utf8_char_t get_utf8_char(const char *c) {return get_utf8_char_and_inc(c);}
+
+ void load_utf8_data(uint32_t addr);
+ #else
+ typedef char utf8_char_t;
+
+ inline utf8_char_t get_utf8_char_and_inc(const char *&c) {return *c++;}
+ inline utf8_char_t get_utf8_char(const char *c) {return *c;}
+
+ inline void load_utf8_data(uint32_t) {}
+ #endif
+
+ void load_utf8_bitmaps(CommandProcessor& cmd);
+
+ uint16_t get_utf8_char_width(utf8_char_t, font_size_t);
+ uint16_t get_utf8_text_width(progmem_str, font_size_t);
+ uint16_t get_utf8_text_width(const char *, font_size_t);
+
+ void draw_utf8_text(CommandProcessor&, int x, int y, progmem_str, font_size_t, uint16_t options = 0);
+ void draw_utf8_text(CommandProcessor&, int x, int y, const char *, font_size_t, uint16_t options = 0);
+
+ // Similar to CLCD::FontMetrics, but can be used with UTF8 encoded strings.
+
+ struct FontMetrics {
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ font_size_t fs;
+ #else
+ CLCD::FontMetrics fm;
+ #endif
+
+ inline void load(uint8_t rom_font_size) {
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ fs = font_size_t::from_romfont(rom_font_size);
+ #else
+ fm.load(rom_font_size);
+ #endif
+ }
+
+ inline uint16_t get_char_width(utf8_char_t c) const {
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ return get_utf8_char_width(c, fs);
+ #else
+ return fm.char_widths[(uint8_t)c];
+ #endif
+ }
+
+ inline uint8_t get_height() const {
+ #if ENABLED(TOUCH_UI_USE_UTF8)
+ return fs.get_height();
+ #else
+ return fm.height;
+ #endif
+ }
+
+ inline FontMetrics(uint8_t rom_font_size) {
+ load(rom_font_size);
+ }
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.cpp
new file mode 100644
index 0000000..4fb2f8f
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.cpp
@@ -0,0 +1,455 @@
+/************************
+ * western_char_set.cpp *
+ ************************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../ftdi_extended.h"
+
+#if ALL(FTDI_EXTENDED, TOUCH_UI_USE_UTF8, TOUCH_UI_UTF8_WESTERN_CHARSET)
+
+ #include "western_char_set_bitmap_31.h"
+
+ #define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
+
+ using namespace FTDI;
+
+ constexpr static uint8_t std_font = 31;
+ constexpr static uint8_t alt_font = 1;
+
+ uint32_t FTDI::WesternCharSet::bitmap_addr;
+
+ /* Glyphs in the WesternCharSet bitmap */
+
+ enum {
+ GRAVE,
+ ACUTE,
+ CIRCUMFLEX,
+ TILDE,
+ DIAERESIS,
+ DOT_ABOVE,
+ CEDILLA,
+ NO_DOT_I,
+ #if ENABLED(TOUCH_UI_UTF8_GERMANIC)
+ SHARP_S,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ LRG_O_STROKE,
+ SML_O_STROKE,
+ LRG_AE,
+ SML_AE,
+ LRG_ETH,
+ SML_ETH,
+ LRG_THORN,
+ SML_THORN,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
+ LEFT_DBL_QUOTE,
+ RIGHT_DBL_QUOTE,
+ INV_EXCLAMATION,
+ INV_QUESTION,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_CURRENCY)
+ CENT_SIGN,
+ POUND_SIGN,
+ CURRENCY_SIGN,
+ YEN_SIGN,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
+ SUPERSCRIPT_1,
+ SUPERSCRIPT_2,
+ SUPERSCRIPT_3,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
+ MASCULINE_ORDINAL,
+ FEMININE_ORDINAL,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
+ COPYRIGHT_SIGN,
+ REGISTERED_SIGN,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
+ PLUS_MINUS_SIGN,
+ MULTIPLICATION_SIGN,
+ DIVISION_SIGN,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
+ FRACTION_QUARTER,
+ FRACTION_HALF,
+ FRACTION_THREE_FOURTHS,
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
+ MICRON_SIGN,
+ PILCROW_SIGN,
+ BROKEN_BAR,
+ SECTION_SIGN,
+ NOT_SIGN
+ #endif
+ };
+
+ /* Centerline of characters that can take accents */
+
+ constexpr int8_t mid_a = 12,
+ mid_e = 12,
+ mid_i = 5,
+ mid_o = 12,
+ mid_u = 12,
+ mid_y = 11,
+ mid_n = 12,
+ mid_c = 12,
+ mid_A = 13,
+ mid_E = 13,
+ mid_I = 6,
+ mid_O = 14,
+ mid_U = 14,
+ mid_Y = 13,
+ mid_N = 15,
+ mid_C = 13;
+
+ /* Centerline of accent glyphs */
+
+ constexpr int8_t mid_accent = 16;
+
+ /* When reusing the DOT_ABOVE accent glyph for the degree sign, we need to trim the leading space */
+ constexpr uint8_t deg_sign_leading = 9;
+
+ /* Look-up table for constructing characters (must be ordered by unicode)
+ *
+ * Characters are either complete symbols from the Western Char Set bitmap,
+ * or they are constructed using a standard letter from the romfont and
+ * drawing an accent from the Western Char Set bitmap over it.
+ */
+
+ #define UTF8(A) uint16_t(utf8(U##A))
+
+ PROGMEM constexpr struct {
+ uint16_t unicode;
+ uint8_t std_char; // Glyph from standard ROMFONT (zero if none)
+ uint8_t alt_char; // Glyph from Western Char Set bitmap
+ uint8_t alt_data; // For accented characters, the centerline; else char width
+ } char_recipe[] = {
+ {0, 0, NO_DOT_I, 10 },
+ #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
+ {UTF8('¡'), 0 , INV_EXCLAMATION, 13 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_CURRENCY)
+ {UTF8('¢'), 0 , CENT_SIGN, 23 },
+ {UTF8('£'), 0 , POUND_SIGN, 24 },
+ {UTF8('¤'), 0 , CURRENCY_SIGN, 26 },
+ {UTF8('¥'), 0 , YEN_SIGN, 26 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
+ {UTF8('¦'), 0 , BROKEN_BAR, 11 },
+ {UTF8('§'), 0 , SECTION_SIGN, 21 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
+ {UTF8('©'), 0 , COPYRIGHT_SIGN, 38 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
+ {UTF8('ª'), 0 , FEMININE_ORDINAL, 19 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
+ {UTF8('«'), 0 , LEFT_DBL_QUOTE, 23 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
+ {UTF8('¬'), 0 , NOT_SIGN, 32 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
+ {UTF8('®'), 0 , REGISTERED_SIGN, 38 },
+ #endif
+ {UTF8('°'), 0 , DOT_ABOVE, 24 },
+ #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
+ {UTF8('±'), 0 , NOT_SIGN, 32 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
+ {UTF8('²'), 0 , SUPERSCRIPT_2, 16 },
+ {UTF8('³'), 0 , SUPERSCRIPT_3, 16 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
+ {UTF8('µ'), 0 , MICRON_SIGN, 28 },
+ {UTF8('¶'), 0 , PILCROW_SIGN, 24 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
+ {UTF8('¹'), 0 , SUPERSCRIPT_1, 16 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_ORDINALS)
+ {UTF8('º'), 0 , MASCULINE_ORDINAL, 19 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
+ {UTF8('»'), 0 , RIGHT_DBL_QUOTE, 24 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
+ {UTF8('¼'), 0 , FRACTION_QUARTER, 40 },
+ {UTF8('½'), 0 , FRACTION_HALF, 40 },
+ {UTF8('¾'), 0 , FRACTION_THREE_FOURTHS, 40 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
+ {UTF8('¿'), 0 , INV_QUESTION, 21 },
+ #endif
+ {UTF8('À'), 'A', GRAVE, mid_A},
+ {UTF8('Á'), 'A', ACUTE, mid_A},
+ {UTF8('Â'), 'A', CIRCUMFLEX, mid_A},
+ {UTF8('Ã'), 'A', TILDE, mid_A},
+ {UTF8('Ä'), 'A', DIAERESIS, mid_A},
+ {UTF8('Å'), 'A', DOT_ABOVE, mid_A},
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('Æ'), 0 , LRG_AE, 40},
+ #endif
+ {UTF8('Ç'), 'C', CEDILLA, mid_C},
+ {UTF8('È'), 'E', GRAVE, mid_E},
+ {UTF8('É'), 'E', ACUTE, mid_E},
+ {UTF8('Ê'), 'E', CIRCUMFLEX, mid_E},
+ {UTF8('Ë'), 'E', DIAERESIS, mid_E},
+ {UTF8('Ì'), 'I', GRAVE, mid_I},
+ {UTF8('Í'), 'I', ACUTE, mid_I},
+ {UTF8('Î'), 'I', CIRCUMFLEX, mid_I},
+ {UTF8('Ï'), 'I', DIAERESIS, mid_I},
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('Ð'), 0, LRG_ETH, 31 },
+ #endif
+ {UTF8('Ñ'), 'N', TILDE, mid_N},
+ {UTF8('Ò'), 'O', GRAVE, mid_O},
+ {UTF8('Ó'), 'O', ACUTE, mid_O},
+ {UTF8('Ô'), 'O', CIRCUMFLEX, mid_O},
+ {UTF8('Õ'), 'O', TILDE, mid_O},
+ {UTF8('Ö'), 'O', DIAERESIS, mid_O},
+ #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
+ {UTF8('×'), 0 , MULTIPLICATION_SIGN, 32 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('Ø'), 0 , LRG_O_STROKE, 32 },
+ #endif
+ {UTF8('Ù'), 'U', GRAVE, mid_U},
+ {UTF8('Ú'), 'U', ACUTE, mid_U},
+ {UTF8('Û'), 'U', CIRCUMFLEX, mid_U},
+ {UTF8('Ü'), 'U', DIAERESIS, mid_U},
+ {UTF8('Ý'), 'Y', ACUTE, mid_Y},
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('Þ'), 0 , LRG_THORN, 25 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_GERMANIC)
+ {UTF8('ß'), 0 , SHARP_S, 26 },
+ #endif
+ {UTF8('à'), 'a', GRAVE, mid_a},
+ {UTF8('á'), 'a', ACUTE, mid_a},
+ {UTF8('â'), 'a', CIRCUMFLEX, mid_a},
+ {UTF8('ã'), 'a', TILDE, mid_a},
+ {UTF8('ä'), 'a', DIAERESIS, mid_a},
+ {UTF8('å'), 'a', DOT_ABOVE, mid_a},
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('æ'), 0 , SML_AE, 40 },
+ #endif
+ {UTF8('ç'), 'c', CEDILLA, mid_c},
+ {UTF8('è'), 'e', GRAVE, mid_e},
+ {UTF8('é'), 'e', ACUTE, mid_e},
+ {UTF8('ê'), 'e', CIRCUMFLEX, mid_e},
+ {UTF8('ë'), 'e', DIAERESIS, mid_e},
+ {UTF8('ì'), 'i', GRAVE, mid_i},
+ {UTF8('í'), 'i', ACUTE, mid_i},
+ {UTF8('î'), 'i', CIRCUMFLEX, mid_i},
+ {UTF8('ï'), 'i', DIAERESIS, mid_i},
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('ð'), 0, SML_ETH, 24 },
+ #endif
+ {UTF8('ñ'), 'n', TILDE, mid_n},
+ {UTF8('ò'), 'o', GRAVE, mid_o},
+ {UTF8('ó'), 'o', ACUTE, mid_o},
+ {UTF8('ô'), 'o', CIRCUMFLEX, mid_o},
+ {UTF8('õ'), 'o', TILDE, mid_o},
+ {UTF8('ö'), 'o', DIAERESIS, mid_o},
+ #if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
+ {UTF8('÷'), 0 , DIVISION_SIGN, 32 },
+ #endif
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('ø'), 0 , SML_O_STROKE, 25 },
+ #endif
+ {UTF8('ù'), 'u', GRAVE, mid_u},
+ {UTF8('ú'), 'u', ACUTE, mid_u},
+ {UTF8('û'), 'u', CIRCUMFLEX, mid_u},
+ {UTF8('ü'), 'u', DIAERESIS, mid_u},
+ {UTF8('ý'), 'y', ACUTE, mid_y},
+ #if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ {UTF8('þ'), 0 , SML_THORN, 25 },
+ #endif
+ {UTF8('ÿ'), 'y', DIAERESIS, mid_y},
+ };
+
+ static_assert(UTF8('¡') == 0xC2A1, "Incorrect encoding for character");
+
+ /* Compile-time check that the table is in sorted order */
+
+ constexpr bool is_sorted(size_t n) {
+ return n < 2 ? true : char_recipe[n-2].unicode < char_recipe[n-1].unicode && is_sorted(n-1);
+ }
+
+ static_assert(is_sorted(NUM_ELEMENTS(char_recipe)), "The table must be sorted by unicode value");
+
+ /* Performs a binary search to find a unicode character in the table */
+
+ static int8_t find_char_data(FTDI::utf8_char_t c) {
+ int8_t min = 0, max = NUM_ELEMENTS(char_recipe), index;
+ for (;;) {
+ index = (min + max)/2;
+ const uint16_t char_at = pgm_read_word(&char_recipe[index].unicode);
+ if (char_at == c) break;
+ if (min == max) return -1;
+ if (c > char_at)
+ min = index + 1;
+ else
+ max = index;
+ }
+ return index;
+ }
+
+ static void get_char_data(uint8_t index, uint8_t &std_char, uint8_t &alt_char, uint8_t &alt_data) {
+ std_char = pgm_read_byte(&char_recipe[index].std_char);
+ alt_char = pgm_read_byte(&char_recipe[index].alt_char);
+ alt_data = pgm_read_byte(&char_recipe[index].alt_data);
+ }
+
+ /**
+ * Load bitmap data into RAMG. This function is called once at the start
+ * of the program.
+ *
+ * Parameters:
+ *
+ * addr - Address in RAMG where the font data is written
+ */
+
+ uint32_t FTDI::WesternCharSet::load_data(uint32_t addr) {
+ if (addr % 4 != 0)
+ addr += 4 - (addr % 4);
+
+ // Load the alternative font metrics
+ CLCD::FontMetrics alt_fm;
+ alt_fm.ptr = addr + 148;
+ alt_fm.format = L4;
+ alt_fm.stride = 19;
+ alt_fm.width = 38;
+ alt_fm.height = 49;
+ LOOP_L_N(i, 127)
+ alt_fm.char_widths[i] = 0;
+
+ // For special characters, copy the character widths from the char tables
+ LOOP_L_N(i, NUM_ELEMENTS(char_recipe)) {
+ uint8_t std_char, alt_char, alt_data;
+ get_char_data(i, std_char, alt_char, alt_data);
+ if (std_char == 0)
+ alt_fm.char_widths[alt_char] = alt_data;
+ }
+ CLCD::mem_write_bulk(addr, &alt_fm, 148);
+
+ // Decode the RLE data and load it into RAMG as a bitmap
+ uint32_t lastaddr = write_rle_data(addr + 148, font, sizeof(font));
+
+ bitmap_addr = addr;
+
+ return lastaddr;
+ }
+
+ /**
+ * Populates the bitmap handles for the custom into the display list.
+ * This function is called once at the start of each display list.
+ *
+ * Parameters:
+ *
+ * cmd - Object used for writing to the FTDI chip command queue.
+ */
+
+ void FTDI::WesternCharSet::load_bitmaps(CommandProcessor& cmd) {
+ CLCD::FontMetrics alt_fm;
+ alt_fm.ptr = bitmap_addr + 148;
+ alt_fm.format = L4;
+ alt_fm.stride = 19;
+ alt_fm.width = 38;
+ alt_fm.height = 49;
+ set_font_bitmap(cmd, alt_fm, alt_font);
+ }
+
+ /**
+ * Renders a character at location x and y. The x position is incremented
+ * by the width of the character.
+ *
+ * Parameters:
+ *
+ * cmd - If non-NULL the symbol is drawn to the screen.
+ * If NULL, only increment position for text measurement.
+ *
+ * x, y - The location at which to draw the character. On output,
+ * incremented to the location of the next character.
+ *
+ * fs - A scaling object used to scale the font. The display will
+ * already be configured to scale bitmaps, but positions
+ * must be scaled using fs.scale()
+ *
+ * c - The unicode code point to draw. If the renderer does not
+ * support the character, it should return false.
+ *
+ * Returns: Whether the character was supported.
+ */
+
+ bool FTDI::WesternCharSet::render_glyph(CommandProcessor* cmd, int &x, int &y, font_size_t fs, utf8_char_t c) {
+
+ // A supported character?
+ if (c < UTF8('¡') || c > UTF8('ÿ')) return false;
+
+ int8_t index = find_char_data(c);
+ if (index == -1) return false;
+
+ // Determine character characteristics
+ uint8_t std_char, alt_char, alt_data;
+ get_char_data(index, std_char, alt_char, alt_data);
+
+ bool base_special;
+ uint8_t base_width;
+ uint8_t base_char;
+ uint8_t accent_char;
+ int8_t accent_dx, accent_dy;
+
+ if (std_char == 0) {
+ // Special character, non-accented
+ base_width = alt_data;
+ base_special = true;
+ base_char = alt_char;
+ accent_char = 0;
+ if (c == UTF8('°'))
+ x -= fs.scale(deg_sign_leading);
+ }
+ else {
+ // Regular character with accent:
+ accent_dx = alt_data - mid_accent;
+ accent_dy = isupper(std_char) ? -7 : 0;
+ accent_char = alt_char;
+ base_width = StandardCharSet::std_char_width(std_char);
+ base_special = std_char == 'i';
+ base_char = base_special ? NO_DOT_I : std_char;
+ }
+
+ // If cmd != nullptr, draw the glyph to the screen
+ if (cmd) {
+ ext_vertex2ii(*cmd, x, y, base_special ? alt_font : std_font, base_char);
+ if (accent_char)
+ ext_vertex2ii(*cmd, x + fs.scale(accent_dx), y + fs.scale(accent_dy), alt_font, accent_char);
+ }
+
+ // Increment X to the next character position
+ x += fs.scale(base_width);
+ return true;
+ }
+
+#endif // FTDI_EXTENDED && TOUCH_UI_USE_UTF8 && TOUCH_UI_UTF8_WESTERN_CHARSET
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.h
new file mode 100644
index 0000000..683093d
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set.h
@@ -0,0 +1,31 @@
+/**********************
+ * western_char_set.h *
+ **********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+namespace FTDI {
+ class WesternCharSet {
+ private:
+ static uint32_t bitmap_addr;
+ public:
+ static uint32_t load_data(uint32_t addr);
+ static void load_bitmaps(CommandProcessor&);
+ static bool render_glyph(CommandProcessor*, int &x, int &y, font_size_t, utf8_char_t);
+ };
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set_bitmap_31.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set_bitmap_31.h
new file mode 100644
index 0000000..3f85cf0
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/western_char_set_bitmap_31.h
@@ -0,0 +1,1315 @@
+/********************************
+ * western_european_bitmap_31.h *
+ ********************************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/* This is a dump of "font_bitmaps/western_european_bitmap_31.png"
+ * using the tool "bitmap2cpp.py". The tool converts the image into
+ * 16-level grayscale and packs two pixels per byte. The resulting
+ * bytes are then RLE compressed to yield (count, byte) pairs.
+ */
+
+const unsigned char font[] PROGMEM = {
+
+ /* 0 GRAVE */
+ 0x76, 0x00, 0x01, 0x08, 0x01, 0xEE, 0x01, 0xE5, 0x11, 0x00, 0x01, 0xAF,
+ 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xD0,
+ 0x10, 0x00, 0x01, 0x01, 0x01, 0xDF, 0x01, 0xF9, 0x11, 0x00, 0x01, 0x2E,
+ 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF2,
+ 0x11, 0x00, 0x01, 0x5F, 0x01, 0xFD, 0x11, 0x00, 0x01, 0x06, 0x01, 0x99,
+ 0x01, 0x40, 0xFF, 0x00, 0xFF, 0x00, 0xA4, 0x00,
+
+ /* 1 ACUTE */
+ 0x7B, 0x00, 0x01, 0x9E, 0x01, 0xEE, 0x01, 0x50, 0x0F, 0x00, 0x01, 0x05,
+ 0x01, 0xFF, 0x01, 0xF8, 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x09, 0x01, 0xFF,
+ 0x01, 0xD1, 0x10, 0x00, 0x01, 0x4F, 0x01, 0xFE, 0x01, 0x20, 0x0F, 0x00,
+ 0x01, 0x01, 0x01, 0xEF, 0x01, 0xF3, 0x10, 0x00, 0x01, 0x07, 0x01, 0xAA,
+ 0x01, 0x40, 0xFF, 0x00, 0xFF, 0x00, 0xA5, 0x00,
+
+ /* 2 CIRCUMFLEX */
+ 0x79, 0x00, 0x01, 0xCF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x07, 0x02, 0xFF,
+ 0x01, 0x60, 0x0F, 0x00, 0x01, 0x2F, 0x02, 0xFF, 0x01, 0xF2, 0x0F, 0x00,
+ 0x01, 0xCF, 0x01, 0xF6, 0x01, 0x6F, 0x01, 0xFB, 0x0E, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xA0, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0x60, 0x0D, 0x00,
+ 0x01, 0x1F, 0x01, 0xFD, 0x01, 0x00, 0x01, 0x01, 0x01, 0xDF, 0x01, 0xF1,
+ 0x0D, 0x00, 0x01, 0xBF, 0x01, 0xF3, 0x02, 0x00, 0x01, 0x3F, 0x01, 0xFB,
+ 0x0C, 0x00, 0x01, 0x02, 0x01, 0x99, 0x01, 0x50, 0x02, 0x00, 0x01, 0x05,
+ 0x01, 0x99, 0x01, 0x20, 0xFF, 0x00, 0xFF, 0x00, 0xA2, 0x00,
+
+ /* 3 TILDE */
+ 0x7C, 0x00, 0x01, 0x11, 0x0D, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xC3,
+ 0x02, 0x00, 0x01, 0xFF, 0x01, 0x80, 0x0C, 0x00, 0x01, 0xAF, 0x02, 0xFF,
+ 0x01, 0x50, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x60, 0x0B, 0x00, 0x01, 0x02,
+ 0x01, 0xFF, 0x01, 0xD9, 0x01, 0xFF, 0x01, 0xF7, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0x40, 0x0B, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0x20, 0x01, 0x3E,
+ 0x02, 0xFF, 0x01, 0xFD, 0x0C, 0x00, 0x01, 0x09, 0x01, 0xFE, 0x01, 0x00,
+ 0x01, 0x02, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xF4, 0x0C, 0x00, 0x01, 0x07,
+ 0x01, 0xA8, 0x02, 0x00, 0x01, 0x06, 0x01, 0x98, 0x01, 0x20, 0xFF, 0x00,
+ 0xFF, 0x00, 0xB6, 0x00,
+
+ /* 4 DIAERESIS */
+ 0x8A, 0x00, 0x02, 0x44, 0x02, 0x00, 0x02, 0x44, 0x0D, 0x00, 0x02, 0xFF,
+ 0x01, 0x10, 0x01, 0x01, 0x02, 0xFF, 0x0D, 0x00, 0x02, 0xFF, 0x01, 0x10,
+ 0x01, 0x01, 0x02, 0xFF, 0x0D, 0x00, 0x02, 0xFF, 0x01, 0x10, 0x01, 0x01,
+ 0x02, 0xFF, 0x0D, 0x00, 0x02, 0xCC, 0x01, 0x10, 0x01, 0x01, 0x02, 0xCC,
+ 0xFF, 0x00, 0xFF, 0x00, 0xC9, 0x00,
+
+ /* 5 DOT_ABOVE / DEGREE_SIGN */
+ 0x2D, 0x00, 0x01, 0x13, 0x01, 0x30, 0x10, 0x00, 0x01, 0x2B, 0x02, 0xFF,
+ 0x01, 0xA1, 0x0E, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x02, 0xFF, 0x01, 0xFD,
+ 0x01, 0x10, 0x0D, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x94, 0x01, 0x5A,
+ 0x01, 0xFF, 0x01, 0xB0, 0x0D, 0x00, 0x01, 0x4F, 0x01, 0xF7, 0x02, 0x00,
+ 0x01, 0x9F, 0x01, 0xF2, 0x0D, 0x00, 0x01, 0x8F, 0x01, 0xF0, 0x02, 0x00,
+ 0x01, 0x2F, 0x01, 0xF6, 0x0D, 0x00, 0x01, 0x8F, 0x01, 0xE0, 0x02, 0x00,
+ 0x01, 0x0F, 0x01, 0xF7, 0x0D, 0x00, 0x01, 0x7F, 0x01, 0xF2, 0x02, 0x00,
+ 0x01, 0x4F, 0x01, 0xF5, 0x0D, 0x00, 0x01, 0x2F, 0x01, 0xFC, 0x01, 0x10,
+ 0x01, 0x02, 0x01, 0xDF, 0x01, 0xF0, 0x0D, 0x00, 0x01, 0x08, 0x01, 0xFF,
+ 0x01, 0xFB, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x60, 0x0E, 0x00, 0x01, 0x9F,
+ 0x02, 0xFF, 0x01, 0xF8, 0x0F, 0x00, 0x01, 0x03, 0x01, 0x9C, 0x01, 0xC9,
+ 0x01, 0x30, 0xFF, 0x00, 0xFF, 0x00, 0xA4, 0x00,
+
+ /* 6 CEDILLA */
+ 0xFF, 0x00, 0xFF, 0x00, 0xEE, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0x20,
+ 0x11, 0x00, 0x01, 0xCF, 0x01, 0xC0, 0x11, 0x00, 0x01, 0x3F, 0x01, 0xF6,
+ 0x11, 0x00, 0x01, 0x0F, 0x01, 0xFB, 0x11, 0x00, 0x01, 0x3F, 0x01, 0xFD,
+ 0x0E, 0x00, 0x01, 0x07, 0x01, 0xD9, 0x01, 0x89, 0x01, 0xFF, 0x01, 0xFB,
+ 0x0E, 0x00, 0x01, 0x07, 0x03, 0xFF, 0x01, 0xF3, 0x0E, 0x00, 0x01, 0x04,
+ 0x01, 0xBD, 0x01, 0xEE, 0x01, 0xD9, 0x01, 0x20, 0x2F, 0x00,
+
+ /* 7 NO_DOT_I */
+ 0xFF, 0x00, 0x32, 0x00, 0x01, 0x01, 0x01, 0x99, 0x01, 0x96, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xF9, 0x10, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0x10, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF9, 0xCD, 0x00,
+
+#if ENABLED(TOUCH_UI_UTF8_GERMANIC)
+ /* 8 SHARP_S */
+ 0x8A, 0x00, 0x01, 0x35, 0x01, 0x66, 0x01, 0x52, 0x0E, 0x00, 0x01, 0x03,
+ 0x01, 0xAF, 0x03, 0xFF, 0x01, 0xE7, 0x0D, 0x00, 0x01, 0x7F, 0x05, 0xFF,
+ 0x01, 0xC1, 0x0B, 0x00, 0x01, 0x07, 0x02, 0xFF, 0x01, 0xFC, 0x01, 0xAA,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xFC, 0x0B, 0x00, 0x01, 0x2F, 0x01, 0xFF,
+ 0x01, 0xF9, 0x01, 0x10, 0x01, 0x00, 0x01, 0x02, 0x01, 0xCF, 0x01, 0xFF,
+ 0x01, 0x70, 0x0A, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x80, 0x03, 0x00,
+ 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xE0, 0x0A, 0x00, 0x01, 0xEF, 0x01, 0xFF,
+ 0x04, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xF3, 0x09, 0x00, 0x01, 0x02,
+ 0x01, 0xFF, 0x01, 0xFB, 0x04, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF7,
+ 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF9, 0x03, 0x00, 0x01, 0x03,
+ 0x01, 0x9E, 0x01, 0xFF, 0x01, 0xF8, 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF8, 0x02, 0x00, 0x01, 0x01, 0x01, 0xAF, 0x02, 0xFF, 0x01, 0xD7,
+ 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x02, 0x00, 0x01, 0x1D,
+ 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x50, 0x0A, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF8, 0x02, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x70, 0x0B, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x01, 0x00, 0x01, 0x01, 0x01, 0xFF,
+ 0x01, 0xFA, 0x0C, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x01, 0x00,
+ 0x01, 0x05, 0x01, 0xFF, 0x01, 0xF4, 0x0C, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF8, 0x01, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF4, 0x0C, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x01, 0x00, 0x01, 0x05, 0x01, 0xFF,
+ 0x01, 0xF9, 0x0C, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x01, 0x00,
+ 0x01, 0x02, 0x02, 0xFF, 0x01, 0x50, 0x0B, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF8, 0x02, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0xF8, 0x0B, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x02, 0x00, 0x01, 0x1D, 0x02, 0xFF,
+ 0x01, 0xD3, 0x0A, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x02, 0x00,
+ 0x01, 0x01, 0x01, 0xCF, 0x02, 0xFF, 0x01, 0x70, 0x09, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF8, 0x03, 0x00, 0x01, 0x07, 0x02, 0xFF, 0x01, 0xFB,
+ 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x04, 0x00, 0x01, 0x2B,
+ 0x02, 0xFF, 0x01, 0xB0, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8,
+ 0x05, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xF6, 0x08, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF8, 0x05, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xFD,
+ 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x06, 0x00, 0x01, 0xDF,
+ 0x01, 0xFF, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x10, 0x07, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF8, 0x06, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x08, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF8, 0x05, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xFD,
+ 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x01, 0x02, 0x01, 0x84,
+ 0x03, 0x00, 0x01, 0x2D, 0x01, 0xFF, 0x01, 0xF8, 0x08, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF8, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xEC, 0x01, 0xA9,
+ 0x01, 0xAC, 0x02, 0xFF, 0x01, 0xE0, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF8, 0x01, 0x02, 0x05, 0xFF, 0x01, 0xFE, 0x01, 0x20, 0x08, 0x00,
+ 0x01, 0x03, 0x01, 0xEE, 0x01, 0xE7, 0x01, 0x01, 0x01, 0xBF, 0x03, 0xFF,
+ 0x01, 0xFE, 0x01, 0x80, 0x0E, 0x00, 0x01, 0x35, 0x01, 0x78, 0x01, 0x76,
+ 0x01, 0x30, 0xB4, 0x00,
+#endif
+
+#if ENABLED(TOUCH_UI_UTF8_SCANDINAVIAN)
+ /* 9 LRG_O_STROKE */
+ 0x93, 0x00, 0x01, 0x40, 0x0A, 0x00, 0x01, 0x47, 0x01, 0x9A, 0x01, 0xBA,
+ 0x01, 0x95, 0x01, 0x10, 0x02, 0x00, 0x01, 0x07, 0x01, 0xF8, 0x08, 0x00,
+ 0x01, 0x02, 0x01, 0xAF, 0x04, 0xFF, 0x01, 0xFC, 0x01, 0x50, 0x01, 0x00,
+ 0x01, 0x5F, 0x01, 0xFF, 0x01, 0x30, 0x07, 0x00, 0x01, 0x8F, 0x06, 0xFF,
+ 0x01, 0xFC, 0x01, 0x23, 0x01, 0xFF, 0x01, 0xF6, 0x07, 0x00, 0x01, 0x1C,
+ 0x03, 0xFF, 0x01, 0xCA, 0x01, 0x9B, 0x01, 0xDF, 0x02, 0xFF, 0x01, 0xFE,
+ 0x01, 0xFF, 0x01, 0x80, 0x07, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0xFD,
+ 0x01, 0x50, 0x02, 0x00, 0x01, 0x02, 0x01, 0x9F, 0x02, 0xFF, 0x01, 0xFA,
+ 0x07, 0x00, 0x01, 0x09, 0x02, 0xFF, 0x01, 0x90, 0x04, 0x00, 0x01, 0x03,
+ 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xF3, 0x07, 0x00, 0x01, 0x5F, 0x01, 0xFF,
+ 0x01, 0xF9, 0x06, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0xFC, 0x07, 0x00,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xC0, 0x05, 0x00, 0x01, 0x06, 0x03, 0xFF,
+ 0x01, 0x60, 0x05, 0x00, 0x01, 0x04, 0x02, 0xFF, 0x01, 0x30, 0x05, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xC0, 0x05, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xFC, 0x05, 0x00, 0x01, 0x02, 0x01, 0xEF,
+ 0x01, 0xF7, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00, 0x01, 0x0F,
+ 0x01, 0xFF, 0x01, 0xF6, 0x05, 0x00, 0x01, 0x1D, 0x01, 0xFF, 0x01, 0xA0,
+ 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xF8, 0x05, 0x00, 0x01, 0x3F, 0x01, 0xFF,
+ 0x01, 0xF2, 0x05, 0x00, 0x01, 0xCF, 0x01, 0xFC, 0x01, 0x00, 0x01, 0x09,
+ 0x01, 0xFF, 0x01, 0xFB, 0x05, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xE0,
+ 0x04, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xD1, 0x01, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xFE, 0x05, 0x00, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0xC0,
+ 0x04, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x01, 0x20, 0x01, 0x00, 0x01, 0x03,
+ 0x02, 0xFF, 0x05, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0xB0, 0x03, 0x00,
+ 0x01, 0x05, 0x01, 0xFF, 0x01, 0xF4, 0x02, 0x00, 0x01, 0x02, 0x02, 0xFF,
+ 0x01, 0x10, 0x04, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xA0, 0x03, 0x00,
+ 0x01, 0x3F, 0x01, 0xFF, 0x01, 0x60, 0x02, 0x00, 0x01, 0x01, 0x02, 0xFF,
+ 0x01, 0x30, 0x04, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xA0, 0x02, 0x00,
+ 0x01, 0x01, 0x01, 0xEF, 0x01, 0xF8, 0x03, 0x00, 0x01, 0x02, 0x02, 0xFF,
+ 0x01, 0x20, 0x04, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0xB0, 0x02, 0x00,
+ 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xB0, 0x03, 0x00, 0x01, 0x03, 0x02, 0xFF,
+ 0x01, 0x10, 0x04, 0x00, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0xC0, 0x02, 0x00,
+ 0x01, 0xBF, 0x01, 0xFD, 0x04, 0x00, 0x01, 0x04, 0x02, 0xFF, 0x05, 0x00,
+ 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xE0, 0x01, 0x00, 0x01, 0x08, 0x01, 0xFF,
+ 0x01, 0xE1, 0x04, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xFE, 0x05, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x6F, 0x01, 0xFF,
+ 0x01, 0x30, 0x04, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xFA, 0x05, 0x00,
+ 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF6, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xF5,
+ 0x05, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF7, 0x05, 0x00, 0x01, 0x09,
+ 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0x70, 0x05, 0x00,
+ 0x01, 0x5F, 0x01, 0xFF, 0x01, 0xF2, 0x05, 0x00, 0x01, 0x03, 0x02, 0xFF,
+ 0x01, 0xEF, 0x01, 0xFA, 0x06, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0xB0,
+ 0x06, 0x00, 0x01, 0xCF, 0x02, 0xFF, 0x01, 0xC0, 0x05, 0x00, 0x01, 0x06,
+ 0x02, 0xFF, 0x01, 0x40, 0x06, 0x00, 0x01, 0x2F, 0x02, 0xFF, 0x01, 0x20,
+ 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xFB, 0x07, 0x00, 0x01, 0x0B,
+ 0x02, 0xFF, 0x01, 0xD2, 0x04, 0x00, 0x01, 0x06, 0x02, 0xFF, 0x01, 0xE1,
+ 0x07, 0x00, 0x01, 0x5F, 0x03, 0xFF, 0x01, 0x93, 0x02, 0x00, 0x01, 0x05,
+ 0x01, 0xCF, 0x02, 0xFF, 0x01, 0x30, 0x06, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xFB, 0x03, 0xFF, 0x01, 0xFD, 0x01, 0xDE, 0x03, 0xFF, 0x01, 0xE3,
+ 0x07, 0x00, 0x01, 0x1E, 0x01, 0xFF, 0x01, 0x80, 0x01, 0x4D, 0x06, 0xFF,
+ 0x01, 0xFA, 0x01, 0x10, 0x07, 0x00, 0x01, 0xBF, 0x01, 0xFB, 0x02, 0x00,
+ 0x01, 0x5C, 0x04, 0xFF, 0x01, 0xE9, 0x01, 0x30, 0x08, 0x00, 0x01, 0x1C,
+ 0x01, 0xD0, 0x03, 0x00, 0x01, 0x04, 0x01, 0x67, 0x01, 0x86, 0x01, 0x53,
+ 0x0B, 0x00, 0x01, 0x10, 0xA8, 0x00,
+
+ /* 10 SML_O_STROKE */
+ 0xFF, 0x00, 0x15, 0x00, 0x01, 0x02, 0x01, 0x20, 0x0C, 0x00, 0x01, 0x02,
+ 0x01, 0x32, 0x01, 0x10, 0x02, 0x00, 0x01, 0x1D, 0x01, 0xE3, 0x0A, 0x00,
+ 0x01, 0x01, 0x01, 0x7C, 0x02, 0xFF, 0x01, 0xFD, 0x01, 0x82, 0x01, 0x00,
+ 0x01, 0xCF, 0x01, 0xF7, 0x0A, 0x00, 0x01, 0x6E, 0x05, 0xFF, 0x01, 0x89,
+ 0x01, 0xFF, 0x01, 0xA0, 0x09, 0x00, 0x01, 0x08, 0x07, 0xFF, 0x01, 0xFC,
+ 0x0A, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x50, 0x01, 0x00,
+ 0x01, 0x3A, 0x02, 0xFF, 0x01, 0xF1, 0x09, 0x00, 0x01, 0x01, 0x02, 0xFF,
+ 0x01, 0x90, 0x03, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x01, 0xF5, 0x09, 0x00,
+ 0x01, 0x08, 0x01, 0xFF, 0x01, 0xFC, 0x03, 0x00, 0x01, 0x01, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0xFD, 0x09, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF3,
+ 0x03, 0x00, 0x01, 0x0B, 0x03, 0xFF, 0x01, 0x30, 0x08, 0x00, 0x01, 0x3F,
+ 0x01, 0xFF, 0x01, 0xD0, 0x03, 0x00, 0x01, 0x9F, 0x01, 0xFA, 0x01, 0x8F,
+ 0x01, 0xFF, 0x01, 0x80, 0x08, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x01, 0x80,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xC0, 0x01, 0x3F, 0x01, 0xFF,
+ 0x01, 0xB0, 0x08, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x50, 0x02, 0x00,
+ 0x01, 0x3F, 0x01, 0xFE, 0x01, 0x10, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xE0,
+ 0x08, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x40, 0x01, 0x00, 0x01, 0x02,
+ 0x01, 0xEF, 0x01, 0xF3, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF0,
+ 0x08, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x30, 0x01, 0x00, 0x01, 0x0D,
+ 0x01, 0xFF, 0x01, 0x50, 0x01, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF0,
+ 0x08, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x30, 0x01, 0x00, 0x01, 0xBF,
+ 0x01, 0xF8, 0x02, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF0, 0x08, 0x00,
+ 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x40, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xB0,
+ 0x02, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xE0, 0x08, 0x00, 0x01, 0x7F,
+ 0x01, 0xFF, 0x01, 0x60, 0x01, 0x5F, 0x01, 0xFD, 0x03, 0x00, 0x01, 0x3F,
+ 0x01, 0xFF, 0x01, 0xC0, 0x08, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xA3,
+ 0x01, 0xFF, 0x01, 0xE2, 0x03, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x01, 0x90,
+ 0x08, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0xFF, 0x01, 0x40,
+ 0x03, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x08, 0x00, 0x01, 0x0A,
+ 0x02, 0xFF, 0x01, 0xF6, 0x03, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xFE,
+ 0x09, 0x00, 0x01, 0x02, 0x02, 0xFF, 0x01, 0xB0, 0x03, 0x00, 0x01, 0x2E,
+ 0x01, 0xFF, 0x01, 0xF8, 0x0A, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0xF7,
+ 0x02, 0x00, 0x01, 0x05, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xD0, 0x09, 0x00,
+ 0x01, 0x04, 0x03, 0xFF, 0x01, 0xFC, 0x01, 0xAB, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xFE, 0x01, 0x20, 0x09, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xAF,
+ 0x05, 0xFF, 0x01, 0xD2, 0x09, 0x00, 0x01, 0x01, 0x01, 0xDF, 0x01, 0xF5,
+ 0x01, 0x04, 0x01, 0xBF, 0x03, 0xFF, 0x01, 0xD6, 0x0A, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0x70, 0x01, 0x00, 0x01, 0x01, 0x01, 0x46, 0x01, 0x76,
+ 0x01, 0x52, 0x0C, 0x00, 0x01, 0x28, 0xA9, 0x00,
+
+ /* 11 LRG_AE */
+ 0x9E, 0x00, 0x01, 0x14, 0x0B, 0x44, 0x01, 0x41, 0x06, 0x00, 0x01, 0x8F,
+ 0x0B, 0xFF, 0x01, 0xF3, 0x06, 0x00, 0x01, 0xEF, 0x0B, 0xFF, 0x01, 0xF3,
+ 0x05, 0x00, 0x01, 0x05, 0x02, 0xFF, 0x01, 0xEE, 0x09, 0xFF, 0x01, 0xF3,
+ 0x05, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xF5, 0x01, 0x00, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0x63, 0x06, 0x33, 0x01, 0x30, 0x05, 0x00, 0x01, 0x3F,
+ 0x01, 0xFF, 0x01, 0xE0, 0x01, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40,
+ 0x0C, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x80, 0x01, 0x00, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0x40, 0x0B, 0x00, 0x01, 0x01, 0x02, 0xFF, 0x01, 0x10,
+ 0x01, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40, 0x0B, 0x00, 0x01, 0x07,
+ 0x01, 0xFF, 0x01, 0xFA, 0x02, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40,
+ 0x0B, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xF3, 0x02, 0x00, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0x40, 0x0B, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xD0,
+ 0x02, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40, 0x0B, 0x00, 0x01, 0xBF,
+ 0x01, 0xFF, 0x01, 0x60, 0x02, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40,
+ 0x0A, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xFE, 0x03, 0x00, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0x40, 0x0A, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xF9,
+ 0x03, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xED, 0x06, 0xDD, 0x01, 0x80,
+ 0x03, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2, 0x03, 0x00, 0x01, 0xDF,
+ 0x08, 0xFF, 0x01, 0xA0, 0x03, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xB0,
+ 0x03, 0x00, 0x01, 0xDF, 0x08, 0xFF, 0x01, 0xA0, 0x03, 0x00, 0x01, 0xCF,
+ 0x01, 0xFF, 0x01, 0x40, 0x03, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xA8,
+ 0x06, 0x88, 0x01, 0x50, 0x02, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFE,
+ 0x04, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40, 0x09, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF7, 0x04, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40,
+ 0x09, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xF4, 0x04, 0x33, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0x40, 0x09, 0x00, 0x01, 0x7F, 0x08, 0xFF, 0x01, 0x40,
+ 0x09, 0x00, 0x01, 0xEF, 0x08, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x01, 0x05,
+ 0x09, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xF7,
+ 0x05, 0x33, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0xE0, 0x05, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40,
+ 0x08, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x80, 0x05, 0x00, 0x01, 0xDF,
+ 0x01, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x05, 0x00,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x40, 0x07, 0x00, 0x01, 0x06, 0x01, 0xFF,
+ 0x01, 0xFB, 0x06, 0x00, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xA8, 0x06, 0x88,
+ 0x01, 0x85, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xF4, 0x06, 0x00, 0x01, 0xDF,
+ 0x08, 0xFF, 0x01, 0xF9, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xE0, 0x06, 0x00,
+ 0x01, 0xDF, 0x08, 0xFF, 0x01, 0xF9, 0x01, 0x8D, 0x01, 0xDD, 0x01, 0x60,
+ 0x06, 0x00, 0x01, 0xBD, 0x08, 0xDD, 0x01, 0xD8, 0xBE, 0x00,
+
+ /* 12 SML_AE */
+ 0xFF, 0x00, 0x22, 0x00, 0x01, 0x01, 0x01, 0x34, 0x01, 0x31, 0x06, 0x00,
+ 0x01, 0x12, 0x01, 0x42, 0x01, 0x10, 0x05, 0x00, 0x01, 0x02, 0x01, 0x7B,
+ 0x01, 0xEF, 0x02, 0xFF, 0x01, 0xFB, 0x01, 0x60, 0x02, 0x00, 0x01, 0x03,
+ 0x01, 0x9E, 0x02, 0xFF, 0x01, 0xFD, 0x01, 0x81, 0x04, 0x00, 0x01, 0xBF,
+ 0x05, 0xFF, 0x01, 0xFE, 0x01, 0x40, 0x01, 0x01, 0x01, 0x9F, 0x05, 0xFF,
+ 0x01, 0x60, 0x03, 0x00, 0x01, 0xDF, 0x02, 0xFF, 0x01, 0xEE, 0x03, 0xFF,
+ 0x01, 0xF5, 0x01, 0x1D, 0x03, 0xFF, 0x01, 0xEF, 0x02, 0xFF, 0x01, 0xF8,
+ 0x03, 0x00, 0x01, 0xDF, 0x01, 0xB6, 0x01, 0x30, 0x01, 0x00, 0x01, 0x01,
+ 0x01, 0x5D, 0x02, 0xFF, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xE7, 0x01, 0x20,
+ 0x01, 0x00, 0x01, 0x29, 0x02, 0xFF, 0x01, 0x50, 0x02, 0x00, 0x01, 0x71,
+ 0x05, 0x00, 0x01, 0xAF, 0x02, 0xFF, 0x01, 0xFB, 0x01, 0x10, 0x03, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xE0, 0x08, 0x00, 0x01, 0x0D, 0x02, 0xFF,
+ 0x01, 0xD0, 0x04, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF7, 0x08, 0x00,
+ 0x01, 0x06, 0x02, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0xEF, 0x01, 0xFD,
+ 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFD, 0x06, 0x00, 0x01, 0x9F,
+ 0x01, 0xFF, 0x04, 0x00, 0x01, 0x02, 0x01, 0x45, 0x02, 0x66, 0x01, 0x67,
+ 0x01, 0xFF, 0x01, 0xF9, 0x06, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x03, 0x00,
+ 0x01, 0x4A, 0x06, 0xFF, 0x01, 0xFB, 0x03, 0x66, 0x01, 0x67, 0x02, 0x77,
+ 0x01, 0xAF, 0x01, 0xFF, 0x02, 0x00, 0x01, 0x1B, 0x10, 0xFF, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0xDF, 0x02, 0xFF, 0x01, 0xCA, 0x01, 0x98, 0x01, 0x88,
+ 0x01, 0x89, 0x0A, 0xFF, 0x01, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xFD,
+ 0x01, 0x40, 0x03, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xFA, 0x08, 0x77,
+ 0x01, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xD0, 0x04, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x09, 0x00, 0x01, 0x5F, 0x01, 0xFF, 0x01, 0x70,
+ 0x04, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xFA, 0x09, 0x00, 0x01, 0x7F,
+ 0x01, 0xFF, 0x01, 0x30, 0x04, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xFE,
+ 0x09, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x01, 0x30, 0x04, 0x00, 0x01, 0x0F,
+ 0x02, 0xFF, 0x01, 0x50, 0x08, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x60,
+ 0x04, 0x00, 0x01, 0x8F, 0x02, 0xFF, 0x01, 0xE1, 0x08, 0x00, 0x01, 0x3F,
+ 0x01, 0xFF, 0x01, 0xD0, 0x03, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xFE,
+ 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x10, 0x05, 0x00, 0x01, 0x45, 0x01, 0x00,
+ 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x20, 0x01, 0x00, 0x01, 0x01,
+ 0x01, 0x9F, 0x01, 0xFF, 0x01, 0xA2, 0x02, 0xFF, 0x01, 0xE6, 0x01, 0x10,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0x8D, 0x01, 0xF8, 0x01, 0x00, 0x01, 0x05,
+ 0x02, 0xFF, 0x01, 0xFD, 0x01, 0xAB, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0xFC,
+ 0x01, 0x00, 0x01, 0x3F, 0x02, 0xFF, 0x01, 0xFD, 0x01, 0xBA, 0x01, 0xBC,
+ 0x02, 0xFF, 0x01, 0xF8, 0x02, 0x00, 0x01, 0x7F, 0x05, 0xFF, 0x01, 0xA0,
+ 0x01, 0x00, 0x01, 0x02, 0x01, 0xCF, 0x06, 0xFF, 0x01, 0xF7, 0x02, 0x00,
+ 0x01, 0x03, 0x01, 0xBF, 0x03, 0xFF, 0x01, 0xB4, 0x03, 0x00, 0x01, 0x05,
+ 0x01, 0xBF, 0x04, 0xFF, 0x01, 0xB7, 0x01, 0x10, 0x03, 0x00, 0x01, 0x01,
+ 0x01, 0x46, 0x01, 0x76, 0x01, 0x41, 0x06, 0x00, 0x01, 0x35, 0x01, 0x67,
+ 0x01, 0x64, 0x01, 0x20, 0xAD, 0x00,
+
+ /* 13 LRG_ETH */
+ 0x9A, 0x00, 0x01, 0x34, 0x03, 0x44, 0x01, 0x43, 0x01, 0x21, 0x0D, 0x00,
+ 0x01, 0xBF, 0x05, 0xFF, 0x01, 0xFE, 0x01, 0xB8, 0x01, 0x40, 0x0A, 0x00,
+ 0x01, 0xBF, 0x07, 0xFF, 0x01, 0xFE, 0x01, 0x81, 0x09, 0x00, 0x01, 0xBF,
+ 0x08, 0xFF, 0x01, 0xFE, 0x01, 0x60, 0x08, 0x00, 0x01, 0xBF, 0x01, 0xFF,
+ 0x01, 0x61, 0x02, 0x11, 0x01, 0x23, 0x01, 0x58, 0x01, 0xCF, 0x02, 0xFF,
+ 0x01, 0xF9, 0x08, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x04, 0x00,
+ 0x01, 0x02, 0x01, 0x9F, 0x02, 0xFF, 0x01, 0x80, 0x07, 0x00, 0x01, 0xBF,
+ 0x01, 0xFF, 0x01, 0x50, 0x05, 0x00, 0x01, 0x04, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xF4, 0x07, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x06, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFD, 0x07, 0x00, 0x01, 0xBF, 0x01, 0xFF,
+ 0x01, 0x50, 0x06, 0x00, 0x01, 0x06, 0x02, 0xFF, 0x01, 0x50, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xB0, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00,
+ 0x01, 0x7F, 0x01, 0xFF, 0x01, 0xF0, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF,
+ 0x01, 0x50, 0x07, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0xF3, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00, 0x01, 0x0F, 0x01, 0xFF,
+ 0x01, 0xF5, 0x04, 0x00, 0x01, 0x23, 0x01, 0x33, 0x01, 0xCF, 0x01, 0xFF,
+ 0x01, 0x73, 0x02, 0x33, 0x01, 0x30, 0x04, 0x00, 0x01, 0x0D, 0x01, 0xFF,
+ 0x01, 0xF6, 0x04, 0x00, 0x01, 0xCF, 0x06, 0xFF, 0x01, 0xF2, 0x04, 0x00,
+ 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xF7, 0x04, 0x00, 0x01, 0xCF, 0x06, 0xFF,
+ 0x01, 0xF2, 0x04, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xF9, 0x04, 0x00,
+ 0x01, 0x9B, 0x01, 0xBB, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xDB, 0x02, 0xBB,
+ 0x01, 0xB1, 0x04, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xF8, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00, 0x01, 0x0D, 0x01, 0xFF,
+ 0x01, 0xF7, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00,
+ 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF6, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF,
+ 0x01, 0x50, 0x07, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xF4, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00, 0x01, 0x5F, 0x01, 0xFF,
+ 0x01, 0xF1, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00,
+ 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xD0, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF,
+ 0x01, 0x50, 0x06, 0x00, 0x01, 0x01, 0x02, 0xFF, 0x01, 0x80, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x06, 0x00, 0x01, 0x0B, 0x02, 0xFF,
+ 0x01, 0x20, 0x06, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x06, 0x00,
+ 0x01, 0x8F, 0x01, 0xFF, 0x01, 0xF9, 0x07, 0x00, 0x01, 0xBF, 0x01, 0xFF,
+ 0x01, 0x50, 0x05, 0x00, 0x01, 0x0A, 0x02, 0xFF, 0x01, 0xE1, 0x07, 0x00,
+ 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x50, 0x04, 0x00, 0x01, 0x29, 0x03, 0xFF,
+ 0x01, 0x30, 0x07, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0xA7, 0x01, 0x77,
+ 0x01, 0x78, 0x01, 0x9A, 0x01, 0xBF, 0x03, 0xFF, 0x01, 0xE3, 0x08, 0x00,
+ 0x01, 0xBF, 0x08, 0xFF, 0x01, 0xF9, 0x01, 0x10, 0x08, 0x00, 0x01, 0xBF,
+ 0x07, 0xFF, 0x01, 0xD8, 0x01, 0x10, 0x09, 0x00, 0x01, 0xAD, 0x03, 0xDD,
+ 0x01, 0xDC, 0x01, 0xCB, 0x01, 0xA7, 0x01, 0x41, 0xC7, 0x00,
+
+ /* 14 SML_ETH */
+ 0x88, 0x00, 0x01, 0x38, 0x01, 0x88, 0x01, 0x81, 0x10, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0xFC, 0x03, 0x00, 0x01, 0x5A, 0x01, 0x40, 0x0C, 0x00,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xB0, 0x01, 0x04, 0x01, 0xAF, 0x01, 0xFF,
+ 0x01, 0xA0, 0x0C, 0x00, 0x01, 0x1E, 0x01, 0xFF, 0x01, 0xFC, 0x02, 0xFF,
+ 0x01, 0xD8, 0x01, 0x20, 0x0C, 0x00, 0x01, 0x07, 0x02, 0xFF, 0x01, 0xFD,
+ 0x01, 0x82, 0x0D, 0x00, 0x01, 0x5A, 0x03, 0xFF, 0x01, 0xF4, 0x0D, 0x00,
+ 0x01, 0x7F, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x87, 0x02, 0xFF, 0x01, 0x30,
+ 0x0C, 0x00, 0x01, 0x6F, 0x01, 0xE9, 0x01, 0x30, 0x01, 0x00, 0x01, 0x8F,
+ 0x01, 0xFF, 0x01, 0xE2, 0x0C, 0x00, 0x01, 0x03, 0x03, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x10, 0x0E, 0x00, 0x01, 0x23, 0x01, 0x44,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xB0, 0x0C, 0x00, 0x01, 0x02, 0x01, 0x9E,
+ 0x04, 0xFF, 0x01, 0xF7, 0x0C, 0x00, 0x01, 0x7F, 0x06, 0xFF, 0x01, 0x30,
+ 0x0A, 0x00, 0x01, 0x09, 0x02, 0xFF, 0x01, 0xFE, 0x01, 0xCB, 0x01, 0xDF,
+ 0x02, 0xFF, 0x01, 0xD0, 0x0A, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xFB,
+ 0x01, 0x30, 0x02, 0x00, 0x01, 0x4E, 0x01, 0xFF, 0x01, 0xF5, 0x09, 0x00,
+ 0x01, 0x02, 0x02, 0xFF, 0x01, 0x70, 0x03, 0x00, 0x01, 0x05, 0x01, 0xFF,
+ 0x01, 0xFD, 0x09, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xFA, 0x05, 0x00,
+ 0x01, 0xEF, 0x01, 0xFF, 0x01, 0x20, 0x08, 0x00, 0x01, 0x0F, 0x01, 0xFF,
+ 0x01, 0xF1, 0x05, 0x00, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xA0, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0xB0, 0x08, 0x00, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0x70, 0x05, 0x00,
+ 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xD0, 0x08, 0x00, 0x01, 0x9F, 0x01, 0xFF,
+ 0x01, 0x40, 0x05, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF0, 0x08, 0x00,
+ 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x30, 0x05, 0x00, 0x01, 0x0E, 0x01, 0xFF,
+ 0x01, 0xF0, 0x08, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x30, 0x05, 0x00,
+ 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF0, 0x08, 0x00, 0x01, 0x9F, 0x01, 0xFF,
+ 0x01, 0x40, 0x05, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xE0, 0x08, 0x00,
+ 0x01, 0x8F, 0x01, 0xFF, 0x01, 0x70, 0x05, 0x00, 0x01, 0x2F, 0x01, 0xFF,
+ 0x01, 0xD0, 0x08, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xA0, 0x05, 0x00,
+ 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x90, 0x08, 0x00, 0x01, 0x0F, 0x01, 0xFF,
+ 0x01, 0xF1, 0x05, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x08, 0x00,
+ 0x01, 0x09, 0x01, 0xFF, 0x01, 0xF9, 0x04, 0x00, 0x01, 0x05, 0x01, 0xFF,
+ 0x01, 0xFE, 0x09, 0x00, 0x01, 0x02, 0x02, 0xFF, 0x01, 0x60, 0x03, 0x00,
+ 0x01, 0x3E, 0x01, 0xFF, 0x01, 0xF6, 0x0A, 0x00, 0x01, 0x7F, 0x01, 0xFF,
+ 0x01, 0xF9, 0x01, 0x20, 0x01, 0x00, 0x01, 0x07, 0x02, 0xFF, 0x01, 0xB0,
+ 0x0A, 0x00, 0x01, 0x09, 0x02, 0xFF, 0x01, 0xFD, 0x01, 0xBD, 0x02, 0xFF,
+ 0x01, 0xFD, 0x01, 0x10, 0x0B, 0x00, 0x01, 0x7F, 0x05, 0xFF, 0x01, 0xB0,
+ 0x0C, 0x00, 0x01, 0x02, 0x01, 0xAE, 0x03, 0xFF, 0x01, 0xB4, 0x0F, 0x00,
+ 0x01, 0x35, 0x01, 0x65, 0x01, 0x40, 0xB6, 0x00,
+
+ /* 15 LRG_THORN */
+ 0x9A, 0x00, 0x02, 0x55, 0x11, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00,
+ 0x05, 0xFF, 0x01, 0xED, 0x01, 0xA7, 0x01, 0x10, 0x0B, 0x00, 0x07, 0xFF,
+ 0x01, 0xFA, 0x01, 0x10, 0x0A, 0x00, 0x08, 0xFF, 0x01, 0xE2, 0x0A, 0x00,
+ 0x02, 0xFF, 0x01, 0x65, 0x01, 0x55, 0x01, 0x56, 0x01, 0x7A, 0x02, 0xFF,
+ 0x01, 0xFE, 0x01, 0x10, 0x09, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x03, 0x00,
+ 0x01, 0x1B, 0x02, 0xFF, 0x01, 0x80, 0x09, 0x00, 0x02, 0xFF, 0x01, 0x20,
+ 0x04, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0xF0, 0x09, 0x00, 0x02, 0xFF,
+ 0x01, 0x20, 0x04, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xF3, 0x09, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF6,
+ 0x09, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0x0D, 0x01, 0xFF,
+ 0x01, 0xF7, 0x09, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0x0D,
+ 0x01, 0xFF, 0x01, 0xF7, 0x09, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x04, 0x00,
+ 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF6, 0x09, 0x00, 0x02, 0xFF, 0x01, 0x20,
+ 0x04, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xF3, 0x09, 0x00, 0x02, 0xFF,
+ 0x01, 0x20, 0x04, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0xF0, 0x09, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x03, 0x00, 0x01, 0x1B, 0x02, 0xFF, 0x01, 0x80,
+ 0x09, 0x00, 0x02, 0xFF, 0x01, 0x65, 0x02, 0x55, 0x01, 0x7A, 0x02, 0xFF,
+ 0x01, 0xFE, 0x01, 0x10, 0x09, 0x00, 0x08, 0xFF, 0x01, 0xE2, 0x0A, 0x00,
+ 0x07, 0xFF, 0x01, 0xFA, 0x01, 0x10, 0x0A, 0x00, 0x05, 0xFF, 0x01, 0xED,
+ 0x01, 0xA7, 0x01, 0x10, 0x0B, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00,
+ 0x02, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x02, 0xCC, 0x01, 0x10, 0xCC, 0x00,
+
+ /* 16 SML_THORN */
+ 0x86, 0x00, 0x01, 0x02, 0x01, 0x99, 0x01, 0x94, 0x10, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7,
+ 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7,
+ 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7,
+ 0x02, 0x00, 0x01, 0x13, 0x01, 0x54, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x01, 0x00, 0x01, 0x5C, 0x02, 0xFF, 0x01, 0xFD,
+ 0x01, 0x70, 0x0A, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x01, 0x0B,
+ 0x04, 0xFF, 0x01, 0xFD, 0x01, 0x20, 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF7, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xEC, 0x01, 0xDF, 0x02, 0xFF,
+ 0x01, 0xE1, 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0xFF,
+ 0x01, 0xC3, 0x02, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xFC, 0x09, 0x00,
+ 0x01, 0x03, 0x02, 0xFF, 0x01, 0xFA, 0x03, 0x00, 0x01, 0x02, 0x01, 0xEF,
+ 0x01, 0xFF, 0x01, 0x60, 0x08, 0x00, 0x01, 0x03, 0x02, 0xFF, 0x01, 0xE0,
+ 0x04, 0x00, 0x01, 0x5F, 0x01, 0xFF, 0x01, 0xD0, 0x08, 0x00, 0x01, 0x03,
+ 0x02, 0xFF, 0x01, 0x60, 0x04, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xF3,
+ 0x08, 0x00, 0x01, 0x03, 0x02, 0xFF, 0x05, 0x00, 0x01, 0x06, 0x01, 0xFF,
+ 0x01, 0xF7, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFC, 0x05, 0x00,
+ 0x01, 0x02, 0x01, 0xFF, 0x01, 0xFB, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF9, 0x06, 0x00, 0x01, 0xFF, 0x01, 0xFD, 0x08, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF8, 0x06, 0x00, 0x01, 0xEF, 0x01, 0xFE, 0x08, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x06, 0x00, 0x01, 0xEF, 0x01, 0xFF,
+ 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF8, 0x06, 0x00, 0x01, 0xEF,
+ 0x01, 0xFE, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF9, 0x06, 0x00,
+ 0x01, 0xFF, 0x01, 0xFD, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFC,
+ 0x05, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xFB, 0x08, 0x00, 0x01, 0x03,
+ 0x02, 0xFF, 0x05, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF8, 0x08, 0x00,
+ 0x01, 0x03, 0x02, 0xFF, 0x01, 0x60, 0x04, 0x00, 0x01, 0x0C, 0x01, 0xFF,
+ 0x01, 0xF3, 0x08, 0x00, 0x01, 0x03, 0x02, 0xFF, 0x01, 0xD0, 0x04, 0x00,
+ 0x01, 0x5F, 0x01, 0xFF, 0x01, 0xD0, 0x08, 0x00, 0x01, 0x03, 0x02, 0xFF,
+ 0x01, 0xFA, 0x03, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0x60,
+ 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0xFF, 0x01, 0xB3,
+ 0x02, 0x00, 0x01, 0x6E, 0x01, 0xFF, 0x01, 0xFC, 0x09, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0xEC, 0x01, 0xCF,
+ 0x02, 0xFF, 0x01, 0xE2, 0x09, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7,
+ 0x01, 0x0B, 0x04, 0xFF, 0x01, 0xFD, 0x01, 0x20, 0x09, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF7, 0x01, 0x00, 0x01, 0x6C, 0x02, 0xFF, 0x01, 0xFE,
+ 0x01, 0x70, 0x0A, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x02, 0x00,
+ 0x01, 0x23, 0x01, 0x54, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x03, 0x01, 0xFF,
+ 0x01, 0xF7, 0x10, 0x00, 0x01, 0x01, 0x01, 0x66, 0x01, 0x63, 0x22, 0x00,
+#endif // TOUCH_UI_UTF8_SCANDINAVIAN
+
+#if ENABLED(TOUCH_UI_UTF8_PUNCTUATION)
+ /* 17 LEFT_DBL_QUOTE */
+ 0xFF, 0x00, 0x4A, 0x00, 0x01, 0x30, 0x03, 0x00, 0x01, 0x02, 0x0D, 0x00,
+ 0x01, 0x08, 0x01, 0xA0, 0x02, 0x00, 0x01, 0x01, 0x01, 0xC6, 0x0D, 0x00,
+ 0x01, 0xAF, 0x01, 0xA0, 0x02, 0x00, 0x01, 0x1D, 0x01, 0xF6, 0x0C, 0x00,
+ 0x01, 0x1C, 0x01, 0xFF, 0x01, 0xA0, 0x01, 0x00, 0x01, 0x02, 0x01, 0xEF,
+ 0x01, 0xF6, 0x0B, 0x00, 0x01, 0x01, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x50,
+ 0x01, 0x00, 0x01, 0x3E, 0x01, 0xFF, 0x01, 0xE2, 0x0B, 0x00, 0x01, 0x2E,
+ 0x01, 0xFF, 0x01, 0xF4, 0x01, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xFD,
+ 0x01, 0x20, 0x0A, 0x00, 0x01, 0x04, 0x01, 0xEF, 0x01, 0xFE, 0x01, 0x30,
+ 0x01, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xD1, 0x0B, 0x00, 0x01, 0x5F,
+ 0x01, 0xFF, 0x01, 0xD2, 0x01, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xFB,
+ 0x0B, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x10, 0x01, 0x00,
+ 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xA0, 0x0B, 0x00, 0x01, 0x0C, 0x01, 0xFF,
+ 0x01, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0x01, 0xFA, 0x0C, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF8, 0x02, 0x00, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0x50,
+ 0x0C, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xA0, 0x01, 0x00, 0x01, 0x1C,
+ 0x01, 0xFF, 0x01, 0xF6, 0x0C, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xFB,
+ 0x02, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x90, 0x0C, 0x00, 0x01, 0x6F,
+ 0x01, 0xFF, 0x01, 0xD1, 0x01, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xFA,
+ 0x0C, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x20, 0x01, 0x00,
+ 0x01, 0x8F, 0x01, 0xFF, 0x01, 0xB0, 0x0C, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0xA0, 0x01, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF6, 0x0C, 0x00,
+ 0x01, 0x02, 0x01, 0xEF, 0x01, 0xA0, 0x02, 0x00, 0x01, 0x5F, 0x01, 0xF6,
+ 0x0D, 0x00, 0x01, 0x1D, 0x01, 0xA0, 0x02, 0x00, 0x01, 0x04, 0x01, 0xE6,
+ 0x0D, 0x00, 0x01, 0x01, 0x01, 0x60, 0x03, 0x00, 0x01, 0x24, 0xFF, 0x00,
+
+ /* 18 RIGHT_DBL_QUOTE */
+ 0xFF, 0x00, 0x46, 0x00, 0x01, 0x20, 0x03, 0x00, 0x01, 0x20, 0x0D, 0x00,
+ 0x01, 0x01, 0x01, 0xE3, 0x03, 0x00, 0x01, 0x5D, 0x01, 0x10, 0x0C, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0x50, 0x02, 0x00, 0x01, 0x5F, 0x01, 0xE2,
+ 0x0C, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF6, 0x02, 0x00, 0x01, 0x5F,
+ 0x01, 0xFE, 0x01, 0x30, 0x0C, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x80,
+ 0x01, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xF5, 0x0C, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xFA, 0x01, 0x00, 0x01, 0x01, 0x01, 0xCF, 0x01, 0xFF,
+ 0x01, 0x60, 0x0C, 0x00, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0xB0, 0x01, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xF9, 0x0C, 0x00, 0x01, 0x06, 0x01, 0xFF,
+ 0x01, 0xFC, 0x01, 0x10, 0x01, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xA0,
+ 0x0C, 0x00, 0x01, 0x5F, 0x01, 0xFF, 0x01, 0xD1, 0x01, 0x00, 0x01, 0x08,
+ 0x01, 0xFF, 0x01, 0xFB, 0x0C, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xF5,
+ 0x02, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x10, 0x0B, 0x00, 0x01, 0x2D,
+ 0x01, 0xFF, 0x01, 0xF3, 0x01, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xFE,
+ 0x01, 0x10, 0x0A, 0x00, 0x01, 0x03, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0x40,
+ 0x01, 0x00, 0x01, 0x5F, 0x01, 0xFF, 0x01, 0xD2, 0x0B, 0x00, 0x01, 0x4F,
+ 0x01, 0xFF, 0x01, 0xE3, 0x01, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xFC,
+ 0x01, 0x10, 0x0A, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x10,
+ 0x01, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0xB0, 0x0B, 0x00, 0x01, 0x6F,
+ 0x01, 0xFF, 0x01, 0xC1, 0x01, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF9,
+ 0x0B, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x5F,
+ 0x01, 0xFF, 0x01, 0x70, 0x0B, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x90,
+ 0x02, 0x00, 0x01, 0x5F, 0x01, 0xF6, 0x0C, 0x00, 0x01, 0x01, 0x01, 0xF8,
+ 0x03, 0x00, 0x01, 0x5F, 0x01, 0x40, 0x0C, 0x00, 0x01, 0x01, 0x01, 0x50,
+ 0x03, 0x00, 0x01, 0x43, 0xFF, 0x00, 0x04, 0x00,
+
+ /* 19 INV_EXCLAMATION */
+ 0xFF, 0x00, 0x34, 0x00, 0x01, 0xAD, 0x01, 0xDD, 0x01, 0x40, 0x10, 0x00,
+ 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF,
+ 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00,
+ 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0x34, 0x01, 0x44,
+ 0x01, 0x10, 0x49, 0x00, 0x01, 0x02, 0x01, 0x22, 0x11, 0x00, 0x01, 0x6F,
+ 0x01, 0xFF, 0x11, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x11, 0x00, 0x01, 0x7F,
+ 0x01, 0xFF, 0x01, 0x10, 0x10, 0x00, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0x20,
+ 0x10, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x30, 0x10, 0x00, 0x01, 0xAF,
+ 0x01, 0xFF, 0x01, 0x30, 0x10, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x40,
+ 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF,
+ 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50,
+ 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF,
+ 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50,
+ 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF,
+ 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50,
+ 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF,
+ 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50,
+ 0x10, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0x34,
+ 0x01, 0x44, 0x01, 0x10, 0x33, 0x00,
+
+ /* 20 INV_QUESTION */
+ 0xFF, 0x00, 0x36, 0x00, 0x02, 0xDD, 0x11, 0x00, 0x02, 0xFF, 0x11, 0x00,
+ 0x02, 0xFF, 0x11, 0x00, 0x02, 0xFF, 0x11, 0x00, 0x02, 0xFF, 0x11, 0x00,
+ 0x02, 0x44, 0x37, 0x00, 0x01, 0xBC, 0x01, 0xCB, 0x11, 0x00, 0x01, 0xEF,
+ 0x01, 0xFE, 0x11, 0x00, 0x01, 0xEF, 0x01, 0xFE, 0x11, 0x00, 0x01, 0xEF,
+ 0x01, 0xFE, 0x11, 0x00, 0x01, 0xFF, 0x01, 0xFD, 0x10, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xFB, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xF6,
+ 0x10, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xD0, 0x0F, 0x00, 0x01, 0x0A,
+ 0x02, 0xFF, 0x01, 0x30, 0x0F, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xF4,
+ 0x0F, 0x00, 0x01, 0x09, 0x02, 0xFF, 0x01, 0x40, 0x0F, 0x00, 0x01, 0x7F,
+ 0x01, 0xFF, 0x01, 0xF4, 0x0F, 0x00, 0x01, 0x03, 0x02, 0xFF, 0x01, 0x40,
+ 0x0F, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF8, 0x10, 0x00, 0x01, 0x0F,
+ 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xF0,
+ 0x10, 0x00, 0x01, 0x0F, 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x0E,
+ 0x01, 0xFF, 0x01, 0xF8, 0x04, 0x00, 0x01, 0x05, 0x01, 0xD0, 0x0A, 0x00,
+ 0x01, 0x08, 0x02, 0xFF, 0x01, 0x70, 0x02, 0x00, 0x01, 0x05, 0x01, 0xCF,
+ 0x01, 0xF0, 0x0A, 0x00, 0x01, 0x01, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xFE,
+ 0x01, 0x98, 0x01, 0x8B, 0x02, 0xFF, 0x01, 0xF0, 0x0B, 0x00, 0x01, 0x3F,
+ 0x06, 0xFF, 0x01, 0xC0, 0x0B, 0x00, 0x01, 0x02, 0x01, 0xCF, 0x04, 0xFF,
+ 0x01, 0xC5, 0x0D, 0x00, 0x01, 0x03, 0x01, 0x8B, 0x01, 0xCC, 0x01, 0xB9,
+ 0x01, 0x62, 0x31, 0x00,
+#endif // TOUCH_UI_UTF8_PUNCTUATION
+
+#if ENABLED(TOUCH_UI_UTF8_CURRENCY)
+ /* 21 CENT_SIGN */
+ 0xB1, 0x00, 0x01, 0x01, 0x01, 0x32, 0x11, 0x00, 0x01, 0x05, 0x01, 0xFB,
+ 0x11, 0x00, 0x01, 0x05, 0x01, 0xFB, 0x11, 0x00, 0x01, 0x05, 0x01, 0xFB,
+ 0x11, 0x00, 0x01, 0x05, 0x01, 0xFC, 0x11, 0x00, 0x01, 0x05, 0x01, 0xFC,
+ 0x11, 0x00, 0x01, 0x39, 0x01, 0xFD, 0x01, 0x42, 0x0E, 0x00, 0x01, 0x05,
+ 0x01, 0xBF, 0x03, 0xFF, 0x01, 0xFB, 0x01, 0x50, 0x0B, 0x00, 0x01, 0x03,
+ 0x01, 0xCF, 0x05, 0xFF, 0x01, 0xF6, 0x0B, 0x00, 0x01, 0x4F, 0x02, 0xFF,
+ 0x02, 0xFE, 0x01, 0xCE, 0x01, 0xFF, 0x01, 0xF6, 0x0A, 0x00, 0x01, 0x02,
+ 0x02, 0xFF, 0x01, 0xE6, 0x01, 0x05, 0x01, 0xFC, 0x01, 0x00, 0x01, 0x38,
+ 0x01, 0xE6, 0x0A, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x10,
+ 0x01, 0x05, 0x01, 0xFC, 0x02, 0x00, 0x01, 0x02, 0x0A, 0x00, 0x01, 0x5F,
+ 0x01, 0xFF, 0x01, 0xE1, 0x01, 0x00, 0x01, 0x05, 0x01, 0xFC, 0x0D, 0x00,
+ 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x60, 0x01, 0x00, 0x01, 0x05, 0x01, 0xFC,
+ 0x0D, 0x00, 0x02, 0xFF, 0x02, 0x00, 0x01, 0x05, 0x01, 0xFC, 0x0C, 0x00,
+ 0x01, 0x04, 0x01, 0xFF, 0x01, 0xFB, 0x02, 0x00, 0x01, 0x05, 0x01, 0xFC,
+ 0x0C, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF8, 0x02, 0x00, 0x01, 0x05,
+ 0x01, 0xFC, 0x0C, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF7, 0x02, 0x00,
+ 0x01, 0x05, 0x01, 0xFB, 0x0C, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xF6,
+ 0x02, 0x00, 0x01, 0x05, 0x01, 0xFC, 0x0C, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF7, 0x02, 0x00, 0x01, 0x05, 0x01, 0xFB, 0x0C, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xF9, 0x02, 0x00, 0x01, 0x05, 0x01, 0xFB, 0x0C, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFC, 0x02, 0x00, 0x01, 0x05, 0x01, 0xFB,
+ 0x0D, 0x00, 0x02, 0xFF, 0x01, 0x10, 0x01, 0x00, 0x01, 0x05, 0x01, 0xFB,
+ 0x0D, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0x80, 0x01, 0x00, 0x01, 0x05,
+ 0x01, 0xFB, 0x0D, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xF3, 0x01, 0x00,
+ 0x01, 0x05, 0x01, 0xFB, 0x0D, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xFE,
+ 0x01, 0x30, 0x01, 0x05, 0x01, 0xFB, 0x02, 0x00, 0x01, 0x33, 0x0A, 0x00,
+ 0x01, 0x01, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xF9, 0x01, 0x35, 0x01, 0xFB,
+ 0x01, 0x02, 0x01, 0x6C, 0x01, 0xF6, 0x0B, 0x00, 0x01, 0x2D, 0x06, 0xFF,
+ 0x01, 0xF6, 0x0B, 0x00, 0x01, 0x01, 0x01, 0x9F, 0x05, 0xFF, 0x01, 0xF5,
+ 0x0C, 0x00, 0x01, 0x02, 0x01, 0x8D, 0x03, 0xFF, 0x01, 0xC7, 0x01, 0x20,
+ 0x0E, 0x00, 0x01, 0x06, 0x01, 0xFC, 0x01, 0x20, 0x10, 0x00, 0x01, 0x05,
+ 0x01, 0xFB, 0x11, 0x00, 0x01, 0x05, 0x01, 0xFB, 0x11, 0x00, 0x01, 0x05,
+ 0x01, 0xFB, 0x11, 0x00, 0x01, 0x05, 0x01, 0xFB, 0x11, 0x00, 0x01, 0x05,
+ 0x01, 0xFB, 0x57, 0x00,
+
+ /* 22 POUND_SIGN */
+ 0x9E, 0x00, 0x01, 0x6B, 0x01, 0xDF, 0x01, 0xFD, 0x01, 0xC9, 0x01, 0x40,
+ 0x0D, 0x00, 0x01, 0x6E, 0x05, 0xFF, 0x01, 0x30, 0x0B, 0x00, 0x01, 0x07,
+ 0x06, 0xFF, 0x01, 0x30, 0x0B, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0xFE,
+ 0x01, 0x85, 0x01, 0x34, 0x01, 0x7B, 0x01, 0xFF, 0x01, 0x30, 0x0B, 0x00,
+ 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xC1, 0x03, 0x00, 0x01, 0x18, 0x01, 0x30,
+ 0x0A, 0x00, 0x01, 0x01, 0x02, 0xFF, 0x01, 0x30, 0x0F, 0x00, 0x01, 0x04,
+ 0x01, 0xFF, 0x01, 0xFD, 0x10, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xFA,
+ 0x10, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xF8, 0x10, 0x00, 0x01, 0x09,
+ 0x01, 0xFF, 0x01, 0xF7, 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6,
+ 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6,
+ 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6, 0x0E, 0x00, 0x01, 0x0A,
+ 0x07, 0xFF, 0x01, 0xF4, 0x0A, 0x00, 0x01, 0x0A, 0x07, 0xFF, 0x01, 0xF4,
+ 0x0A, 0x00, 0x01, 0x08, 0x01, 0xDD, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xFE,
+ 0x03, 0xDD, 0x01, 0xD4, 0x0C, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6,
+ 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6,
+ 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6,
+ 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF6, 0x0E, 0x00, 0x01, 0x4B, 0x01, 0xBB, 0x01, 0xBE,
+ 0x01, 0xFF, 0x01, 0xFD, 0x05, 0xBB, 0x01, 0x70, 0x08, 0x00, 0x01, 0x6F,
+ 0x09, 0xFF, 0x01, 0xA0, 0x08, 0x00, 0x01, 0x6F, 0x09, 0xFF, 0x01, 0xA0,
+ 0x08, 0x00, 0x01, 0x4A, 0x09, 0xAA, 0x01, 0x60, 0xC5, 0x00,
+
+ /* 23 CURRENCY_SIGN */
+ 0xFF, 0x00, 0x0D, 0x00, 0x01, 0x30, 0x07, 0x00, 0x01, 0x01, 0x01, 0x40,
+ 0x08, 0x00, 0x01, 0x0B, 0x01, 0xF5, 0x07, 0x00, 0x01, 0x1D, 0x01, 0xF4,
+ 0x08, 0x00, 0x01, 0xBF, 0x01, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0x01,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x30, 0x07, 0x00, 0x01, 0x5F, 0x01, 0xFF,
+ 0x01, 0xF4, 0x01, 0x00, 0x01, 0x6B, 0x01, 0xDD, 0x01, 0xC8, 0x01, 0x20,
+ 0x01, 0x1D, 0x01, 0xFF, 0x01, 0xFA, 0x08, 0x00, 0x01, 0x05, 0x02, 0xFF,
+ 0x01, 0x8E, 0x03, 0xFF, 0x01, 0xFA, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xA0,
+ 0x09, 0x00, 0x01, 0x5F, 0x07, 0xFF, 0x01, 0xFA, 0x0A, 0x00, 0x01, 0x05,
+ 0x02, 0xFF, 0x01, 0xE9, 0x01, 0x55, 0x01, 0x7C, 0x02, 0xFF, 0x01, 0xA0,
+ 0x0A, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0xFB, 0x01, 0x10, 0x02, 0x00,
+ 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xA0, 0x0A, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0xC0, 0x03, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF2, 0x0A, 0x00,
+ 0x01, 0x1F, 0x01, 0xFF, 0x01, 0x30, 0x04, 0x00, 0x01, 0xDF, 0x01, 0xF7,
+ 0x0A, 0x00, 0x01, 0x4F, 0x01, 0xFD, 0x05, 0x00, 0x01, 0x8F, 0x01, 0xFA,
+ 0x0A, 0x00, 0x01, 0x6F, 0x01, 0xFC, 0x05, 0x00, 0x01, 0x6F, 0x01, 0xFC,
+ 0x0A, 0x00, 0x01, 0x5F, 0x01, 0xFC, 0x05, 0x00, 0x01, 0x7F, 0x01, 0xFB,
+ 0x0A, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0x10, 0x04, 0x00, 0x01, 0xBF,
+ 0x01, 0xF8, 0x0A, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0x80, 0x03, 0x00,
+ 0x01, 0x03, 0x01, 0xFF, 0x01, 0xF3, 0x0A, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF5, 0x03, 0x00, 0x01, 0x1D, 0x01, 0xFF, 0x01, 0xC0, 0x0A, 0x00,
+ 0x01, 0x01, 0x02, 0xFF, 0x01, 0x92, 0x01, 0x00, 0x01, 0x16, 0x01, 0xEF,
+ 0x01, 0xFF, 0x01, 0x60, 0x0A, 0x00, 0x01, 0x1D, 0x03, 0xFF, 0x01, 0xFE,
+ 0x03, 0xFF, 0x01, 0xF4, 0x09, 0x00, 0x01, 0x01, 0x01, 0xDF, 0x05, 0xFF,
+ 0x01, 0xFE, 0x02, 0xFF, 0x01, 0x40, 0x08, 0x00, 0x01, 0x1D, 0x01, 0xFF,
+ 0x01, 0xFA, 0x01, 0x06, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0x81,
+ 0x01, 0x5F, 0x01, 0xFF, 0x01, 0xF4, 0x08, 0x00, 0x01, 0xCF, 0x01, 0xFF,
+ 0x01, 0xA0, 0x01, 0x00, 0x01, 0x01, 0x01, 0x44, 0x01, 0x20, 0x01, 0x00,
+ 0x01, 0x05, 0x02, 0xFF, 0x01, 0x20, 0x07, 0x00, 0x01, 0x4F, 0x01, 0xFA,
+ 0x07, 0x00, 0x01, 0x4F, 0x01, 0xF8, 0x08, 0x00, 0x01, 0x05, 0x01, 0xA0,
+ 0x07, 0x00, 0x01, 0x05, 0x01, 0x80, 0xEB, 0x00,
+
+ /* 24 YEN_SIGN */
+ 0x98, 0x00, 0x01, 0x01, 0x01, 0x88, 0x01, 0x85, 0x07, 0x00, 0x01, 0x38,
+ 0x01, 0x88, 0x01, 0x40, 0x07, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x10,
+ 0x06, 0x00, 0x01, 0xCF, 0x01, 0xFF, 0x01, 0x10, 0x07, 0x00, 0x01, 0x3F,
+ 0x01, 0xFF, 0x01, 0x90, 0x05, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xF8,
+ 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xF2, 0x05, 0x00, 0x01, 0x0D,
+ 0x01, 0xFF, 0x01, 0xE0, 0x08, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xFA,
+ 0x05, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x60, 0x09, 0x00, 0x01, 0xAF,
+ 0x01, 0xFF, 0x01, 0x30, 0x04, 0x00, 0x01, 0xEF, 0x01, 0xFD, 0x0A, 0x00,
+ 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xC0, 0x03, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF5, 0x0A, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xF4, 0x03, 0x00,
+ 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xC0, 0x0A, 0x00, 0x01, 0x01, 0x01, 0xEF,
+ 0x01, 0xFD, 0x03, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x40, 0x0B, 0x00,
+ 0x01, 0x7F, 0x01, 0xFF, 0x01, 0x50, 0x01, 0x00, 0x01, 0x02, 0x01, 0xFF,
+ 0x01, 0xFB, 0x0C, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xE0, 0x01, 0x00,
+ 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF3, 0x0C, 0x00, 0x01, 0x06, 0x01, 0xFF,
+ 0x01, 0xF7, 0x01, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xA0, 0x0A, 0x00,
+ 0x01, 0x2A, 0x02, 0xAA, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0x10, 0x01, 0xBF,
+ 0x01, 0xFF, 0x01, 0xCA, 0x01, 0xAA, 0x01, 0xA5, 0x08, 0x00, 0x01, 0x4F,
+ 0x04, 0xFF, 0x01, 0x83, 0x04, 0xFF, 0x01, 0xF8, 0x08, 0x00, 0x01, 0x3C,
+ 0x02, 0xCC, 0x01, 0xCE, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0xFF, 0x01, 0xFC,
+ 0x02, 0xCC, 0x01, 0xC6, 0x0B, 0x00, 0x01, 0x03, 0x03, 0xFF, 0x01, 0x70,
+ 0x0F, 0x00, 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xFE, 0x10, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0xF5, 0x0C, 0x00, 0x01, 0x01, 0x03, 0x11, 0x01, 0x1E,
+ 0x01, 0xFF, 0x01, 0xF3, 0x03, 0x11, 0x01, 0x10, 0x08, 0x00, 0x01, 0x4F,
+ 0x09, 0xFF, 0x01, 0xF8, 0x08, 0x00, 0x01, 0x4F, 0x09, 0xFF, 0x01, 0xF8,
+ 0x08, 0x00, 0x01, 0x27, 0x03, 0x77, 0x01, 0x7E, 0x01, 0xFF, 0x01, 0xF8,
+ 0x03, 0x77, 0x01, 0x73, 0x0C, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2,
+ 0x10, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x0E,
+ 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2,
+ 0x10, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x0E,
+ 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2,
+ 0x10, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x08,
+ 0x01, 0x99, 0x01, 0x91, 0xC9, 0x00,
+#endif // TOUCH_UI_UTF8_CURRENCY
+
+#if ENABLED(TOUCH_UI_UTF8_SUPERSCRIPTS)
+ /* 25 SUPERSCRIPT_ONE */
+ 0x99, 0x00, 0x01, 0x01, 0x01, 0x36, 0x01, 0x9B, 0x01, 0xBB, 0x01, 0x20,
+ 0x0E, 0x00, 0x01, 0x3F, 0x03, 0xFF, 0x01, 0x20, 0x0E, 0x00, 0x01, 0x3F,
+ 0x01, 0xFE, 0x01, 0xBE, 0x01, 0xFF, 0x01, 0x20, 0x0E, 0x00, 0x01, 0x14,
+ 0x01, 0x10, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20,
+ 0x10, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20,
+ 0x10, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20,
+ 0x10, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x10, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x0F, 0x00, 0x01, 0x11, 0x01, 0x1C, 0x01, 0xFF,
+ 0x01, 0x31, 0x01, 0x11, 0x0D, 0x00, 0x01, 0x0D, 0x05, 0xFF, 0x01, 0x40,
+ 0x0C, 0x00, 0x01, 0x0D, 0x05, 0xFF, 0x01, 0x40, 0x0C, 0x00, 0x01, 0x01,
+ 0x05, 0x22, 0xFF, 0x00, 0xC2, 0x00,
+
+ /* 26 SUPERSCRIPT_TWO */
+ 0x88, 0x00, 0x01, 0x01, 0x10, 0x00, 0x01, 0x16, 0x01, 0xAE, 0x01, 0xFF,
+ 0x01, 0xFD, 0x01, 0x92, 0x0E, 0x00, 0x05, 0xFF, 0x01, 0x60, 0x0D, 0x00,
+ 0x01, 0xFE, 0x01, 0x84, 0x01, 0x22, 0x01, 0x5C, 0x01, 0xFF, 0x01, 0xF3,
+ 0x0D, 0x00, 0x01, 0x50, 0x03, 0x00, 0x01, 0xCF, 0x01, 0xFA, 0x11, 0x00,
+ 0x01, 0x5F, 0x01, 0xFC, 0x11, 0x00, 0x01, 0x5F, 0x01, 0xFB, 0x11, 0x00,
+ 0x01, 0xCF, 0x01, 0xF4, 0x10, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x6F, 0x01, 0xFE, 0x01, 0x10, 0x0F, 0x00, 0x01, 0x05,
+ 0x01, 0xFF, 0x01, 0xE2, 0x10, 0x00, 0x01, 0x5F, 0x01, 0xFF, 0x01, 0x30,
+ 0x0F, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xE3, 0x10, 0x00, 0x01, 0x6F,
+ 0x01, 0xFE, 0x01, 0x20, 0x0F, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xD1,
+ 0x10, 0x00, 0x01, 0xAF, 0x01, 0xFD, 0x01, 0x43, 0x03, 0x33, 0x0C, 0x00,
+ 0x01, 0x01, 0x06, 0xFF, 0x0C, 0x00, 0x01, 0x01, 0x06, 0xFF, 0x0D, 0x00,
+ 0x06, 0x22, 0xFF, 0x00, 0xC2, 0x00,
+
+ /* 27 SUPERSCRIPT_THREE */
+ 0x88, 0x00, 0x01, 0x01, 0x01, 0x10, 0x0F, 0x00, 0x01, 0x39, 0x01, 0xCE,
+ 0x02, 0xFF, 0x01, 0xB5, 0x0E, 0x00, 0x01, 0x7F, 0x04, 0xFF, 0x01, 0xB0,
+ 0x0D, 0x00, 0x01, 0x6B, 0x01, 0x73, 0x01, 0x22, 0x01, 0x38, 0x01, 0xFF,
+ 0x01, 0xF9, 0x11, 0x00, 0x01, 0x5F, 0x01, 0xFF, 0x11, 0x00, 0x01, 0x0F,
+ 0x01, 0xFF, 0x11, 0x00, 0x01, 0x4F, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x27,
+ 0x01, 0xFF, 0x01, 0xF3, 0x0E, 0x00, 0x01, 0x0C, 0x02, 0xFF, 0x01, 0xFA,
+ 0x01, 0x20, 0x0E, 0x00, 0x01, 0x0C, 0x02, 0xFF, 0x01, 0xFB, 0x01, 0x40,
+ 0x0E, 0x00, 0x01, 0x01, 0x01, 0x23, 0x01, 0x49, 0x01, 0xFF, 0x01, 0xF6,
+ 0x11, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0x10, 0x10, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x50, 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0x60,
+ 0x10, 0x00, 0x01, 0x1E, 0x01, 0xFF, 0x01, 0x40, 0x0C, 0x00, 0x01, 0xA4,
+ 0x02, 0x00, 0x01, 0x05, 0x01, 0xDF, 0x01, 0xFD, 0x0D, 0x00, 0x02, 0xFF,
+ 0x01, 0xDE, 0x02, 0xFF, 0x01, 0xE3, 0x0D, 0x00, 0x01, 0xAE, 0x03, 0xFF,
+ 0x01, 0xE9, 0x01, 0x10, 0x0E, 0x00, 0x01, 0x24, 0x01, 0x55, 0x01, 0x52,
+ 0xFF, 0x00, 0xC4, 0x00,
+#endif // TOUCH_UI_UTF8_SUPERSCRIPTS
+
+#if ENABLED(TOUCH_UI_UTF8_ORDINALS)
+ /* 28 MASCULINE_ORDINAL */
+ 0x89, 0x00, 0x01, 0x01, 0x01, 0x10, 0x0F, 0x00, 0x01, 0x01, 0x01, 0x8D,
+ 0x02, 0xFF, 0x01, 0xB4, 0x0E, 0x00, 0x01, 0x4F, 0x04, 0xFF, 0x01, 0xA0,
+ 0x0C, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x63, 0x01, 0x48,
+ 0x01, 0xFF, 0x01, 0xFB, 0x0C, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xA0,
+ 0x02, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0x60, 0x0B, 0x00, 0x01, 0x6F,
+ 0x01, 0xFE, 0x03, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xD0, 0x0B, 0x00,
+ 0x01, 0xBF, 0x01, 0xF7, 0x04, 0x00, 0x01, 0xFF, 0x01, 0xF2, 0x0B, 0x00,
+ 0x01, 0xEF, 0x01, 0xF3, 0x04, 0x00, 0x01, 0xCF, 0x01, 0xF6, 0x0B, 0x00,
+ 0x01, 0xFF, 0x01, 0xF1, 0x04, 0x00, 0x01, 0xAF, 0x01, 0xF7, 0x0B, 0x00,
+ 0x01, 0xFF, 0x01, 0xF1, 0x04, 0x00, 0x01, 0xAF, 0x01, 0xF7, 0x0B, 0x00,
+ 0x01, 0xFF, 0x01, 0xF2, 0x04, 0x00, 0x01, 0xBF, 0x01, 0xF6, 0x0B, 0x00,
+ 0x01, 0xCF, 0x01, 0xF6, 0x04, 0x00, 0x01, 0xEF, 0x01, 0xF4, 0x0B, 0x00,
+ 0x01, 0x8F, 0x01, 0xFC, 0x03, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xF0,
+ 0x0B, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x60, 0x02, 0x00, 0x01, 0x1D,
+ 0x01, 0xFF, 0x01, 0x90, 0x0B, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xF8,
+ 0x01, 0x10, 0x01, 0x04, 0x01, 0xDF, 0x01, 0xFE, 0x01, 0x10, 0x0C, 0x00,
+ 0x01, 0xAF, 0x04, 0xFF, 0x01, 0xE3, 0x0D, 0x00, 0x01, 0x05, 0x01, 0xDF,
+ 0x02, 0xFF, 0x01, 0xFA, 0x01, 0x10, 0x0E, 0x00, 0x01, 0x02, 0x01, 0x56,
+ 0x01, 0x64, 0x21, 0x00, 0x01, 0x16, 0x06, 0x66, 0x01, 0x40, 0x0B, 0x00,
+ 0x01, 0x3F, 0x06, 0xFF, 0x01, 0xB0, 0x0B, 0x00, 0x01, 0x3F, 0x06, 0xFF,
+ 0x01, 0xB0, 0x0B, 0x00, 0x01, 0x01, 0x06, 0x11, 0xFF, 0x00, 0x75, 0x00,
+
+ /* 29 FEMININE_ORDINAL */
+ 0x89, 0x00, 0x01, 0x12, 0x01, 0x10, 0x0F, 0x00, 0x01, 0x49, 0x01, 0xDF,
+ 0x02, 0xFF, 0x01, 0xB4, 0x0D, 0x00, 0x01, 0x07, 0x05, 0xFF, 0x01, 0xA0,
+ 0x0C, 0x00, 0x01, 0x07, 0x01, 0xFC, 0x01, 0x74, 0x01, 0x33, 0x01, 0x59,
+ 0x01, 0xFF, 0x01, 0xF8, 0x0C, 0x00, 0x01, 0x03, 0x01, 0x20, 0x03, 0x00,
+ 0x01, 0x3F, 0x01, 0xFF, 0x01, 0x10, 0x10, 0x00, 0x01, 0x09, 0x01, 0xFF,
+ 0x01, 0x50, 0x0E, 0x00, 0x01, 0x01, 0x01, 0x11, 0x01, 0x16, 0x01, 0xFF,
+ 0x01, 0x80, 0x0C, 0x00, 0x01, 0x05, 0x01, 0xAE, 0x04, 0xFF, 0x01, 0x90,
+ 0x0B, 0x00, 0x01, 0x01, 0x01, 0xCF, 0x05, 0xFF, 0x01, 0xA0, 0x0B, 0x00,
+ 0x01, 0x0D, 0x01, 0xFF, 0x01, 0xE9, 0x01, 0x65, 0x01, 0x44, 0x01, 0x48,
+ 0x01, 0xFF, 0x01, 0xA0, 0x0B, 0x00, 0x01, 0x5F, 0x01, 0xFD, 0x01, 0x10,
+ 0x02, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xA0, 0x0B, 0x00, 0x01, 0x9F,
+ 0x01, 0xF6, 0x03, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xA0, 0x0B, 0x00,
+ 0x01, 0xAF, 0x01, 0xF5, 0x03, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x01, 0xA0,
+ 0x0B, 0x00, 0x01, 0x9F, 0x01, 0xFA, 0x03, 0x00, 0x01, 0xAF, 0x01, 0xFF,
+ 0x01, 0xA0, 0x0B, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0xA2, 0x01, 0x00,
+ 0x01, 0x3B, 0x02, 0xFF, 0x01, 0xA0, 0x0B, 0x00, 0x01, 0x0A, 0x04, 0xFF,
+ 0x01, 0xE7, 0x01, 0xFF, 0x01, 0xA0, 0x0C, 0x00, 0x01, 0x8F, 0x02, 0xFF,
+ 0x01, 0xF9, 0x01, 0x15, 0x01, 0xFF, 0x01, 0xA0, 0x0D, 0x00, 0x01, 0x46,
+ 0x01, 0x64, 0x02, 0x00, 0x01, 0x11, 0x1F, 0x00, 0x01, 0x16, 0x06, 0x66,
+ 0x01, 0x40, 0x0B, 0x00, 0x01, 0x3F, 0x06, 0xFF, 0x01, 0xB0, 0x0B, 0x00,
+ 0x01, 0x3F, 0x06, 0xFF, 0x01, 0xB0, 0x0B, 0x00, 0x01, 0x01, 0x06, 0x11,
+ 0xFF, 0x00, 0x75, 0x00,
+#endif // TOUCH_UI_UTF8_ORDINALS
+
+#if ENABLED(TOUCH_UI_UTF8_COPYRIGHT)
+ /* 30 COPYRIGHT_SIGN */
+ 0xA0, 0x00, 0x01, 0x01, 0x01, 0x45, 0x01, 0x76, 0x01, 0x43, 0x0E, 0x00,
+ 0x01, 0x28, 0x01, 0xDF, 0x03, 0xFF, 0x01, 0xE9, 0x01, 0x40, 0x0B, 0x00,
+ 0x01, 0x19, 0x02, 0xFF, 0x01, 0xDB, 0x01, 0xAB, 0x01, 0xCE, 0x01, 0xFF,
+ 0x01, 0xFB, 0x01, 0x30, 0x09, 0x00, 0x01, 0x03, 0x01, 0xEF, 0x01, 0xFB,
+ 0x01, 0x50, 0x03, 0x00, 0x01, 0x38, 0x01, 0xFF, 0x01, 0xF7, 0x09, 0x00,
+ 0x01, 0x6F, 0x01, 0xFC, 0x01, 0x30, 0x05, 0x00, 0x01, 0x19, 0x01, 0xFF,
+ 0x01, 0xA0, 0x07, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xA0, 0x07, 0x00,
+ 0x01, 0x5F, 0x01, 0xFB, 0x07, 0x00, 0x01, 0x3F, 0x01, 0xF8, 0x03, 0x00,
+ 0x01, 0x46, 0x01, 0x88, 0x01, 0x65, 0x01, 0x10, 0x01, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0x80, 0x06, 0x00, 0x01, 0xEF, 0x01, 0xA0, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x9F, 0x03, 0xFF, 0x01, 0xFC, 0x01, 0x60, 0x01, 0x00,
+ 0x01, 0x4F, 0x01, 0xF4, 0x05, 0x00, 0x01, 0x08, 0x01, 0xFD, 0x02, 0x00,
+ 0x01, 0x4E, 0x02, 0xFF, 0x01, 0xED, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0,
+ 0x01, 0x00, 0x01, 0x08, 0x01, 0xFD, 0x05, 0x00, 0x01, 0x1F, 0x01, 0xF4,
+ 0x01, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0x61, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x4A, 0x01, 0xA0, 0x02, 0x00, 0x01, 0xEF, 0x01, 0x60,
+ 0x04, 0x00, 0x01, 0x6F, 0x01, 0xC0, 0x01, 0x00, 0x01, 0x0E, 0x01, 0xFF,
+ 0x01, 0xC1, 0x07, 0x00, 0x01, 0x7F, 0x01, 0xB0, 0x04, 0x00, 0x01, 0xBF,
+ 0x01, 0x60, 0x01, 0x00, 0x01, 0x7F, 0x01, 0xFF, 0x01, 0x10, 0x07, 0x00,
+ 0x01, 0x1F, 0x01, 0xF0, 0x04, 0x00, 0x01, 0xFF, 0x01, 0x20, 0x01, 0x00,
+ 0x01, 0xDF, 0x01, 0xF9, 0x08, 0x00, 0x01, 0x0D, 0x01, 0xF4, 0x03, 0x00,
+ 0x01, 0x01, 0x01, 0xFE, 0x01, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF4,
+ 0x08, 0x00, 0x01, 0x0A, 0x01, 0xF6, 0x03, 0x00, 0x01, 0x03, 0x01, 0xFD,
+ 0x01, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xF1, 0x08, 0x00, 0x01, 0x08,
+ 0x01, 0xF8, 0x03, 0x00, 0x01, 0x04, 0x01, 0xFC, 0x01, 0x00, 0x01, 0x03,
+ 0x01, 0xFF, 0x01, 0xF0, 0x08, 0x00, 0x01, 0x07, 0x01, 0xF9, 0x03, 0x00,
+ 0x01, 0x03, 0x01, 0xFD, 0x01, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xF1,
+ 0x08, 0x00, 0x01, 0x08, 0x01, 0xF8, 0x03, 0x00, 0x01, 0x01, 0x01, 0xFE,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF3, 0x08, 0x00, 0x01, 0x09,
+ 0x01, 0xF7, 0x04, 0x00, 0x01, 0xFF, 0x01, 0x10, 0x01, 0x00, 0x01, 0xDF,
+ 0x01, 0xF8, 0x08, 0x00, 0x01, 0x0C, 0x01, 0xF5, 0x04, 0x00, 0x01, 0xBF,
+ 0x01, 0x60, 0x01, 0x00, 0x01, 0x8F, 0x01, 0xFE, 0x01, 0x10, 0x07, 0x00,
+ 0x01, 0x1F, 0x01, 0xF1, 0x04, 0x00, 0x01, 0x6F, 0x01, 0xB0, 0x01, 0x00,
+ 0x01, 0x1F, 0x01, 0xFF, 0x01, 0xB0, 0x07, 0x00, 0x01, 0x6F, 0x01, 0xC0,
+ 0x04, 0x00, 0x01, 0x1F, 0x01, 0xF4, 0x01, 0x00, 0x01, 0x05, 0x01, 0xFF,
+ 0x01, 0xFD, 0x01, 0x50, 0x02, 0x00, 0x01, 0x29, 0x01, 0xA0, 0x02, 0x00,
+ 0x01, 0xEF, 0x01, 0x60, 0x04, 0x00, 0x01, 0x08, 0x01, 0xFD, 0x02, 0x00,
+ 0x01, 0x6F, 0x02, 0xFF, 0x01, 0xDB, 0x01, 0xCE, 0x01, 0xFF, 0x01, 0xB0,
+ 0x01, 0x00, 0x01, 0x07, 0x01, 0xFD, 0x05, 0x00, 0x01, 0x01, 0x01, 0xEF,
+ 0x01, 0x90, 0x01, 0x00, 0x01, 0x02, 0x01, 0xBF, 0x03, 0xFF, 0x01, 0xFE,
+ 0x01, 0x70, 0x01, 0x00, 0x01, 0x4F, 0x01, 0xF4, 0x06, 0x00, 0x01, 0x4F,
+ 0x01, 0xF7, 0x02, 0x00, 0x01, 0x01, 0x01, 0x58, 0x01, 0x9A, 0x01, 0x86,
+ 0x01, 0x30, 0x01, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0x80, 0x06, 0x00,
+ 0x01, 0x06, 0x01, 0xFF, 0x01, 0x90, 0x07, 0x00, 0x01, 0x4F, 0x01, 0xFB,
+ 0x08, 0x00, 0x01, 0x6F, 0x01, 0xFC, 0x01, 0x30, 0x05, 0x00, 0x01, 0x18,
+ 0x01, 0xFF, 0x01, 0xB0, 0x08, 0x00, 0x01, 0x04, 0x01, 0xEF, 0x01, 0xFA,
+ 0x01, 0x40, 0x03, 0x00, 0x01, 0x27, 0x01, 0xEF, 0x01, 0xF8, 0x0A, 0x00,
+ 0x01, 0x19, 0x02, 0xFF, 0x01, 0xCA, 0x01, 0x9A, 0x01, 0xBE, 0x01, 0xFF,
+ 0x01, 0xFC, 0x01, 0x30, 0x0B, 0x00, 0x01, 0x29, 0x01, 0xDF, 0x03, 0xFF,
+ 0x01, 0xFA, 0x01, 0x40, 0x0D, 0x00, 0x01, 0x02, 0x01, 0x46, 0x01, 0x76,
+ 0x01, 0x53, 0xC5, 0x00,
+
+ /* 31 REGISTERED_SIGN */
+ 0xA0, 0x00, 0x01, 0x02, 0x01, 0x46, 0x01, 0x76, 0x01, 0x53, 0x0E, 0x00,
+ 0x01, 0x28, 0x01, 0xDF, 0x03, 0xFF, 0x01, 0xEA, 0x01, 0x40, 0x0B, 0x00,
+ 0x01, 0x19, 0x02, 0xFF, 0x01, 0xCB, 0x01, 0x9A, 0x01, 0xCE, 0x01, 0xFF,
+ 0x01, 0xFC, 0x01, 0x30, 0x09, 0x00, 0x01, 0x04, 0x01, 0xEF, 0x01, 0xFA,
+ 0x01, 0x40, 0x03, 0x00, 0x01, 0x38, 0x01, 0xFF, 0x01, 0xF8, 0x09, 0x00,
+ 0x01, 0x6F, 0x01, 0xFC, 0x01, 0x30, 0x05, 0x00, 0x01, 0x18, 0x01, 0xFF,
+ 0x01, 0xA0, 0x07, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0x90, 0x07, 0x00,
+ 0x01, 0x4F, 0x01, 0xFB, 0x07, 0x00, 0x01, 0x3F, 0x01, 0xF7, 0x01, 0x00,
+ 0x01, 0x13, 0x02, 0x33, 0x01, 0x32, 0x03, 0x00, 0x01, 0x02, 0x01, 0xFF,
+ 0x01, 0x80, 0x06, 0x00, 0x01, 0xEF, 0x01, 0xA0, 0x01, 0x00, 0x01, 0x7F,
+ 0x03, 0xFF, 0x01, 0xFD, 0x01, 0x81, 0x02, 0x00, 0x01, 0x4F, 0x01, 0xF5,
+ 0x05, 0x00, 0x01, 0x08, 0x01, 0xFD, 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFF,
+ 0x01, 0xDD, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0x30, 0x01, 0x00,
+ 0x01, 0x08, 0x01, 0xFE, 0x05, 0x00, 0x01, 0x1F, 0x01, 0xF4, 0x02, 0x00,
+ 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x3C, 0x01, 0xFF, 0x01, 0xD0,
+ 0x02, 0x00, 0x01, 0xEF, 0x01, 0x60, 0x04, 0x00, 0x01, 0x6F, 0x01, 0xC0,
+ 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x02, 0x01, 0xFF,
+ 0x01, 0xF3, 0x02, 0x00, 0x01, 0x7F, 0x01, 0xB0, 0x04, 0x00, 0x01, 0xBF,
+ 0x01, 0x60, 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x03, 0x00, 0x01, 0xFF,
+ 0x01, 0xF4, 0x02, 0x00, 0x01, 0x1F, 0x01, 0xF0, 0x04, 0x00, 0x01, 0xFF,
+ 0x01, 0x10, 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x03, 0x00, 0x01, 0xFF,
+ 0x01, 0xF2, 0x02, 0x00, 0x01, 0x0C, 0x01, 0xF5, 0x03, 0x00, 0x01, 0x01,
+ 0x01, 0xFE, 0x03, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x08,
+ 0x01, 0xFF, 0x01, 0xE0, 0x02, 0x00, 0x01, 0x0A, 0x01, 0xF6, 0x03, 0x00,
+ 0x01, 0x03, 0x01, 0xFD, 0x03, 0x00, 0x01, 0x7F, 0x01, 0xFD, 0x01, 0x88,
+ 0x01, 0x9A, 0x01, 0xEF, 0x01, 0xFE, 0x01, 0x30, 0x02, 0x00, 0x01, 0x08,
+ 0x01, 0xF8, 0x03, 0x00, 0x01, 0x04, 0x01, 0xFC, 0x03, 0x00, 0x01, 0x7F,
+ 0x03, 0xFF, 0x01, 0xFE, 0x01, 0x91, 0x03, 0x00, 0x01, 0x07, 0x01, 0xF9,
+ 0x03, 0x00, 0x01, 0x03, 0x01, 0xFD, 0x03, 0x00, 0x01, 0x7F, 0x01, 0xFC,
+ 0x01, 0x78, 0x01, 0xDF, 0x01, 0xFD, 0x01, 0x20, 0x03, 0x00, 0x01, 0x08,
+ 0x01, 0xF8, 0x03, 0x00, 0x01, 0x01, 0x01, 0xFE, 0x03, 0x00, 0x01, 0x7F,
+ 0x01, 0xFA, 0x01, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xC0, 0x03, 0x00,
+ 0x01, 0x09, 0x01, 0xF6, 0x04, 0x00, 0x01, 0xFF, 0x01, 0x10, 0x02, 0x00,
+ 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0xDF, 0x01, 0xF8, 0x03, 0x00,
+ 0x01, 0x0C, 0x01, 0xF5, 0x04, 0x00, 0x01, 0xBF, 0x01, 0x60, 0x02, 0x00,
+ 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x30,
+ 0x02, 0x00, 0x01, 0x1F, 0x01, 0xF1, 0x04, 0x00, 0x01, 0x6F, 0x01, 0xC0,
+ 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x09, 0x01, 0xFF,
+ 0x01, 0xD0, 0x02, 0x00, 0x01, 0x6F, 0x01, 0xB0, 0x04, 0x00, 0x01, 0x1F,
+ 0x01, 0xF4, 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0xEF, 0x01, 0xF7, 0x02, 0x00, 0x01, 0xEF, 0x01, 0x60, 0x04, 0x00,
+ 0x01, 0x08, 0x01, 0xFD, 0x02, 0x00, 0x01, 0x7F, 0x01, 0xFA, 0x03, 0x00,
+ 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x20, 0x01, 0x08, 0x01, 0xFE, 0x06, 0x00,
+ 0x01, 0xEF, 0x01, 0xA0, 0x01, 0x00, 0x01, 0x5A, 0x01, 0xA6, 0x03, 0x00,
+ 0x01, 0x09, 0x01, 0xAA, 0x01, 0x60, 0x01, 0x4F, 0x01, 0xF4, 0x06, 0x00,
+ 0x01, 0x3F, 0x01, 0xF8, 0x08, 0x00, 0x01, 0x03, 0x01, 0xFF, 0x01, 0x80,
+ 0x06, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0x90, 0x07, 0x00, 0x01, 0x4F,
+ 0x01, 0xFB, 0x08, 0x00, 0x01, 0x6F, 0x01, 0xFC, 0x01, 0x30, 0x05, 0x00,
+ 0x01, 0x19, 0x01, 0xFF, 0x01, 0xA0, 0x08, 0x00, 0x01, 0x04, 0x01, 0xEF,
+ 0x01, 0xFA, 0x01, 0x40, 0x03, 0x00, 0x01, 0x38, 0x01, 0xEF, 0x01, 0xF8,
+ 0x0A, 0x00, 0x01, 0x19, 0x02, 0xFF, 0x01, 0xCB, 0x01, 0x9A, 0x01, 0xCE,
+ 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x30, 0x0B, 0x00, 0x01, 0x28, 0x01, 0xDF,
+ 0x03, 0xFF, 0x01, 0xEA, 0x01, 0x40, 0x0D, 0x00, 0x01, 0x02, 0x01, 0x45,
+ 0x01, 0x76, 0x01, 0x43, 0xC5, 0x00,
+#endif // TOUCH_UI_UTF8_COPYRIGHT
+
+#if ENABLED(TOUCH_UI_UTF8_MATHEMATICS)
+ /* 32 PLUS_MINUS_SIGN */
+ 0xEB, 0x00, 0x01, 0x02, 0x01, 0x77, 0x01, 0x70, 0x10, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0,
+ 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0,
+ 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xF0, 0x0B, 0x00, 0x01, 0x6A, 0x04, 0xAA, 0x01, 0xAC,
+ 0x01, 0xFF, 0x01, 0xFA, 0x05, 0xAA, 0x01, 0x20, 0x05, 0x00, 0x01, 0x9F,
+ 0x0C, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40,
+ 0x05, 0x00, 0x01, 0x7C, 0x04, 0xCC, 0x01, 0xCD, 0x01, 0xFF, 0x01, 0xFC,
+ 0x05, 0xCC, 0x01, 0x30, 0x0A, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0,
+ 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0,
+ 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06,
+ 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF0,
+ 0x10, 0x00, 0x01, 0x03, 0x01, 0x99, 0x01, 0x90, 0x44, 0x00, 0x01, 0x9F,
+ 0x0C, 0xFF, 0x01, 0x30, 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40,
+ 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0x47,
+ 0x0C, 0x77, 0x01, 0x10, 0xC1, 0x00,
+
+ /* 33 MULTIPLICATION_SIGN */
+ 0xFF, 0x00, 0x0E, 0x00, 0x01, 0x09, 0x01, 0xB0, 0x07, 0x00, 0x01, 0x03,
+ 0x01, 0xE4, 0x08, 0x00, 0x01, 0x9F, 0x01, 0xFB, 0x07, 0x00, 0x01, 0x3E,
+ 0x01, 0xFF, 0x01, 0x40, 0x06, 0x00, 0x01, 0x01, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xB0, 0x05, 0x00, 0x01, 0x03, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xA0,
+ 0x07, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xFB, 0x05, 0x00, 0x01, 0x3E,
+ 0x01, 0xFF, 0x01, 0xFB, 0x08, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xB0, 0x03, 0x00, 0x01, 0x03, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0,
+ 0x09, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xFB, 0x03, 0x00, 0x01, 0x3E,
+ 0x01, 0xFF, 0x01, 0xFB, 0x0A, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xB0, 0x01, 0x00, 0x01, 0x03, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0,
+ 0x0B, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xFB, 0x01, 0x00, 0x01, 0x3E,
+ 0x01, 0xFF, 0x01, 0xFB, 0x0C, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xB3, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x0D, 0x00, 0x01, 0x3E,
+ 0x03, 0xFF, 0x01, 0xFB, 0x0E, 0x00, 0x01, 0x03, 0x01, 0xEF, 0x02, 0xFF,
+ 0x01, 0xB0, 0x0F, 0x00, 0x01, 0x5F, 0x02, 0xFF, 0x01, 0x10, 0x0E, 0x00,
+ 0x01, 0x03, 0x01, 0xEF, 0x02, 0xFF, 0x01, 0xB0, 0x0E, 0x00, 0x01, 0x3E,
+ 0x03, 0xFF, 0x01, 0xFB, 0x0D, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xB3, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x0C, 0x00, 0x01, 0x2E,
+ 0x01, 0xFF, 0x01, 0xFB, 0x01, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xFB,
+ 0x0B, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x01, 0x00,
+ 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x0A, 0x00, 0x01, 0x2E,
+ 0x01, 0xFF, 0x01, 0xFB, 0x03, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xFB,
+ 0x09, 0x00, 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x03, 0x00,
+ 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x08, 0x00, 0x01, 0x2E,
+ 0x01, 0xFF, 0x01, 0xFB, 0x05, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0xFB,
+ 0x07, 0x00, 0x01, 0x01, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xB0, 0x05, 0x00,
+ 0x01, 0x02, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xA0, 0x07, 0x00, 0x01, 0x8F,
+ 0x01, 0xFB, 0x07, 0x00, 0x01, 0x2E, 0x01, 0xFF, 0x01, 0x40, 0x07, 0x00,
+ 0x01, 0x09, 0x01, 0xB0, 0x07, 0x00, 0x01, 0x02, 0x01, 0xE4, 0xE9, 0x00,
+
+ /* 34 DIVISION_SIGN */
+ 0xFF, 0x00, 0x25, 0x00, 0x01, 0x17, 0x01, 0x77, 0x01, 0x76, 0x10, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF,
+ 0x01, 0xFC, 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFC, 0x10, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x17, 0x01, 0x77,
+ 0x01, 0x76, 0x31, 0x00, 0x01, 0x24, 0x0C, 0x44, 0x01, 0x10, 0x05, 0x00,
+ 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF,
+ 0x01, 0x40, 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40, 0x05, 0x00,
+ 0x01, 0x12, 0x0C, 0x22, 0x31, 0x00, 0x01, 0x18, 0x01, 0x88, 0x01, 0x87,
+ 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFC,
+ 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0xFC, 0x10, 0x00, 0x01, 0x16,
+ 0x01, 0x66, 0x01, 0x65, 0xFF, 0x00, 0x01, 0x00,
+#endif // TOUCH_UI_UTF8_MATHEMATICS
+
+#if ENABLED(TOUCH_UI_UTF8_FRACTIONS)
+ /* 35 FRACTION_QUARTER */
+ 0x92, 0x00, 0x01, 0x01, 0x01, 0x44, 0x01, 0x40, 0x04, 0x00, 0x01, 0x04,
+ 0x01, 0x79, 0x01, 0xCE, 0x01, 0xEE, 0x01, 0x20, 0x07, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0x90, 0x04, 0x00, 0x01, 0x3F, 0x03, 0xFF, 0x01, 0x20,
+ 0x07, 0x00, 0x01, 0x3F, 0x01, 0xFE, 0x01, 0x10, 0x04, 0x00, 0x01, 0x3F,
+ 0x01, 0xDB, 0x01, 0x8D, 0x01, 0xFF, 0x01, 0x20, 0x07, 0x00, 0x01, 0xDF,
+ 0x01, 0xF5, 0x05, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0x20, 0x06, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xC0, 0x07, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x06, 0x00, 0x01, 0x1F, 0x01, 0xFF,
+ 0x01, 0x20, 0x07, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x06, 0x00,
+ 0x01, 0xAF, 0x01, 0xF8, 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20,
+ 0x05, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xE1, 0x08, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x05, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x50,
+ 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x05, 0x00, 0x01, 0x7F,
+ 0x01, 0xFC, 0x09, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x04, 0x00,
+ 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF2, 0x09, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0x20, 0x04, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0x80, 0x09, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0x4F, 0x01, 0xFE,
+ 0x0A, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0xDF,
+ 0x01, 0xF5, 0x0A, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x03, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xB0, 0x04, 0x00, 0x01, 0x37, 0x01, 0x77,
+ 0x02, 0x00, 0x01, 0x04, 0x01, 0x55, 0x01, 0x5D, 0x01, 0xFF, 0x01, 0x75,
+ 0x01, 0x55, 0x01, 0x10, 0x01, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0x20,
+ 0x03, 0x00, 0x01, 0x01, 0x01, 0xEF, 0x01, 0xFF, 0x02, 0x00, 0x01, 0x0D,
+ 0x05, 0xFF, 0x01, 0x40, 0x01, 0x00, 0x01, 0xAF, 0x01, 0xF8, 0x04, 0x00,
+ 0x01, 0x0C, 0x02, 0xFF, 0x02, 0x00, 0x01, 0x0C, 0x05, 0xEE, 0x01, 0x40,
+ 0x01, 0x04, 0x01, 0xFF, 0x01, 0xE0, 0x04, 0x00, 0x01, 0x8F, 0x01, 0xBE,
+ 0x01, 0xFF, 0x09, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x50, 0x03, 0x00,
+ 0x01, 0x04, 0x01, 0xFE, 0x01, 0x1E, 0x01, 0xFF, 0x09, 0x00, 0x01, 0x7F,
+ 0x01, 0xFC, 0x04, 0x00, 0x01, 0x1E, 0x01, 0xF4, 0x01, 0x0E, 0x01, 0xFF,
+ 0x08, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF2, 0x04, 0x00, 0x01, 0xBF,
+ 0x01, 0x80, 0x01, 0x0E, 0x01, 0xFF, 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0x80, 0x03, 0x00, 0x01, 0x08, 0x01, 0xFC, 0x01, 0x00, 0x01, 0x0E,
+ 0x01, 0xFF, 0x08, 0x00, 0x01, 0x4F, 0x01, 0xFE, 0x04, 0x00, 0x01, 0x4F,
+ 0x01, 0xE1, 0x01, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x08, 0x00, 0x01, 0xDF,
+ 0x01, 0xF5, 0x03, 0x00, 0x01, 0x01, 0x01, 0xEF, 0x01, 0x40, 0x01, 0x00,
+ 0x01, 0x0E, 0x01, 0xFF, 0x07, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xB0,
+ 0x03, 0x00, 0x01, 0x0B, 0x01, 0xF8, 0x02, 0x00, 0x01, 0x0E, 0x01, 0xFF,
+ 0x07, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x20, 0x03, 0x00, 0x01, 0x3F,
+ 0x01, 0xF8, 0x02, 0x88, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0x88, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xF8, 0x04, 0x00, 0x01, 0x4F, 0x06, 0xFF, 0x05, 0x00,
+ 0x01, 0x04, 0x01, 0xFF, 0x01, 0xE0, 0x04, 0x00, 0x01, 0x2A, 0x03, 0xAA,
+ 0x01, 0xAF, 0x01, 0xFF, 0x01, 0xAA, 0x05, 0x00, 0x01, 0x0D, 0x01, 0xFF,
+ 0x01, 0x50, 0x08, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x06, 0x00, 0x01, 0x8F,
+ 0x01, 0xFB, 0x09, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x05, 0x00, 0x01, 0x02,
+ 0x01, 0xFF, 0x01, 0xF2, 0x09, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x05, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x80, 0x09, 0x00, 0x01, 0x05, 0x01, 0x66,
+ 0xBF, 0x00,
+
+ /* 36 FRACTION_HALF */
+ 0x92, 0x00, 0x01, 0x01, 0x01, 0x44, 0x01, 0x40, 0x04, 0x00, 0x01, 0x04,
+ 0x01, 0x7A, 0x01, 0xCE, 0x01, 0xEE, 0x01, 0x20, 0x07, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0x80, 0x04, 0x00, 0x01, 0x3F, 0x03, 0xFF, 0x01, 0x20,
+ 0x07, 0x00, 0x01, 0x4F, 0x01, 0xFE, 0x05, 0x00, 0x01, 0x3F, 0x01, 0xDA,
+ 0x01, 0x7D, 0x01, 0xFF, 0x01, 0x20, 0x07, 0x00, 0x01, 0xDF, 0x01, 0xF5,
+ 0x07, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x06, 0x00, 0x01, 0x07,
+ 0x01, 0xFF, 0x01, 0xC0, 0x07, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20,
+ 0x06, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x01, 0x20, 0x07, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x06, 0x00, 0x01, 0xAF, 0x01, 0xF8, 0x08, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x05, 0x00, 0x01, 0x04, 0x01, 0xFF,
+ 0x01, 0xE0, 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x05, 0x00,
+ 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x50, 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0x20, 0x05, 0x00, 0x01, 0x7F, 0x01, 0xFC, 0x09, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF2,
+ 0x09, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20, 0x04, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0x80, 0x09, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x20,
+ 0x04, 0x00, 0x01, 0x4F, 0x01, 0xFE, 0x0A, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0x20, 0x04, 0x00, 0x01, 0xDF, 0x01, 0xF5, 0x0A, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0x20, 0x03, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xB0,
+ 0x01, 0x00, 0x01, 0x04, 0x01, 0x8A, 0x01, 0xCC, 0x01, 0xA7, 0x01, 0x10,
+ 0x02, 0x00, 0x01, 0x04, 0x01, 0x55, 0x01, 0x5D, 0x01, 0xFF, 0x01, 0x75,
+ 0x01, 0x55, 0x01, 0x10, 0x01, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x20,
+ 0x01, 0x06, 0x04, 0xFF, 0x01, 0xF7, 0x02, 0x00, 0x01, 0x0D, 0x05, 0xFF,
+ 0x01, 0x40, 0x01, 0x00, 0x01, 0xBF, 0x01, 0xF8, 0x01, 0x00, 0x01, 0x08,
+ 0x01, 0xFF, 0x01, 0xA7, 0x01, 0x68, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0x70,
+ 0x01, 0x00, 0x01, 0x0B, 0x05, 0xDD, 0x01, 0x40, 0x01, 0x04, 0x01, 0xFF,
+ 0x01, 0xE0, 0x01, 0x00, 0x01, 0x05, 0x01, 0x60, 0x02, 0x00, 0x01, 0x08,
+ 0x01, 0xFF, 0x01, 0xF1, 0x08, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x50,
+ 0x06, 0x00, 0x01, 0xEF, 0x01, 0xF4, 0x08, 0x00, 0x01, 0x7F, 0x01, 0xFB,
+ 0x07, 0x00, 0x01, 0xCF, 0x01, 0xF3, 0x07, 0x00, 0x01, 0x02, 0x01, 0xFF,
+ 0x01, 0xF2, 0x06, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xE0, 0x07, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x80, 0x06, 0x00, 0x01, 0x0D, 0x01, 0xFF,
+ 0x01, 0x50, 0x07, 0x00, 0x01, 0x4F, 0x01, 0xFE, 0x07, 0x00, 0x01, 0xAF,
+ 0x01, 0xFA, 0x08, 0x00, 0x01, 0xDF, 0x01, 0xF5, 0x06, 0x00, 0x01, 0x09,
+ 0x01, 0xFF, 0x01, 0xC0, 0x07, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xB0,
+ 0x06, 0x00, 0x01, 0x8F, 0x01, 0xFD, 0x01, 0x10, 0x07, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0x20, 0x05, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xC1,
+ 0x08, 0x00, 0x01, 0xBF, 0x01, 0xF8, 0x06, 0x00, 0x01, 0xAF, 0x01, 0xFB,
+ 0x08, 0x00, 0x01, 0x05, 0x01, 0xFF, 0x01, 0xE0, 0x05, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0xA0, 0x08, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x50,
+ 0x04, 0x00, 0x01, 0x01, 0x01, 0xCF, 0x01, 0xF9, 0x09, 0x00, 0x01, 0x8F,
+ 0x01, 0xFB, 0x05, 0x00, 0x01, 0x09, 0x01, 0xFF, 0x01, 0xFE, 0x03, 0xEE,
+ 0x01, 0xE6, 0x04, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xF2, 0x05, 0x00,
+ 0x01, 0x0A, 0x05, 0xFF, 0x01, 0xF7, 0x04, 0x00, 0x01, 0x0A, 0x01, 0xEE,
+ 0x01, 0x70, 0x05, 0x00, 0x01, 0x04, 0x05, 0x66, 0x01, 0x62, 0xBE, 0x00,
+
+ /* 37 FRACTION_THREE_FOURTHS */
+ 0x87, 0x00, 0x01, 0x02, 0x01, 0x34, 0x01, 0x42, 0x08, 0x00, 0x01, 0x01,
+ 0x01, 0x55, 0x01, 0x50, 0x04, 0x00, 0x01, 0x4C, 0x03, 0xFF, 0x01, 0xE9,
+ 0x01, 0x10, 0x06, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0x80, 0x04, 0x00,
+ 0x01, 0x7F, 0x01, 0xFF, 0x01, 0xFE, 0x02, 0xFF, 0x01, 0xE2, 0x06, 0x00,
+ 0x01, 0x4F, 0x01, 0xFE, 0x05, 0x00, 0x01, 0x47, 0x01, 0x30, 0x01, 0x00,
+ 0x01, 0x05, 0x01, 0xEF, 0x01, 0xFB, 0x06, 0x00, 0x01, 0xDF, 0x01, 0xF5,
+ 0x09, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x05, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xB0, 0x09, 0x00, 0x01, 0x1F, 0x01, 0xFF, 0x05, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0x20, 0x09, 0x00, 0x01, 0x6F, 0x01, 0xFB, 0x05, 0x00,
+ 0x01, 0xBF, 0x01, 0xF8, 0x07, 0x00, 0x01, 0x03, 0x01, 0x44, 0x01, 0x5A,
+ 0x01, 0xFF, 0x01, 0xD1, 0x04, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xE0,
+ 0x07, 0x00, 0x01, 0x0C, 0x02, 0xFF, 0x01, 0xE7, 0x05, 0x00, 0x01, 0x0D,
+ 0x01, 0xFF, 0x01, 0x50, 0x07, 0x00, 0x01, 0x0B, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0xFE, 0x01, 0x70, 0x04, 0x00, 0x01, 0x7F, 0x01, 0xFB, 0x0A, 0x00,
+ 0x01, 0x16, 0x01, 0xDF, 0x01, 0xF9, 0x03, 0x00, 0x01, 0x02, 0x01, 0xFF,
+ 0x01, 0xF2, 0x0B, 0x00, 0x01, 0x1E, 0x01, 0xFF, 0x01, 0x20, 0x02, 0x00,
+ 0x01, 0x0B, 0x01, 0xFF, 0x01, 0x80, 0x0B, 0x00, 0x01, 0x0A, 0x01, 0xFF,
+ 0x01, 0x60, 0x02, 0x00, 0x01, 0x4F, 0x01, 0xFE, 0x0C, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0x60, 0x02, 0x00, 0x01, 0xDF, 0x01, 0xF5, 0x0C, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x30, 0x01, 0x00, 0x01, 0x08, 0x01, 0xFF,
+ 0x01, 0xB0, 0x04, 0x00, 0x01, 0x47, 0x01, 0x77, 0x02, 0x00, 0x01, 0xD7,
+ 0x01, 0x42, 0x01, 0x01, 0x01, 0x38, 0x01, 0xEF, 0x01, 0xFC, 0x02, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x20, 0x03, 0x00, 0x01, 0x02, 0x02, 0xFF,
+ 0x02, 0x00, 0x05, 0xFF, 0x01, 0xC1, 0x02, 0x00, 0x01, 0xBF, 0x01, 0xF8,
+ 0x04, 0x00, 0x01, 0x0C, 0x02, 0xFF, 0x02, 0x00, 0x01, 0x7B, 0x01, 0xEF,
+ 0x02, 0xFF, 0x01, 0xB6, 0x02, 0x00, 0x01, 0x04, 0x01, 0xFF, 0x01, 0xE0,
+ 0x04, 0x00, 0x01, 0x9F, 0x01, 0xBE, 0x01, 0xFF, 0x04, 0x00, 0x01, 0x22,
+ 0x01, 0x10, 0x03, 0x00, 0x01, 0x0D, 0x01, 0xFF, 0x01, 0x50, 0x03, 0x00,
+ 0x01, 0x04, 0x01, 0xFE, 0x01, 0x1E, 0x01, 0xFF, 0x09, 0x00, 0x01, 0x8F,
+ 0x01, 0xFB, 0x04, 0x00, 0x01, 0x1E, 0x01, 0xF3, 0x01, 0x0E, 0x01, 0xFF,
+ 0x08, 0x00, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xF2, 0x04, 0x00, 0x01, 0xCF,
+ 0x01, 0x70, 0x01, 0x0E, 0x01, 0xFF, 0x08, 0x00, 0x01, 0x0B, 0x01, 0xFF,
+ 0x01, 0x80, 0x03, 0x00, 0x01, 0x08, 0x01, 0xFB, 0x01, 0x00, 0x01, 0x0E,
+ 0x01, 0xFF, 0x08, 0x00, 0x01, 0x5F, 0x01, 0xFE, 0x04, 0x00, 0x01, 0x4F,
+ 0x01, 0xE1, 0x01, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x08, 0x00, 0x01, 0xDF,
+ 0x01, 0xF4, 0x03, 0x00, 0x01, 0x01, 0x01, 0xEF, 0x01, 0x40, 0x01, 0x00,
+ 0x01, 0x0E, 0x01, 0xFF, 0x07, 0x00, 0x01, 0x08, 0x01, 0xFF, 0x01, 0xB0,
+ 0x03, 0x00, 0x01, 0x0B, 0x01, 0xF8, 0x02, 0x00, 0x01, 0x0E, 0x01, 0xFF,
+ 0x07, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x20, 0x03, 0x00, 0x01, 0x3F,
+ 0x01, 0xF9, 0x02, 0x99, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x99, 0x06, 0x00,
+ 0x01, 0xBF, 0x01, 0xF8, 0x04, 0x00, 0x01, 0x4F, 0x06, 0xFF, 0x05, 0x00,
+ 0x01, 0x05, 0x01, 0xFF, 0x01, 0xD0, 0x04, 0x00, 0x01, 0x29, 0x03, 0x99,
+ 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x99, 0x05, 0x00, 0x01, 0x0D, 0x01, 0xFF,
+ 0x01, 0x40, 0x08, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x06, 0x00, 0x01, 0x8F,
+ 0x01, 0xFB, 0x09, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x05, 0x00, 0x01, 0x02,
+ 0x01, 0xFF, 0x01, 0xF2, 0x09, 0x00, 0x01, 0x0E, 0x01, 0xFF, 0x05, 0x00,
+ 0x01, 0x0A, 0x01, 0xEE, 0x01, 0x70, 0x09, 0x00, 0x01, 0x04, 0x01, 0x55,
+ 0xBF, 0x00,
+#endif // TOUCH_UI_UTF8_FRACTIONS
+
+#if ENABLED(TOUCH_UI_UTF8_SYMBOLS)
+ /* 38 MICRON_SIGN */
+ 0xFF, 0x00, 0x1F, 0x00, 0x01, 0x02, 0x01, 0x44, 0x01, 0x40, 0x05, 0x00,
+ 0x01, 0x14, 0x01, 0x44, 0x01, 0x10, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00,
+ 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x05, 0x00, 0x01, 0x4F, 0x01, 0xFF,
+ 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF4, 0x05, 0x00,
+ 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF6, 0x05, 0x00, 0x01, 0x9F, 0x01, 0xFF, 0x01, 0x70, 0x08, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xFA, 0x05, 0x00, 0x01, 0xEF, 0x01, 0xFF,
+ 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x02, 0xFF, 0x01, 0x20, 0x03, 0x00,
+ 0x01, 0x07, 0x02, 0xFF, 0x01, 0x70, 0x08, 0x00, 0x01, 0x07, 0x02, 0xFF,
+ 0x01, 0xD2, 0x03, 0x00, 0x01, 0x6F, 0x02, 0xFF, 0x01, 0xA0, 0x08, 0x00,
+ 0x01, 0x07, 0x03, 0xFF, 0x01, 0xA6, 0x01, 0x55, 0x01, 0x8D, 0x03, 0xFF,
+ 0x01, 0xF9, 0x01, 0xA4, 0x07, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF7,
+ 0x05, 0xFF, 0x01, 0x5D, 0x02, 0xFF, 0x01, 0xF4, 0x07, 0x00, 0x01, 0x07,
+ 0x01, 0xFF, 0x01, 0xF3, 0x01, 0x5F, 0x03, 0xFF, 0x01, 0xF5, 0x01, 0x06,
+ 0x02, 0xFF, 0x01, 0xF4, 0x07, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3,
+ 0x01, 0x01, 0x01, 0x7C, 0x01, 0xDD, 0x01, 0xC7, 0x01, 0x10, 0x01, 0x00,
+ 0x01, 0x6C, 0x01, 0xDB, 0x01, 0x50, 0x07, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x10, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x10, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x10, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x10, 0x00, 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x10, 0x00,
+ 0x01, 0x07, 0x01, 0xFF, 0x01, 0xF3, 0x10, 0x00, 0x01, 0x07, 0x01, 0xFF,
+ 0x01, 0xF3, 0x10, 0x00, 0x01, 0x07, 0x01, 0xEE, 0x01, 0xE3, 0x35, 0x00,
+
+ /* 39 PILCROW_SIGN */
+ 0x9C, 0x00, 0x01, 0x16, 0x01, 0x9B, 0x04, 0xCC, 0x01, 0xCA, 0x0B, 0x00,
+ 0x01, 0x19, 0x06, 0xFF, 0x01, 0xFD, 0x0A, 0x00, 0x01, 0x03, 0x01, 0xEF,
+ 0x03, 0xFF, 0x01, 0xFB, 0x01, 0xAA, 0x01, 0xAF, 0x01, 0xFD, 0x0A, 0x00,
+ 0x01, 0x2E, 0x04, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD,
+ 0x0A, 0x00, 0x01, 0xBF, 0x04, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F,
+ 0x01, 0xFD, 0x09, 0x00, 0x01, 0x03, 0x05, 0xFF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x09, 0x00, 0x01, 0x08, 0x05, 0xFF, 0x01, 0xF2,
+ 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD, 0x09, 0x00, 0x01, 0x0B, 0x05, 0xFF,
+ 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD, 0x09, 0x00, 0x01, 0x0C,
+ 0x05, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD, 0x09, 0x00,
+ 0x01, 0x0B, 0x05, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD,
+ 0x09, 0x00, 0x01, 0x0A, 0x05, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F,
+ 0x01, 0xFD, 0x09, 0x00, 0x01, 0x06, 0x05, 0xFF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0A, 0x00, 0x01, 0xEF, 0x04, 0xFF, 0x01, 0xF2,
+ 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD, 0x0A, 0x00, 0x01, 0x6F, 0x04, 0xFF,
+ 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD, 0x0A, 0x00, 0x01, 0x08,
+ 0x04, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD, 0x0B, 0x00,
+ 0x01, 0x5E, 0x03, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F, 0x01, 0xFD,
+ 0x0C, 0x00, 0x01, 0x6B, 0x02, 0xFF, 0x01, 0xF2, 0x01, 0x00, 0x01, 0x0F,
+ 0x01, 0xFD, 0x0D, 0x00, 0x01, 0x01, 0x01, 0xCF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0xBF, 0x01, 0xF2, 0x01, 0x00,
+ 0x01, 0x0F, 0x01, 0xFD, 0x0E, 0x00, 0x01, 0x34, 0x01, 0x40, 0x01, 0x00,
+ 0x01, 0x04, 0x01, 0x43, 0x7A, 0x00,
+
+ /* 40 BROKEN_BAR */
+ 0xAD, 0x00, 0x01, 0x07, 0x01, 0x99, 0x01, 0x60, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x08, 0x01, 0xBB, 0x01, 0x70, 0x6F, 0x00, 0x01, 0x0B,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0,
+ 0x10, 0x00, 0x01, 0x0C, 0x01, 0xFF, 0x01, 0xA0, 0x10, 0x00, 0x01, 0x04,
+ 0x01, 0x55, 0x01, 0x30, 0x47, 0x00,
+
+ /* 41 SECTION_SIGN */
+ 0x89, 0x00, 0x01, 0x35, 0x01, 0x64, 0x01, 0x31, 0x0E, 0x00, 0x01, 0x01,
+ 0x01, 0x9E, 0x03, 0xFF, 0x01, 0xD9, 0x01, 0x30, 0x0C, 0x00, 0x01, 0x2E,
+ 0x05, 0xFF, 0x01, 0xB0, 0x0C, 0x00, 0x01, 0xEF, 0x01, 0xFF, 0x01, 0xFB,
+ 0x01, 0x98, 0x01, 0xAE, 0x01, 0xFF, 0x01, 0xB0, 0x0B, 0x00, 0x01, 0x07,
+ 0x01, 0xFF, 0x01, 0xFC, 0x01, 0x10, 0x02, 0x00, 0x01, 0x39, 0x01, 0xA0,
+ 0x0B, 0x00, 0x01, 0x0B, 0x01, 0xFF, 0x01, 0xF2, 0x10, 0x00, 0x01, 0x0C,
+ 0x01, 0xFF, 0x01, 0xF0, 0x10, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xF3,
+ 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x20, 0x10, 0x00,
+ 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xE4, 0x10, 0x00, 0x01, 0x1D, 0x02, 0xFF,
+ 0x01, 0xA1, 0x0F, 0x00, 0x01, 0x4E, 0x03, 0xFF, 0x01, 0x70, 0x0D, 0x00,
+ 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF9, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xFD,
+ 0x01, 0x30, 0x0C, 0x00, 0x01, 0x3F, 0x01, 0xFF, 0x01, 0x60, 0x01, 0x07,
+ 0x02, 0xFF, 0x01, 0xF8, 0x0C, 0x00, 0x01, 0xBF, 0x01, 0xF9, 0x02, 0x00,
+ 0x01, 0x19, 0x02, 0xFF, 0x01, 0xC0, 0x0B, 0x00, 0x01, 0xFF, 0x01, 0xF3,
+ 0x03, 0x00, 0x01, 0x4E, 0x01, 0xFF, 0x01, 0xFB, 0x0A, 0x00, 0x01, 0x01,
+ 0x01, 0xFF, 0x01, 0xF2, 0x03, 0x00, 0x01, 0x01, 0x01, 0xDF, 0x01, 0xFF,
+ 0x01, 0x40, 0x09, 0x00, 0x01, 0x01, 0x01, 0xFF, 0x01, 0xF7, 0x04, 0x00,
+ 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x90, 0x0A, 0x00, 0x01, 0xDF, 0x01, 0xFF,
+ 0x01, 0x20, 0x03, 0x00, 0x01, 0x0A, 0x01, 0xFF, 0x01, 0xB0, 0x0A, 0x00,
+ 0x01, 0x6F, 0x01, 0xFF, 0x01, 0xF5, 0x03, 0x00, 0x01, 0x08, 0x01, 0xFF,
+ 0x01, 0xA0, 0x0A, 0x00, 0x01, 0x0A, 0x02, 0xFF, 0x01, 0x91, 0x02, 0x00,
+ 0x01, 0x0C, 0x01, 0xFF, 0x01, 0x70, 0x0B, 0x00, 0x01, 0x8F, 0x01, 0xFF,
+ 0x01, 0xFE, 0x01, 0x60, 0x01, 0x00, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x10,
+ 0x0B, 0x00, 0x01, 0x03, 0x01, 0xDF, 0x01, 0xFF, 0x01, 0xFD, 0x01, 0x46,
+ 0x01, 0xFF, 0x01, 0xF5, 0x0D, 0x00, 0x01, 0x07, 0x04, 0xFF, 0x01, 0x50,
+ 0x0E, 0x00, 0x01, 0x2A, 0x02, 0xFF, 0x01, 0xF5, 0x10, 0x00, 0x01, 0x4E,
+ 0x01, 0xFF, 0x01, 0xFE, 0x01, 0x20, 0x0F, 0x00, 0x01, 0x01, 0x01, 0xCF,
+ 0x01, 0xFF, 0x01, 0xC0, 0x10, 0x00, 0x01, 0x1E, 0x01, 0xFF, 0x01, 0xF3,
+ 0x10, 0x00, 0x01, 0x06, 0x01, 0xFF, 0x01, 0xF6, 0x10, 0x00, 0x01, 0x05,
+ 0x01, 0xFF, 0x01, 0xF6, 0x0B, 0x00, 0x01, 0x01, 0x04, 0x00, 0x01, 0x0A,
+ 0x01, 0xFF, 0x01, 0xF3, 0x0B, 0x00, 0x01, 0x08, 0x01, 0xE8, 0x01, 0x20,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0x8F, 0x01, 0xFF, 0x01, 0xE0, 0x0B, 0x00,
+ 0x01, 0x08, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0xCB, 0x01, 0xDF, 0x02, 0xFF,
+ 0x01, 0x40, 0x0B, 0x00, 0x01, 0x08, 0x05, 0xFF, 0x01, 0xF5, 0x0D, 0x00,
+ 0x01, 0x49, 0x01, 0xDF, 0x02, 0xFF, 0x01, 0xE8, 0x01, 0x20, 0x0F, 0x00,
+ 0x01, 0x12, 0x01, 0x21, 0x7F, 0x00,
+
+ /* 42 NOT_SIGN */
+ 0xFF, 0x00, 0x7F, 0x00, 0x01, 0x12, 0x0C, 0x22, 0x06, 0x00, 0x01, 0x9F,
+ 0x0C, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40,
+ 0x05, 0x00, 0x01, 0x9F, 0x0C, 0xFF, 0x01, 0x40, 0x05, 0x00, 0x01, 0x24,
+ 0x0A, 0x44, 0x01, 0x6F, 0x01, 0xFF, 0x01, 0x40, 0x10, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0x40, 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x40,
+ 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x40, 0x10, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0x40, 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x40,
+ 0x10, 0x00, 0x01, 0x2F, 0x01, 0xFF, 0x01, 0x40, 0x10, 0x00, 0x01, 0x2F,
+ 0x01, 0xFF, 0x01, 0x40, 0x10, 0x00, 0x01, 0x17, 0x01, 0x77, 0x01, 0x10,
+ 0xFF, 0x00, 0x34, 0x00
+#endif // TOUCH_UI_UTF8_SYMBOLS
+};
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/bitmap2cpp.py b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/bitmap2cpp.py
new file mode 100644
index 0000000..0c4499e
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/bitmap2cpp.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+
+# Written By Marcio Teixeira 2019 - Aleph Objects, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# To view a copy of the GNU General Public License, go to the following
+# location: .
+
+from __future__ import print_function
+from PIL import Image
+import argparse
+import textwrap
+
+def pack_rle(data):
+ """Use run-length encoding to pack the bytes"""
+ rle = []
+ value = data[0]
+ count = 0
+ for i in data:
+ if i != value or count == 255:
+ rle.append(count)
+ rle.append(value)
+ value = i
+ count = 1
+ else:
+ count += 1
+ rle.append(count)
+ rle.append(value)
+ return rle
+
+class WriteSource:
+ def __init__(self, lines_in_blocks):
+ self.blocks = []
+ self.values = []
+ self.block_size = lines_in_blocks
+ self.rows = 0
+
+ def add_pixel(self, value):
+ self.values.append(value)
+
+ def convert_to_4bpp(self, data, chunk_size = 0):
+ # Invert the image
+ data = list(map(lambda i: 255 - i, data))
+ # Quanitize 8-bit values into 4-bits
+ data = list(map(lambda i: i >> 4, data))
+ # Make sure there is an even number of elements
+ if (len(data) & 1) == 1:
+ data.append(0)
+ # Combine each two adjacent values into one
+ i = iter(data)
+ data = list(map(lambda a, b: a << 4 | b, i ,i))
+ # Pack the data
+ data = pack_rle(data)
+ # Convert values into hex strings
+ return list(map(lambda a: "0x" + format(a, '02x'), data))
+
+ def end_row(self, y):
+ # Pad each row into even number of values
+ if len(self.values) & 1:
+ self.values.append(0)
+
+ self.rows += 1
+ if self.block_size and (self.rows % self.block_size) == 0:
+ self.blocks.append(self.values)
+ self.values = []
+
+ def write(self):
+ if len(self.values):
+ self.blocks.append(self.values)
+
+ block_strs = [];
+ for b in self.blocks:
+ data = self.convert_to_4bpp(b)
+ data = ', '.join(data)
+ data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ')
+ block_strs.append(data)
+
+ print("const unsigned char font[] PROGMEM = {")
+ for i, b in enumerate(block_strs):
+ if i:
+ print(',')
+ print('\n /* {} */'.format(i))
+ print(b, end='')
+ print("\n};")
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='Converts a grayscale bitmap into a 16-level RLE packed C array for use as font data')
+ parser.add_argument("input")
+ parser.add_argument('--char_height', help='Adds a separator every so many lines', type=int)
+ args = parser.parse_args()
+
+ writer = WriteSource(args.char_height)
+
+ img = Image.open(args.input).convert('L')
+ for y in range(img.height):
+ for x in range(img.width):
+ writer.add_pixel(img.getpixel((x,y)))
+ writer.end_row(y)
+ writer.write()
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/circular_progress.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/circular_progress.h
new file mode 100644
index 0000000..6695134
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/circular_progress.h
@@ -0,0 +1,105 @@
+/***********************
+ * circular_progress.h *
+ ***********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/* This function draws a circular progress "ring" */
+
+void draw_circular_progress(CommandProcessor& cmd, int x, int y, int w, int h, float percent, char *text, uint32_t bgcolor, uint32_t fgcolor) {
+ using namespace FTDI;
+
+ const float rim = 0.3;
+ const float a = percent/100.0*2.0*PI;
+ const float a1 = min(PI/2, a);
+ const float a2 = min(PI/2, a-a1);
+ const float a3 = min(PI/2, a-a1-a2);
+ const float a4 = min(PI/2, a-a1-a2-a3);
+
+ const int ro = min(w,h) * 8;
+ const int rr = ro * rim;
+ const int cx = x * 16 + w * 8;
+ const int cy = y * 16 + h * 8;
+
+ // Load a rim shape into stencil buffer
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(TAG_MASK(0));
+ cmd.cmd(CLEAR(0,1,0));
+ cmd.cmd(COLOR_MASK(0,0,0,0));
+ cmd.cmd(STENCIL_OP(STENCIL_OP_KEEP, STENCIL_OP_INVERT));
+ cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_ALWAYS, 255, 255));
+ cmd.cmd(BEGIN(POINTS));
+ cmd.cmd(POINT_SIZE(ro));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(POINT_SIZE(ro - rr));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(RESTORE_CONTEXT());
+
+ // Mask further drawing by stencil buffer
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(STENCIL_FUNC(STENCIL_FUNC_NOTEQUAL, 0, 255));
+
+ // Fill the background
+ cmd.cmd(COLOR_RGB(bgcolor));
+ cmd.cmd(BEGIN(POINTS));
+ cmd.cmd(POINT_SIZE(ro));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(COLOR_RGB(fgcolor));
+
+ // Paint upper-right quadrant
+ cmd.cmd(BEGIN(EDGE_STRIP_A));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(VERTEX2F(cx + ro*sin(a1) + 16,cy - ro*cos(a1) + 8));
+
+ // Paint lower-right quadrant
+ if (a > PI/2) {
+ cmd.cmd(BEGIN(EDGE_STRIP_R));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(VERTEX2F(cx + ro*cos(a2),cy + ro*sin(a2) + 16));
+ }
+
+ // Paint lower-left quadrant
+ if (a > PI) {
+ cmd.cmd(BEGIN(EDGE_STRIP_B));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(VERTEX2F(cx - ro*sin(a3) - 8,cy + ro*cos(a3)));
+ }
+
+ // Paint upper-left quadrant
+ if (a > 1.5*PI) {
+ cmd.cmd(BEGIN(EDGE_STRIP_L));
+ cmd.cmd(VERTEX2F(cx, cy));
+ cmd.cmd(VERTEX2F(cx - ro*cos(a4),cy - ro*sin(a4)));
+ }
+ cmd.cmd(RESTORE_CONTEXT());
+
+ // Draw the text
+
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(COLOR_RGB(fgcolor));
+ cmd.text(x,y,w,h,text, OPT_CENTERX | OPT_CENTERY);
+ cmd.cmd(RESTORE_CONTEXT());
+}
+
+void draw_circular_progress(CommandProcessor& cmd, int x, int y, int w, int h, float percent, uint32_t bgcolor, uint32_t fgcolor) {
+ char str[5];
+ sprintf(str,"%d\%%",int(percent));
+ draw_circular_progress(cmd, x, y, w, h, percent, str, bgcolor, fgcolor);
+}
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/poly_ui.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/poly_ui.h
new file mode 100644
index 0000000..ba41650
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/poly_ui.h
@@ -0,0 +1,408 @@
+/*************
+ * poly_ui.h *
+ *************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2019 - Aleph Objects, Inc. *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * The PolyReader class iterates over an array of (x,y) pairs.
+ * For supporting polygons with holes an end-of-loop marker may
+ * be embedded into the data stream:
+ *
+ * const PROGMEM uint16_t data[] = {
+ * x, y, x, y, ..., eol,
+ * ...
+ * x, y, x, y, ..., eol
+ * }
+ *
+ * The PolyReader object can be used to iterate over the points.
+ *
+ * PolyReader r(data, N_ELEMENTS(data));
+ *
+ * for (r.start();r.has_more(); r.next()) {
+ * uint16_t x = r.x;
+ * uint16_t y = r.y;
+ *
+ * // Do something with the point
+ * ...
+ *
+ * // Do something else if this point
+ * // closes a loop.
+ * if (r.end_of_loop()) {
+ * ...
+ * }
+ * }
+ */
+
+class PolyReader {
+ public:
+ typedef uint16_t type_t;
+
+ private:
+ static constexpr type_t eol = 0xFFFF;
+
+ const type_t *p, *top, *end;
+ type_t start_x, start_y;
+
+ void close_loop() {
+ x = start_x;
+ y = start_y;
+ start_x = eol;
+ start_y = eol;
+ }
+
+ public:
+ type_t x, y;
+
+ // Begin reading a polygon data structure
+ PolyReader(const uint16_t data[], const size_t n_elements) : top(data), end(data + n_elements) {
+ start();
+ }
+
+ void start() {
+ p = top;
+ start_x = eol;
+ next();
+ }
+
+ // Reads the next point in the polygon data structure
+ void next() {
+ if (!p) return;
+
+ if (p == end) {
+ if (start_x != eol)
+ close_loop();
+ else
+ p = nullptr;
+ }
+ else {
+ x = pgm_read_word_far(p++);
+ if (x == eol)
+ close_loop();
+ else {
+ y = pgm_read_word_far(p++);
+ if (start_x == eol) {
+ start_x = x;
+ start_y = y;
+ }
+ }
+ }
+ }
+
+ bool has_more() { return p != nullptr; }
+ bool end_of_loop() { return start_x == eol; }
+};
+
+/**
+ * The TransformedPolyReader class works like the PolyReader,
+ * but the (x,y) input is assumed to be normalized onto a
+ * unit square and then mapped to the full 16-bits, i.e.
+ * (0.0,1.0) => (0x0000,0xFFFE). This class will scale the
+ * data to fit the entire display, a bounding box, or apply
+ * some arbitrary affine transform.
+ *
+ * This class is suitable for reading data from "svg2cpp.py"
+ */
+class TransformedPolyReader : public PolyReader {
+ private:
+ /**
+ * Fixed point type for fast transformations, supports
+ * values from 0 to 1024, with 1/32 precision.
+ */
+ static constexpr uint8_t fract_bits = 5;
+ typedef int16_t fix_t;
+ fix_t makefix(float f) { return f * (1 << fract_bits); }
+
+ // First two rows of 3x3 transformation matrix
+ fix_t a, b, c;
+ fix_t d, e, f;
+
+ void transform() {
+ /**
+ * Values from PolyReader vary from 0 to FFFE.
+ * As an approximation to dividing by FFFE,
+ * we perform a bit shift right by 16.
+ */
+ const int32_t px = PolyReader::x;
+ const int32_t py = PolyReader::y;
+ const int32_t round = 1 << (fract_bits-1);
+ x = (((((a * px) + (b * py)) >> 16) + c) + round) >> fract_bits;
+ y = (((((d * px) + (e * py)) >> 16) + f) + round) >> fract_bits;
+ }
+
+ void set_transform(
+ fix_t A, fix_t B, fix_t C,
+ fix_t D, fix_t E, fix_t F
+ ) {
+ a = A; b = B; c = C;
+ d = D; e = E; f = F;
+ }
+
+ public:
+ typedef int16_t type_t;
+
+ type_t x, y;
+
+ TransformedPolyReader(const uint16_t data[], const size_t n) : PolyReader(data, n) {
+ scale_to_fit();
+ transform();
+ }
+
+ // Set an arbitrary affine transform
+ void set_transform(
+ float A, float B, float C,
+ float D, float E, float F
+ ) {
+ set_transform(
+ makefix(A), makefix(B), makefix(C),
+ makefix(D), makefix(E), makefix(F)
+ );
+ }
+
+ // Scale the data to fit a specified bounding box
+ void scale_to_fit(type_t x_min, type_t y_min, type_t x_max, type_t y_max) {
+ fix_t sx = makefix(x_max - x_min);
+ fix_t sy = makefix(y_max - y_min);
+ fix_t tx = makefix(x_min);
+ fix_t ty = makefix(y_min);
+ set_transform(
+ sx, 0, tx,
+ 0, sy, ty
+ );
+ }
+
+ // Scale to fit the entire display (default)
+ void scale_to_fit() {
+ scale_to_fit(0, 0, FTDI::display_width, FTDI::display_height);
+ }
+
+ void next() {
+ PolyReader::next();
+ transform();
+ }
+};
+
+/**
+ * The DeduplicatedPolyReader wraps around another PolyReader
+ * class to remove repeated points from the data. This could
+ * happen when scaling down using TransformedPolyReader, for
+ * example.
+ */
+template
+class DeduplicatedPolyReader : public POLY_READER {
+ private:
+ typename POLY_READER::type_t last_x, last_y;
+
+ static constexpr typename POLY_READER::type_t eol = 0xFFFF;
+
+ public:
+ DeduplicatedPolyReader(const uint16_t data[], const size_t n) : POLY_READER(data, n) {
+ last_x = POLY_READER::x;
+ last_y = POLY_READER::y;
+ }
+
+ void next() {
+ do {
+ if (!POLY_READER::has_more()) return;
+ POLY_READER::next();
+ } while (POLY_READER::x == last_x && POLY_READER::y == last_y && !POLY_READER::end_of_loop());
+ if (POLY_READER::end_of_loop()) {
+ last_x = last_y = eol;
+ }
+ else {
+ last_x = POLY_READER::x;
+ last_y = POLY_READER::y;
+ }
+ }
+};
+
+/**
+ * The helper class allows you to build an interface based on arbitrary
+ * shapes.
+ */
+template>
+class GenericPolyUI {
+ private:
+ CommandProcessor &cmd;
+
+ // Attributes used to paint buttons
+
+ uint32_t btn_fill_color = 0x000000;
+ uint32_t btn_shadow_color = 0xF3E0E0;
+ uint8_t btn_shadow_depth = 5;
+ uint32_t btn_stroke_color = 0x000000;
+ uint8_t btn_stroke_width = 28;
+
+ draw_mode_t mode;
+
+ public:
+ enum ButtonStyle : uint8_t {
+ FILL = 1,
+ STROKE = 2,
+ SHADOW = 4,
+ REGULAR = 7
+ };
+
+ typedef POLY_READER poly_reader_t;
+
+ GenericPolyUI(CommandProcessor &c, draw_mode_t what = BOTH) : cmd(c), mode(what) {}
+
+ // Fills a polygon with the current COLOR_RGB
+ void fill(poly_reader_t r, bool clip = true) {
+ using namespace FTDI;
+ int16_t x, y, w, h;
+
+ if (clip) {
+ // Clipping reduces the number of pixels that are
+ // filled, allowing more complex shapes to be drawn
+ // in the alloted time.
+ bounds(r, x, y, w, h);
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(SCISSOR_XY(x, y));
+ cmd.cmd(SCISSOR_SIZE(w, h));
+ }
+
+ Polygon p(cmd);
+ p.begin_fill();
+ p.begin_loop();
+ for (r.start();r.has_more();r.next()) {
+ p(r.x * 16, r.y * 16);
+ if (r.end_of_loop()) {
+ p.end_loop();
+ p.begin_loop();
+ }
+ }
+ p.end_loop();
+ p.end_fill();
+ if (clip)
+ cmd.cmd(RESTORE_CONTEXT());
+ }
+
+ void shadow(poly_reader_t r, uint8_t offset) {
+ #if FTDI_API_LEVEL >= 810
+ using namespace FTDI;
+ cmd.cmd(VERTEX_TRANSLATE_X(offset * 16));
+ cmd.cmd(VERTEX_TRANSLATE_Y(offset * 16));
+ fill(r, false);
+ cmd.cmd(VERTEX_TRANSLATE_X(0));
+ cmd.cmd(VERTEX_TRANSLATE_Y(0));
+ #endif
+ }
+
+ // Strokes a polygon with the current COLOR_RGB
+ void stroke(poly_reader_t r) {
+ using namespace FTDI;
+ Polygon p(cmd);
+ p.begin_stroke();
+ p.begin_loop();
+ for (r.start();r.has_more(); r.next()) {
+ p(r.x * 16, r.y * 16);
+ if (r.end_of_loop()) {
+ p.end_loop();
+ p.begin_loop();
+ }
+ }
+ p.end_loop();
+ p.end_stroke();
+ }
+
+ // Compute the bounds of a polygon
+ void bounds(poly_reader_t r, int16_t &x, int16_t &y, int16_t &w, int16_t &h) {
+ int16_t x_min = INT16_MAX;
+ int16_t y_min = INT16_MAX;
+ int16_t x_max = INT16_MIN;
+ int16_t y_max = INT16_MIN;
+ for (r.start(); r.has_more(); r.next()) {
+ x_min = min(x_min, int16_t(r.x));
+ x_max = max(x_max, int16_t(r.x));
+ y_min = min(y_min, int16_t(r.y));
+ y_max = max(y_max, int16_t(r.y));
+ }
+ x = x_min;
+ y = y_min;
+ w = x_max - x_min;
+ h = y_max - y_min;
+ }
+
+ /**
+ * Draw shaped buttons. Buttons are drawn out of a polygon which is
+ * filled and stroked on top of a drop shadow. The button will
+ * become "pushed" when touched.
+ */
+
+ void button_fill(const uint32_t color) {
+ btn_fill_color = color;
+ }
+
+ void button_stroke(const uint32_t color, const uint8_t width) {
+ btn_stroke_color = color;
+ btn_stroke_width = width;
+ }
+
+ void button_shadow(const uint32_t color, const uint8_t depth) {
+ btn_shadow_color = color;
+ btn_shadow_depth = depth;
+ }
+
+ void button(const uint8_t tag, poly_reader_t r, uint8_t style = REGULAR) {
+ using namespace FTDI;
+ // Draw the shadow
+ #if FTDI_API_LEVEL >= 810
+ if (mode & BACKGROUND && style & SHADOW) {
+ cmd.cmd(SAVE_CONTEXT());
+ cmd.cmd(TAG(tag));
+ cmd.cmd(VERTEX_TRANSLATE_X(btn_shadow_depth * 16));
+ cmd.cmd(VERTEX_TRANSLATE_Y(btn_shadow_depth * 16));
+ cmd.cmd(COLOR_RGB(btn_shadow_color));
+ fill(r, false);
+ cmd.cmd(RESTORE_CONTEXT());
+ }
+ #endif
+
+ if (mode & FOREGROUND) {
+ cmd.cmd(SAVE_CONTEXT());
+ #if FTDI_API_LEVEL >= 810
+ if (EventLoop::get_pressed_tag() == tag) {
+ // "Push" the button
+ cmd.cmd(VERTEX_TRANSLATE_X(btn_shadow_depth * 16));
+ cmd.cmd(VERTEX_TRANSLATE_Y(btn_shadow_depth * 16));
+ }
+ #endif
+ // Draw the fill and stroke
+ cmd.cmd(TAG(tag));
+ if (style & FILL) {
+ cmd.cmd(COLOR_RGB(btn_fill_color));
+ fill(r, false);
+ }
+ if (style & STROKE) {
+ cmd.cmd(COLOR_RGB(btn_stroke_color));
+ cmd.cmd(LINE_WIDTH(btn_stroke_width));
+ stroke(r);
+ }
+ cmd.cmd(RESTORE_CONTEXT());
+ }
+ }
+
+ void color(const uint32_t color) {
+ cmd.cmd(FTDI::COLOR_RGB(color));
+ }
+};
+
+typedef GenericPolyUI<> PolyUI;
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/svg2cpp.py b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/svg2cpp.py
new file mode 100644
index 0000000..c6eba39
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/svg2cpp.py
@@ -0,0 +1,280 @@
+#!/usr/bin/python
+
+# Written By Marcio Teixeira 2018 - Aleph Objects, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# To view a copy of the GNU General Public License, go to the following
+# location: .
+
+from __future__ import print_function
+import argparse, re, sys
+
+usage = '''
+This program extracts line segments from a SVG file and writes
+them as coordinates in a C array. The x and y values will be
+scaled from 0x0000 to 0xFFFE. 0xFFFF is used as path separator.
+
+This program can only interpret straight segments, not curves.
+It also cannot handle SVG transform attributes. To convert an
+SVG file into the proper format, use the following procedure:
+
+ - Load SVG file into Inkscape
+ - Convert all Objects to Paths (Path -> Object to Path)
+ - Convert all Strokes to Paths (Path -> Stroke to Path)
+ - Combine all paths into one (Path -> Combine) [1]
+ - Convert all curves into short line segments
+ (Extensions -> Modify Paths -> Flatten Beziers...)
+ - Save as new SVG
+ - Convert into a header file using this utility
+ - To give paths individual names, break apart paths and
+ use the XML Editor to set the "id" attributes.
+
+[1] Combining paths is necessary to remove transforms. You
+could also use inkscape-applytransforms Inkscape extension.
+
+'''
+
+header = '''
+/****************************************************************************
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+/**
+ * This file was auto-generated using "svg2cpp.py"
+ *
+ * The encoding consists of x,y pairs with the min and max scaled to
+ * 0x0000 and 0xFFFE. A single 0xFFFF in the data stream indicates the
+ * start of a new closed path.
+ */
+
+#pragma once
+'''
+
+class ComputeBoundingBox:
+ def reset(self):
+ self.x_min = float(" inf")
+ self.y_min = float(" inf")
+ self.x_max = float("-inf")
+ self.y_max = float("-inf")
+ self.n_points = 0
+ self.n_paths = 0
+
+ def command(self, type, x, y):
+ self.x_min = min(self.x_min, x)
+ self.x_max = max(self.x_max, x)
+ self.y_min = min(self.y_min, y)
+ self.y_max = max(self.y_max, y)
+
+ if type == "M":
+ self.n_paths += 1
+ self.n_points += 1
+
+ def scale(self, x, y):
+ x -= self.x_min
+ y -= self.y_min
+ x /= self.x_max - self.x_min
+ y /= self.y_max - self.y_min
+ #y = 1 - y # Flip upside down
+ return (x, y)
+
+ def path_finished(self, id):
+ pass
+
+ def write(self):
+ print("constexpr float x_min = %f;" % self.x_min)
+ print("constexpr float x_max = %f;" % self.x_max)
+ print("constexpr float y_min = %f;" % self.y_min)
+ print("constexpr float y_max = %f;" % self.y_max)
+ print()
+
+ def from_svg_view_box(self, svg):
+ s = re.search('